Hi ppl, I am having a problem with playing mp3's in my program.
Let me explain, I am writing a program for my choire, I need to do it in a low base languege like pascal since the systems used are not great.
My program is writen on exact timing program that flashes lyrics at the exact time of play, I need to start a song the exact same time as the lyrics to make it function as I intended, If it is 1 sec off the hole progam is viod, how do I link a key to an external program function (play and pause on say winamp or WMP) to start my lyric flash at the same time as the program, or maby have some code I could use for a mp3 player for pascal.
In your case i will use Delphi, with the Multi-Media Player component, that you can play, pause, stop, FF, FW, also in movies...
And for the lyrics that you want to play(i understand this) you can use a Timer to put the in a TextBox or something else.
I wish I could do Delphi, but I need the DB and I don't know how to use it with Delphi.
What is the type of DB, because you only have to search in Google for this: Delphi+Your DB Type+Tutorial
Thank you, I'll rater use Delphi, If you find a Mp3 player that has source code for Pascal, pls let me know.
FearlessFourie, i searched in Google and i see this program, that you can download the *.zip that haves the compiled program and the sources, of version 1 and 2.
Here is the link: http://www.nova-sys.net/oldhp/mp3play.htm
I'm going to read more this code, it's very interesting.
Hope it helps and post here if it helps, please!
Now this post is really solved!
If you don't want to download the file, here is the source for:
mp3play.pp
{$MODE Delphi}
PROGRAM MP3Play;
{ A simple MP3 player
Demonstrates use of XAudio and MIDAS.
Platform: DOS
Copyright (c) 1999 Udo Giacomozzi
May be used for free use only.
}
USES
Crt, Dos, Decode, IO;
{ Note: unit 'IO' must be *after* unit 'Decode'. This may be because MIDAS
needs to be initialized after XAudio... }
{ Sets the default file extension if none given
FName - the file name to be modified
DefExt - Default extension (format ".XXX" !!) }
function SetDefaultExt(const FName, DefExt:String):String;
var
fp,fn,fe : String; // file path/name/extension
begin
FSplit(FName, fp, fn, fe);
If fe = '' then fe := DefExt;
Result := fp+fn+fe;
end;
{ Returns only the name (no path, no extension) of a file name
FName - The file name to be modified }
function GetFName(const FName:String):String;
var
fp,fn,fe : String; // file path/name/extension
begin
FSplit(FName, fp, fn, fe);
Result := fn;
end;
{ adds a leading zero if needed (1 -> '01') }
function LeadingZero(w:Word):String;
begin
Str(w,Result);
if w<10 then Result:='0'+Result;
end;
VAR
InFileName : String;
MP3 : tMP3Player;
Buffer : Array[Word] of Byte;
ToWrite : Word;
CurFreq : LongInt;
NewFreq : LongInt;
BEGIN
{ Read commandline parameters ------------------------------------------- }
if ParamCount<1 then
begin
writeln('Usage:');
writeln(' MP3PLAY InputFile[.MP3]');
Halt;
end;
InFileName := SetDefaultExt(ParamStr(1), '.MP3');
{ Initialize audio I/O -------------------------------------------------- }
writeln('Initializing MP3 decoder...');
MP3 := tMP3Player.Create(InFileName);
writeln('Initializing audio I/O routines...');
Audio_Init;
writeln('Starting audio output...');
Audio_Start;
writeln('Starting playback...');
CurFreq:=0;
repeat
{ Decode one block }
ToWrite:=MP3.BufSize;
MP3.DecodeBlock(Buffer, ToWrite);
{ Convert to stereo if needed }
If MP3.NumChannels<2 then
begin
For i:=(ToWrite div 2)-1 downto 0 do
begin
Buffer[i*2 ] := Buffer[i];
Buffer[i*2+1] := Buffer[i];
end;
end;
{ play buffer }
Audio_Feed(Buffer, ToWrite);
{ Set frequency }
NewFreq:=MP3.Frequency;
If NewFreq<>CurFreq then
begin
write(#13'Playback rate: ',NewFreq,' Hz.'); ClrEol; writeln;
Audio_SetFreq(NewFreq);
CurFreq:=NewFreq;
end;
{ Show information }
with MP3.Position do
write(#13,'Position: ',LeadingZero(h)+':'+
LeadingZero(m)+':'+
LeadingZero(s)+'.'+
LeadingZero(f));
write(' Length: ',LeadingZero(MP3.Duration div 60 div 60)+':'+
LeadingZero(MP3.Duration div 60 mod 60)+':'+
LeadingZero(MP3.Duration mod 60));
until MP3.EOF or keypressed;
writeln;
writeln('Stoping audio I/O...');
Audio_Done;
writeln('Releasing decoder...');
MP3.Destroy;
writeln('Have a nice day! :)');
END.
mp3play2.pp
{$MODE Delphi}
PROGRAM MP3Play2;
{ A simple MP3 player
Demonstrates use of XAudio and MIDAS.
Platform: DOS
Copyright (c) 1999 Udo Giacomozzi
May be used for free use only.
}
USES
Crt, Dos, Decode, IO;
{ Note: unit 'IO' must be *after* unit 'Decode'. This may be because MIDAS
needs to be initialized after XAudio... }
{ Sets the default file extension if none given
FName - the file name to be modified
DefExt - Default extension (format ".XXX" !!) }
function SetDefaultExt(const FName, DefExt:String):String;
var
fp,fn,fe : String; // file path/name/extension
begin
FSplit(FName, fp, fn, fe);
If fe = '' then fe := DefExt;
Result := fp+fn+fe;
end;
{ Returns only the name (no path, no extension) of a file name
FName - The file name to be modified }
function GetFName(const FName:String):String;
var
fp,fn,fe : String; // file path/name/extension
begin
FSplit(FName, fp, fn, fe);
Result := fn;
end;
{ adds a leading zero if needed (1 -> '01') }
function LeadingZero(w:Word):String;
begin
Str(w,Result);
if w<10 then Result:='0'+Result;
end;
VAR
InFileName : String;
MP3 : tMP3Player;
Buffer : Array[Word] of SmallInt;
ToWrite : Word;
CurFreq : LongInt;
NewFreq : LongInt;
SpeedFact : Real; // playback speed factor (1=normal)
NewSpeed : Boolean; // speed factor changed
i : Integer;
xc : Char;
Paused : Boolean;
BEGIN
{ Read commandline parameters ------------------------------------------- }
if ParamCount<1 then
begin
writeln('Usage:');
writeln(' MP3PLAY InputFile[.MP3]');
Halt;
end;
InFileName := SetDefaultExt(ParamStr(1), '.MP3');
{ Initialize audio I/O -------------------------------------------------- }
writeln('Initializing MP3 decoder...');
MP3 := tMP3Player.Create(InFileName);
writeln('Initializing audio I/O routines...');
Audio_Init;
writeln('Starting audio output...');
Audio_Start;
writeln('Starting playback...');
writeln('*** Keys ***');
writeln('ESC............Exit');
writeln('Cursor LEFT....2 sec backward jump');
writeln('Cursor RIGHT...2 sec forward jump');
writeln('Cursor UP......Faster playback');
writeln('Cursor DOWN....Slower playback');
writeln('Return.........Original speed');
writeln('Space..........Play/Pause');
CurFreq:=0;
SpeedFact:=1;
NewSpeed:=FALSE;
Paused:=FALSE;
repeat
IF not Paused then
begin
{ Decode one block }
ToWrite:=MP3.BufSize;
MP3.DecodeBlock(Buffer, ToWrite);
{ Convert to stereo if needed }
If MP3.NumChannels<2 then
begin
For i:=(ToWrite div 2)-1 downto 0 do
begin
Buffer[i*2 ] := Buffer[i];
Buffer[i*2+1] := Buffer[i];
end;
end;
{ play buffer }
Audio_Feed(Buffer, ToWrite);
end;
{ Set frequency }
NewFreq:=MP3.Frequency;
If (NewFreq<>CurFreq) or (NewSpeed) then
begin
If not NewSpeed then
begin
write(#13'Playback rate: ',NewFreq,' Hz.'); ClrEol; writeln;
end;
Audio_SetFreq(Round(NewFreq*SpeedFact));
CurFreq:=NewFreq;
NewSpeed:=FALSE;
end;
{ Show information }
with MP3.Position do
write(#13,'Position: ',LeadingZero(h)+':'+
LeadingZero(m)+':'+
LeadingZero(s)+'.'+
LeadingZero(f));
write(' Length: ',LeadingZero(MP3.Duration div 60 div 60)+':'+
LeadingZero(MP3.Duration div 60 mod 60)+':'+
LeadingZero(MP3.Duration mod 60));
write(' Speed: ',SpeedFact*100:3:0,'%');
If Paused then write(' *PAUSED*');
ClrEol; // clear rest of line
{ Keyboard handling }
xc:=#255;
while keypressed do
begin
xc:=ReadKey;
CASE xc OF
#0 : begin // Special key (cursors etc.)
xc:=ReadKey;
CASE xc OF
#72 : begin // up key
SpeedFact:=SpeedFact * 1.01;
If SpeedFact>3 then SpeedFact:=3;
NewSpeed:=TRUE;
end;
#80 : begin // down key
SpeedFact:=SpeedFact / 1.01;
If SpeedFact<0.05 then SpeedFact:=0.05;
NewSpeed:=TRUE;
end;
#75 : begin // left key
MP3.PositionSec:=MP3.PositionSec - 2;
end;
#77 : begin // right key
MP3.PositionSec:=MP3.PositionSec + 2;
end;
END;
xc:=#255;
end;
#13 : begin // return key
SpeedFact:=1;
NewSpeed:=TRUE;
end;
' ' : Paused:=not Paused; // space key
END;
end;
until (MP3.EOF) or (xc=#27);
writeln;
writeln('Stoping audio I/O...');
Audio_Done;
writeln('Releasing decoder...');
MP3.Destroy;
writeln('Have a nice day! :)');
END.
IO.pp
{$MODE Delphi}
UNIT IO;
(**************************************************************************)
(* AUDIO I/O FUNCTIONS *)
(**************************************************************************)
INTERFACE
{ Initalizes MIDAS and show configuration screen }
procedure Audio_Init;
{ Starts audio playback }
procedure Audio_Start;
{ stops audio playback and frees MIDAS }
procedure Audio_Done;
{ sets the playback frequency }
procedure Audio_SetFreq(Freq:LongInt);
{ sends data to the soundcard }
procedure Audio_Feed(var Buffer; Size:Word);
IMPLEMENTATION
uses
MidasDLL;
var
stream : MIDASstreamhandle;
procedure MIDASerror;
var
ErrNo : LongInt;
begin
Write('*** MIDAS error #');
ErrNo:=MIDASgetLastError;
write(ErrNo,': ');
writeln(' ', MIDASgetErrorMessage(ErrNo));
If ErrNo<>0 then
begin
MIDASclose;
write(#7);
halt;
end else begin
writeln('Press ENTER...');
ReadLn;
end;
end;
procedure CheckError;
var
ErrNo : LongInt;
begin
ErrNo:=MIDASgetLastError;
If ErrNo<>0 then
begin
Write('*** MIDAS error #');
write(ErrNo,': ');
writeln(#7' ', MIDASgetErrorMessage(ErrNo));
halt;
end;
end;
procedure Audio_Init;
begin
MIDASstartup;
CheckError;
if not MIDASconfig then
BEGIN
writeln('Config failed!');
MIDASerror;
END;
if not MIDASinit then
MIDASerror;
end;
procedure Audio_Start;
begin
if not MIDASstartBackgroundPlay(0) then
MIDASerror;
{--------------}
If not MIDASopenChannels(1) then MIDASerror;
stream:=nil;
stream:=MIDASplayStreamPolling(MIDAS_SAMPLE_16BIT_STEREO,
44100, // Hz
200); // ms
If stream=nil then
begin
MIDASerror;
end;
end;
procedure Audio_Done;
begin
If not MIDASstopStream(stream) then MidasError;
if not MIDASstopBackgroundPlay then MIDASerror;
if not MIDASclose then MIDASerror;
end;
procedure Audio_SetFreq(Freq:LongInt);
begin
MIDASsetStreamRate(stream, freq);
end;
procedure Audio_Feed(var Buffer; Size:Word);
begin
MIDASfeedStreamData(stream, @Buffer, Size, true);
end;
END.
decode.pp
{$MODE Delphi}
UNIT Decode;
(**************************************************************************)
(* MP3 DECODING FUNCTIONS *)
(**************************************************************************)
{ Object-oriented interface to the XAudio functions.
Note: you can create multiple instances of this class, so you can
mix MP3 files! }
INTERFACE
USES
XAudio;
TYPE
tMP3Player = class
constructor Create(FName:String);
{ creates the class and prepares the decoder }
destructor Destroy; virtual;
{ frees decoder }
function DecodeBlock(var Buffer; BlockSize:LongInt):Boolean;
{ decodes one block of size 'BlockSize'. You should use the
size returned by the property 'BufSize' for optimal performance.
Returns TRUE if successfull or FALSE if there was an error
decoding a frame. }
procedure SeekRel(RelPosition:Real);
{ seeks to a position in MP3 stream:
0 = start of stream
1 = end of stream
this means SeekRel(0.5) seeks to the middle of the stream }
procedure Seek(Seconds:Real);
{ seeks to a position in MP3 stream. 'Seconds' is the position
in seconds in the stream }
private
decoder : PXA_DecoderInfo;
Status : Longint; // XAudio return code
Module : XA_InputModule; // Input/output module handle
BufLevel : LongInt; // number of unused bytes in XAudio output buffer
BufPos : LongInt; // position in XAudio output buffer
EOF_Flag : Boolean; // TRUE: encoded to the end
function GetDuration:LongInt;
function GetNumChannels:Word;
function GetMode:Word;
function GetFrequency:LongInt;
function GetBufSize:LongInt;
function GetPosition:XA_TimeCode;
function GetPositionSec:Real;
function GetEOF:Boolean;
public // PROPERTIES
property Duration:LongInt read GetDuration;
{ duration of the file in seconds }
property NumChannels:Word read GetNumChannels;
{ number of channels (1=MONO, 2=STEREO) }
property Mode:Word read GetMode;
{ stereo mode
0 = stereo
1 = joint-stereo
2 = dual-channel
3 = mono }
property Frequency:LongInt read GetFrequency;
{ encoded frequency (Hz) }
property BufSize:LongInt read GetBufSize;
{ size, in bytes, of buffer returned by DecodeBlock }
property Position:XA_TimeCode read GetPosition;
{ position in MP3 file as TimeCode (h:m:s.f) }
property PositionSec:Real read GetPositionSec write Seek;
{ position in MP3 file in seconds }
property EOF:Boolean read GetEOF;
{ TRUE, when MP3 file has been decoded to the end }
end;
IMPLEMENTATION
constructor tMP3Player.Create(FName:String);
var
CharBuf : Array[Byte] of Char;
begin
{ Create new decoder }
Status := decoder_new(@decoder);
if Status <> XA_SUCCESS then
begin
writeln('*** ERROR: Cannot init decoder (',
xaudio_error_string(status),')');
Halt(1);
end;
{ Register the input module }
Status:=file_input_module_register(@module);
if Status <> XA_SUCCESS then
begin
writeln('*** ERROR: Cannot register file input module (',
xaudio_error_string(status),')');
Halt(2);
end;
Status:=decoder_input_module_register(decoder, @module);
if Status <> XA_SUCCESS then
begin
writeln('*** ERROR: Cannot register decoder input module (',
xaudio_error_string(status),')');
Halt(3);
end;
decoder^.notification_client.client := decoder;
{ output parameters }
decoder^.output^.channels := XA_OUTPUT_STEREO;
{ open input }
Move((FName+#0)[1], CharBuf, Length(FName)+1); { copy to PChar buf }
Status:=decoder_input_new(decoder, @CharBuf, XA_DECODER_INPUT_AUTOSELECT);
if Status <> XA_SUCCESS then
begin
writeln('*** ERROR: Cannot create input with decoder_input_new (',
xaudio_error_string(status),')');
Halt(4);
end;
Status:=decoder_input_open(decoder);
if Status <> XA_SUCCESS then
begin
writeln('*** ERROR: Cannot open input with decoder_input_open (',
xaudio_error_string(status),')');
Halt(5);
end;
BufLevel:=0;
BufPos:=0;
EOF_Flag:=FALSE;
end;
destructor tMP3Player.Destroy;
begin
Status:=decoder_delete(decoder);
if Status <> XA_SUCCESS then
begin
writeln('*** ERROR: Cannot delete decoder (',
xaudio_error_string(status),')');
Halt(99);
end;
end;
function tMP3Player.GetDuration:LongInt;
begin
Result:=decoder^.input^.duration;
end;
function tMP3Player.GetNumChannels:Word;
begin
If decoder^.status^.info.mode=3 then Result:=1
else Result:=2;
end;
function tMP3Player.GetMode:Word;
begin
Result:=decoder^.status^.info.mode;
end;
function tMP3Player.GetFrequency:LongInt;
begin
Result:=decoder^.status^.info.frequency;
end;
function tMP3Player.GetBufSize:LongInt;
begin
Result:=decoder^.output_buffer.size;
end;
function tMP3Player.GetPosition:XA_TimeCode;
begin
Result := decoder^.status.timecode;
end;
function tMP3Player.GetPositionSec:Real;
begin
Result := (decoder^.status.timecode.h*60*60) +
(decoder^.status.timecode.m*60 ) +
(decoder^.status.timecode.s ) +
(decoder^.status.timecode.f/100 );
end;
function tMP3Player.GetEOF:Boolean;
begin
Result := EOF_Flag;
end;
function tMP3Player.DecodeBlock(var Buffer; BlockSize:LongInt):Boolean;
type
tByteArr = Array[0..1] of Byte;
pByteArr = ^tByteArr;
var
BytesWritten : LongInt;
BufArr : tByteArr absolute Buffer;
ToWrite : LongInt;
begin
Result:=TRUE;
{ clear buffer }
FillChar(Buffer, BlockSize, 0);
BytesWritten:=0;
repeat
If BufLevel<=0 then
begin
BufLevel:=BufSize;
BufPos:=0;
Status := decoder_decode(decoder, NIL);
If Status<>XA_SUCCESS then Result:=FALSE;
If Status=XA_ERROR_INPUT_EOF then EOF_Flag := true;
end;
If BufLevel > BlockSize-BytesWritten
then ToWrite:=BlockSize-BytesWritten
else ToWrite:=BufLevel;
Move(pByteArr(decoder^.output_buffer^.pcm_samples)^[BufPos],
BufArr[BytesWritten],
ToWrite);
Inc(BufPos, ToWrite);
Dec(BufLevel, ToWrite);
Inc(BytesWritten, ToWrite);
until BytesWritten>=BlockSize;
end;
procedure tMP3Player.SeekRel(RelPosition:Real);
begin
Status := decoder_input_seek_to_position(decoder, RelPosition);
EOF_Flag:=FALSE;
end;
procedure tMP3Player.Seek(Seconds:Real);
begin
Status := decoder_input_seek_to_time(decoder, Seconds);
EOF_Flag:=FALSE;
end;
END. Hope it helps!
wow, thanx, cool beans, I'm using Delphi 5 now, maby I'll post some dumb Q's later on. but I downloaded the software for the mp3 player for later on. Thanx again.