我已经成功地播放出了声音!这里先说一下大概的思路: 1、定义类: class CSynchronousExampleStream : public CBase, public MMdaAudioOutputStreamCallback { public: //from MMdaAudioOutputStreamCallback virtual void MaoscOpenComplete(TInt aError); virtual void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer); virtual void MaoscPlayComplete(TInt aError);
void ConstructL(CAudio3Engine* aEngine); virtual ~CSynchronousExampleStream(); void StartPlayL(); void Stop(); private: void OpenFileL(); void CloseFile();
void NextBuffer(); void PlayEnded(TInt aError); TInt FillBuffer(); private: CMdaAudioOutputStream* iStream; RFs iSession; TBuf8<KBufferSize*2> iBuffer; RFs iSession_mp3; TBuf16<KBufferSize> iBuffer16; CMP3DecodeEngine *iMP3Decode; TInt iDecodeCount;//记录解码次数 TInt iFileError; CAudio3Engine* iEngine; }; 2、关键部分的代码的 void CSynchronousExampleStream::OpenFileL() { User::LeaveIfError(iSession_mp3.Connect()); iMP3Decode->OpenFile(iSession_mp3 , _L("c:\\play.mp3")); iMP3Decode->SetResampleRate(16000); iMP3Decode->DecodeStart(); } void CSynchronousExampleStream::CloseFile() { iMP3Decode->DecodeStop(); iMP3Decode->CloseFile(); iSession_mp3.Close(); } void CSynchronousExampleStream::ConstructL(CAudio3Engine* aEngine) { iDecodeCount = 0; iMP3Decode = CMP3DecodeEngine::NewL(); iEngine=aEngine; iStream=CMdaAudioOutputStream::NewL(*this); iStream->Open(NULL); } void CSynchronousExampleStream::NextBuffer() { if (iFileError==KErrNone) { iMP3Decode->DecodeOneFrame(iBuffer16);//解码一个桢 if(iBuffer16.Length()!=0) { iFileError=KErrNone; iDecodeCount++;//记录桢数 } else { iFileError=KErrEof; } //复制到原来的数组中 //iBuffer.Copy(iBuffer16);//这样做不行,会丢掉16bit的高8位的,必须要转换 TInt i=0 ;//临时循环变量 TInt len ; len = iBuffer16.Length()*2; TUint8 *buf16_ptr; TUint8 *buf8_ptr; buf16_ptr = (TUint8* )iBuffer16.Ptr(); buf8_ptr = (TUint8* )iBuffer.Ptr(); for(i=0 ; i<len ; i++) { //双字节复制到单字节数组中,长度增加一倍 buf8_ptr[i] = (TUint8)buf16_ptr[i]; } iBuffer.SetLength(len); TRAPD(err,iStream->WriteL(iBuffer)); if (err!=KErrNone) Stop(); } } CSynchronousExampleStream::~CSynchronousExampleStream() { CloseFile(); delete iMP3Decode; delete iStream; } void CSynchronousExampleStream::MaoscOpenComplete(TInt aError) { if (aError==KErrNone) { iStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate16000Hz,TMdaAudioDataSettings::EChannelsMono); iStream->SetVolume(iStream->MaxVolume()); iEngine->SetState(CAudio3Engine::EReadySynchronous); } }
大体上就是如此,思路上是:媒体文件流化后,每播放一个缓冲的内容后,会回调MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/) 在这个函数里面再调NextBuffer()填充缓冲区。
|