/** * @file soundmng.cpp * @brief サウンド マネージャ クラスの動作の定義を行います */ #include "compiler.h" #include "soundmng.h" #include "np2.h" #if defined(SUPPORT_ROMEO) #include "ext\externalchipmanager.h" #endif #if defined(MT32SOUND_DLL) #include "ext\mt32snd.h" #endif #if defined(SUPPORT_ASIO) #include "soundmng\sdasio.h" #endif // defined(SUPPORT_ASIO) #include "soundmng\sddsound3.h" #if defined(SUPPORT_WASAPI) #include "soundmng\sdwasapi.h" #endif // defined(SUPPORT_WASAPI) #include "common\parts.h" #include "sound\sound.h" #if defined(VERMOUTH_LIB) #include "sound\vermouth\vermouth.h" #endif #if !defined(_WIN64) #ifdef __cplusplus extern "C" { #endif /** * satuation * @param[out] dst 出力バッファ * @param[in] src 入力バッファ * @param[in] size サイズ */ void __fastcall satuation_s16mmx(SINT16 *dst, const SINT32 *src, UINT size); #ifdef __cplusplus } #endif #endif #if defined(VERMOUTH_LIB) MIDIMOD vermouth_module = NULL; #endif //! 唯一のインスタンスです CSoundMng CSoundMng::sm_instance; /** * 初期化 */ void CSoundMng::Initialize() { #if defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) ::CoInitializeEx(NULL, COINIT_MULTITHREADED); #endif // defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) CSoundDeviceDSound3::Initialize(); #if defined(SUPPORT_WASAPI) CSoundDeviceWasapi::Initialize(); #endif // defined(SUPPORT_WASAPI) #if defined(SUPPORT_ASIO) CSoundDeviceAsio::Initialize(); #endif // defined(SUPPORT_ASIO) #if defined(SUPPORT_ROMEO) CExternalChipManager::GetInstance()->Initialize(); #endif // defined(SUPPORT_ROMEO) } /** * 解放 */ void CSoundMng::Deinitialize() { #if defined(SUPPORT_ROMEO) CExternalChipManager::GetInstance()->Deinitialize(); #endif // defined(SUPPORT_ROMEO) #if defined(SUPPORT_WASAPI) CSoundDeviceWasapi::Deinitialize(); #endif // defined(SUPPORT_WASAPI) #if defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) ::CoUninitialize(); #endif // defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) } /** * コンストラクタ */ CSoundMng::CSoundMng() : m_pSoundDevice(NULL) , m_nMute(0) { SetReverse(false); } /** * オープン * @param[in] nType デバイス タイプ * @param[in] lpName デバイス名 * @param[in] hWnd ウィンドウ ハンドル * @retval true 成功 * @retval false 失敗 */ bool CSoundMng::Open(DeviceType nType, LPCTSTR lpName, HWND hWnd) { Close(); CSoundDeviceBase* pSoundDevice = NULL; switch (nType) { case kDefault: pSoundDevice = new CSoundDeviceDSound3; lpName = NULL; break; case kDSound3: pSoundDevice = new CSoundDeviceDSound3; break; #if defined(SUPPORT_WASAPI) case kWasapi: pSoundDevice = new CSoundDeviceWasapi; break; #endif // defined(SUPPORT_WASAPI) #if defined(SUPPORT_ASIO) case kAsio: pSoundDevice = new CSoundDeviceAsio; break; #endif // defined(SUPPORT_ASIO) } if (pSoundDevice) { if (!pSoundDevice->Open(lpName, hWnd)) { delete pSoundDevice; pSoundDevice = NULL; } } if (pSoundDevice == NULL) { return false; } m_pSoundDevice = pSoundDevice; #if defined(MT32SOUND_DLL) MT32Sound::GetInstance()->Initialize(); #endif return true; } /** * クローズ */ void CSoundMng::Close() { if (m_pSoundDevice) { m_pSoundDevice->Close(); delete m_pSoundDevice; m_pSoundDevice = NULL; } #if defined(MT32SOUND_DLL) MT32Sound::GetInstance()->Deinitialize(); #endif } /** * サウンド有効 * @param[in] nProc プロシージャ */ void CSoundMng::Enable(SoundProc nProc) { const UINT nBit = 1 << nProc; if (!(m_nMute & nBit)) { return; } m_nMute &= ~nBit; if (!m_nMute) { if (m_pSoundDevice) { m_pSoundDevice->PlayStream(); } #if defined(SUPPORT_ROMEO) CExternalChipManager::GetInstance()->Mute(false); #endif // defined(SUPPORT_ROMEO) } } /** * サウンド無効 * @param[in] nProc プロシージャ */ void CSoundMng::Disable(SoundProc nProc) { if (!m_nMute) { if (m_pSoundDevice) { m_pSoundDevice->StopStream(); m_pSoundDevice->StopAllPCM(); } #if defined(SUPPORT_ROMEO) CExternalChipManager::GetInstance()->Mute(true); #endif // defined(SUPPORT_ROMEO) } m_nMute |= (1 << nProc); } /** * ストリームを作成 * @param[in] nSamplingRate サンプリング レート * @param[in] ms バッファ長(ミリ秒) * @return バッファ数 */ UINT CSoundMng::CreateStream(UINT nSamplingRate, UINT ms) { if (m_pSoundDevice == NULL) { return 0; } if (ms < 40) { ms = 40; } else if (ms > 1000) { ms = 1000; } UINT nBuffer = (nSamplingRate * ms) / 2000; nBuffer = (nBuffer + 1) & (~1); nBuffer = m_pSoundDevice->CreateStream(nSamplingRate, 2, nBuffer); if (nBuffer == 0) { return 0; } m_pSoundDevice->SetStreamData(this); #if defined(VERMOUTH_LIB) vermouth_module = midimod_create(nSamplingRate); midimod_loadall(vermouth_module); #endif #if defined(MT32SOUND_DLL) MT32Sound::GetInstance()->SetRate(nSamplingRate); #endif return nBuffer; } /** * ストリームを破棄 */ inline void CSoundMng::DestroyStream() { if (m_pSoundDevice) { m_pSoundDevice->DestroyStream(); } #if defined(VERMOUTH_LIB) midimod_destroy(vermouth_module); vermouth_module = NULL; #endif #if defined(MT32SOUND_DLL) MT32Sound::GetInstance()->SetRate(0); #endif } /** * ストリームのリセット */ inline void CSoundMng::ResetStream() { if (m_pSoundDevice) { m_pSoundDevice->ResetStream(); } } /** * ストリームの再生 */ inline void CSoundMng::PlayStream() { if (!m_nMute) { if (m_pSoundDevice) { m_pSoundDevice->PlayStream(); } } } /** * ストリームの停止 */ inline void CSoundMng::StopStream() { if (!m_nMute) { if (m_pSoundDevice) { m_pSoundDevice->StopStream(); } } } /** * ストリームを得る * @param[out] lpBuffer バッファ * @param[in] nBufferCount バッファ カウント * @return サンプル数 */ UINT CSoundMng::Get16(SINT16* lpBuffer, UINT nBufferCount) { const SINT32* lpSource = ::sound_pcmlock(); if (lpSource) { (*m_fnMix)(lpBuffer, lpSource, nBufferCount * 4); ::sound_pcmunlock(lpSource); return nBufferCount; } else { return 0; } } /** * パン反転を設定する * @param[in] bReverse 反転フラグ */ inline void CSoundMng::SetReverse(bool bReverse) { if (!bReverse) { #if !defined(_WIN64) if (mmxflag) { m_fnMix = satuation_s16; } else { m_fnMix = satuation_s16mmx; } #else m_fnMix = satuation_s16; #endif } else { m_fnMix = satuation_s16x; } } /** * PCM データ読み込み * @param[in] nNum PCM 番号 * @param[in] lpFilename ファイル名 */ void CSoundMng::LoadPCM(SoundPCMNumber nNum, LPCTSTR lpFilename) { if (m_pSoundDevice) { m_pSoundDevice->LoadPCM(nNum, lpFilename); } } /** * PCM ヴォリューム設定 * @param[in] nNum PCM 番号 * @param[in] nVolume ヴォリューム */ void CSoundMng::SetPCMVolume(SoundPCMNumber nNum, int nVolume) { if (m_pSoundDevice) { m_pSoundDevice->SetPCMVolume(nNum, nVolume); } } /** * PCM 再生 * @param[in] nNum PCM 番号 * @param[in] bLoop ループ フラグ * @retval true 成功 * @retval false 失敗 */ inline bool CSoundMng::PlayPCM(SoundPCMNumber nNum, BOOL bLoop) { if (!m_nMute) { if (m_pSoundDevice) { return m_pSoundDevice->PlayPCM(nNum, bLoop); } } return false; } /** * PCM 停止 * @param[in] nNum PCM 番号 */ inline void CSoundMng::StopPCM(SoundPCMNumber nNum) { if (m_pSoundDevice) { m_pSoundDevice->StopPCM(nNum); } } // ---- C ラッパー /** * ストリーム作成 * @param[in] rate サンプリング レート * @param[in] ms バッファ長(ミリ秒) * @return バッファ サイズ */ UINT soundmng_create(UINT rate, UINT ms) { return CSoundMng::GetInstance()->CreateStream(rate, ms); } /** * ストリーム破棄 */ void soundmng_destroy(void) { CSoundMng::GetInstance()->DestroyStream(); } /** * ストリーム リセット */ void soundmng_reset(void) { CSoundMng::GetInstance()->ResetStream(); } /** * ストリーム開始 */ void soundmng_play(void) { CSoundMng::GetInstance()->PlayStream(); } /** * ストリーム停止 */ void soundmng_stop(void) { CSoundMng::GetInstance()->StopStream(); } /** * ストリーム パン反転設定 * @param[in] bReverse 反転 */ void soundmng_setreverse(BOOL bReverse) { CSoundMng::GetInstance()->SetReverse((bReverse) ? true : false); } /** * PCM 再生 * @param[in] nNum PCM 番号 * @param[in] bLoop ループ * @retval SUCCESS 成功 * @retval FAILURE 失敗 */ BRESULT soundmng_pcmplay(enum SoundPCMNumber nNum, BOOL bLoop) { return (CSoundMng::GetInstance()->PlayPCM(nNum, bLoop)) ? SUCCESS : FAILURE; } /** * PCM 停止 * @param[in] nNum PCM 番号 */ void soundmng_pcmstop(enum SoundPCMNumber nNum) { CSoundMng::GetInstance()->StopPCM(nNum); }