关于如何编写指向内存插放的音频解码器

前不久没事研究了一下音频无损压缩,在想出压缩算法后,压缩后的文件格式没有专门的解码器,所以就研究了一下解码器,我的思路是在插放时,从文件中读取压缩码,在内存中解压,然后再用插放的指针指向我还原码的内存区进行插放.由于压缩算法的代码和解压算法的代码比较多,在这先讲一下如何实现直接从内存区中插放文件,下面的代码是把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;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值