diff --git a/GpApp/Music.cpp b/GpApp/Music.cpp index f95848f..a5765bc 100644 --- a/GpApp/Music.cpp +++ b/GpApp/Music.cpp @@ -14,6 +14,7 @@ #include "SoundSync.h" #include "HostMutex.h" #include "HostSystemServices.h" +#include "MemoryManager.h" #define kBaseBufferMusicID 2000 @@ -22,15 +23,14 @@ #define kLastGamePiece 6 -void MusicCallBack (SndChannelPtr, SndCommand *); +void MusicCallBack (PortabilityLayer::AudioChannel *channel); PLError_t LoadMusicSounds (void); PLError_t DumpMusicSounds (void); PLError_t OpenMusicChannel (void); PLError_t CloseMusicChannel (void); -SndCallBackUPP musicCallBackUPP; -SndChannelPtr musicChannel; +PortabilityLayer::AudioChannel *musicChannel; Ptr theMusicData[kMaxMusic]; short musicScore[kLastMusicPiece]; short gameScore[kLastGamePiece]; @@ -56,7 +56,6 @@ extern Boolean isSoundOn; PLError_t StartMusic (void) { - SndCommand theCommand; PLError_t theErr; short soundVolume; @@ -72,37 +71,16 @@ PLError_t StartMusic (void) if ((soundVolume != 0) && (!failedMusic)) { - theCommand.cmd = bufferCmd; - theCommand.param1 = 0; - theCommand.param2 = (intptr_t)(theMusicData[musicState.musicSoundID]); - theErr = SndDoCommand(musicChannel, &theCommand, false); - if (theErr != PLErrors::kNone) - return (theErr); - - // GP: No idea what "1964" means - theCommand.cmd = nullCmd; - theCommand.param1 = 1964; - theCommand.param2 = 0; - theErr = SndDoCommand(musicChannel, &theCommand, false); - if (theErr != PLErrors::kNone) - return (theErr); - + musicChannel->AddBuffer(theMusicData[musicState.musicSoundID], true); + + // Don't need to lock here because the callback should not trigger until queued musicState.musicCursor++; if (musicState.musicCursor >= kLastMusicPiece) musicState.musicCursor = 0; musicState.musicSoundID = musicScore[musicState.musicCursor]; - - theCommand.cmd = bufferCmd; - theCommand.param1 = 0; - theCommand.param2 = (intptr_t)(theMusicData[musicState.musicSoundID]); - theErr = SndDoCommand(musicChannel, &theCommand, false); - if (theErr != PLErrors::kNone) - return (theErr); - - theCommand.cmd = callBackCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoCommand(musicChannel, &theCommand, false); + + musicChannel->AddBuffer(theMusicData[musicState.musicSoundID], true); + musicChannel->AddCallback(MusicCallBack, true); isMusicOn = true; } @@ -114,7 +92,6 @@ PLError_t StartMusic (void) void StopTheMusic (void) { - SndCommand theCommand; PLError_t theErr; if (dontLoadMusic) @@ -123,15 +100,8 @@ void StopTheMusic (void) theErr = PLErrors::kNone; if ((isMusicOn) && (!failedMusic)) { - theCommand.cmd = flushCmd; - theCommand.param1 = 0; - theCommand.param2 = 0L; - theErr = SndDoImmediate(musicChannel, &theCommand); - - theCommand.cmd = quietCmd; - theCommand.param1 = 0; - theCommand.param2 = 0L; - theErr = SndDoImmediate(musicChannel, &theCommand); + musicChannel->ClearAllCommands(); + musicChannel->Stop(); isMusicOn = false; } @@ -186,12 +156,9 @@ void SetMusicalMode (short newMode) //-------------------------------------------------------------- MusicCallBack -void MusicCallBack (SndChannelPtr theChannel, SndCommand *theCommand) +void MusicCallBack (PortabilityLayer::AudioChannel *theChannel) { PLError_t theErr; - -// gameA5 = theCommand.param2; -// thisA5 = SetA5(gameA5); musicMutex->Lock(); switch (musicState.musicMode) @@ -222,16 +189,9 @@ void MusicCallBack (SndChannelPtr theChannel, SndCommand *theCommand) short musicSoundID = musicState.musicSoundID; musicMutex->Unlock(); - - theCommand->cmd = bufferCmd; - theCommand->param1 = 0; - theCommand->param2 = (intptr_t)(theMusicData[musicSoundID]); - theErr = SndDoCommand(musicChannel, theCommand, false); - - theCommand->cmd = callBackCmd; - theCommand->param1 = 0; - theCommand->param2 = 0; - theErr = SndDoCommand(musicChannel, theCommand, false); + + theChannel->AddBuffer(theMusicData[musicSoundID], true); + theChannel->AddCallback(MusicCallBack, true); } //-------------------------------------------------------------- LoadMusicSounds @@ -256,7 +216,7 @@ PLError_t LoadMusicSounds (void) soundDataSize = GetHandleSize(theSound) - 20L; - theMusicData[i] = NewPtr(soundDataSize); + theMusicData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); if (theMusicData[i] == nil) return PLErrors::kOutOfMemory; @@ -278,7 +238,7 @@ PLError_t DumpMusicSounds (void) for (i = 0; i < kMaxMusic; i++) { if (theMusicData[i] != nil) - DisposePtr(theMusicData[i]); + PortabilityLayer::MemoryManager::GetInstance()->Release(theMusicData[i]); theMusicData[i] = nil; } @@ -291,18 +251,16 @@ PLError_t OpenMusicChannel (void) { PLError_t theErr; - musicCallBackUPP = NewSndCallBackProc(MusicCallBack); - theErr = PLErrors::kNone; if (musicChannel != nil) return (theErr); - musicChannel = nil; - theErr = SndNewChannel(&musicChannel, - sampledSynth, initNoInterp + initMono, - (SndCallBackUPP)musicCallBackUPP); - + musicChannel = PortabilityLayer::SoundSystem::GetInstance()->CreateChannel(); + + if (musicChannel == nil) + theErr = PLErrors::kAudioError; + return (theErr); } @@ -315,11 +273,9 @@ PLError_t CloseMusicChannel (void) theErr = PLErrors::kNone; if (musicChannel != nil) - theErr = SndDisposeChannel(musicChannel, true); + musicChannel->Destroy(false); musicChannel = nil; - DisposeSndCallBackUPP(musicCallBackUPP); - return (theErr); } diff --git a/GpApp/Sound.cpp b/GpApp/Sound.cpp index e1108e1..fa98644 100644 --- a/GpApp/Sound.cpp +++ b/GpApp/Sound.cpp @@ -9,6 +9,7 @@ #include "PLResources.h" #include "PLSound.h" #include "Externs.h" +#include "MemoryManager.h" #include "SoundSync.h" #include "VirtualDirectory.h" @@ -17,17 +18,16 @@ #define kMaxSounds 64 -void CallBack0 (SndChannelPtr, SndCommand *); -void CallBack1 (SndChannelPtr, SndCommand *); -void CallBack2 (SndChannelPtr, SndCommand *); +void CallBack0 (PortabilityLayer::AudioChannel *); +void CallBack1 (PortabilityLayer::AudioChannel *); +void CallBack2 (PortabilityLayer::AudioChannel *); PLError_t LoadBufferSounds (void); void DumpBufferSounds (void); PLError_t OpenSoundChannels (void); -PLError_t CloseSoundChannels (void); +void CloseSoundChannels (void); -SndCallBackUPP callBack0UPP, callBack1UPP, callBack2UPP; -SndChannelPtr channel0, channel1, channel2; +PortabilityLayer::AudioChannel *channel0, *channel1, *channel2; Ptr theSoundData[kMaxSounds]; short numSoundsLoaded; Boolean soundLoaded[kMaxSounds], dontLoadSounds; @@ -76,131 +76,97 @@ void PlayPrioritySound (short which, short priority) void FlushAnyTriggerPlaying (void) { - SndCommand theCommand; - PLError_t theErr; - SoundSyncState ss = SoundSync_ReadAll(); if (ss.priority0 == kTriggerPriority) { - theCommand.cmd = quietCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel0, &theCommand); - theCommand.cmd = flushCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel0, &theCommand); + channel0->ClearAllCommands(); + channel0->Stop(); } if (ss.priority1 == kTriggerPriority) { - theCommand.cmd = quietCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel1, &theCommand); - theCommand.cmd = flushCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel1, &theCommand); + channel1->ClearAllCommands(); + channel1->Stop(); } if (ss.priority2 == kTriggerPriority) { - theCommand.cmd = quietCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel2, &theCommand); - theCommand.cmd = flushCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel2, &theCommand); - } -} - -//-------------------------------------------------------------- PlaySound0 - -void PlayExclusiveSoundChannel(short channelIndex, short soundID, short oldPriority, short newPriority) -{ - SndCommand theCommand; - PLError_t theErr; - - if (failedSound || dontLoadSounds) - return; - - SndChannelPtr channel = nil; - switch (channelIndex) - { - case 0: - channel = channel0; - break; - case 1: - channel = channel2; - break; - case 2: - channel = channel2; - break; - default: - return; - } - - theErr = PLErrors::kNone; - if (isSoundOn) - { - if (oldPriority != 0) - { - // Flush the queue and stop the channel, which will remove the pending callback - theCommand.cmd = flushCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel, &theCommand); - - theCommand.cmd = quietCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoImmediate(channel, &theCommand); - - SoundSync_ClearPriority(channelIndex); - } - - SoundSync_PutPriority(channelIndex, newPriority); - - theCommand.cmd = bufferCmd; - theCommand.param1 = 0; - theCommand.param2 = (intptr_t)(theSoundData[soundID]); - theErr = SndDoCommand(channel, &theCommand, true); - - theCommand.cmd = callBackCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoCommand(channel, &theCommand, true); - - if (theErr != PLErrors::kNone) - SoundSync_ClearPriority(channelIndex); + channel2->ClearAllCommands(); + channel2->Stop(); } } //-------------------------------------------------------------- CallBack0 -void CallBack0 (SndChannelPtr theChannel, SndCommand *theCommand) +void CallBack0(PortabilityLayer::AudioChannel *theChannel) { SoundSync_ClearPriority(0); } //-------------------------------------------------------------- CallBack1 -void CallBack1 (SndChannelPtr theChannel, SndCommand *theCommand) +void CallBack1(PortabilityLayer::AudioChannel *theChannel) { SoundSync_ClearPriority(1); } //-------------------------------------------------------------- CallBack2 -void CallBack2 (SndChannelPtr theChannel, SndCommand *theCommand) +void CallBack2(PortabilityLayer::AudioChannel *theChannel) { SoundSync_ClearPriority(2); } +//-------------------------------------------------------------- PlaySound0 + +void PlayExclusiveSoundChannel(short channelIndex, short soundID, short oldPriority, short newPriority) +{ + if (failedSound || dontLoadSounds) + return; + + PortabilityLayer::AudioChannel *channel = nil; + PortabilityLayer::AudioChannelCallback_t callback = nil; + + switch (channelIndex) + { + case 0: + channel = channel0; + callback = CallBack0; + break; + case 1: + channel = channel1; + callback = CallBack1; + break; + case 2: + channel = channel2; + callback = CallBack2; + break; + default: + return; + } + + if (isSoundOn) + { + if (oldPriority != 0) + { + // Flush the queue and stop the channel, which will remove the pending callback + channel->ClearAllCommands(); + channel->Stop(); + + SoundSync_ClearPriority(channelIndex); + } + + SoundSync_PutPriority(channelIndex, newPriority); + + bool succeeded = channel->AddBuffer(theSoundData[soundID], false); + succeeded &= channel->AddCallback(callback, false); + + if (!succeeded) + SoundSync_ClearPriority(channelIndex); + } +} + //-------------------------------------------------------------- LoadTriggerSound PLError_t LoadTriggerSound (short soundID) @@ -225,7 +191,7 @@ PLError_t LoadTriggerSound (short soundID) else { soundDataSize = GetHandleSize(theSound) - 20L; - theSoundData[kMaxSounds - 1] = NewPtr(soundDataSize); + theSoundData[kMaxSounds - 1] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); if (theSoundData[kMaxSounds - 1] == nil) { theSound.Dispose(); @@ -247,7 +213,7 @@ PLError_t LoadTriggerSound (short soundID) void DumpTriggerSound (void) { if (theSoundData[kMaxSounds - 1] != nil) - DisposePtr(theSoundData[kMaxSounds - 1]); + PortabilityLayer::MemoryManager::GetInstance()->Release(theSoundData[kMaxSounds - 1]); theSoundData[kMaxSounds - 1] = nil; } @@ -270,7 +236,7 @@ PLError_t LoadBufferSounds (void) soundDataSize = GetHandleSize(theSound) - 20L; - theSoundData[i] = NewPtr(soundDataSize); + theSoundData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); if (theSoundData[i] == nil) return (PLErrors::kOutOfMemory); @@ -292,7 +258,7 @@ void DumpBufferSounds (void) for (i = 0; i < kMaxSounds; i++) { if (theSoundData[i] != nil) - DisposePtr(theSoundData[i]); + PortabilityLayer::MemoryManager::GetInstance()->Release(theSoundData[i]); theSoundData[i] = nil; } } @@ -301,73 +267,50 @@ void DumpBufferSounds (void) PLError_t OpenSoundChannels (void) { - PLError_t theErr; - - callBack0UPP = NewSndCallBackProc(CallBack0); - callBack1UPP = NewSndCallBackProc(CallBack1); - callBack2UPP = NewSndCallBackProc(CallBack2); - - theErr = PLErrors::kNone; - if (channelOpen) - return (theErr); + return PLErrors::kAudioError; - theErr = SndNewChannel(&channel0, - sampledSynth, initNoInterp + initMono, - (SndCallBackUPP)callBack0UPP); - if (theErr == PLErrors::kNone) + channel0 = PortabilityLayer::SoundSystem::GetInstance()->CreateChannel(); + if (channel0) channelOpen = true; else - return (theErr); - - theErr = SndNewChannel(&channel1, - sampledSynth, initNoInterp + initMono, - (SndCallBackUPP)callBack1UPP); - if (theErr == PLErrors::kNone) + return PLErrors::kAudioError; + + channel1 = PortabilityLayer::SoundSystem::GetInstance()->CreateChannel(); + if (channel1) channelOpen = true; else - return (theErr); - - theErr = SndNewChannel(&channel2, - sampledSynth, initNoInterp + initMono, - (SndCallBackUPP)callBack2UPP); - if (theErr == PLErrors::kNone) + return PLErrors::kAudioError; + + channel2 = PortabilityLayer::SoundSystem::GetInstance()->CreateChannel(); + if (channel2) channelOpen = true; + else + return PLErrors::kAudioError; - return (theErr); + return PLErrors::kNone; } //-------------------------------------------------------------- CloseSoundChannels -PLError_t CloseSoundChannels (void) +void CloseSoundChannels (void) { - PLError_t theErr; - - theErr = PLErrors::kNone; - if (!channelOpen) - return (theErr); + return; if (channel0 != nil) - theErr = SndDisposeChannel(channel0, true); + channel0->Destroy(false); channel0 = nil; if (channel1 != nil) - theErr = SndDisposeChannel(channel1, true); + channel1->Destroy(false); channel1 = nil; if (channel2 != nil) - theErr = SndDisposeChannel(channel2, true); + channel2->Destroy(false); channel2 = nil; - - if (theErr == PLErrors::kNone) - channelOpen = false; - - DisposeSndCallBackUPP(callBack0UPP); - DisposeSndCallBackUPP(callBack1UPP); - DisposeSndCallBackUPP(callBack2UPP); - - return (theErr); + + channelOpen = false; } //-------------------------------------------------------------- InitSound @@ -411,13 +354,11 @@ void InitSound (void) void KillSound (void) { - PLError_t theErr; - if (dontLoadSounds) return; DumpBufferSounds(); - theErr = CloseSoundChannels(); + CloseSoundChannels(); } //-------------------------------------------------------------- SoundBytesNeeded diff --git a/GpApp/Utilities.cpp b/GpApp/Utilities.cpp index 0c5dddc..fabb484 100644 --- a/GpApp/Utilities.cpp +++ b/GpApp/Utilities.cpp @@ -511,8 +511,8 @@ void UnivGetSoundVolume (short *volume, Boolean hasSM3) // if (hasSM3) // { - theErr = GetDefaultOutputVolume(&longVol); - *volume = LoWord(longVol) / 0x0024; + longVol = PortabilityLayer::SoundSystem::GetInstance()->GetVolume(); + *volume = longVol / 0x0024; // } // else // GetSoundVol(volume); @@ -530,7 +530,6 @@ void UnivGetSoundVolume (short *volume, Boolean hasSM3) void UnivSetSoundVolume (short volume, Boolean hasSM3) { long longVol; - PLError_t theErr; if (volume > 7) volume = 7; @@ -542,8 +541,8 @@ void UnivSetSoundVolume (short volume, Boolean hasSM3) longVol = (long)volume * 0x0025; if (longVol > 0x00000100) longVol = 0x00000100; - longVol = longVol + (longVol << 16); - theErr = SetDefaultOutputVolume(longVol); + + PortabilityLayer::SoundSystem::GetInstance()->SetVolume(longVol); // } // else // SetSoundVol(volume); diff --git a/PortabilityLayer/PLSound.cpp b/PortabilityLayer/PLSound.cpp index 7f62a6a..ea4bda0 100644 --- a/PortabilityLayer/PLSound.cpp +++ b/PortabilityLayer/PLSound.cpp @@ -12,25 +12,53 @@ namespace PortabilityLayer { - class AudioChannelImpl : public SndChannel, public ClientAudioChannelContext + namespace AudioCommandTypes + { + enum AudioCommandType + { + kBuffer, + kCallback, + }; + } + + typedef AudioCommandTypes::AudioCommandType AudioCommandType_t; + + struct AudioCommand + { + union AudioCommandParam + { + const void *m_ptr; + AudioChannelCallback_t m_callback; + }; + + AudioCommandType_t m_commandType; + AudioCommandParam m_param; + }; + + class AudioChannelImpl final : public AudioChannel, public ClientAudioChannelContext { public: - explicit AudioChannelImpl(PortabilityLayer::HostAudioChannel *channel, SndCallBackUPP callback, HostThreadEvent *threadEvent, HostMutex *mutex); + explicit AudioChannelImpl(PortabilityLayer::HostAudioChannel *channel, HostThreadEvent *threadEvent, HostMutex *mutex); ~AudioChannelImpl(); - bool PushCommand(const SndCommand &command, bool blocking); - void ClearAllCommands(); - void Stop(); + void Destroy(bool wait) override; + bool AddBuffer(const void *smBuffer, bool blocking) override; + bool AddCallback(AudioChannelCallback_t callback, bool blocking) override; + void ClearAllCommands() override; + void Stop() override; void NotifyBufferFinished() override; private: + bool PushCommand(const AudioCommand &command, bool blocking); + enum WorkingState { State_Idle, // No thread is playing sound, the sound thread is out of work State_PlayingAsync, // Sound thread is playing sound. When it finishes, it will digest queue events under a lock. State_PlayingBlocked, // Sound thread is playing sound. When it finishes, it will transition to Idle and fire the thread event. State_FlushStarting, // Sound thread is aborting. When it aborts, it will transition to Idle and fire the thread event. + State_ShuttingDown, // Sound thread is shutting down. When it finishes, it will transition to idle and fire the thread event. }; static const unsigned int kMaxQueuedCommands = 64; @@ -39,12 +67,12 @@ namespace PortabilityLayer void DigestBufferCommand(const void *dataPointer); PortabilityLayer::HostAudioChannel *m_audioChannel; - SndCallBackUPP m_callback; + ; HostMutex *m_mutex; HostThreadEvent *m_threadEvent; - SndCommand m_commandQueue[kMaxQueuedCommands]; + AudioCommand m_commandQueue[kMaxQueuedCommands]; size_t m_numQueuedCommands; size_t m_nextInsertCommandPos; size_t m_nextDequeueCommandPos; @@ -52,9 +80,8 @@ namespace PortabilityLayer bool m_isIdle; }; - AudioChannelImpl::AudioChannelImpl(PortabilityLayer::HostAudioChannel *channel, SndCallBackUPP callback, HostThreadEvent *threadEvent, HostMutex *mutex) + AudioChannelImpl::AudioChannelImpl(PortabilityLayer::HostAudioChannel *channel, HostThreadEvent *threadEvent, HostMutex *mutex) : m_audioChannel(channel) - , m_callback(callback) , m_threadEvent(threadEvent) , m_mutex(mutex) , m_nextInsertCommandPos(0) @@ -81,7 +108,7 @@ namespace PortabilityLayer m_state = State_Idle; DigestQueueItems(); } - else if (m_state == State_PlayingBlocked || m_state == State_FlushStarting) + else if (m_state == State_PlayingBlocked || m_state == State_FlushStarting || m_state == State_ShuttingDown) { m_state = State_Idle; m_threadEvent->Signal(); @@ -90,6 +117,52 @@ namespace PortabilityLayer m_mutex->Unlock(); } + void AudioChannelImpl::Destroy(bool wait) + { + ClearAllCommands(); + + if (!wait) + Stop(); + else + { + m_mutex->Lock(); + + if (m_state == State_PlayingAsync) + { + m_state = State_ShuttingDown; + m_mutex->Unlock(); + + m_threadEvent->Wait(); + } + else + { + assert(m_state == State_Idle); + m_mutex->Unlock(); + } + } + + this->~AudioChannelImpl(); + PortabilityLayer::MemoryManager::GetInstance()->Release(this); + } + + bool AudioChannelImpl::AddBuffer(const void *smBuffer, bool blocking) + { + AudioCommand cmd; + cmd.m_commandType = AudioCommandTypes::kBuffer; + cmd.m_param.m_ptr = smBuffer; + + return this->PushCommand(cmd, blocking); + } + + bool AudioChannelImpl::AddCallback(AudioChannelCallback_t callback, bool blocking) + { + AudioCommand cmd; + cmd.m_commandType = AudioCommandTypes::kCallback; + cmd.m_param.m_ptr = callback; + + return this->PushCommand(cmd, blocking); + } + void AudioChannelImpl::DigestQueueItems() { m_mutex->Lock(); @@ -98,29 +171,22 @@ namespace PortabilityLayer while (m_numQueuedCommands > 0) { - const SndCommand &command = m_commandQueue[m_nextDequeueCommandPos]; + const AudioCommand &command = m_commandQueue[m_nextDequeueCommandPos]; m_numQueuedCommands--; m_nextDequeueCommandPos = (m_nextDequeueCommandPos + 1) % static_cast(kMaxQueuedCommands); - switch (command.cmd) + switch (command.m_commandType) { - case nullCmd: - break; - case bufferCmd: - DigestBufferCommand(reinterpret_cast(command.param2)); + case AudioCommandTypes::kBuffer: + DigestBufferCommand(command.m_param.m_ptr); assert(m_state == State_PlayingAsync); m_mutex->Unlock(); return; - case callBackCmd: - { - SndCommand commandCopy = command; - m_callback(this, &commandCopy); - } + case AudioCommandTypes::kCallback: + command.m_param.m_callback(this); break; default: - case flushCmd: - case quietCmd: - assert(false); // These shouldn't be in the queue + assert(false); break; } } @@ -152,14 +218,14 @@ namespace PortabilityLayer m_state = State_PlayingAsync; } - bool AudioChannelImpl::PushCommand(const SndCommand &command, bool failIfFull) + bool AudioChannelImpl::PushCommand(const AudioCommand &command, bool blocking) { bool digestOnThisThread = false; m_mutex->Lock(); if (m_numQueuedCommands == kMaxQueuedCommands) { - if (failIfFull) + if (!blocking) { m_mutex->Unlock(); return false; @@ -250,98 +316,78 @@ PLError_t SetDefaultOutputVolume(long vol) } -SndCallBackUPP NewSndCallBackProc(SndCallBackProc callback) +namespace PortabilityLayer { - return callback; -} - -void DisposeSndCallBackUPP(SndCallBackUPP upp) -{ -} - -PLError_t SndNewChannel(SndChannelPtr *outChannel, SndSynthType synthType, int initFlags, SndCallBackUPP callback) -{ - PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); - void *storage = mm->Alloc(sizeof(PortabilityLayer::AudioChannelImpl)); - if (!storage) - return PLErrors::kOutOfMemory; - - PortabilityLayer::HostAudioDriver *audioDriver = PortabilityLayer::HostAudioDriver::GetInstance(); - PortabilityLayer::HostAudioChannel *audioChannel = audioDriver->CreateChannel(); - if (!audioChannel) + class SoundSystemImpl final : public SoundSystem { - mm->Release(storage); - return PLErrors::kAudioError; + public: + AudioChannel *CreateChannel() override; + + void SetVolume(uint8_t vol) override; + uint8_t GetVolume() const override; + + static SoundSystemImpl *GetInstance(); + + private: + static SoundSystemImpl ms_instance; + }; + + AudioChannel *SoundSystemImpl::CreateChannel() + { + PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); + void *storage = mm->Alloc(sizeof(PortabilityLayer::AudioChannelImpl)); + if (!storage) + return nullptr; + + PortabilityLayer::HostAudioDriver *audioDriver = PortabilityLayer::HostAudioDriver::GetInstance(); + PortabilityLayer::HostAudioChannel *audioChannel = audioDriver->CreateChannel(); + if (!audioChannel) + { + mm->Release(storage); + return nullptr; + } + + PortabilityLayer::HostMutex *mutex = PortabilityLayer::HostSystemServices::GetInstance()->CreateMutex(); + if (!mutex) + { + audioChannel->Destroy(); + mm->Release(storage); + return nullptr; + } + + PortabilityLayer::HostThreadEvent *threadEvent = PortabilityLayer::HostSystemServices::GetInstance()->CreateThreadEvent(true, false); + if (!threadEvent) + { + mutex->Destroy(); + audioChannel->Destroy(); + mm->Release(storage); + return nullptr; + } + + return new (storage) PortabilityLayer::AudioChannelImpl(audioChannel, threadEvent, mutex); } - PortabilityLayer::HostMutex *mutex = PortabilityLayer::HostSystemServices::GetInstance()->CreateMutex(); - if (!mutex) + + void SoundSystemImpl::SetVolume(uint8_t vol) { - audioChannel->Destroy(); - mm->Release(storage); - return PLErrors::kAudioError; + PL_NotYetImplemented_TODO("Volume"); } - PortabilityLayer::HostThreadEvent *threadEvent = PortabilityLayer::HostSystemServices::GetInstance()->CreateThreadEvent(true, false); - if (!threadEvent) + uint8_t SoundSystemImpl::GetVolume() const { - mutex->Destroy(); - audioChannel->Destroy(); - mm->Release(storage); - return PLErrors::kAudioError; + PL_NotYetImplemented_TODO("Volume"); + return 255; } - *outChannel = new (storage) PortabilityLayer::AudioChannelImpl(audioChannel, callback, threadEvent, mutex); - - return PLErrors::kNone; -} - -PLError_t SndDisposeChannel(SndChannelPtr channel, Boolean flush) -{ - if (flush) + SoundSystemImpl *SoundSystemImpl::GetInstance() { - SndCommand cmd; - cmd.cmd = flushCmd; - cmd.param1 = cmd.param2 = 0; - - SndDoImmediate(channel, &cmd); - - cmd.cmd = quietCmd; - cmd.param1 = cmd.param2 = 0; - SndDoImmediate(channel, &cmd); + return &ms_instance; } - PortabilityLayer::AudioChannelImpl *audioChannelImpl = static_cast(channel); - audioChannelImpl->~AudioChannelImpl(); + SoundSystemImpl SoundSystemImpl::ms_instance; - PortabilityLayer::MemoryManager::GetInstance()->Release(audioChannelImpl); - - return PLErrors::kNone; -} - -PLError_t SndDoCommand(SndChannelPtr channel, const SndCommand *command, Boolean failIfFull) -{ - PortabilityLayer::AudioChannelImpl *audioChannelImpl = static_cast(channel); - - if (!audioChannelImpl->PushCommand(*command, failIfFull == 0)) - return PLErrors::kAudioError; - - return PLErrors::kNone; -} - -PLError_t SndDoImmediate(SndChannelPtr channel, const SndCommand *command) -{ - PortabilityLayer::AudioChannelImpl *audioChannelImpl = static_cast(channel); - - if (command->cmd == flushCmd) - audioChannelImpl->ClearAllCommands(); - else if (command->cmd == quietCmd) - audioChannelImpl->Stop(); - else + SoundSystem *SoundSystem::GetInstance() { - assert(false); - return PLErrors::kAudioError; + return SoundSystemImpl::GetInstance(); } - - return PLErrors::kNone; } diff --git a/PortabilityLayer/PLSound.h b/PortabilityLayer/PLSound.h index 7faefd0..80cb556 100644 --- a/PortabilityLayer/PLSound.h +++ b/PortabilityLayer/PLSound.h @@ -1,56 +1,30 @@ #pragma once -#ifndef __PL_SOUND_H__ -#define __PL_SOUND_H__ #include "PLCore.h" -enum SndCommandType +namespace PortabilityLayer { - nullCmd, - bufferCmd, // Param1: 0 Param2: Offset to sound header - callBackCmd, - flushCmd, - quietCmd -}; + struct AudioChannel; -struct SndChannel -{ -}; + typedef void (*AudioChannelCallback_t)(PortabilityLayer::AudioChannel *channel); -struct SndCommand -{ - SndCommandType cmd; - intptr_t param1; - intptr_t param2; -}; + struct AudioChannel + { + virtual void Destroy(bool wait) = 0; + virtual bool AddBuffer(const void *smBuffer, bool blocking) = 0; + virtual bool AddCallback(AudioChannelCallback_t callback, bool blocking) = 0; + virtual void ClearAllCommands() = 0; + virtual void Stop() = 0; + }; -enum SndSynthType -{ - sampledSynth -}; + class SoundSystem + { + public: + virtual AudioChannel *CreateChannel() = 0; -enum SndInitFlags -{ - initNoInterp = 1, - initMono = 2, -}; + virtual void SetVolume(uint8_t vol) = 0; + virtual uint8_t GetVolume() const = 0; -typedef SndChannel *SndChannelPtr; - -typedef void(*SndCallBackProc)(SndChannelPtr channel, SndCommand *command); -typedef SndCallBackProc SndCallBackUPP; - -// Vol seems to be a packed stereo DWord - -PLError_t GetDefaultOutputVolume(long *vol); -PLError_t SetDefaultOutputVolume(long vol); - - -SndCallBackUPP NewSndCallBackProc(SndCallBackProc callback); -void DisposeSndCallBackUPP(SndCallBackUPP upp); -PLError_t SndNewChannel(SndChannelPtr *outChannel, SndSynthType synthType, int initFlags, SndCallBackUPP callback); -PLError_t SndDisposeChannel(SndChannelPtr channel, Boolean flush); -PLError_t SndDoCommand(SndChannelPtr channel, const SndCommand *command, Boolean failIfFull); -PLError_t SndDoImmediate(SndChannelPtr channel, const SndCommand *command); - -#endif + static SoundSystem *GetInstance(); + }; +} diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj index 4263ad8..037081d 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj +++ b/PortabilityLayer/PortabilityLayer.vcxproj @@ -194,7 +194,6 @@ - diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters index 791e7e4..717c91f 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj.filters +++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters @@ -123,9 +123,6 @@ Header Files - - Header Files - Header Files