Files
XCEngine/MVS/Music fluctuations/source/audio/AudioEngine.cpp

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;
}