DSOUND播放WAVE文件问题

isrobert 2008-03-26 09:15:09
在读取WAVE文件给WAVEFORMAT赋值的时候,发现wFormatag不为WAVE_FORMAT_PCM的声音播放不了。
如何解决这个问题?

代码如下:
DWORD WINAPI ThreadPlaySound(LPVOID pVoid)
{
......
FILE *stream;
WAVE wav;
if((stream = fopen( sFileName, "r" )) == NULL) /* open a file for reading */
{
return 0;
}

fread(wav.ChunkID, 4, 1, stream);
wav.ChunkID[4] = (char)0;
fread(&(wav.ChunkSize), 4, 1, stream);
fread(wav.Format, 4, 1, stream);
wav.Format[4] = (char)0;
fread(wav.SubChunk1ID, 4, 1, stream);
wav.SubChunk1ID[4] = (char)0;
fread(&(wav.SubChunk1Size), 4, 1, stream);
fread(&(wav.AudioFormat), 2, 1, stream);
fread(&(wav.NumChannels), 2, 1, stream);
fread(&(wav.SampleRate), 4, 1, stream);
fread(&(wav.ByteRate), 4, 1, stream);
fread(&(wav.BlockAlign), 2, 1, stream);
fread(&(wav.BitsPerSample), 2, 1, stream);
fread(wav.SubChunk2ID, 4, 1, stream);
wav.SubChunk2ID[4] = (char)0;
fread(&(wav.SubChunk2Size), 4, 1, stream);
fclose(stream);

unsigned char audiobuf[160000];
CFile file;
WAVEFORMATEX format;
DSBUFFERDESC BufferDesc;
LPDIRECTSOUND lpDirectSound;
LPDIRECTSOUNDBUFFER lpDSoundBuffer;
LPVOID ptr1, ptr2;
DWORD pwd1, pwd2;

if(!IsWaveSuccess(wav))
{
return FALSE;
}
file.Open(sFileName, CFile::modeRead | CFile::shareDenyNone);
file.Seek(44,0L);
file.Read(audiobuf, wav.SubChunk2Size);
file.Close();

memset(&format, 0, sizeof(format));
format.wFormatTag = wav.AudioFormat;//WAVE_FORMAT_PCM;
format.nChannels = wav.NumChannels;
format.nSamplesPerSec = wav.SampleRate;
format.nAvgBytesPerSec = wav.ByteRate;
format.nBlockAlign = wav.BlockAlign;
format.wBitsPerSample = wav.BitsPerSample;

memset(&BufferDesc, 0, sizeof (BufferDesc));
BufferDesc.dwSize = sizeof(DSBUFFERDESC);
BufferDesc.dwBufferBytes = wav.SubChunk2Size;
BufferDesc.lpwfxFormat = &format;
BufferDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
HRESULT hr = DirectSoundCreate(0, &lpDirectSound, 0);
if(DS_OK != hr)
{
return 0;
}
hr = lpDirectSound->SetCooperativeLevel(*g_pWnd, DSSCL_NORMAL);
if(DS_OK != hr)
{
return 0;
}
hr = lpDirectSound->CreateSoundBuffer(&BufferDesc, &lpDSoundBuffer, 0);
if(DS_OK != hr)//如果format.wFormatTag为2,都是从这里退出。我查看返回值,发现是DSERR_INVALIDPARAM 。
{
return 0;
}
hr = lpDSoundBuffer->Lock(0, wav.SubChunk2Size, &ptr1, &pwd1, &ptr2, &pwd2, 0);
if(DS_OK != hr)
{
return 0;
}

memcpy(ptr1, audiobuf, pwd1);
memcpy(ptr2, audiobuf+pwd1, pwd2);
hr = lpDSoundBuffer->Unlock(ptr1, pwd1, ptr2, pwd2);
if(DS_OK != hr)
{
return 0;
}
hr = lpDSoundBuffer->Play(0, 0, DSBPLAY_LOOPING );
if(DS_OK != hr)
{
return 0;
}

DWORD dCurTime = GetTickCount();
while(1)
{
if(pBtn->GetSoundMark())//是否退出线程用的
{
break;
}
if((GetTickCount() - dCurTime) > pListen->m_nSoundTime * 1000)//播放时间是否到了
{
break;
}
Sleep(1);
}
lpDSoundBuffer->Stop();
lpDSoundBuffer->Release();
lpDirectSound->Release();
return 0;
}


我查了MSDN,如果调用CreateSoundBuffer返回DSERR_INVALIDPARAM 的话,说明
An invalid parameter was passed to the returning function.
但是,我没发现哪里错了。 哪为对音频播放比较熟悉,告诉下小弟,谢谢!

另外,WAVE结构定义如下
typedef struct wave_tag
{
char ChunkID[5];
unsigned long int ChunkSize;
char Format[5];
char SubChunk1ID[5];
unsigned long int SubChunk1Size;
unsigned short int AudioFormat;
unsigned short int NumChannels;
unsigned long int SampleRate;
unsigned long int ByteRate;
unsigned short int BlockAlign;
unsigned short int BitsPerSample;
char SubChunk2ID[5];
unsigned long int SubChunk2Size;
} WAVE;
...全文
219 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yxz_lp 2008-03-31
  • 打赏
  • 举报
回复
WAVEFORMATEX.wFormatTag = WAVE_FORMAT_PCM; //always need this
或者用
扩展的WAVEFORMATEX(WAVEFORMATEXTENSIBLE)
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/waveformatextensible.asp
isrobert 2008-03-31
  • 打赏
  • 举报
回复
楼上的朋友,谢谢你的代码。
但是,你的代码仍然无法说明问题呀。
我的程序可以播放声音,但是只能播放WAVE_FORMAT_PCM格式的声音。WAVE_FORMAT_PCM外的压缩格式则无法播放。
我想问的就是如何播放WAVE_FORMAT_PCM格式以外的wave文件~
yxz_lp 2008-03-28
  • 打赏
  • 举报
回复

if (DirectSoundCreate(NULL, &lpds, NULL)!=DS_OK )
return(0);

// set cooperation level
if (lpds->SetCooperativeLevel(main_window_handle,DSSCL_NORMAL)!=DS_OK)
return(0);

// clear array out
memset(sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS);

// initialize the sound fx array
for (int index=0; index<MAX_SOUNDS; index++)
{
// test if this sound has been loaded
if (sound_fx[index].dsbuffer)
{
// stop the sound
sound_fx[index].dsbuffer->Stop();

// release the buffer
sound_fx[index].dsbuffer->Release();

} // end if

// clear the record out
memset(&sound_fx[index],0,sizeof(pcm_sound));

// now set up the fields
sound_fx[index].state = SOUND_NULL;
sound_fx[index].id = index;

} // end for index

// load a wav file in
if ((sound_id = DSound_Load_WAV("FLIGHT.WAV"))!=-1)
{
// start the voc playing in looping mode
sound_fx[sound_id].dsbuffer->Play(0,0,DSBPLAY_LOOPING);
} // end if

yxz_lp 2008-03-28
  • 打赏
  • 举报
回复

// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN

#include <windows.h> // include important windows stuff
#include <windowsx.h>
#include <mmsystem.h>
#include <iostream> // include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>

#include <ddraw.h> // directX includes
#include <dsound.h>

// directx 7.0 compatibility

#ifndef DSBCAPS_CTRLDEFAULT
#define DSBCAPS_CTRLDEFAULT (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME )
#endif

// DEFINES ////////////////////////////////////////////////

// defines for windows
#define WINDOW_CLASS_NAME "WINCLASS1" // class name

#define WINDOW_WIDTH 400 // size of window
#define WINDOW_HEIGHT 300
#define SCREEN_WIDTH 640 // size of screen
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8 // bits per pixel

#define MAX_SOUNDS 256 // max number of sounds in system at once

// digital sound object state defines
#define SOUND_NULL 0 // " "
#define SOUND_LOADED 1
#define SOUND_PLAYING 2
#define SOUND_STOPPED 3



// TYPES //////////////////////////////////////////////////

typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;

// this holds a single sound
typedef struct pcm_sound_typ
{
LPDIRECTSOUNDBUFFER dsbuffer; // the ds buffer containing the sound
int state; // state of the sound
int rate; // playback rate
int size; // size of sound
int id; // id number of the sound
} pcm_sound, *pcm_sound_ptr;



// GLOBALS ////////////////////////////////////////////////


char buffer[80]; // used to print text

LPDIRECTSOUND lpds; // directsound interface pointer
DSBUFFERDESC dsbd; // directsound description
DSCAPS dscaps; // directsound caps
HRESULT dsresult; // general directsound result
DSBCAPS dsbcaps; // directsound buffer caps

LPDIRECTSOUNDBUFFER lpdsbprimary, // you won't need this normally
lpdsbsecondary; // the sound buffers

WAVEFORMATEX pcmwf; // generic waveformat structure

pcm_sound sound_fx[MAX_SOUNDS]; // the array of secondary sound buffers


HWND freq_hwnd, // window handles for controls
volume_hwnd,
pan_hwnd;


int sound_id = -1; // id of sound we load for demo
////////////////////////////////////////////////////////////////////////////////
int DSound_Load_WAV(char *filename, int control_flags)
{
// this function loads a .wav file, sets up the directsound
// buffer and loads the data into memory, the function returns
// the id number of the sound


HMMIO hwav; // handle to wave file
MMCKINFO parent, // parent chunk
child; // child chunk
WAVEFORMATEX wfmtx; // wave format structure

int sound_id = -1, // id of sound to be loaded
index; // looping variable

UCHAR *snd_buffer, // temporary sound buffer to hold voc data
*audio_ptr_1=NULL, // data ptr to first write buffer
*audio_ptr_2=NULL; // data ptr to second write buffer

DWORD audio_length_1=0, // length of first write buffer
audio_length_2=0; // length of second write buffer

// step one: are there any open id's ?
for (index=0; index < MAX_SOUNDS; index++)
{
// make sure this sound is unused
if (sound_fx[index].state==SOUND_NULL)
{
sound_id = index;
break;
} // end if

} // end for index

// did we get a free id?
if (sound_id==-1)
return(-1);

// set up chunk info structure
parent.ckid = (FOURCC)0;
parent.cksize = 0;
parent.fccType = (FOURCC)0;
parent.dwDataOffset = 0;
parent.dwFlags = 0;

// copy data
child = parent;

// open the WAV file
if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
return(-1);

// descend into the RIFF
parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');

if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
{
// close the file
mmioClose(hwav, 0);

// return error, no wave section
return(-1);
} // end if

// descend to the WAVEfmt
child.ckid = mmioFOURCC('f', 'm', 't', ' ');

if (mmioDescend(hwav, &child, &parent, 0))
{
// close the file
mmioClose(hwav, 0);

// return error, no format section
return(-1);
} // end if

// now read the wave format information from file
if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
{
// close file
mmioClose(hwav, 0);

// return error, no wave format data
return(-1);
} // end if

// make sure that the data format is PCM
if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
{
// close the file
mmioClose(hwav, 0);

// return error, not the right data format
return(-1);
} // end if

// now ascend up one level, so we can access data chunk
if (mmioAscend(hwav, &child, 0))
{
// close file
mmioClose(hwav, 0);

// return error, couldn't ascend
return(-1);
} // end if

// descend to the data chunk
child.ckid = mmioFOURCC('d', 'a', 't', 'a');

if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
{
// close file
mmioClose(hwav, 0);

// return error, no data
return(-1);
} // end if

// finally!!!! now all we have to do is read the data in and
// set up the directsound buffer

// allocate the memory to load sound data
snd_buffer = (UCHAR *)malloc(child.cksize);

// read the wave data
mmioRead(hwav, (char *)snd_buffer, child.cksize);

// close the file
mmioClose(hwav, 0);

// set rate and size in data structure
sound_fx[sound_id].rate = wfmtx.nSamplesPerSec;
sound_fx[sound_id].size = child.cksize;
sound_fx[sound_id].state = SOUND_LOADED;

// set up the format data structure
memset(&pcmwf, 0, sizeof(WAVEFORMATEX));

pcmwf.wFormatTag = WAVE_FORMAT_PCM; // pulse code modulation
pcmwf.nChannels = 1; // mono
pcmwf.nSamplesPerSec = 11025; // always this rate
pcmwf.nBlockAlign = 1;
pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
pcmwf.wBitsPerSample = 8;
pcmwf.cbSize = 0;

// prepare to create sounds buffer
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
dsbd.dwBufferBytes = child.cksize;
dsbd.lpwfxFormat = &pcmwf;

// create the sound buffer
if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)))
{
// release memory
free(snd_buffer);

// return error
return(-1);
} // end if

// copy data into sound buffer
if (FAILED(sound_fx[sound_id].dsbuffer->Lock(0,
child.cksize,
(void **) &audio_ptr_1,
&audio_length_1,
(void **)&audio_ptr_2,
&audio_length_2,
DSBLOCK_FROMWRITECURSOR)))
return(0);

// copy first section of circular buffer
memcpy(audio_ptr_1, snd_buffer, audio_length_1);

// copy last section of circular buffer
memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);

// unlock the buffer
if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1,
audio_length_1,
audio_ptr_2,
audio_length_2)))
return(0);

// release the temp buffer
free(snd_buffer);

// return id
return(sound_id);

} // end DSound_Load_WAV
//////////////////////////////////////////////


isrobert 2008-03-28
  • 打赏
  • 举报
回复
vfw可以支持类似DSBCAPS_GLOBALFOCUS的效果?
scq2099yt 2008-03-28
  • 打赏
  • 举报
回复
up
isrobert 2008-03-26
  • 打赏
  • 举报
回复
没人会么? 给点意见~
draculacsdn 2008-03-26
  • 打赏
  • 举报
回复
播放wav文件完全不用DSOUND ,vfw就可以

19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧