MP3 playback engine header file
# If! Defined (_ wavegen_engine_h __)
# DEFINE _ wavegen_engine_h __
# If! Defined (_ mda_common_audio_h __)
# Include <MDA/common/audio. h>
# Endif
# If! Defined (_ mda_client_utility_h __)
# Include <MDA/client/utility. h>
# Endif
# If! Defined (_ mda_common_resource_h __)
# Include <MDA/common/resource. h>
# Endif
# If! Defined (_ mdaaudiooutputstream_h __)
# Include <mdaaudiooutputstream. h>
# Endif
Const tint kvolsliderlength = 10;
Const tint kinitialvolume = 9;
Const tint knumbuf = 2;
Const tint kbuffersize = 5000;
Class ceikonenv;
Class cmp3decodeengine;
Class cstreamaudioengine: Public cbase, public mmdaaudiooutputstreamcallback
{
Public:
Enum tenginestatus
{
Eenginenotready,
Eengineready,
Eenginetopause,
Eenginepause,
Eengineplaying
};
Static cstreamaudioengine * newl ();
~ Cstreamaudioengine ();
Void playl ();
Void pause ();
Void Stopl ();
Void setrepeat (tbool arepeat );
Void openl (tfilename afilename );
Virtual void maoscopencomplete (tint aerror );
Virtual void maoscbuffercopied (tint aerror, const tdesc8 & abuffer );
Virtual void maoscplaycomplete (tint aerror );
Inline tint volume ();
Inline tbool streamready ();
Inline tbool streamplaying ();
Inline tbool streampause ();
Inline tbool streamrepeat ();
Void setvolume (tint avol );
Protected:
// Protected contructor
Cstreamaudioengine (/* cwavegenappui & aappui */);
// 2nd phase Constructor
Void constructl ();
// Displays error messages
Void showerrormsg (tint aresourcebuf, tint aerror );
PRIVATE:
Void nextbuffer (const tdesc8 & abuffer );
Tint ivolume; // volume
Tint ivolstep;
Tbool ifileok; // indicates if file has been successfully read to buffer
Tenginestatus imp3status; // engine status
Tbool iplayfile; // which buffer is currently in use
Tbool irepeat;
Tuint16 * AA;
Tptr imp3buf;
Tbool istart;
Tbuf8 <kbuffersize> ibuflist [knumbuf];
Cmdaaudiooutputstream * istream;
// Cmdaaudiooutputstream * istream1;
Tmdaaudiodatasettings iset.pdf;
Ceikonenv * ienv;
Cmp3decodeengine * imp3;
Rfs fss;
Tfilename tfullfilename;
Tint FM;
Tint bufx;
};
// Inlines
Inline tint cstreamaudioengine: volume () {return ivolume ;}
Inline tbool cstreamaudioengine: streamready () {return (imp3status = eengineready )? Etrue: efalse ;}
Inline tbool cstreamaudioengine: streamplaying () {return (imp3status = eengineplaying )? Etrue: efalse ;}
Inline tbool cstreamaudioengine: streampause () {return (imp3status = eenginepause )? Etrue: efalse ;}
Inline tbool cstreamaudioengine: streamrepeat () {return irepeat ;}
// Writes 2 bytes to buffer in LSB order
# Endif
The MP3 playback engine implements file, and uses two buffers for alternate decoding.
# Include <eikenv. h>
# Include <eikapp. h>
# Include <eikdef. h>
# Include <e32math. h>
# Include "mp3_engine.h"
# Include "mp3decodeengine. H"
Cstreamaudioengine: cstreamaudioengine ()
: Ivolume (kinitialvolume ),
Ivolstep (0 ),
Ifileok (efalse ),
Imp3status (eenginenotready ),
Iplayfile (etrue ),
Irepeat (efalse ),
Imp3buf (0, 0 ),
Istart (efalse ),
FM (0 ),
Bufx (0)
{
}
Cstreamaudioengine ::~ Cstreamaudioengine ()
{
Delete istream;
Delete [] AA;
Delete imp3;
FSS. Close ();
}
Cstreamaudioengine * cstreamaudioengine: newl ()
{
Cstreamaudioengine * Self = new (eleave) cstreamaudioengine ();
Cleanupstack: pushl (Self );
Self-> constructl ();
Cleanupstack: Pop (); // self
Return self;
}
Void cstreamaudioengine: constructl ()
{
// Get the Eikon Environment
Ienv = ceikonenv: static ();
Imp3 = cmp3decodeengine: newl ();
Ifileok = efalse;
AA = new (eleave) tuint16 [2400]; // buffer, stores the content of a single frame, the size is not fixed, it is best to set large enough, otherwise it will report an error
Imp3buf. Set (AA, 2400,2400 );
FSS. Connect ();
// Create and initialize output stream
Istream = cmdaaudiooutputstream: newl (* This );
Istream-> open (& isettings );
}
Void cstreamaudioengine: maoscopencomplete (tint aerror)
{
If (aerror = kerrnone)
{
// Set stream properties to 16bit, 8 kHz mono echannelsmono echannelsstereo
// Because the decoded content is a single channel, you must use tmdaaudiodatasettings: echannelsmono. In addition, the sampling rate must be consistent with that set by imp3-> setresamplerate.
Istream-> setaudiopropertiesl (tmdaaudiodatasettings: esamplerate44100hz,
Tmdaaudiodatasettings: echannelsmono );
// Set the appropriate volume step. Values for the target
// Device are scaled down to get the optimal volume level
# If defined (_ wins __)
// For emulator (maxvolume = 65535)
Ivolstep = istream-> maxvolume ()/kvolsliderlength;
# Else
// For target device (maxvolume = 9)
Ivolstep = istream-> maxvolume ()/(KVolSliderLength-1 );
# Endif
Istream-> setvolume (ivolstep * kinitialvolume );
Istream-> setpriority (eprioritynormal, emd1_oritypreferencenone );
Imp3status = eengineready;
}
Else
Showerrormsg (r_wavegen_error_opencomplete, aerror );
// Playl ();
}
Void cstreamaudioengine: maoscbuffercopied (tint aerror, const tdesc8 & abuffer)
{
// If a single file (buffer) is played, return immediately
If (aerror = kerrnone | aerror = kerrabort)
{
If (imp3status = eenginetopause)
{
Imp3status = eenginepause;
Istream-> stop ();
Return;
}
If (imp3status = eenginepause)
{
Return;
}
If (iplayfile)
{
If (imp3status = eengineplaying & ifileok)
{
Nextbuffer (abuffer );
}
Return;
}
}
Else
{
// If (imp3status! = Eengineready)
//{
Imp3status = eenginepause;
// Istream-> stop ();
//}
// User: invariant ();
}
}
Void cstreamaudioengine: maoscplaycomplete (tint aerror)
{
If (aerror = kerrnone | aerror = kerrcancel)
{
If (imp3status = eengineplaying)
{
Bufx = 0;
Ifileok = efalse;
Istart = efalse;
Imp3status = eengineready;
Imp3-> closefile ();
Ibuflist [0]. setlength (0 );
Ibuflist [1]. setlength (0 );
}
}
Else
{
Imp3status = eenginepause;
// If (imp3status = eengineplaying)
//{
// Imp3status = eenginepause;
// Istream-> stop ();
//}
// User: invariant ();
}
}
Void cstreamaudioengine: playl ()
{
If (imp3status = eengineready | imp3status = eenginepause)
{
Imp3status = eengineplaying;
If (! Ifileok)
{
Imp3-> openfile (FSS, tfullfilename );
Imp3> setresamplerate (44100 );
Imp3-> decodestart ();
Ifileok = etrue;
}
If (! Istart)
{
Imp3-> decodeoneframe (imp3buf );
Ibuflist [0]. Copy (tuint8 *) imp3buf. PTR (), imp3buf. Length () * 2 );
Imp3-> decodeoneframe (imp3buf );
Ibuflist [1]. Copy (tuint8 *) imp3buf. PTR (), imp3buf. Length () * 2 );
}
Else
{
Imp3-> decodeoneframe (imp3buf );
Ibuflist [1]. Copy (tuint8 *) imp3buf. PTR (), imp3buf. Length () * 2 );
}
Istream-> writel (ibuflist [bufx]);
If (bufx = 0)
Bufx = 1;
Else
Bufx = 0;
Istart = etrue;
If (imp3-> getfileposition () = imp3-> getfilelength ())
{
Imp3-> closefile ();
If (irepeat)
{
Imp3-> openfile (FSS, tfullfilename );
Imp3> setresamplerate (44100 );
Imp3-> decodestart ();
}
Else
{
Ifileok = efalse;
}
}
}
}
Void cstreamaudioengine: Pause ()
{
Imp3status = eenginetopause;
}
Void cstreamaudioengine: Stopl ()
{
Bufx = 0;
Ifileok = efalse;
Istart = efalse;
Imp3status = eengineready;
Istream-> stop ();
Imp3-> closefile ();
Ibuflist [0]. setlength (0 );
Ibuflist [1]. setlength (0 );
}
Void cstreamaudioengine: setrepeat (tbool arepeat)
{
Irepeat = arepeat;
}
Void cstreamaudioengine: openl (tfilename afilename)
{
If (imp3status = eengineplaying | imp3status = eenginepause)
{
Stopl ();
}
Tfullfilename = afilename;
Playl ();
}
Void cstreamaudioengine: setvolume (tint avol)
{
Ivolume = avol;
// If value has changed, pass it directly to audiostream object.
If (ivolume * ivolstep )! = Istream-> volume ())
Istream-> setvolume (ivolume * ivolstep );
}
Void cstreamaudioengine: showerrormsg (tint aresourcebuf, tint aerror)
{
Tbuf <16> errornum;
Tbuf <128> rdes;
Errornum. Num (aerror );
Ienv-> readresource (rdes, aresourcebuf );
Rdes. append (errornum );
Cakninformationnote * DLG = new (eleave) cakninformationnote ();
DLG-> executeld (rdes );
}
Void cstreamaudioengine: nextbuffer (const tdesc8 & abuffer)
{
// Assume the buffer is already there!
Istream-> writel (ibuflist [bufx]);
If (bufx = 0)
Bufx = 1;
Else
Bufx = 0;
If (imp3-> getfileposition () = imp3-> getfilelength ())
{
Imp3-> closefile ();
If (irepeat)
{
Imp3-> openfile (FSS, tfullfilename );
Imp3> setresamplerate (44100 );
Imp3-> decodestart ();
}
Else
{
Ifileok = efalse;
}
}
Assert (ibuflist [bufx] = abuffer );
Ibuflist [bufx]. setlength (0 );
Imp3-> decodeoneframe (imp3buf );
Ibuflist [bufx]. Copy (tuint8 *) imp3buf. PTR (), imp3buf. Length () * 2 );
}
Finally, because the cmp3decodeengine: closefile () in the mp3decodedll Code does not have any content, you need to modify and add it yourself. Otherwise, memory leakage will occur. It may be a problem with my mp3decodedll version.