Page 1 of 1
Perfect looping possible?
Posted:
November 14th, 2004, 1:00 pm
by Cluq
Hi
I'm using the AudioPlayer to play a looping wave file. The looping works, but not perfectly. There is a very small silence before the wave starts over again and I would like it to loop without that silence. I have checked the wave file - it loops perfectly in SoundForge.
This is the simple code I've been using:
-----------------
type
TForm1 = class(TForm)
CheckBox1: TCheckBox;
AudioPlayer1: TAudioPlayer;
procedure AudioPlayer1Deactivate(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AudioPlayer1Deactivate(Sender: TObject);
begin
AudioPlayer1.Active := checkbox1.Checked;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
AudioPlayer1.Active := checkbox1.Checked;
end;
------------
Have any of you a better idea to get perfect looping?
Best regards,
Cluq.
Posted:
November 14th, 2004, 4:27 pm
by Kambiz
Hi,
You can use LiveAudioPlayer. In the event hanlder for supplying the wave data, you can specify the number of loops.
Cheers,
Kambiz
Posted:
November 15th, 2004, 8:32 am
by Cluq
Ok, thank you very much.
I've been looking at the LiveAudioPlayer Demo (the receiver part). I get the part that the variable WaveFormat is where the actual wave data is loaded into, right? But how would you go about loading wave data from a local wave-file on your harddrive?
/Cluq
Posted:
November 15th, 2004, 9:12 am
by Kambiz
Use a TWaveStorage instance.
- Code: Select all
procedure TForm1.LiveAudioPlayer1Format(Sender: TObject;
out pWaveFormat: PWaveFormatEx; var FreeIt: Boolean);
begin
FreeIt := False;
pWaveFormat := WaveStorage1.Wave.WaveFormat;
end;
function TForm1.LiveAudioPlayer1DataPtr(Sender: TObject;
out Buffer: Pointer; var NumLoops: Cardinal;
var FreeIt: Boolean): Cardinal;
begin
FreeIt := False;
NumLoops := $FFFFFFFF; // infinite
Buffer := WaveStorage1.Wave.Data;
Result := WaveStorage1.Wave.DataSize;
end;
By the way, set LiveAudioPlayer.BufferCount to 1 and LiveAudioPlayer.BufferInternally to False.
Posted:
November 15th, 2004, 12:14 pm
by Cluq
Ahh...of course...I'll be trying that out...
Btw, if I get positive results from this, I will most likely use this in my freeware game I'm writing... It is almost done, except for the sound. I have been using another unit for playing sound, but it had memory leaks and other crappy things wrong with it, so I'm looking for a better unit.
But this is looking quite nice so far...
/Cluq
Posted:
November 16th, 2004, 9:24 am
by Cluq
I have now done exactly as you said, but the sound doesn't loop. It only play once... LiveAudioPlayer.Active remains true - there is just silence...
The audio file is PCM 44,100 kHz, 16bit, Stereo...
Posted:
November 17th, 2004, 11:38 am
by Cluq
Have I found a bug?
Posted:
November 24th, 2004, 12:02 pm
by Kambiz
Yes, there's a bug. Open the WaveOut.pas file and look for
- Code: Select all
WHDR_BEGINLOOP or WHDR_BEGINLOOP
then replace it with
- Code: Select all
WHDR_BEGINLOOP or WHDR_ENDLOOP
By the way, you can leave the NumLoops as zero. Because when a buffer finished, the OnDataPtr event will be raised once more, until your return zero as result. If you set the NumLoops parameter, in the next call of the event you should return zero. So, my prevoius code is wrong.
Solution 1:
- Code: Select all
LiveAudioPlayer1.BufferInternally := False;
procedure TForm1.LiveAudioPlayer1Format(Sender: TObject;
out pWaveFormat: PWaveFormatEx; var FreeIt: Boolean);
begin
FreeIt := False;
pWaveFormat := WaveStorage1.Wave.WaveFormat;
end;
function TForm1.LiveAudioPlayer1DataPtr(Sender: TObject;
out Buffer: Pointer; var NumLoops: Cardinal;
var FreeIt: Boolean): Cardinal;
begin
FreeIt := False;
Buffer := WaveStorage1.Wave.Data;
Result := WaveStorage1.Wave.DataSize;
end;
Solution 2:
- Code: Select all
var
AlreadyFed: Boolean = False;
LiveAudioPlayer1.BufferInternally := False;
procedure TForm1.LiveAudioPlayer1Format(Sender: TObject;
out pWaveFormat: PWaveFormatEx; var FreeIt: Boolean);
begin
FreeIt := False;
pWaveFormat := WaveStorage1.Wave.WaveFormat;
end;
function TForm1.LiveAudioPlayer1DataPtr(Sender: TObject;
out Buffer: Pointer; var NumLoops: Cardinal;
var FreeIt: Boolean): Cardinal;
begin
if not AlreadyFed then
begin
FreeIt := False;
NumLoops := $FFFFFFF; // Infinite
Buffer := WaveStorage1.Wave.Data;
Result := WaveStorage1.Wave.DataSize;
AlreadyFed := True;
end
else
Result := 0;
end;
I'm sorry for being so late.
Posted:
November 7th, 2005, 12:28 pm
by cozturk
when I load a stream from a file the loop is excellent.
unfortunately my stream is not static. For example
Buffer := filebuf4.Memory;
Result := filebuf4.Size;
NumLoops := $FFFFFFF; // Infinite
yes it plays continuous. But I need to clear the stream and load new data. To playing live audio stream which comes from a hardware
But it can not be done this when player loops .
If It plays the stream for once only, how can I load new data ? LiveAudioPlayer disable, and load new data and Enable again? It can be interrupted.
Is it possible to modify TAudioRedirector to fed with my stream?
Posted:
November 7th, 2005, 1:38 pm
by Kambiz
cozturk,
There was a missing method in
TLiveAudioPlayer for breaking the loop. I added it (
BreakLoop), and you can download the update from the site.
After calling the
BreakLoop method, the player continues with the next buffer if any.
Here is a sample (suppose all waves are same format):
- Code: Select all
object Form1: TForm1
Left = 192
Top = 114
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object CheckBox1: TCheckBox
Left = 96
Top = 24
Width = 97
Height = 17
Caption = 'Active'
TabOrder = 0
OnClick = CheckBox1Click
end
object Button1: TButton
Left = 208
Top = 24
Width = 75
Height = 25
Caption = 'Break Loop'
TabOrder = 1
OnClick = Button1Click
end
object LiveAudioPlayer1: TLiveAudioPlayer
PCMFormat = Stereo16bit22050Hz
BufferInternally = False
OnActivate = LiveAudioPlayer1Activate
OnDeactivate = LiveAudioPlayer1Deactivate
OnDataPtr = LiveAudioPlayer1DataPtr
Left = 40
Top = 64
end
object WaveCollection1: TWaveCollection
Waves = <
item
Name = 'chimes'
Data = {
// Data is removed to simplify the view...
}
end
item
Name = 'ding'
Data = {
// Data is removed to simplify the view...
}
end>
Left = 40
Top = 16
end
end
- Code: Select all
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, mmSystem, WaveUtils, WaveIO, WaveOut, WavePlayers, WaveStorage,
StdCtrls;
type
TForm1 = class(TForm)
LiveAudioPlayer1: TLiveAudioPlayer;
CheckBox1: TCheckBox;
WaveCollection1: TWaveCollection;
Button1: TButton;
function LiveAudioPlayer1DataPtr(Sender: TObject; out Buffer: Pointer;
var NumLoops: Cardinal; var FreeIt: Boolean): Cardinal;
procedure CheckBox1Click(Sender: TObject);
procedure LiveAudioPlayer1Activate(Sender: TObject);
procedure LiveAudioPlayer1Deactivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.LiveAudioPlayer1DataPtr(Sender: TObject;
out Buffer: Pointer; var NumLoops: Cardinal;
var FreeIt: Boolean): Cardinal;
begin
FreeIt := False;
if (Tag >= 0) and (Tag < WaveCollection1.Waves.Count) then
begin
Buffer := WaveCollection1.Waves[Tag].Wave.Data;
Result := WaveCollection1.Waves[Tag].Wave.DataSize;
NumLoops := $FFFFFFFF;
Tag := Tag + 1;
end
else
begin
Buffer := nil;
Result := 0;
end;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
LiveAudioPlayer1.Active := CheckBox1.Checked;
end;
procedure TForm1.LiveAudioPlayer1Activate(Sender: TObject);
begin
Tag := 0;
CheckBox1.Checked := True;
end;
procedure TForm1.LiveAudioPlayer1Deactivate(Sender: TObject);
begin
CheckBox1.Checked := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
LiveAudioPlayer1.BreakLoop;
end;
end.
Cheers
Posted:
November 10th, 2005, 1:00 pm
by cozturk
thanks. I tested your demo and understood that:
We must load the next buffer before calling the BreakLoop method.
Here is example(mentioned above) to easy testing or modifiying for other members:
http://s6.ultrashare.net/hosting/fs/94708f65b808b2c9/
I wish
www.delphiarea.com have
Project(or examples) Sharing Area
Re: Perfect looping possible?
Posted:
November 28th, 2013, 11:50 am
by Pherreira
Hello,
I was testing the function and the delphi is complaining over this line, the property Data doesn't exist .
Can you please help me?
I am using Delphi XE2 with Windows 7
- Code: Select all
function TForm1.LiveAudioPlayer1DataPtr(Sender: TObject;
out Buffer: Pointer; var NumLoops: Cardinal;
var FreeIt: Boolean): Cardinal;
begin
FreeIt := False;
if (Tag >= 0) and (Tag < WaveCollection1.Waves.Count) then
begin
Buffer := WaveCollection1.Waves[Tag].Wave.Data; // <- here is the error
Result := WaveCollection1.Waves[Tag].Wave.DataSize;
NumLoops := $FFFFFFFF;
Tag := Tag + 1;
end
else
begin
Buffer := nil;
Result := 0;
end;
end;
Re: Perfect looping possible?
Posted:
December 7th, 2013, 10:58 pm
by Kambiz
Hello Pherreira,
I'm sorry but currently my computer is broken and I can check the code. However, as I remember the WaveAudio package has no issue with Delphi XE3.