[英]Stream sine wave to XAudio2
我正在嘗試編寫一個通過 XAudio2 播放的非常簡單的正弦波發生器。
目前有聲音播放,如果我調用 Win32XAudioInit() 然后 Win32PlayTone() 會播放一個音調,並且在隨后調用 Win32PlayTone() 時音調會改變,但是幾乎每次音調改變時都會有明顯的點擊。
我知道有幾個原因可能會導致這種情況:
關於#2,我不確定 XAudio 是否希望我創建一個新的 XAUDIO2_BUFFER 並在每次更改音調時重新提交,或者我是否應該以某種方式跟蹤“播放頭”的位置(因為沒有更好的術語) 並且只更新已經播放過的字節。
我知道 #2 是否有問題,如果我修復它我將聽不到我仍然受到問題 #1 的困擾。 我已經通讀了XAudio2 - Play generated sine, when changed frequency click sound ,如果我知道 XAudio2 設置正確,我想我可以找出正弦波問題。
任何想法都會有所幫助,謝謝!
struct win32_audio_buffer
{
real32 Memory[44100 * 1]; // samples per buffer (44100) * channels 1
int BytesPerBuffer;
XAUDIO2_BUFFER XBuffer;
IXAudio2 *XEngine;
IXAudio2SourceVoice *SourceVoice;
WAVEFORMATEX WaveFormat;
};
// NOTE XAUDIO2
internal HRESULT
Win32XAudioInit(win32_audio_buffer *AudioBuffer)
{
// Initialize a COM:
HRESULT HRes;
HRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(HRes)) { return(HRes); }
// Init XAUDIO Engine
AudioBuffer->XEngine = {};
if (FAILED(HRes = XAudio2Create(&AudioBuffer->XEngine, 0, XAUDIO2_DEFAULT_PROCESSOR)))
{ return HRes; }
// MASTER VOICE
IXAudio2MasteringVoice* XAudioMasterVoice = nullptr;
if (FAILED(HRes = AudioBuffer->XEngine->CreateMasteringVoice(&XAudioMasterVoice)))
{ return HRes; }
AudioBuffer->WaveFormat = {};
//int32 SamplesPerBuffer = 4410;
int SampleHz = 44100;
WORD Channels = 1;
WORD BitsPerChannel = 32; // 4 byte samples
int32 BufferSize = Channels * BitsPerChannel * SampleHz;
AudioBuffer->BytesPerBuffer = SampleHz * Channels;
AudioBuffer->WaveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; // or could use WAVE_FORMAT_PCM WAVE_FORMAT_IEEE_FLOAT
AudioBuffer->WaveFormat.nChannels = Channels;
AudioBuffer->WaveFormat.nSamplesPerSec = SampleHz;
AudioBuffer->WaveFormat.wBitsPerSample = BitsPerChannel; // 32
AudioBuffer->WaveFormat.nBlockAlign = (Channels * BitsPerChannel) / 8;
AudioBuffer->WaveFormat.nAvgBytesPerSec = SampleHz * Channels * BitsPerChannel / 8;
AudioBuffer->WaveFormat.cbSize = 0; // set to zero for PCM or IEEE float
AudioBuffer->XBuffer.Flags = 0;
AudioBuffer->XBuffer.AudioBytes = SampleHz * Channels * BitsPerChannel / 8;
AudioBuffer->XBuffer.PlayBegin = 0;
AudioBuffer->XBuffer.PlayLength = 0;
AudioBuffer->XBuffer.LoopBegin = 0;
AudioBuffer->XBuffer.LoopLength = 0;
AudioBuffer->XBuffer.LoopCount = XAUDIO2_LOOP_INFINITE;
AudioBuffer->XBuffer.pContext = NULL;
AudioBuffer->XBuffer.pAudioData = (BYTE *)&AudioBuffer->Memory;
if(FAILED(HRes = AudioBuffer->XEngine->CreateSourceVoice(&AudioBuffer->SourceVoice, (WAVEFORMATEX*)&AudioBuffer->WaveFormat)))
{ return HRes; }
if(FAILED(HRes = AudioBuffer->SourceVoice->Start(0)))
{ return HRes; }
if(FAILED(HRes = AudioBuffer->SourceVoice->SubmitSourceBuffer(&AudioBuffer->XBuffer)))
{ return HRes; }
return(S_OK);
}
internal HRESULT
Win32PlayTone(win32_audio_buffer *Buffer, int32 Hz)
{
real32 PI2 = (real32)6.28318; //530718;
for(int i = 0;
i < Buffer->BytesPerBuffer;
i++)
{
real32 CurrentSample = sinf(i * PI2 / 44100 * Hz);
Buffer->Memory[i] = CurrentSample;
}
return(S_OK);
}
XAudio2 是完全異步的,因此在播放數據包完成之前,您不應更改播放數據包指向的 memory,否則您將獲得您所描述的點擊。
此外,當當前數據包完成時,如果您希望聲音連續,您希望另一個已經排隊。
請參閱以下資源以了解如何對 XAudio2 進行編程:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.