diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/tony/sound.cpp | 937 | ||||
-rw-r--r-- | engines/tony/sound.h | 32 | ||||
-rw-r--r-- | engines/tony/tony.cpp | 2 |
3 files changed, 79 insertions, 892 deletions
diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp index 75ae82298d..b0a2c69fd6 100644 --- a/engines/tony/sound.cpp +++ b/engines/tony/sound.cpp @@ -36,401 +36,6 @@ namespace Tony { - -#define RELEASE(x) {if ((x) != NULL) { (x)->release(); x = NULL; }} - - -/****************************************************************************\ -***************************************************************************** -* class CODECRAW -* -------------- -* Description: CODEC to play hard from pure samples -***************************************************************************** -\****************************************************************************/ - -class CODECRAW : public CODEC { -public: - CODECRAW(bool _bLoop = true); - - virtual ~CODECRAW(); - virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize); - virtual void loopReset(); -}; - - -/****************************************************************************\ -***************************************************************************** -* class CODECADPCM -* ---------------- -* Description: Play ADPCM compressed data -***************************************************************************** -\****************************************************************************/ - -class CODECADPCM : public CODECRAW { -protected: - byte *lpTemp; - static const int indexTable[16]; - static const int stepSizeTable[89]; - -public: - CODECADPCM(bool _bLoop = true, byte *lpTempBuffer = NULL); - virtual ~CODECADPCM(); - virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize) = 0; - virtual void loopReset() = 0; -}; - -class CODECADPCMSTEREO : public CODECADPCM { -protected: - int valpred[2], index[2]; - -public: - CODECADPCMSTEREO(bool _bLoop=true, byte *lpTempBuffer = NULL); - virtual ~CODECADPCMSTEREO(); - virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize); - virtual void loopReset(); -}; - -class CODECADPCMMONO : public CODECADPCM { -protected: - int valpred, index; - -public: - CODECADPCMMONO(bool _bLoop = true, byte *lpTempBuffer = NULL); - virtual ~CODECADPCMMONO(); - virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize); - virtual void loopReset(); -}; - -/****************************************************************************\ -* CODEC Methods -\****************************************************************************/ - -/** - * Standard cosntructor. It's possible to specify whether you want to - * enable or disable the loop (which by default, and 'active). - * - * @param loop True if you want to loop, false to disable - */ -CODEC::CODEC(bool loop) { - _bLoop = loop; - _bEndReached = false; -} - -CODEC::~CODEC() { -} - -/** - * Tell whether we have reached the end of the stream - * - * @return True if we're done, false otherwise. - */ -bool CODEC::endOfStream() { - return _bEndReached; -} - - -/****************************************************************************\ -* CODECRAW Methods -\****************************************************************************/ - -/** - * Standard cosntructor. Simply calls the inherited constructor - */ -CODECRAW::CODECRAW(bool loop) : CODEC(loop) { -} - -CODECRAW::~CODECRAW() { -} - -/** - * Reset the stream to the beginning of the file. In the case of RAW files, does nothing - */ -void CODECRAW::loopReset() { -} - -/** - * Manage the RAW format. Simply copies the file's stream buffer - * - * @return Indicates the position of the file for the end of the loop - */ -uint32 CODECRAW::decompress(Common::SeekableReadStream *stream, void *buf, uint32 dwSize) { - byte *lpBuf = (byte *)buf; - uint32 dwRead; - uint32 dwEOF; - - _bEndReached = false; - dwEOF = 0; - dwRead = stream->read(lpBuf, dwSize); - - if (dwRead < dwSize) { - dwEOF = dwRead; - _bEndReached = true; - - if (!_bLoop) { - Common::fill(lpBuf + dwRead, lpBuf + dwRead + (dwSize - dwRead), 0); - } else { - stream->seek(0); - dwRead = stream->read(lpBuf + dwRead, dwSize - dwRead); - } - } - - return dwEOF; -} - -/****************************************************************************\ -* CODECADPCM Methods -\****************************************************************************/ - -const int CODECADPCM::indexTable[16] = { - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8, -}; - -const int CODECADPCM::stepSizeTable[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 -}; - -#define MAXDECODESIZE (44100 * 2 * 2) - -/** - * Standard constructor. Initialises and allocates temporary memory tables - */ -CODECADPCM::CODECADPCM(bool loop, byte *lpTempBuffer) : CODECRAW(loop) { - // Alloca la memoria temporanea - if (lpTempBuffer != NULL) { - lpTemp = lpTempBuffer; - } else { - lpTemp = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, MAXDECODESIZE); - - if (lpTemp == NULL) { - error("Insufficient memory!"); - return; - } - } -} - - -CODECADPCMMONO::CODECADPCMMONO(bool loop, byte *lpTempBuffer) : CODECADPCM(loop,lpTempBuffer) { - // Inizializza per il playing - loopReset(); -} - -CODECADPCMMONO::~CODECADPCMMONO() { -} - - -CODECADPCMSTEREO::CODECADPCMSTEREO(bool loop, byte *lpTempBuffer) : CODECADPCM(loop, lpTempBuffer) { - // Initialise for playing - loopReset(); -} - -CODECADPCMSTEREO::~CODECADPCMSTEREO() { -} - -/** - * Destructor. Free the buffer - */ -CODECADPCM::~CODECADPCM() { - globalDestroy(lpTemp); -} - - -/** - * Reset the player before each play or loop - */ -void CODECADPCMSTEREO::loopReset() { - valpred[0] = 0; - valpred[1] = 0; - index[0] = 0; - index[1] = 0; -} - -void CODECADPCMMONO::loopReset() { - valpred = 0; - index = 0; -} - - -/** - * Manages decompressing the ADPCM 16:4 format. - */ -uint32 CODECADPCMMONO::decompress(Common::SeekableReadStream *stream, void *buf, uint32 dwSize) { - uint16 *lpBuf = (uint16 *)buf; - byte *inp; - int bufferstep; - int cache = 0; - int delta; - int sign; - int vpdiff; - uint32 eof, i; - int step; - - bufferstep = 1; - step = stepSizeTable[index]; - - // Invokes the raw codec to read the stream from disk to loop. - eof = CODECRAW::decompress(stream, lpTemp, dwSize / 4); - inp = lpTemp; - - eof *= 2; - - // If you must do an immediate loop - if (endOfStream() && eof == 0) { - loopReset(); - bufferstep = 1; - step = stepSizeTable[index]; - } else if (!endOfStream()) - eof = 0; - - dwSize /= 2; - for (i = 0; i < dwSize; i++) { - // Check if we are at the end of the file, and are looping - if (eof != 0 && i == eof) { - loopReset(); - bufferstep=1; - step = stepSizeTable[index]; - } - - // Read the delta (4 bits) - if (bufferstep) { - cache = *inp++; - delta = (cache >> 4) & 0xF; - } else - delta = cache & 0xF; - - // Find the new index - index += indexTable[delta]; - if (index < 0) index = 0; - if (index > 88) index = 88; - - // Reads the sign and separates it - sign = delta & 8; - delta = delta & 7; - - // Find the difference from the previous value - vpdiff = step >> 3; - if (delta & 4) vpdiff += step; - if (delta & 2) vpdiff += step >> 1; - if (delta & 1) vpdiff += step >> 2; - - if (sign) - valpred -= vpdiff; - else - valpred += vpdiff; - - // Check the limits of the found value - if (valpred > 32767) - valpred = 32767; - else if (valpred < -32768) - valpred = -32768; - - // Update the step - step = stepSizeTable[index]; - - // Write the value found - *lpBuf++ = (uint16)valpred; - - bufferstep = !bufferstep; - } - - return eof / 2; -} - -uint32 CODECADPCMSTEREO::decompress(Common::SeekableReadStream *stream, void *buf, uint32 dwSize) { - uint16 *lpBuf=(uint16 *)buf; - byte *inp; - int bufferstep; - int cache = 0; - int delta; - int sign; - int vpdiff; - uint32 eof, i; - int step[2]; - - bufferstep = 1; - step[0] = stepSizeTable[index[0]]; - step[1] = stepSizeTable[index[1]]; - - // Invokes the RAW codec to read the stream from disk. - eof = CODECRAW::decompress(stream, lpTemp, dwSize / 4); - inp = lpTemp; - - eof *= 2; - - // If you must do an immediate loop - if (endOfStream() && eof == 0) { - loopReset(); - bufferstep = 1; - step[0] = stepSizeTable[index[0]]; - step[1] = stepSizeTable[index[1]]; - - } else if (!endOfStream()) - eof = 0; - - dwSize /= 2; - - for (i = 0;i < dwSize; i++) { - // If you must do an immediate loop - if (eof != 0 && i == eof) { - loopReset(); - bufferstep = 1; - step[0] = stepSizeTable[index[0]]; - step[1] = stepSizeTable[index[1]]; - } - - // Reads the delta (4 bits) - if (bufferstep) { - cache = *inp++; - delta = cache & 0xF; - } else - delta = (cache >> 4) & 0xF; - - // Find the new index - index[bufferstep] += indexTable[delta]; - if (index[bufferstep] < 0) index[bufferstep] = 0; - if (index[bufferstep] > 88) index[bufferstep] = 88; - - // Reads the sign and separates it - sign = delta & 8; - delta = delta & 7; - - // Find the difference from the previous value - vpdiff = step[bufferstep] >> 3; - if (delta & 4) vpdiff += step[bufferstep]; - if (delta & 2) vpdiff += step[bufferstep] >> 1; - if (delta & 1) vpdiff += step[bufferstep] >> 2; - - if (sign) - valpred[bufferstep] -= vpdiff; - else - valpred[bufferstep] += vpdiff; - - // Check the limits of the value - if (valpred[bufferstep] > 32767) - valpred[bufferstep] = 32767; - else if (valpred[bufferstep] < -32768) - valpred[bufferstep] =- 32768; - - // Update the step - step[bufferstep] = stepSizeTable[index[bufferstep]]; - - // Write the found value - *lpBuf++ = (uint16)valpred[bufferstep]; - - bufferstep = !bufferstep; - } - - return eof / 2; -} - /****************************************************************************\ * FPSOUND Methods \****************************************************************************/ @@ -818,94 +423,17 @@ void FPSfx::soundCheckProcess(CORO_PARAM, const void *param) { * create it using FPSound::CreateStream() */ FPStream::FPStream(bool bSoundOn) { -#ifdef REFACTOR_ME - hwnd=hWnd; - lpDS = LPDS; - _lpDSBuffer = NULL; - _lpDSNotify = NULL; -#endif _bSoundSupported = bSoundOn; _bFileLoaded = false; - _bIsPlaying = false; _bPaused = false; _bLoop = false; _bDoFadeOut = false; _bSyncExit = false; - _hHot1 = _hHot2 = _hHot3 = CORO_INVALID_PID_VALUE; - _hPlayThread = _hPlayThreadPlayFast = _hPlayThreadPlayNormal = CORO_INVALID_PID_VALUE; - _hThreadEnd = CORO_INVALID_PID_VALUE; _dwBufferSize = _dwSize = 0; - _dwCodec = 0; _lastVolume = 0; - _lpTempBuffer = NULL; _syncToPlay = NULL; - _codec = NULL; -} - -bool FPStream::createBuffer(int nBufSize) { -#ifdef REFACTOR_ME - static PCMWAVEFORMAT pcmwf; - static DSBUFFERDESC dsbdesc; - static HRESULT err; - static char errbuf[128]; - - if (bSoundSupported == false) - return true; - - /* Set the required structures for the creation of a secondary buffer for the stream containing exactly 1 second of music. - Also activate the volume control, in order to lower and raise the volume of the music regardless of the general volume. - Obviously it is a buffer in RAM */ - - pcmwf.wBitsPerSample = 16; - pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; - pcmwf.wf.nChannels = 2; - pcmwf.wf.nSamplesPerSec = 44100; - pcmwf.wf.nBlockAlign = (pcmwf.wBitsPerSample / 8) * pcmwf.wf.nChannels; - pcmwf.wf.nAvgBytesPerSec = (uint32)pcmwf.wf.nBlockAlign * (uint32)pcmwf.wf.nSamplesPerSec; - - dsbdesc.dwSize = sizeof(dsbdesc); - dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY; - dwBufferSize = dsbdesc.dwBufferBytes = (((uint32)(pcmwf.wf.nAvgBytesPerSec * nBufSize) / 1000 + 31) / 32) * 32; - dsbdesc.lpwfxFormat = (LPWAVEFORMATEX) & pcmwf; - - if ((err = lpDS->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL)) != DS_OK) { - wsprintf(errbuf, "Error creating the secondary buffer (%lx)", err); - MessageBox(hwnd, errbuf, "FPStream::FPStream()", MB_OK); - bSoundSupported = false; - return false; - } - SetVolume(63); - - - /* Create an alert when key positions are reached in the stream. - Key positions are located, respectively, immediately after - the start and immediately after the middle of the buffer */ - err = lpDSBuffer->QueryInterface(IID_IDirectSoundNotify, (void **)&lpDSNotify); - - if (FAILED(err)) { - wsprintf(errbuf, "Error creating notify object! (%lx)", err); - MessageBox(hwnd, errbuf, "FPStream::FPStream()", MB_OK); - bSoundSupported = false; - return false; - } - - hHot1 = CreateEvent(NULL, false, false, NULL); - hHot2 = CreateEvent(NULL, false, false, NULL); - hHot3 = CreateEvent(NULL, false, false, NULL); - hPlayThread_PlayFast = CreateEvent(NULL, false, false, NULL); - - dspnHot[0].dwOffset = 32; - dspnHot[0].hEventNotify = hHot1; - - dspnHot[1].dwOffset = dwBufferSize / 2 + 32; - dspnHot[1].hEventNotify = hHot2; - - dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP; - dspnHot[2].hEventNotify = hHot3; - - lpDSNotify->SetNotificationPositions(3, dspnHot); -#endif - return true; + _loopStream = NULL; + _rewindableStream = NULL; } /** @@ -918,38 +446,13 @@ FPStream::~FPStream() { if (!_bSoundSupported) return; - if (_bIsPlaying) + if (g_system->getMixer()->isSoundHandleActive(_handle)) stop(); if (_bFileLoaded) unloadFile(); - if (_hHot1) { - CoroScheduler.closeEvent(_hHot1); - _hHot1 = CORO_INVALID_PID_VALUE; - } - if (_hHot2) { - CoroScheduler.closeEvent(_hHot2); - _hHot2 = CORO_INVALID_PID_VALUE; - } - if (_hHot3) { - CoroScheduler.closeEvent(_hHot3); - _hHot3 = CORO_INVALID_PID_VALUE; - } - if (_hPlayThreadPlayFast != CORO_INVALID_PID_VALUE) { - CoroScheduler.closeEvent(_hPlayThreadPlayFast); - _hPlayThreadPlayFast = CORO_INVALID_PID_VALUE; - } - if (_hPlayThreadPlayNormal != CORO_INVALID_PID_VALUE) { - CoroScheduler.closeEvent(_hPlayThreadPlayNormal); - _hPlayThreadPlayNormal = CORO_INVALID_PID_VALUE; - } - _syncToPlay = NULL; -#ifdef REFACTOR_ME - RELEASE(lpDSNotify); - RELEASE(lpDSBuffer); -#endif } /** @@ -976,13 +479,12 @@ bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nB if (!_bSoundSupported) return true; + if (_bFileLoaded) + unloadFile(); + // Save the codec type _dwCodec = dwCodType; - // Create the buffer - if (!createBuffer(nBufSize)) - return true; - // Open the file stream for reading if (!_file.open(fileName)) return false; @@ -990,11 +492,26 @@ bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nB // Save the size of the stream _dwSize = _file.size(); + switch (_dwCodec) { + case FPCODEC_RAW: + _rewindableStream = Audio::makeRawStream(&_file, 44100, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO, DisposeAfterUse::NO); + break; + + case FPCODEC_ADPCM: + _rewindableStream = Audio::makeADPCMStream(&_file, DisposeAfterUse::NO, 0, Audio::kADPCMDVI, 44100, 2); + break; + + default: + _file.close(); + return false; + } + // All done _bFileLoaded = true; - _bIsPlaying = false; _bPaused = false; + setVolume(63); + return true; } @@ -1011,12 +528,12 @@ bool FPStream::unloadFile() { if (!_bSoundSupported || !_bFileLoaded) return true; + assert(!g_system->getMixer()->isSoundHandleActive(_handle)); + /* Closes the file handle stream */ + delete _loopStream; + delete _rewindableStream; _file.close(); -#ifdef REFACTOR_ME - RELEASE(lpDSNotify); - RELEASE(lpDSBuffer); -#endif // Flag that the file is no longer in memory _bFileLoaded = false; @@ -1024,96 +541,6 @@ bool FPStream::unloadFile() { return true; } -void FPStream::prefetch() { - void *lpBuf = NULL; - - if (!_bSoundSupported || !_bFileLoaded) - return; - - // Allocates a temporary buffer - _lpTempBuffer = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _dwBufferSize / 2); - if (_lpTempBuffer == NULL) - return; - - if (_dwCodec == FPCODEC_RAW) { - _codec = new CODECRAW(_bLoop); - } else if (_dwCodec == FPCODEC_ADPCM) { - _codec = new CODECADPCMSTEREO(_bLoop); - } else { - return; - } - - // reset the file position - _file.seek(0); - -#ifdef REFACTOR_ME - // Fills the buffer for the data already ready - if ((err = lpDSBuffer->Lock(0, dwBufferSize / 2, &lpBuf, (uint32 *)&dwHi, NULL, NULL, 0)) != DS_OK) { - _vm->GUIError("Cannot lock stream buffer!", "soundLoadStream()"); - return; - } -#else - // Return, since lpBuf hasn't been set - return; -#endif - - // Uncompress the data from the stream directly into the locked buffer - _codec->decompress(_file.readStream(_file.size()), lpBuf, _dwBufferSize / 2); - - // Unlock the buffer -#ifdef REFACTOR_ME - lpDSBuffer->unlock(lpBuf, _dwBufferSize / 2, NULL, NULL); -#endif - - // Create a thread to play the stream - _hThreadEnd = CoroScheduler.createEvent(false, false); - _hPlayThread = CoroScheduler.createProcess(playThread, this, sizeof(FPStream *)); - - // Start to play the buffer -#ifdef REFACTOR_ME - lpDSBuffer->setCurrentPosition(0); -#endif - _bIsPlaying = true; - -#ifdef REFACTOR_ME - _dspnHot[0].dwOffset = 32; - _dspnHot[0].hEventNotify = _hHot1; - - _dspnHot[1].dwOffset = dwBufferSize / 2 + 32; - _dspnHot[1].hEventNotify = _hHot2; - - _dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP; - _dspnHot[2].hEventNotify = _hHot3; - - if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) { - int a = 1; - } -#endif -} - -void FPStream::playFast() { -#ifdef REFACTOR_ME - dspnHot[0].dwOffset = 32; - dspnHot[0].hEventNotify = hHot1; - - dspnHot[1].dwOffset = dwBufferSize / 2 + 32; - dspnHot[1].hEventNotify = hHot2; - - dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP; - dspnHot[2].hEventNotify = hHot3; - - lpDSBuffer->Stop(); - - if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) { - warning("PlayFast SNP failed!"); - } - - if (FAILED(lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING))) { - warning("PlayFast failed!\n"); - } -#endif -} - /** * Play the stream. * @@ -1121,79 +548,27 @@ void FPStream::playFast() { */ bool FPStream::play() { -#ifdef REFACTOR_ME - uint32 dwId; - void *lpBuf; - uint32 dwHi; - HRESULT err; - - if (!bSoundSupported || !bFileLoaded) - return false; - - /* Allocate a temporary buffer */ - lpTempBuffer = (byte *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwBufferSize / 2); - if (lpTempBuffer == NULL) - return false; - - switch (dwCodec) { - case FPCODEC_RAW: - _codec = new CODECRAW(_bLoop); - break; - - case FPCODEC_ADPCM: - _codec = new CODECADPCMSTEREO(_bLoop); - break; - - default: + if (!_bSoundSupported || !_bFileLoaded) return false; - } - - /* Reset the file position */ - _file.seek(0); - lpDSBuffer->Stop(); - lpDSBuffer->SetCurrentPosition(0); - - /* Fills the buffer for the data already ready */ - if ((err = lpDSBuffer->Lock(0, dwBufferSize / 2, &lpBuf, (uint32 *)&dwHi, NULL, NULL, 0)) != DS_OK) { - error("Cannot lock stream buffer!", "soundLoadStream()"); - } - - /* Uncompress the data from the stream directly into the locked buffer */ - _codec->Decompress(hFile, lpBuf, dwBufferSize / 2); - - /* Unlock the buffer */ - lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL); - - /* Create a thread to play the stream */ - hThreadEnd = CreateEvent(NULL, false, false, NULL); - hPlayThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)PlayThread, (void *)this, 0, &dwId); - SetThreadPriority(hPlayThread, THREAD_PRIORITY_HIGHEST); - SetEvent(hPlayThread_PlayFast); + stop(); -#if 0 - /* Start to play the buffer */ - lpDSBuffer->SetCurrentPosition(0); + _rewindableStream->rewind(); - dspnHot[0].dwOffset = 32; - dspnHot[0].hEventNotify = hHot1; + Audio::AudioStream *stream = _rewindableStream; - dspnHot[1].dwOffset = dwBufferSize / 2 + 32; - dspnHot[1].hEventNotify = hHot2; + if (_bLoop) { + if (!_loopStream) + _loopStream = new Audio::LoopingAudioStream(_rewindableStream, 0, DisposeAfterUse::NO); - dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP; - dspnHot[2].hEventNotify = hHot3; - - if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) { - int a = 1; + stream = _loopStream; } + // FIXME: Should this be kMusicSoundType or KPlainSoundType? + g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_handle, stream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); + setVolume(_lastVolume); + _bPaused = false; - lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING); -#endif - - bIsPlaying = true; -#endif return true; } @@ -1205,177 +580,37 @@ bool FPStream::play() { */ bool FPStream::stop(bool bSync) { -#ifdef REFACTOR_ME - - if (!bSoundSupported) + if (!_bSoundSupported) return true; - if (!bFileLoaded) + if (!_bFileLoaded) return false; - if (!bIsPlaying) + if (!g_system->getMixer()->isSoundHandleActive(_handle)) return false; if (bSync) { -// bSyncExit = true; -// lpDSBuffer->Stop(); -// lpDSBuffer->Play(0, 0, 0); + // The caller intends to call waitForSync. + // FIXME: Why call this in that case?! Looks like old code. Remove that parameter. return true; } else { - /* Close the DirectSound buffer */ - lpDSBuffer->Stop(); - - /* Notify the thread is should stop */ - SetEvent(hThreadEnd); - WaitForSingleObject(hPlayThread, CORO_INFINITE); - - /* Closes the handle used by the stream and free its memory */ - CloseHandle(hPlayThread); - CloseHandle(hThreadEnd); - GlobalFree(lpTempBuffer); - - /* Close and free the CODEC */ - delete _codec; + g_system->getMixer()->stopHandle(_handle); - bIsPlaying = false; - bPaused = false; + _bPaused = false; } -#endif + return true; } void FPStream::waitForSync(FPStream *toplay) { -#ifdef REFACTOR_ME - if (!bSoundSupported) - return; - - if (!bFileLoaded) - return; - - if (!bIsPlaying) - return; - - SyncToPlay = toplay; - bSyncExit = true; - - char buf[1024]; - sprintf(buf, "Wait for sync: %x (SyncToPlay: [%x]=%x, SyncExit: [%x]=%d) MyThread: 0x%x\n", - this->lpDSBuffer, &this->SyncToPlay, SyncToPlay, &bSyncExit, bSyncExit, GetCurrentThreadId()); - warning(buf); - - WaitForSingleObject(hPlayThread, CORO_INFINITE); - - /* Closes the handle used by the stream and free its memory */ - CloseHandle(hPlayThread); - CloseHandle(hThreadEnd); - GlobalFree(lpTempBuffer); - - /* Close and free the CODEC */ - delete _codec; -#endif - _bIsPlaying = false; -} - -/** - * Thread playing the stream - * - */ - -void FPStream::playThread(CORO_PARAM, const void *param) { - CORO_BEGIN_CONTEXT; - byte *lpLockBuf; - uint32 dwResult; - byte *lpLockBuf2; - uint32 dwResult2; - bool cicla; - uint32 countEnd; - bool bPrecache; - char buf[1024]; - uint32 hList[5]; - CORO_END_CONTEXT(_ctx); - -// FPStream *This = *(FPStream **)param; - - CORO_BEGIN_CODE(_ctx); -#ifdef REFACTOR_ME - // Events that signal when you need to do something - _ctx->hList[0] = This->_hThreadEnd; - _ctx->hList[1] = This->_hHot1; - _ctx->hList[2] = This->_hHot2; - _ctx->hList[3] = This->_hHot3; - _ctx->hList[4] = This->_hPlayThreadPlayFast; - - _ctx->cicla = true; - _ctx->bPrecache = true; - _ctx->countEnd = 0; - while (_ctx->cicla) { - if (This->_codec->endOfStream() && This->_codec->_bLoop == false) { - _ctx->countEnd++; - if (_ctx->countEnd == 3) - break; - } - - // Uncompresses the data being written into the temporary buffer - if (This->_lastVolume == 0) - ZeroMemory(This->_lpTempBuffer, This->_dwBufferSize / 2); - else if (_ctx->bPrecache) - This->_codec->decompress(This->_file.readStream(This->_file.size()), This->_lpTempBuffer, This->_dwBufferSize / 2); - - _ctx->bPrecache = false; - - // Waits for an event. Since they are all in automatic reset, there is no need to reset it after - - uint32 dwBufStatus; - - CORO_INVOKE_4(CoroScheduler.waitForMultipleObjects, 5, _ctx->hList, false, CORO_INFINITE, &_ctx->dwResult); - - // Check to determine which event has been set - if (CoroScheduler.getEvent(This->_hThreadEnd)->signalled) { - /* Must leave the thread */ - _ctx->cicla = false; - - } else if (CoroScheduler.getEvent(This->_hHot1)->signalled) { - // Must fill the second half of the buffer - This->lpDSBuffer->Lock(This->_dwBufferSize / 2, This->_dwBufferSize / 2, (void **)&_ctx->lpLockBuf, &_ctx->dwResult, (void **)&_ctx->lpLockBuf2, &_ctx->dwResult2, 0); + // FIXME: The idea here is that you wait for this stream to reach + // a buffer which is a multiple of nBufSize/nSync, and then the + // thread stops it and immediately starts the 'toplay' stream. - copyMemory(_ctx->lpLockBuf, This->_lpTempBuffer, This->_dwBufferSize / 2); - This->lpDSBuffer->Unlock(_ctx->lpLockBuf, This->_dwBufferSize / 2, _ctx->lpLockBuf2, 0); - - _ctx->bPrecache = true; - - } else if (CoroScheduler.getEvent(This->_hHot2)->signalled) { - This->lpDSBuffer->Lock(0, This->_dwBufferSize / 2, (void **)&_ctx->lpLockBuf, &_ctx->dwResult, NULL, NULL, 0); - - copyMemory(_ctx->lpLockBuf, This->_lpTempBuffer, This->_dwBufferSize / 2); - This->lpDSBuffer->Unlock(_ctx->lpLockBuf, This->_dwBufferSize / 2, NULL, NULL); - - _ctx->bPrecache = true; - - } else if (CoroScheduler.getEvent(This->_hHot3)->signalled) { - - if (This->_bSyncExit) { - CoroScheduler.setEvent(This->_syncToPlay->_hPlayThreadPlayFast); - - // Transfer immediatly control to the other threads - CORO_SLEEP(1); - - This->_bSyncExit = false; - _ctx->cicla = false; - break; - } - } else if (CoroScheduler.getEvent(This->_hPlayThreadPlayFast)->signalled) { - This->playFast(); - } - } - - // Close the DirectSound buffer - This->lpDSBuffer->Stop(); -#endif - - CORO_END_CODE; + stop(); + toplay->play(); } - /** * Unables or disables stream loop. * @@ -1389,44 +624,25 @@ void FPStream::setLoop(bool loop) { _bLoop = loop; } - /** * Pause sound effect * * @param bPause True enables pause, False disables it */ void FPStream::pause(bool bPause) { - if (_bFileLoaded) { - if (bPause && _bIsPlaying) { -#ifdef REFACTOR_ME - _lpDSBuffer->Stop(); -#endif - _bIsPlaying = false; - _bPaused = true; - } else if (!bPause && _bPaused) { -#ifdef REFACTOR_ME - _dspnHot[0].dwOffset = 32; - _dspnHot[0].hEventNotify = hHot1; - - _dspnHot[1].dwOffset = dwBufferSize / 2 + 32; - _dspnHot[1].hEventNotify = hHot2; - - _dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP; - _dspnHot[2].hEventNotify = hHot3; - - if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) { - int a = 1; - } - - lpDSBuffer->Play(0, 0, _bLoop); -#endif - _bIsPlaying = true; - _bPaused = false; - - // Trick to reset the volume after a possible new sound configuration - setVolume(_lastVolume); - } - } + if (!_bFileLoaded) + return; + + if (bPause == _bPaused) + return; + + if (g_system->getMixer()->isSoundHandleActive(_handle)) + g_system->getMixer()->pauseHandle(_handle, bPause); + + _bPaused = bPause; + + // Trick to reset the volume after a possible new sound configuration + setVolume(_lastVolume); } /** @@ -1437,38 +653,33 @@ void FPStream::pause(bool bPause) { */ void FPStream::setVolume(int dwVolume) { -#ifdef REFACTOR_ME if (dwVolume > 63) dwVolume = 63; if (dwVolume < 0) dwVolume = 0; - lastVolume = dwVolume; + _lastVolume = dwVolume; - if (!GLOBALS.bCfgMusic) dwVolume = 0; + if (!GLOBALS._bCfgMusic) dwVolume = 0; else { - dwVolume -= (10 - GLOBALS.nCfgMusicVolume) * 2; + dwVolume -= (10 - GLOBALS._nCfgMusicVolume) * 2; if (dwVolume < 0) dwVolume = 0; } - if (lpDSBuffer) - lpDSBuffer->SetVolume(dwVolume * (DSBVOLUME_MAX - DSBVOLUME_MIN) / 64 + DSBVOLUME_MIN); -#endif + if (g_system->getMixer()->isSoundHandleActive(_handle)) + g_system->getMixer()->setChannelVolume(_handle, dwVolume * Audio::Mixer::kMaxChannelVolume / 63); } /** - * Gets the vgolume of the stream + * Gets the volume of the stream * * @param lpdwVolume Variable that will contain the current volume * */ void FPStream::getVolume(int *lpdwVolume) { -#ifdef REFACTOR_ME - if (lpDSBuffer) - lpDSBuffer->GetVolume((uint32 *)lpdwVolume); - *lpdwVolume -= (DSBVOLUME_MIN); - *lpdwVolume *= 64; - *lpdwVolume /= (DSBVOLUME_MAX - DSBVOLUME_MIN); -#endif + if (g_system->getMixer()->isSoundHandleActive(_handle)) + *lpdwVolume = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume; + else + *lpdwVolume = 0; } } // End of namespace Tony diff --git a/engines/tony/sound.h b/engines/tony/sound.h index 38ce6de2a7..585247db83 100644 --- a/engines/tony/sound.h +++ b/engines/tony/sound.h @@ -265,23 +265,11 @@ public: class FPStream { private: - // HWND hwnd; - // LPDIRECTSOUND lpDS; - // LPDIRECTSOUNDBUFFER lpDSBuffer; // DirectSound circular buffer - // LPDIRECTSOUNDNOTIFY lpDSNotify; // Notify hotspots in the buffer - - byte *_lpTempBuffer; // Temporary buffer use for decompression - uint32 _dwBufferSize; // Buffer size (bytes) uint32 _dwSize; // Stream size (bytes) uint32 _dwCodec; // CODEC used - uint32 _hThreadEnd; // Event used to close thread Common::File _file; // File handle used for the stream - uint32 _hPlayThread; // Handle of the Play thread - uint32 _hHot1, _hHot2, _hHot3; // Events set by DirectSoundNotify - uint32 _hPlayThreadPlayFast; - uint32 _hPlayThreadPlayNormal; bool _bSoundSupported; // True if the sound is active bool _bFileLoaded; // True if the file is open @@ -291,21 +279,10 @@ private: bool _bPaused; int _lastVolume; FPStream *_syncToPlay; - CODEC *_codec; - - // DSBPOSITIONNOTIFY dspnHot[3]; - - bool createBuffer(int nBufSize); -public: - bool _bIsPlaying; // True if the stream is playing - -private: - /** - * Thread playing the stream - * - */ - static void playThread(CORO_PARAM, const void *param); + Audio::AudioStream *_loopStream; + Audio::RewindableAudioStream *_rewindableStream; + Audio::SoundHandle _handle; public: @@ -368,7 +345,6 @@ public: bool play(); void playFast(); - void prefetch(); /** * Closes the stream. @@ -408,7 +384,7 @@ public: void setVolume(int dwVolume); /** - * Gets the vgolume of the stream + * Gets the volume of the stream * * @param lpdwVolume Variable that will contain the current volume * diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index 8ae95af862..475683d0f4 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -268,7 +268,7 @@ void TonyEngine::doNextMusic(CORO_PARAM, const void *param) { } streams[GLOBALS._nextChannel]->setLoop(GLOBALS._nextLoop); - streams[GLOBALS._nextChannel]->prefetch(); + //streams[GLOBALS._nextChannel]->prefetch(); streams[GLOBALS._curChannel]->stop(true); streams[GLOBALS._curChannel]->waitForSync(streams[GLOBALS._nextChannel]); |