关于如何编写指向内存插放的音频解码器
前不久没事研究了一下音频无损压缩,在想出压缩算法后,压缩后的文件格式没有专门的解码器,所以就研究了一下解码器,我的思路是在插放时,从文件中读取压缩码,在内存中解压,然后再用插放的指针指向我还原码的内存区进行插放.由于压缩算法的代码和解压算法的代码比较多,在这先讲一下如何实现直接从内存区中插放文件,下面的代码是把WAV文件读到内存中,再把内存中的音频数据送去插放.(代码是用C++写的,因本人比较懒,没有写出代码的注释)
#include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::btnEixtClick(TObject *Sender) { bExit=true; Close(); } //--------------------------------------------------------------------------- void __fastcall TForm1::btnOpenClick(TObject *Sender) { if(pVoiceBuffer) pVoiceBuffer=NULL; if(f) { f=NULL; } bExit=false; OpenDialog1->InitialDir =GetCurrentDir(); if(OpenDialog1->Execute()==false) { btnOpen->Enabled =true; return; } btnPlay->Enabled==true; sOpenFileName=OpenDialog1->FileName ; Label5->Caption =sOpenFileName.SubString(sOpenFileName.LastDelimiter('//')+1,sOpenFileName.Length() ); Form1->Caption =Label5->Caption ; f=new TFileStream(sOpenFileName,fmShareDenyWrite); cpHeader=new char[44]; f->ReadBuffer(cpHeader,44); f->Seek(22,soFromBeginning); f->Read(&sChannels,sizeof(short)); Label10->Caption =IntToStr(sChannels); f->Seek(24,soFromBeginning); f->Read(&lSamplingRate,sizeof(long)); Label6->Caption =IntToStr(lSamplingRate)+"samples/second"; f->Seek(34,soFromBeginning); f->Read(&sBitsPerSample,sizeof(short)); Label8->Caption =IntToStr(sBitsPerSample)+"bits/sample"; /*f->Seek(40,soFromBeginning); f->Read(&lFileSize,sizeof(long)); Label7->Caption =IntToStr(lFileSize)+"bytes"; */ f->Seek(4,soFromBeginning); f->Read(&lFileSize,sizeof(long)); lFileSize-=44; Label7->Caption =IntToStr(lFileSize)+"bytes"; if(sBitsPerSample==8) iSampleSize=lFileSize; else if(sBitsPerSample==16) iSampleSize=lFileSize/2; else { MessageDlg("not pcm formats",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } pVoiceBuffer=new short[iSampleSize]; f->Seek(44,soFromBeginning); f->Read(pVoiceBuffer,lFileSize); } //--------------------------------------------------------------------------- void __fastcall TForm1::btnStopClick(TObject *Sender) { if(pVoiceBuffer==NULL) { MessageDlg("no data for playing",mtWarning,TMsgDlgButtons()<<mbOK,0); return; } waveOutUnprepareHeader(hWaveOut,lpWaveHdr,sizeof(WAVEHDR)); if(waveOutReset(hWaveOut)!=MMSYSERR_NOERROR) { MessageDlg("waveoutreset error",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } if(waveOutClose(hWaveOut)!=MMSYSERR_NOERROR) { MessageDlg("waveoutClose error",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } if(lpWaveHdr) { GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); hWaveHdr=NULL; } btnPlay->Enabled=true; btnStop->Enabled=false; } //--------------------------------------------------------------------------- void __fastcall TForm1::btnPlayClick(TObject *Sender) { char szOpenError[]="Open device Error !"; if(pVoiceBuffer==NULL) { MessageDlg("no data for playing",mtWarning,TMsgDlgButtons()<<mbOK,0); return; } btnStop->Enabled=true; dwDataSize=lFileSize; pFormat.wFormatTag =WAVE_FORMAT_PCM; pFormat.nChannels =sChannels; pFormat.nSamplesPerSec =lSamplingRate; if(sBitsPerSample==8) { pFormat.nAvgBytesPerSec =lSamplingRate*sChannels*(sBitsPerSample/8); pFormat.nBlockAlign =sChannels*(sBitsPerSample/8); pFormat.wBitsPerSample =8; }else{ pFormat.nAvgBytesPerSec =lSamplingRate*sChannels*(sBitsPerSample/8); pFormat.nBlockAlign =sChannels*(sBitsPerSample/8); pFormat.wBitsPerSample =16; } pFormat.cbSize =0; if(!(waveOutOpen((LPHWAVEOUT)&hWaveOut,WAVE_MAPPER,(LPWAVEFORMATEX)&pFormat,(DWORD)Form1->Handle ,0,0)==MMSYSERR_NOERROR)) { MessageDlg(szOpenError,mtInformation,TMsgDlgButtons()<<mbOK,0); return; }else{ btnPlay->Enabled=false; hWaveHdr=GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,(DWORD)sizeof(WAVEHDR)); if(hWaveHdr==NULL) { MessageDlg("not enough menory for header.",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } lpWaveHdr=(LPWAVEHDR)GlobalLock(hWaveHdr); if(lpWaveHdr==NULL) { MessageDlg("Failed to lock memory for header..",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } lpWaveHdr->lpData=(char*)pVoiceBuffer; lpWaveHdr->dwBufferLength =lFileSize; lpWaveHdr->dwFlags =0L; lpWaveHdr->dwLoops =0L; if(waveOutPrepareHeader(hWaveOut,lpWaveHdr,sizeof(WAVEHDR))!=MMSYSERR_NOERROR) { MessageDlg("WAVEOUTPREPAREHEADER ERROR .",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } wResult=waveOutWrite(hWaveOut,lpWaveHdr,sizeof(WAVEHDR)); if(wResult!=0) { waveOutUnprepareHeader(hWaveOut,lpWaveHdr,sizeof(WAVEHDR)); GlobalUnlock(lpWaveHdr); GlobalFree(hWaveHdr); MessageDlg("waveoutwrite error.",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } else while(waveOutUnprepareHeader(hWaveOut,lpWaveHdr,sizeof(WAVEHDR))!=MMSYSERR_NOERROR) { if(bExit) break; Application->ProcessMessages(); } if(waveOutReset(hWaveOut)!=MMSYSERR_NOERROR) { MessageDlg("waveoutreset error",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } if(waveOutClose(hWaveOut)!=MMSYSERR_NOERROR) { MessageDlg("waveoutclose error",mtInformation,TMsgDlgButtons()<<mbOK,0); return; } if(lpWaveHdr) { GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } btnPlay->Enabled=true; btnStop->Enabled=false; } } |
关于如何编写指向内存插放的音频解码器
最新推荐文章于 2024-09-14 20:03:08 发布