164 lines
4.4 KiB
C++
164 lines
4.4 KiB
C++
#include"AudioEngine.h"
|
|
|
|
|
|
AudioEngine::AudioEngine()
|
|
{
|
|
|
|
}
|
|
|
|
AudioEngine::~AudioEngine()
|
|
{
|
|
ExitAudioEngine();
|
|
delete[] m_audioBuffer1;
|
|
delete[] m_audioBuffer2;
|
|
}
|
|
|
|
void AudioEngine::InitAudioEngine()
|
|
{
|
|
InitWavFormat();
|
|
InitDevice();
|
|
InitWavHeader();
|
|
InitAudioThread();
|
|
}
|
|
|
|
void AudioEngine::ExitAudioEngine()
|
|
{
|
|
m_isRunning = false;
|
|
m_audioThread.join();
|
|
waveOutUnprepareHeader(m_hWaveOut, &m_waveHeader1, sizeof(WAVEHDR));
|
|
waveOutUnprepareHeader(m_hWaveOut, &m_waveHeader2, sizeof(WAVEHDR));
|
|
waveOutClose(m_hWaveOut);
|
|
}
|
|
|
|
void AudioEngine::SubmitSource(AudioSource* p_audioSource)
|
|
{
|
|
if (p_audioSource)
|
|
{
|
|
m_audioSource = p_audioSource;
|
|
}
|
|
}
|
|
|
|
void AudioEngine::Update(double p_deltaTime)
|
|
{
|
|
|
|
}
|
|
|
|
MMRESULT AudioEngine::PlayFrontData()
|
|
{
|
|
WAVEHDR* m_frontHeader = m_isBuffer1Front ? &m_waveHeader1 : &m_waveHeader2;
|
|
MMRESULT result = waveOutWrite(m_hWaveOut, m_frontHeader, sizeof(WAVEHDR));
|
|
if (result != MMSYSERR_NOERROR)
|
|
{
|
|
std::cout << "Failed to write audio data1" << std::endl;
|
|
return result;
|
|
}
|
|
return MMSYSERR_NOERROR;
|
|
}
|
|
|
|
void AudioEngine::PrepareBackData()
|
|
{
|
|
if (!m_audioSource || !m_audioSource->IsActive()) { return; }
|
|
m_audioSource->PrepareBufferData();
|
|
short* backBuffer = (m_isBuffer1Front ? m_audioBuffer2 : m_audioBuffer1);
|
|
memcpy(backBuffer, m_audioSource->GetBufferData(), sizeof(m_audioBuffer1));
|
|
}
|
|
|
|
void AudioEngine::SwapBuffer()
|
|
{
|
|
m_isBuffer1Front = !m_isBuffer1Front;
|
|
}
|
|
|
|
MMRESULT AudioEngine::InitAudioThread()
|
|
{
|
|
MMRESULT result = MMSYSERR_NOERROR;
|
|
m_isRunning = true;
|
|
m_audioThread = std::thread([&]() {
|
|
PlayFrontData();
|
|
SwapBuffer();
|
|
PlayFrontData();
|
|
});
|
|
|
|
if (!m_audioThread.joinable()) {
|
|
std::cout << "Failed to create audio thread" << std::endl;
|
|
result = MMSYSERR_ERROR;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void AudioEngine::InitWavFormat()
|
|
{
|
|
m_waveFormat.wFormatTag = WAVE_FORMAT_PCM;
|
|
m_waveFormat.nChannels = 2;
|
|
m_waveFormat.nSamplesPerSec = 44100;
|
|
m_waveFormat.nAvgBytesPerSec = 176400;
|
|
m_waveFormat.nBlockAlign = 4;
|
|
m_waveFormat.wBitsPerSample = 16;
|
|
m_waveFormat.cbSize = 0;
|
|
}
|
|
|
|
MMRESULT AudioEngine::InitDevice()
|
|
{
|
|
MMRESULT result;
|
|
/*音频设备枚举*/
|
|
WAVEOUTCAPS waveOutCaps;
|
|
for (UINT i = 0; i < waveOutGetNumDevs(); ++i)
|
|
{
|
|
waveOutGetDevCaps(i, &waveOutCaps, sizeof(WAVEOUTCAPS));
|
|
m_waveOutCaps.push_back(waveOutCaps);
|
|
std::cout << "Device #" << i << ": " << waveOutCaps.szPname << std::endl;
|
|
}
|
|
/*打开默认音频设备*/
|
|
//同时设置该设备的回调
|
|
result = waveOutOpen(&m_hWaveOut, WAVE_MAPPER, &m_waveFormat, (DWORD_PTR)&AudioEngine::StaticAudioCallback, reinterpret_cast<DWORD_PTR>(this), CALLBACK_FUNCTION);
|
|
if (result != MMSYSERR_NOERROR)
|
|
{
|
|
std::cout << "Failed to open audio device" << std::endl;
|
|
return result;
|
|
}
|
|
return MMSYSERR_NOERROR;
|
|
}
|
|
|
|
void AudioEngine::OnAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
|
{
|
|
// 在这里处理音频事件
|
|
if (uMsg == WOM_DONE) {
|
|
PrepareBackData();
|
|
SwapBuffer();
|
|
PlayFrontData();
|
|
}
|
|
}
|
|
|
|
void CALLBACK AudioEngine::StaticAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
|
{
|
|
// 通过 dwInstance 恢复到实际的 AudioEngine 实例
|
|
AudioEngine* audioEngine = reinterpret_cast<AudioEngine*>(dwInstance);
|
|
if (audioEngine != nullptr) {
|
|
audioEngine->OnAudioCallback(hwo, uMsg, dwInstance, dwParam1, dwParam2);
|
|
}
|
|
}
|
|
|
|
MMRESULT AudioEngine::InitWavHeader()
|
|
{
|
|
MMRESULT result;
|
|
/*header1-initialize*/
|
|
m_waveHeader1.lpData = (LPSTR)m_audioBuffer1;
|
|
m_waveHeader1.dwBufferLength = sizeof(m_audioBuffer1);
|
|
m_waveHeader1.dwFlags = 0;
|
|
result = waveOutPrepareHeader(m_hWaveOut, &m_waveHeader1, sizeof(WAVEHDR));
|
|
if (result != MMSYSERR_NOERROR)
|
|
{
|
|
std::cout << "Failed to prepare audio header1" << std::endl;
|
|
return result;
|
|
}
|
|
/*header2-initialize*/
|
|
m_waveHeader2.lpData = (LPSTR)m_audioBuffer2;
|
|
m_waveHeader2.dwBufferLength = sizeof(m_audioBuffer2);
|
|
m_waveHeader2.dwFlags = 0;
|
|
result = waveOutPrepareHeader(m_hWaveOut, &m_waveHeader2, sizeof(WAVEHDR));
|
|
if (result != MMSYSERR_NOERROR)
|
|
{
|
|
std::cout << "Failed to prepare audio header2" << std::endl;
|
|
return result;
|
|
}
|
|
return MMSYSERR_NOERROR;
|
|
} |