博客园丁

我是博客园的一丁,我会永不停顿,不停创新。
  首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

symbian-使用libmad播放mp3

Posted on 2006-11-02 20:22  Jason.Jiang  阅读(1766)  评论(3编辑  收藏  举报

大体上思路是:媒体文件流化后,每播放一个缓冲的内容后,会回调MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
在这个函数里面再调NextBuffer()填充缓冲区。

1、定义类:

 class CAudioPlayerEngine : public CBase,
       public MMdaAudioPlayerCallback,
       public MMdaAudioOutputStreamCallback
{
public:
//from MMdaAudioOutputStreamCallback
virtual void MaoscOpenComplete(TInt aError);
virtual void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer);
virtual void MaoscPlayComplete(TInt aError);
void OpenFileL();
void CloseFile();

private:

void ConstructL(CAudio3Engine* aEngine);
virtual ~CAudioPlayerEngine();
void NextBuffer();

void TBuf16ToTBuf8(const TDesC16 &aTbuf16, TDes8 &aTbuf8);

private:
RFs iSession;
TBuf8<KBufferSize*2> iBuffer;
RFs iSession_mp3;
TBuf16<KBufferSize> iBuffer16;
TInt iDecodeCount;//记录解码次数
TInt iFileError;

CMdaAudioOutputStream*  iPlayerOutputStream;
CMP3DecodeEngine*   iMP3DecodeEngine;
TMdaAudioDataSettings  iStreamSettings;
};

2、关键部分的代码
void CAudioPlayerEngine::OpenFileL()
{
User::LeaveIfError(iSession_mp3.Connect());
iMP3DecodeEngine->OpenFile(iSession_mp3 , _L("c:\\play.mp3"));
iMP3DecodeEngine->SetResampleRate(16000);
iMP3DecodeEngine->DecodeStart();

iPlayerOutputStream->Open(&iStreamSettings);
}
void CAudioPlayerEngine::CloseFile()
{
iMP3DecodeEngine->DecodeStop();
iMP3DecodeEngine->CloseFile();
iSession_mp3.Close();
}
void CAudioPlayerEngine::ConstructL(CAudio3Engine* aEngine)
{
iDecodeCount = 0;
 iMP3DecodeEngine = CMP3DecodeEngine::NewL();
 iPlayerOutputStream=CMdaAudioOutputStream::NewL(*this);
 CurVolumn=iPlayerOutputStream->MaxVolume()/2;
}

CAudioPlayerEngine::~CAudioPlayerEngine()
{
 CloseFile();
 if (iPlayerOutputStream)
 {
  delete iPlayerOutputStream;
  iPlayerOutputStream=NULL;
 }
 if (iMP3DecodeEngine)
 {
  delete iMP3DecodeEngine;
  iMP3DecodeEngine=NULL;
 }
}

void CAudioPlayerEngine::NextBuffer()
{
 iBuffer.Delete(0,iBuffer.Length());
 iBuffer16.Delete(0,iBuffer16.Length());

 if (iFileError==KErrNone)
 {
  if(iMP3DecodeEngine->DecodeOneFrame(iBuffer16)==-1) //解码一个桢
  {
   iPlayerOutputStream->Stop();  //音乐结束
   return;
  }
  if(iBuffer16.Length()!=0)
  {
  iFileError=KErrNone;
  iDecodeCount++;//记录桢数
  }
  else
  {
  iFileError=KErrEof;
  }

  //复制到原来的数组中
  TBuf16ToTBuf8(iBuffer16,iBuffer);
  TRAPD(err,iPlayerOutputStream->WriteL(iBuffer));
  if (err!=KErrNone) Stop();
 }
}
void CAudioPlayerEngine::MaoscOpenComplete(TInt aError)
{
if (aError==KErrNone)
{
  iPlayerOutputStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate16000Hz,TMdaAudioDataSettings::EChannelsMono);
  iPlayerOutputStream->SetVolume(CurVolumn);
  iPlayerOutputStream->SetPriority(EPriorityMuchMore, EMdaPriorityPreferenceTimeAndQuality);
NextBuffer();

} else
 {
 EndPlay();
 }
}
void CAudioPlayerEngine::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
{
 if (aError == KErrNone)
 {
   NextBuffer();
 }else
 {
 EndPlay();
 }
}
void CAudioPlayerEngine::MaoscPlayComplete(TInt /*aError*/)
{
EndPlay();
}
void CAudioPlayerEngine::TBuf16ToTBuf8(const TDesC16 &aTbuf16, TDes8 &aTbuf8)
{
 if(aTbuf16.Length()==0)
 {
  return;
 }
 TInt length = aTbuf16.Length()*2;
 TPtrC ptr16(aTbuf16);
 TPtrC8 ptr8((TText8*) ptr16.Ptr(),length);
 TBuf8<1024> buf8(ptr8);
 aTbuf8.Append(buf8);
}