DELPHI AREA
MESSAGE BOARD
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   FavoritesFavorites   Watched TopicsWatched Topics     RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Perfect looping possible?

 
Post new topic   Reply to topic   printer-friendly view    DELPHI AREA Forum Index -> DELPHI AREA's Products
View previous topic :: View next topic  
Author Message
Cluq
Member


Joined: 04 Nov 2004
Posts: 6

PostPosted: 14/11/04 13:00    Post subject: Perfect looping possible? Reply with quote

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.
Back to top
View user's profile Send private message
Kambiz
Administrator


Joined: 07 Mar 2003
Posts: 1044
Location: Tehran, Iran

PostPosted: 14/11/04 16:27    Post subject: Reply with quote

Hi,

You can use LiveAudioPlayer. In the event hanlder for supplying the wave data, you can specify the number of loops.

Cheers,
Kambiz
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Cluq
Member


Joined: 04 Nov 2004
Posts: 6

PostPosted: 15/11/04 08:32    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
Kambiz
Administrator


Joined: 07 Mar 2003
Posts: 1044
Location: Tehran, Iran

PostPosted: 15/11/04 09:12    Post subject: Reply with quote

Use a TWaveStorage instance.

Code:
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.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Cluq
Member


Joined: 04 Nov 2004
Posts: 6

PostPosted: 15/11/04 12:14    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
Cluq
Member


Joined: 04 Nov 2004
Posts: 6

PostPosted: 16/11/04 09:24    Post subject: Reply with quote

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...
Back to top
View user's profile Send private message
Cluq
Member


Joined: 04 Nov 2004
Posts: 6

PostPosted: 17/11/04 11:38    Post subject: Reply with quote

Have I found a bug? Wink
Back to top
View user's profile Send private message
Kambiz
Administrator


Joined: 07 Mar 2003
Posts: 1044
Location: Tehran, Iran

PostPosted: 24/11/04 12:02    Post subject: Reply with quote

Yes, there's a bug. Open the WaveOut.pas file and look for

Code:
WHDR_BEGINLOOP or WHDR_BEGINLOOP


then replace it with

Code:
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:
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:
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.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
cozturk
Member


Joined: 30 Jun 2005
Posts: 29
Location: Istanbul - Turkiye

PostPosted: 07/11/05 12:28    Post subject: Reply with quote

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?
Back to top
View user's profile Send private message MSN Messenger
Kambiz
Administrator


Joined: 07 Mar 2003
Posts: 1044
Location: Tehran, Iran

PostPosted: 07/11/05 13:38    Post subject: Reply with quote

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:
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:
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

_________________
Kambiz
Back to top
View user's profile Send private message Send e-mail Visit poster's website
cozturk
Member


Joined: 30 Jun 2005
Posts: 29
Location: Istanbul - Turkiye

PostPosted: 10/11/05 13:00    Post subject: Reply with quote

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
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic   printer-friendly view    DELPHI AREA Forum Index -> DELPHI AREA's Products All times are GMT
Page 1 of 1

Add to favorites

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group