Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

audiodrv_er6.cpp

Go to the documentation of this file.
00001 
00012 #include "audiodrv_er6.h"
00013 #include "alaw.h"
00014 #include "elog.h"
00015 
00016 // does not work properly
00017 #if defined(__CRYSTAL__) && defined(__WINS__)
00018 #undef HAVE_AUDIO_DRIVER
00019 #else
00020 #define HAVE_AUDIO_DRIVER
00021 #endif
00022 
00023 const TInt KFileOpenWritable = EFileWrite | EFileShareAny | EFileStream;
00024 
00025 struct wav_hdr                  // little endian
00026         {
00027         char main_chunk[4];         // 'RIFF'
00028         TUint32 length;              // filelength
00029         char chunk_type[4];         // 'WAVE'
00030 
00031         char sub_chunk[4];          // 'fmt '
00032         TUint32 clength;             // length of sub_chunk, always 16 bytes
00033         TUint16 format;              // currently always = 1 = PCM-Code
00034         TUint16 modus;               // 1 = mono, 2 = stereo
00035         TUint32 samplefreq;          // sample-frequency
00036         TUint32 bytespersec;         // frequency * bytespersmpl
00037         TUint16 bytespersmpl;        // bytes per sample; 1 = 8-bit, 2 = 16-bit
00038         TUint16 bitspersmpl;
00039         char data_chunk[4];         // keyword, begin of data chunk; = 'data'
00040         TUint32 data_length;         // length of data
00041         };
00042 
00043 const wav_hdr my_wav_hdr =
00044 {
00045         {'R','I','F','F'}, 0 /* file length */, {'W','A','V','E'},
00046         {'f','m','t',' '}, 16, 1, 1, SAMPLE_FREQ, SAMPLE_FREQ*2, 2, 16,
00047         {'d','a','t','a'}, 0 /* data length */
00048 };
00049 
00050 
00051 //
00052 // implementation of audioDriver
00053 //
00054 
00055 
00056 audioDriver::audioDriver()
00060         :audioHd(-1)
00061         ,frequency(0)
00062         ,encoding(0)
00063         ,precision(0)
00064         ,channels(0)
00065         ,iIsReady(EFalse)
00066         ,iBlocksInQueue(0)
00067         ,iPrefilled(EFalse)
00068         ,iIsWavDumping(0)
00069         {
00070         CTOR(audioDriver);
00071         }
00072 
00073 
00074 void audioDriver::ConstructL()
00078         {
00079         errorString = "None";
00080 
00081         iSettings.iCaps = 0;
00082         iSettings.iMaxVolume = 0;
00083 
00084 #ifdef HAVE_AUDIO_DRIVER
00085         iMdaAudio = CMdaAudioOutputStream::NewL(*this);
00086         iMdaAudio->Open(&iSettings);
00087 #endif
00088         }
00089 
00090 
00091 audioDriver::~audioDriver()
00095         {
00096         DTOR(audioDriver);
00097         if(iMdaAudio)
00098                 {
00099                 iMdaAudio->Stop();
00100                 delete iMdaAudio;
00101                 iMdaAudio = NULL;
00102                 }
00103         }
00104 
00105 
00106 bool audioDriver::IsThere()
00112         {
00113         return true;
00114         }
00115 
00116 
00117 bool audioDriver::Open(udword inFreq, int inPrecision, int inChannels,
00118                                            int inFragments, int inFragBase)
00129         {
00130         audioHd = KErrNone; // means OK and opened
00131 
00132         // Transfer input parameters to this object.
00133         // May later be replaced with driver defaults.
00134         frequency = inFreq;
00135         precision = inPrecision;
00136         channels = inChannels;
00137         fragments = inFragments;
00138         fragSizeBase = inFragBase;
00139 
00140         // Set sample precision and type of encoding. (only 8 bit for EPOC)
00141         if (precision != SIDEMU_16BIT )
00142                 {
00143                 errorString = "AUDIO: Could not set sample size.(only 16 bit for ER6)";
00144                 return false;
00145                 }
00146 
00147         encoding = SIDEMU_SIGNED_PCM; // SIDEMU_UNSIGNED_PCM
00148 
00149         if (channels != SIDEMU_MONO)
00150                 {
00151                 errorString = "AUDIO: only Mono supported for EPOC.";
00152                 return false;
00153                 }
00154 
00155         // Set mono/stereo.
00156         int dsp_stereo;
00157         if (channels == SIDEMU_STEREO)
00158                 dsp_stereo = 1;
00159         else if (channels == SIDEMU_MONO)
00160                 dsp_stereo = 0;
00161         else
00162                 {
00163                 errorString = "AUDIO: Could not set mono/stereo.";
00164                 return false;
00165                 }
00166 
00167         // Verify and accept the number of channels the driver accepted.
00168         if (dsp_stereo == 1)
00169                 channels = SIDEMU_STEREO;
00170         else if (dsp_stereo == 0)
00171                 channels = SIDEMU_MONO;
00172 
00173         blockSize = KDefaultBufSize;
00174         fragments = 2; //TODO: find a value for this
00175 
00176         return true; // success !
00177         }
00178 
00179 
00180 void audioDriver::Close()
00185         {
00186         if (audioHd != (-1))
00187                 {
00188                 audioHd = (-1);
00189                 }
00190         }
00191 
00192 
00193 void audioDriver::Play(ubyte* pBuffer, int bufferSize)
00200         {
00201         if (audioHd != (-1))
00202                 {
00203                 /*
00204                  * WARNING! This descriptor *CAN NOT* be on the stack!!!
00205                  * keep it persisent. (argh)
00206                  */
00207                 iExtraBuf.Copy(pBuffer, bufferSize);
00208 
00209 // TODO just for testing
00210 #ifdef HAVE_AUDIO_DRIVER
00211                 TRAPD(ret, iMdaAudio->WriteL(iExtraBuf));
00212                 if(ret)
00213                         {
00214                         ELOG2(_L8("WARNING! WriteL left with %d \n"), ret);
00215                         }
00216 #else
00217                 User::After(200000); // simulate delay
00218 #endif
00219 
00220                 if(IsWavDumping())
00221                         DoWavDump(iExtraBuf);
00222                 }
00223         }
00224 
00225 
00226 void audioDriver::StopStream(void)
00230         {
00231         if(iMdaAudio)
00232                 {
00233                 if(iIsReady)
00234                         iMdaAudio->Stop();
00235                 ResetStream();
00236                 }
00237         }
00238 
00239 
00240 void audioDriver::ResetStream(void)
00244         {
00245         iBlocksInQueue = 0;
00246         iPrefilled = EFalse;
00247         }
00248 
00249 
00250 TInt audioDriver::VolumeDelta(TInt aDelta)
00254         {
00255         iVolume += aDelta;
00256         if(iVolume < 0)
00257                 iVolume = 0;
00258         else if(iVolume >= KVolumeSteps)
00259                 iVolume = KVolumeSteps - 1;
00260 
00261         if(iMdaAudio && iIsReady)
00262                 iMdaAudio->SetVolume(iVolume * iMdaAudio->MaxVolume()/KVolumeSteps );
00263 
00264         return iVolume;
00265         }
00266 
00267 
00268 void audioDriver::MaoscOpenComplete(TInt aError)
00274         {
00275         ELOG2(_L8("MaoscOpenComplete [aError=%d] \n"), aError);
00276 
00277 #if (SAMPLE_FREQ == 44100)
00278 #define EPOC_SAMPLE_RATE TMdaAudioDataSettings::ESampleRate44100Hz
00279 #elif (SAMPLE_FREQ == 8000)
00280 #define EPOC_SAMPLE_RATE TMdaAudioDataSettings::ESampleRate8000Hz
00281 #else
00282 #error unsupported sample frequency
00283 #endif
00284 
00285         // kick it
00286         if(aError == KErrNone)
00287                 {
00288                 // init audio again
00289                 iMdaAudio->SetAudioPropertiesL(EPOC_SAMPLE_RATE,
00290                         TMdaAudioDataSettings::EChannelsMono);
00291                 iMdaAudio->SetPriority(EPriorityNormal, EMdaPriorityPreferenceNone);
00292 
00293                 // update internal volume
00294                 iVolume = iMdaAudio->MaxVolume() / 2 / KVolumeSteps;
00295 
00296                 iIsReady = ETrue;
00297                 }
00298         }
00299 
00300 
00301 void audioDriver::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
00309         {
00310         if(aError)
00311                 {
00312                 ELOG2(_L8("WARNING! MaoscBufferCopied [aError=%d] \n"), aError);
00313                 }
00314 
00315         // check if stream was closed
00316         if(aError == KErrCancel)
00317                 {
00318                 ResetStream();
00319                 }
00320 
00321         iBlocksInQueue = 0;
00322         }
00323 
00324 
00325 void audioDriver::MaoscPlayComplete(TInt aError)
00329         {
00330         if(aError)
00331                 {
00332                 ELOG2(_L8("MaoscPlayComplete [aError=%d] \n"), aError);
00333                 }
00334 
00335         // check if stream was closed
00336         if(aError == KErrCancel)
00337                 {
00338                 ResetStream();
00339                 }
00340         }
00341 
00342 
00343 TInt audioDriver::StartWavDump(const TDesC& aSidTune)
00347         {
00348         ELOG(TBuf8<128> buf8;)
00349         ELOG(buf8.Copy(aSidTune);)
00350         ELOG2(_L8("Starting WAV dump of '%S.wav'\n"), &buf8);
00351 
00352         if(iIsWavDumping)
00353                 {
00354                 ELOG1(_L8("already dumping wav\n"));
00355                 return KErrAlreadyExists;
00356                 }
00357 
00358         TInt ret = iFs.Connect();
00359         if( (ret != KErrNone) && (ret != KErrAlreadyExists) )
00360                 return ret;
00361 
00362         iWavDump.Copy(aSidTune);
00363         iWavDump.Append(_L(".wav"));
00364 
00365         // just in case
00366         (void)iFs.Delete(iWavDump);
00367 
00368         RFile file;
00369         ret = file.Open(iFs, iWavDump, KFileOpenWritable);
00370         if(ret == KErrNotFound)
00371                 ret = file.Replace(iFs, iWavDump, KFileOpenWritable);
00372         if(ret == KErrNone)
00373                 {
00374                 // write WAV header
00375                 TPtrC8 ptr((TUint8*)&my_wav_hdr, sizeof(wav_hdr));
00376                 ret = file.Write(ptr);
00377                 if(ret)
00378                         {
00379                         file.Close();
00380                         return ret;
00381                         }
00382                 }
00383         else
00384                 return ret;
00385 
00386         file.Close();
00387 
00388         // alls well
00389         iIsWavDumping = ETrue;
00390         return KErrNone;
00391         }
00392 
00393 
00394 TInt audioDriver::StopWavDump()
00398         {
00399         ELOG(TBuf8<128> buf8;)
00400         ELOG(buf8.Copy(iWavDump);)
00401         ELOG2(_L8("Stopping WAV dump of '%S'\n"), &buf8);
00402 
00403         RFile file;
00404         TInt ret = file.Open(iFs, iWavDump, KFileOpenWritable);
00405         if(ret)
00406                 {
00407                 ELOG2(_L8("Serious problem, was supposed to open file [ret=%d]\n"), ret);
00408                 iIsWavDumping = EFalse;
00409                 return ret;
00410                 }
00411 
00412         // update WAV header
00413         TInt size = 0;
00414         ret = file.Size(size);
00415         if(ret)
00416                 {
00417                 ELOG2(_L8("Wavdump: could not get size [ret=%d]\n"), ret);
00418                 iIsWavDumping = EFalse;
00419                 return ret;
00420                 }
00421 
00422         /*
00423          * I did not find any better way of doing this, please
00424          * improve this code if any better solutions exist.
00425          */
00426         const TUint32 file_length = size - 8;
00427         const TUint32 data_length = size - sizeof(wav_hdr);
00428 
00429         TBuf8<4> file_len;
00430         file_len.SetLength(4);
00431         file_len[0] = (TUint8)((file_length >> 0) & 0xff);
00432         file_len[1] = (TUint8)((file_length >> 8) & 0xff);
00433         file_len[2] = (TUint8)((file_length >> 16) & 0xff);
00434         file_len[3] = (TUint8)((file_length >> 24) & 0xff);
00435 
00436         TBuf8<4> data_len;
00437         data_len.SetLength(4);
00438         data_len[0] = (TUint8)((data_length >> 0) & 0xff);
00439         data_len[1] = (TUint8)((data_length >> 8) & 0xff);
00440         data_len[2] = (TUint8)((data_length >> 16) & 0xff);
00441         data_len[3] = (TUint8)((data_length >> 24) & 0xff);
00442 
00443         (void)file.Write(4, file_len);
00444         (void)file.Write(40, data_len);
00445 
00446         iFs.Close();
00447         iIsWavDumping = EFalse;
00448         return size;
00449         }
00450 
00451 
00452 TBool audioDriver::IsWavDumping()
00456         {
00457         return iIsWavDumping;
00458         }
00459 
00460 
00461 void audioDriver::DoWavDump(const TDesC8& aBuffer)
00465         {
00466         RFile file;
00467         TInt ret = file.Open(iFs, iWavDump, KFileOpenWritable);
00468         if(ret)
00469                 {
00470                 ELOG2(_L8("Serious problem, was supposed to open wav file [ret=%d]\n"), ret);
00471                 return;
00472                 }
00473 
00474         // append the stream
00475         TInt pos;
00476         ret = file.Seek(ESeekEnd, pos);
00477         if (ret==KErrNone)
00478                 {
00479                 (void)file.Write(aBuffer);
00480                 }
00481         else
00482                 {
00483                 ELOG2(_L8("Wavdump: could not seek due to %d\n"), ret);
00484                 }
00485 
00486         file.Close();
00487         }
00488 
00489 
00490 // EOF - AUDIODRV_ER6.CPP

Generated on Tue Feb 8 04:13:57 2005 for Esidplay by doxygen 1.3.3