使用directsound播放pcm流文件.txt

 

刚开始用waveOutWrite系列函数想实现动态流缓冲区播放MP3 decoder解码后的PCM音频流,在缓冲切换的时候总是出现爆破音,想了很多的办法,在网上也找了很多资料,都没有解决,后来想可能waveOutWrite这系列的函数根本就不能实现流缓冲播放音频。后来不得以开始转向directsound,DirectSound应用程序开发快速入门给了很大的帮助,但里面的程序好像也有点小问题的。将我在VC6.0控制台下写的PCM文件播放程序贴出来供大家交流学习,程序很短,很适合directsound 的学习。#include

<windows.h>//这个头文件要放在最前面,否着会提示有些东西找不到
#define DIRECTSOUND_VERSION 0x0800
/*因为我们用的是DX8,所以一定要定义哈,否则会有一大堆类似LPDIRECTSOUNDBUFFER8的东西找不到的
另外如果用的是VC6,请大家下载directx 8并把当中的库文件和头文件拷到VC6的相应目录*/
#include <mmsystem.h>
#include <dsound.h>
#include <stdio.h>
#include <stdlib.h>

#pragma   comment(lib,"winmm.lib")
#pragma   comment(lib,"dsound.lib")
#pragma   comment(lib,"dxguid.lib")

#define MAX_AUDIO_BUF 4 //播放缓冲的通知索引
#define BUFFERNOTIFYSIZE 192000 //通知位置的大小,请参见DirectSound应用程序开发快速入门
DWORD g_dwNextWriteOffset ;
#define SAMPLE_RATE      44100 //pcm 的采样率
#define N_CHANNEL          2   //PCM 声道数
#define BITS_PER_SAMPLE    16 //每个采样点的比特数
int ProcessBuffer(LPDIRECTSOUNDBUFFER8 g_pDSBuffer8, FILE *fp);//缓冲填写函数

BOOL main(int argc,char * argv[])
{
int i;
FILE * fp;
if((fp=fopen("test_out.pcm","rb"))==NULL)//打开你的PCM 文件
{
   printf("cannot open this file\n");
}
LPDIRECTSOUNDBUFFER8 g_pDSBuffer8=NULL; //buffer
    LPDIRECTSOUND8 g_pDsd=0; //dsound
BOOL g_bPlaying = FALSE; //是否正在播放
LPDIRECTSOUNDNOTIFY8 g_pDSNotify=0;
DSBPOSITIONNOTIFY g_aPosNotify[MAX_AUDIO_BUF];//设置通知标志的数组
HANDLE g_event[MAX_AUDIO_BUF];

SetConsoleTitle("player");//设置窗口名称

    //初始化DirectSound
HRESULT hr;
if(FAILED(hr=DirectSoundCreate8(NULL,&g_pDsd,NULL)))
   return FALSE;
if(FAILED(hr=g_pDsd->SetCooperativeLevel(FindWindow(NULL,"player"),DSSCL_NORMAL)))
{
   switch(hr)
   {
   case DSERR_ALLOCATED:
    printf("DSERR_ALLOCATED\n");
    break;
   case DSERR_INVALIDPARAM:
    printf("DSERR_INVALIDPARAM\n");
    break;
   case DSERR_UNINITIALIZED:
    printf("DSERR_UNINITIALIZED\n");
    break;
   case DSERR_UNSUPPORTED:
    printf("DSERR_UNSUPPORTED\n");
    break;
   default:
    break;
   }
   return FALSE;
}

DSBUFFERDESC dsbd;
printf("%d\n",sizeof(dsbd));
memset(&dsbd,0,sizeof(dsbd));
dsbd.dwSize=sizeof(dsbd);
dsbd.dwFlags=DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
dsbd.dwBufferBytes=MAX_AUDIO_BUF*BUFFERNOTIFYSIZE;
dsbd.lpwfxFormat=(WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX));
dsbd.lpwfxFormat->wFormatTag=WAVE_FORMAT_PCM;  
/* format type */
    (dsbd.lpwfxFormat)->nChannels=N_CHANNEL;         
/* number of channels (i.e. mono, stereo...) */
    (dsbd.lpwfxFormat)->nSamplesPerSec=SAMPLE_RATE;    
/* sample rate */
    (dsbd.lpwfxFormat)->nAvgBytesPerSec=SAMPLE_RATE*(BITS_PER_SAMPLE/8)*N_CHANNEL;
/* for buffer estimation */
    (dsbd.lpwfxFormat)->nBlockAlign=(BITS_PER_SAMPLE/8)*N_CHANNEL;       
/* block size of data */
    (dsbd.lpwfxFormat)->wBitsPerSample=BITS_PER_SAMPLE;    
/* number of bits per sample of mono data */
    (dsbd.lpwfxFormat)->cbSize=0;

//创建DirectSound辅助缓冲区
LPDIRECTSOUNDBUFFER lpbuffer;
HRESULT hr1;
if(DS_OK != (hr1=(g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL))))
{  
   switch(hr1)
   {
   case DSERR_ALLOCATED:
    printf("DSERR_ALLOCATED\n");
    break;
   case DSERR_BADFORMAT:
    printf("DSERR_BADFORMAT\n");
    break;
/*   case DSERR_BUFFERTOOSMALL:
    printf("DSERR_BUFFERTOOSMALL\n");
    break;*/
   case DSERR_CONTROLUNAVAIL:
    printf("DSERR_CONTROLUNAVAIL\n");
    break;
/*   case DSERR_DS8_REQUIRED:
    printf("DSERR_DS8_REQUIRED\n");
    break;*/
   case DSERR_INVALIDCALL:
    printf("DSERR_INVALIDCALL\n");
    break;
   case DSERR_INVALIDPARAM:
    printf("DSERR_INVALIDPARAM\n");
    break;
   case DSERR_NOAGGREGATION:
    printf("DSERR_NOAGGREGATION\n");
    break;
   case DSERR_OUTOFMEMORY:
    printf("DSERR_OUTOFMEMORY\n");
    break;
   case DSERR_UNINITIALIZED:
    printf("DSERR_UNINITIALIZED\n");
    break;
   case DSERR_UNSUPPORTED:
    printf("DSERR_UNSUPPORTED\n");
    break;
   }
   return FALSE;
}
HRESULT hr2;
if( FAILED(hr2=(lpbuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*)&g_pDSBuffer8))))
{
   switch(hr2)
   {
   case E_NOINTERFACE:
    printf("E_NOINTERFACE on hr2 \n");
    break;
   default:
    printf("an unknow error on hr2\n");
    break;
   }
   return false ;
}
lpbuffer->Release();

//设置DirectSound通知 机制
HRESULT hr3;
if(FAILED(hr3=(g_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID*)&g_pDSNotify))))
{
   switch(hr3)
   {
   case E_NOINTERFACE:
    printf("E_NOINTERFACE hr3\n");
    break;
   default:
    printf("an unknow error hr3,%d\n",hr3);
    break;
   }
   return false ;
}
for(i =0;i<MAX_AUDIO_BUF;i++)
{
   g_aPosNotify[i].dwOffset =i*BUFFERNOTIFYSIZE;
   g_event[i]=::CreateEvent(NULL,false,false,NULL);
   g_aPosNotify[i].hEventNotify=g_event[i];
}
g_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);
g_pDSNotify->Release();

//开始播放缓冲中的内容
g_bPlaying =TRUE;
DWORD res=5;
LPVOID lplockbuf;
DWORD len;
int flag=1;
g_pDSBuffer8->Lock(0,BUFFERNOTIFYSIZE*3,&lplockbuf,&len,NULL,NULL,0);
fread(lplockbuf,len,1,fp);
printf("%d\n",len);
printf("%d\n",sizeof(BYTE));
g_pDSBuffer8->Unlock(lplockbuf,len,NULL,0);
g_pDSBuffer8->SetCurrentPosition(0);
g_pDSBuffer8->Play(0,0,DSBPLAY_LOOPING);
g_dwNextWriteOffset=BUFFERNOTIFYSIZE*3;
Sleep(2000);
while(g_bPlaying)
{
   res = WaitForMultipleObjects (MAX_AUDIO_BUF, g_event, FALSE, INFINITE);
   if((res >=WAIT_OBJECT_0)&&(res <=WAIT_OBJECT_0+3))
   {
    printf("%d\n",res);
    flag=ProcessBuffer(g_pDSBuffer8,fp);
    res=5;
    if(flag=0)
     g_bPlaying=false;
   }
}

printf("this is a test of directsound\n");
return true;

}
int ProcessBuffer(LPDIRECTSOUNDBUFFER8 g_pDSBuffer8, FILE *fp)
{
printf("this is processBuffer in \n");
VOID* pDSLockedBuffer = NULL;
VOID* pDSLockedBuffer2 = NULL;
DWORD dwDSLockedBufferSize;
DWORD dwDSLockedBufferSize2;
HRESULT hr;
int test;
hr=g_pDSBuffer8->Lock(g_dwNextWriteOffset,BUFFERNOTIFYSIZE,&pDSLockedBuffer
      ,&dwDSLockedBufferSize, &pDSLockedBuffer2,&dwDSLockedBufferSize2,0);
if(hr == DSERR_BUFFERLOST)
{
   g_pDSBuffer8->Restore();
        g_pDSBuffer8->Lock(g_dwNextWriteOffset,BUFFERNOTIFYSIZE,&pDSLockedBuffer
      ,&dwDSLockedBufferSize,&pDSLockedBuffer2,&dwDSLockedBufferSize2,0);
}
if(SUCCEEDED(hr))
{
   //fread((BYTE*)pDSLockedBuffer,dwDSLockedBufferSize,1,fp);
   if(0==(test=fread((BYTE*)pDSLockedBuffer,dwDSLockedBufferSize,1,fp)))
    return 0;
   //printf("dwDSLockedBufferSize is%d\n",test);
   g_dwNextWriteOffset+=dwDSLockedBufferSize;
   if (NULL != pDSLockedBuffer2)
   {
    //fread((BYTE*)pDSLockedBuffer2,dwDSLockedBufferSize2,1,fp);
    if(0==(test=fread((BYTE*)pDSLockedBuffer2,dwDSLockedBufferSize2,1,fp)))
     return 0;
    //printf("dwDSLockedBufferSize2 is%d\n",test);
    g_dwNextWriteOffset+=dwDSLockedBufferSize2;
   }
   g_dwNextWriteOffset %= (BUFFERNOTIFYSIZE * MAX_AUDIO_BUF);
   printf("this is %d of buffer\n",g_dwNextWriteOffset);
   hr = g_pDSBuffer8->Unlock(pDSLockedBuffer,dwDSLockedBufferSize,
   pDSLockedBuffer2,dwDSLockedBufferSize2);
}
return 1;
}

你可能感兴趣的:(null,buffer,byte,FP,audio,程序开发)