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.

Recommended Answers

All 7 Replies

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.