如何使辅助 DirectBuffer 声音
How to make secondary DirectBuffer sound?
我正在尝试从简单的点击键盘中获取声音。看起来像一个小鼓机。如果 DirectSound 不是执行此操作的正确方法,请提出其他建议。在我的代码中,我不知道出了什么问题。这里没有错误检查和翻译:
//Declaring the IDirectSound object
IDirectSound* device;
DirectSoundCreate(NULL, &device, NULL);
device->SetCooperativeLevel(hWnd, DSSCL_NORMAL );
/* Declaring secondary buffers */
IDirectSoundBuffer* kickbuf;
IDirectSoundBuffer* snarebuf;
/* Declaring .wav files pointers
And to structures for reading the information int the begining of the .wav file */
FILE* fkick;
FILE* fsnare;
sWaveHeader kickHdr;
sWaveHeader snareHdr;
结构 sWaveHeader 是这样声明的:
typedef struct sWaveHeader
{
char RiffSig[4]; // 'RIFF'
unsigned long WaveformChunkSize; // 8
char WaveSig[4]; // 'WAVE'
char FormatSig[4]; // 'fmt '
unsigned long FormatChunkSize; // 16
unsigned short FormatTag; // WAVE_FORMAT_PCM
unsigned short Channels; // Channels
unsigned long SampleRate;
unsigned long BytesPerSec;
unsigned short BlockAlign;
unsigned short BitsPerSample;
char DataSig[4]; // 'data'
unsigned long DataSize;
} sWaveHeader;
文件打开.wav
#define KICK "D:/muzic/kick.wav"
#define SNARE "D:/muzic/snare.wav"
fkick = fopen(KICK, "rb")
fsnare = fopen(SNARE, "rb")
在这里,我做了一个函数,它为 snarebuf* 和 **kickbuf 做共同的工作
int read_wav_to_WaveHeader (sWaveHeader* , FILE* , IDirectSoundBuffer* ); // The declaring
但是我不会写这个函数,只是展示它与kickbuf一起工作的方式,例如。
fseek(fkick, 0, SEEK_SET); // Zero the position in file
fread(&kickHdr, 1, sizeof(sWaveHeader), fkick); // reading the sWaveHeader structure from file
下面检查是否适合 sWaveHeader 结构:
if(memcmp(pwvHdr.RiffSig, "RIFF", 4) ||
memcmp(pwvHdr.WaveSig, "WAVE", 4) ||
memcmp(pwvHdr.FormatSig, "fmt ", 4) ||
memcmp(pwvHdr.DataSig, "data", 4))
return 1;
声明缓冲区的格式和描述符并填充它们:
DSBUFFERDESC bufDesc;
WAVEFORMATEX wvFormat;
ZeroMemory(&wvFormat, sizeof(WAVEFORMATEX));
wvFormat.wFormatTag = WAVE_FORMAT_PCM;
wvFormat.nChannels = kickHdr.Channels;
wvFormat.nSamplesPerSec = kickHdr.SampleRate;
wvFormat.wBitsPerSample = kickHdr.BitsPerSample;
wvFormat.nBlockAlign = wvFormat.wBitsPerSample / 8 * wvFormat.nChannels;
ZeroMemory(&bufDesc, sizeof(DSBUFFERDESC));
bufDesc.dwSize = sizeof(DSBUFFERDESC);
bufDesc.dwFlags = DSBCAPS_CTRLVOLUME |
DSBCAPS_CTRLPAN |
DSBCAPS_CTRLFREQUENCY;
bufDesc.dwBufferBytes = kickHdr.DataSize;
bufDesc.lpwfxFormat = &wvFormat;
好吧,创建缓冲区:
device->CreateSoundBuffer(&bufDesc, &kickbuf, NULL); // Any mistakes by this point?
现在锁定缓冲区并向其中加载一些数据。此数据在 WAVE 文件中的 sizeof(sWaveHeader( 字节之后开始,我错了吗?
LPVOID Ptr1; // pointer on a pointer on a First block of data
LPVOID Ptr2; // pointer on a pointer on a Second block of data
DWORD Size1, Size2; // their sizes
现在调用 Lock(( 方法:
kickbuf->Lock((DWORD)LockPos, (DWORD)Size,
&Ptr1, &Size1,
&Ptr2, &Size2, 0);
加载数据(可以吗?
fseek(fkick, sizeof(sWaveHeader), SEEK_SET);
fread(Ptr1, 1, Size1, fkick);
if(Ptr2 != NULL)
fread(Ptr2, 1, Size2, fkick);
解锁缓冲区:
kickbuf->Unlock(Ptr1, Size1, Ptr2, Size2);
设置音量:
kickbuf->SetVolume(-2500);
然后我做了一个wile(1(循环:1. 要求按键2. 如果按下:
kickbuf->SetCurrentPosition(0)
kickbuf->Play(0,0,0);
但是没有声音播放,请说,在我的代码中或整个概念中什么是不合适的。谢谢。
当您初始化 WAVEFORMATEX 时,您忘记设置 nAvgBytesPerSec 成员。 在初始化 wvFormat.nBlockAlign 后添加此行:
wvFormat.nAvgBytesPerSec = wvFormat.nSamplesPerSec * wvFormat.nBlockAlign;
另外,我怀疑这可能是一个问题:
kickbuf->SetVolume(-2500);
我怀疑这只会将您的样本衰减到绝对静音。尝试将该调用取出,以便以最大音量播放。
但更有可能的是,上面的示例代码都没有显示来自任何 DirectSound API 的返回值的验证,也没有显示任何文件 I/O 值的验证。 您是否验证了所有 DSound API 返回的 HRESULT 是否返回S_OK? 您是否尝试过打印或使用 OutputDebugString 来打印为 WAVEFORMATEX 成员计算的值?
您是否调试了 fread 调用以验证是否将有效数据放入缓冲区?
希望这有帮助。
- Xaudio2在更改缓冲区或循环时弹出声音
- 如何更改'a'声音?
- 如何收听Windows当前正在播放的声音?
- 如何在 c++ 中循环中使用频率变化的声音?
- 如何在C++中播放声音?
- 波形音频 - waveOutWrite 发出断断续续的声音
- 如何使用 ALSA API 在应用程序中在单声道和立体声之间切换声音输出?
- 有没有办法毫不拖延地播放声音?
- 在不打开应用程序的情况下在MinGW c++中播放声音(.wav)文件
- SFML c ++ 当包含文件内游戏中发生事件时,如何使用铃声函数为我的游戏创建声音类?
- 如何在QT中飞溅之前播放声音?
- 如何根据物体位置和速度,玩家位置和向前矢量计算左耳和右耳的音量?(3D声音)
- 计时器达到零时如何播放声音?
- 如何在主游戏循环中使用 sfml 只播放一次声音
- 避免在暂停时破坏声音
- 每次播放前都会出现超强的 SDK 声音故障
- Qt - 重新实现QIODevice,实时听到我自己的声音
- 使用MinGW播放声音
- 如何为音频应用程序/插件模拟真空管的声音
- 如何使辅助 DirectBuffer 声音