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

164 lines
4.4 KiB
C++
Raw Normal View History

#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;
/*<2A><>Ƶ<EFBFBD>豸ö<E8B1B8><C3B6>*/
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;
}
/*<2A><><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>Ƶ<EFBFBD>豸*/
//ͬʱ<CDAC><CAB1><EFBFBD>ø<EFBFBD><C3B8><EFBFBD>Ļص<C4BB>
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)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFB4A6><EFBFBD><EFBFBD>Ƶ<EFBFBD>¼<EFBFBD>
if (uMsg == WOM_DONE) {
PrepareBackData();
SwapBuffer();
PlayFrontData();
}
}
void CALLBACK AudioEngine::StaticAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
// ͨ<><CDA8> dwInstance <20>ָ<EFBFBD><D6B8><EFBFBD>ʵ<EFBFBD>ʵ<EFBFBD> AudioEngine ʵ<><CAB5>
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;
}