TONY: Implement more of the music related code from the original
This commit is contained in:
parent
0aa3d39cf7
commit
61d460a854
6 changed files with 673 additions and 286 deletions
|
@ -2198,14 +2198,14 @@ DECLARE_CUSTOM_FUNCTION(DemuteJingle)(CORO_PARAM, uint32, uint32, uint32, uint32
|
|||
void CustPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int nSync = 0) {
|
||||
if (nSync == 0)
|
||||
nSync = 2000;
|
||||
debug("Start CustPlayMusic");
|
||||
debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "Start CustPlayMusic");
|
||||
GLOBALS.PlayMusic(nChannel, mFN, nFX, bLoop, nSync);
|
||||
debug("End CustPlayMusic");
|
||||
debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "End CustPlayMusic");
|
||||
}
|
||||
|
||||
DECLARE_CUSTOM_FUNCTION(PlaySoundEffect)(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) {
|
||||
if (nFX == 0 || nFX == 1 || nFX == 2) {
|
||||
debug("PlaySoundEffect stop fadeout");
|
||||
debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "PlaySoundEffect stop fadeout");
|
||||
GLOBALS._bFadeOutStop = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -473,8 +473,6 @@ void RMGfxEngine::init() {
|
|||
delete load;
|
||||
|
||||
// Display 'Loading' screen
|
||||
// TODO: The loading screen isn't currently optimal, since the game doesn't respond to events
|
||||
// whilst the mpalInit code is being executed.
|
||||
_vm->_window.getNewFrame(*this, NULL);
|
||||
_vm->_window.repaint();
|
||||
|
||||
|
|
|
@ -39,11 +39,406 @@ 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;
|
||||
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;
|
||||
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
|
||||
\****************************************************************************/
|
||||
|
||||
/**
|
||||
* Default constructor. Initializes the attributes.
|
||||
*
|
||||
*/
|
||||
|
||||
FPSound::FPSound() {
|
||||
_bSoundSupported = false;
|
||||
}
|
||||
|
@ -53,7 +448,6 @@ FPSound::FPSound() {
|
|||
*
|
||||
* @returns True is everything is OK, False otherwise
|
||||
*/
|
||||
|
||||
bool FPSound::init() {
|
||||
_bSoundSupported = g_system->getMixer()->isReady();
|
||||
return _bSoundSupported;
|
||||
|
@ -308,7 +702,7 @@ bool FPSfx::stop() {
|
|||
/**
|
||||
* Enables or disables the Sfx loop.
|
||||
*
|
||||
* @param bLoop True to enable the loop, False to disable
|
||||
* @param _bLoop True to enable the loop, False to disable
|
||||
*
|
||||
* @remarks The loop must be activated BEFORE the sfx starts
|
||||
* playing. Any changes made during the play will have
|
||||
|
@ -423,20 +817,19 @@ void FPSfx::soundCheckProcess(CORO_PARAM, const void *param) {
|
|||
* @remarks Do *NOT* declare an object directly, but rather
|
||||
* create it using FPSound::CreateStream()
|
||||
*/
|
||||
|
||||
FPStream::FPStream(bool bSoundOn) {
|
||||
#ifdef REFACTOR_ME
|
||||
//hwnd=hWnd;
|
||||
hwnd=hWnd;
|
||||
lpDS = LPDS;
|
||||
bSoundSupported = bSoundOn;
|
||||
bFileLoaded = false;
|
||||
bIsPlaying = false;
|
||||
bPaused = false;
|
||||
bSyncExit = false;
|
||||
lpDSBuffer = NULL;
|
||||
lpDSNotify = NULL;
|
||||
hHot1 = hHot2 = hHot3 = hPlayThread_PlayFast = hPlayThread_PlayNormal = NULL;
|
||||
_lpDSBuffer = NULL;
|
||||
_lpDSNotify = NULL;
|
||||
#endif
|
||||
_bSoundSupported = bSoundOn;
|
||||
_bFileLoaded = false;
|
||||
_bIsPlaying = false;
|
||||
_bPaused = false;
|
||||
_bSyncExit = false;
|
||||
_hHot1 = _hHot2 = _hHot3 = _hPlayThreadPlayFast = _hPlayThreadPlayNormal = CORO_INVALID_PID_VALUE;
|
||||
}
|
||||
|
||||
bool FPStream::createBuffer(int nBufSize) {
|
||||
|
@ -512,40 +905,38 @@ bool FPStream::createBuffer(int nBufSize) {
|
|||
*/
|
||||
|
||||
FPStream::~FPStream() {
|
||||
#ifdef REFACTOR_ME
|
||||
|
||||
if (!bSoundSupported)
|
||||
if (!_bSoundSupported)
|
||||
return;
|
||||
|
||||
if (bIsPlaying)
|
||||
Stop();
|
||||
if (_bIsPlaying)
|
||||
stop();
|
||||
|
||||
if (bFileLoaded)
|
||||
UnloadFile();
|
||||
if (_bFileLoaded)
|
||||
unloadFile();
|
||||
|
||||
if (hHot1) {
|
||||
CloseHandle(hHot1);
|
||||
hHot1 = NULL;
|
||||
if (_hHot1) {
|
||||
CoroScheduler.closeEvent(_hHot1);
|
||||
_hHot1 = CORO_INVALID_PID_VALUE;
|
||||
}
|
||||
if (hHot2) {
|
||||
CloseHandle(hHot2);
|
||||
hHot2 = NULL;
|
||||
if (_hHot2) {
|
||||
CoroScheduler.closeEvent(_hHot2);
|
||||
_hHot2 = CORO_INVALID_PID_VALUE;
|
||||
}
|
||||
if (hHot3) {
|
||||
CloseHandle(hHot3);
|
||||
hHot3 = NULL;
|
||||
if (_hHot3) {
|
||||
CoroScheduler.closeEvent(_hHot3);
|
||||
_hHot3 = CORO_INVALID_PID_VALUE;
|
||||
}
|
||||
if (hPlayThread_PlayFast) {
|
||||
CloseHandle(hPlayThread_PlayFast);
|
||||
hPlayThread_PlayFast = NULL;
|
||||
if (_hPlayThreadPlayFast != CORO_INVALID_PID_VALUE) {
|
||||
CoroScheduler.closeEvent(_hPlayThreadPlayFast);
|
||||
_hPlayThreadPlayFast = CORO_INVALID_PID_VALUE;
|
||||
}
|
||||
if (hPlayThread_PlayNormal) {
|
||||
CloseHandle(hPlayThread_PlayNormal);
|
||||
hPlayThread_PlayNormal = NULL;
|
||||
if (_hPlayThreadPlayNormal != CORO_INVALID_PID_VALUE) {
|
||||
CoroScheduler.closeEvent(_hPlayThreadPlayNormal);
|
||||
_hPlayThreadPlayNormal = CORO_INVALID_PID_VALUE;
|
||||
}
|
||||
|
||||
SyncToPlay = NULL;
|
||||
|
||||
_syncToPlay = NULL;
|
||||
#ifdef REFACTOR_ME
|
||||
RELEASE(lpDSNotify);
|
||||
RELEASE(lpDSBuffer);
|
||||
#endif
|
||||
|
@ -559,7 +950,6 @@ FPStream::~FPStream() {
|
|||
* FPSound::CreateStream().
|
||||
* Object pointers are no longer valid after this call.
|
||||
*/
|
||||
|
||||
void FPStream::release() {
|
||||
delete this;
|
||||
}
|
||||
|
@ -567,44 +957,35 @@ void FPStream::release() {
|
|||
/**
|
||||
* Opens a file stream
|
||||
*
|
||||
* @param lpszFile Filename to be opened
|
||||
* @param fileName Filename to be opened
|
||||
* @param dwCodec CODEC to be used to uncompress samples
|
||||
*
|
||||
* @returns True is everything is OK, False otherwise
|
||||
*/
|
||||
|
||||
bool FPStream::loadFile(const char *lpszFileName, uint32 dwCodType, int nBufSize) {
|
||||
#ifdef REFACTOR_ME
|
||||
HRESULT err;
|
||||
void *lpBuf;
|
||||
uint32 dwHi;
|
||||
|
||||
if (!bSoundSupported)
|
||||
bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nBufSize) {
|
||||
if (!_bSoundSupported)
|
||||
return true;
|
||||
|
||||
/* Si salva il tipo di codec */
|
||||
dwCodec = dwCodType;
|
||||
// Save the codec type
|
||||
_dwCodec = dwCodType;
|
||||
|
||||
/* Crea il buffer */
|
||||
if (!CreateBuffer(nBufSize))
|
||||
// Create the buffer
|
||||
if (!createBuffer(nBufSize))
|
||||
return true;
|
||||
|
||||
/* Apre il file di stream in lettura */
|
||||
if (!_file.open(lpszFileName))
|
||||
//MessageBox(hwnd,"Cannot open stream file!","FPStream::LoadFile()", MB_OK);
|
||||
// Open the file stream for reading
|
||||
if (!_file.open(fileName))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Si salva la lunghezza dello stream */
|
||||
dwSize = _file.size();
|
||||
_file.seek(0);
|
||||
// Save the size of the stream
|
||||
_dwSize = _file.size();
|
||||
|
||||
/* Tutto a posto, possiamo uscire */
|
||||
bFileLoaded = true;
|
||||
bIsPlaying = false;
|
||||
bPaused = false;
|
||||
#endif
|
||||
return true;
|
||||
// All done
|
||||
_bFileLoaded = true;
|
||||
_bIsPlaying = false;
|
||||
_bPaused = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -616,85 +997,80 @@ return true;
|
|||
* @remarks It is necessary to call this function to free the
|
||||
* memory used by the stream.
|
||||
*/
|
||||
|
||||
bool FPStream::unloadFile() {
|
||||
#ifdef REFACTOR_ME
|
||||
|
||||
if (!bSoundSupported || !bFileLoaded)
|
||||
if (!_bSoundSupported || !_bFileLoaded)
|
||||
return true;
|
||||
|
||||
/* Closes the file handle stream */
|
||||
_file.close();
|
||||
|
||||
#ifdef REFACTOR_ME
|
||||
RELEASE(lpDSNotify);
|
||||
RELEASE(lpDSBuffer);
|
||||
|
||||
/* Remember no more file is loaded in memory */
|
||||
bFileLoaded = false;
|
||||
#endif
|
||||
|
||||
// Flag that the file is no longer in memory
|
||||
_bFileLoaded = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FPStream::prefetch() {
|
||||
#ifdef REFACTOR_ME
|
||||
uint32 dwId;
|
||||
void *lpBuf;
|
||||
uint32 dwHi;
|
||||
HRESULT err;
|
||||
|
||||
if (!bSoundSupported || !bFileLoaded)
|
||||
if (!_bSoundSupported || !_bFileLoaded)
|
||||
return;
|
||||
|
||||
/* Allocates a temporary buffer */
|
||||
lpTempBuffer = (byte *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwBufferSize / 2);
|
||||
if (lpTempBuffer == NULL)
|
||||
// Allocates a temporary buffer
|
||||
_lpTempBuffer = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _dwBufferSize / 2);
|
||||
if (_lpTempBuffer == NULL)
|
||||
return;
|
||||
|
||||
switch (dwCodec) {
|
||||
case FPCODEC_RAW:
|
||||
lpCodec = new CODECRAW(bLoop);
|
||||
break;
|
||||
|
||||
case FPCODEC_ADPCM:
|
||||
lpCodec = new CODECADPCMSTEREO(bLoop);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (_dwCodec == FPCODEC_RAW) {
|
||||
_codec = new CODECRAW(_bLoop);
|
||||
} else if (_dwCodec == FPCODEC_ADPCM) {
|
||||
_codec = new CODECADPCMSTEREO(_bLoop);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* reset the file position */
|
||||
// reset the file position
|
||||
_file.seek(0);
|
||||
|
||||
/* Fills the buffer for the data already ready */
|
||||
#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) {
|
||||
MessageBox(hwnd, "Cannot lock stream buffer!", "soundLoadStream()", MB_OK);
|
||||
_vm->GUIError("Cannot lock stream buffer!", "soundLoadStream()");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Uncompress the data from the stream directly into the locked buffer */
|
||||
lpCodec->Decompress(hFile, lpBuf, dwBufferSize / 2);
|
||||
// Uncompress the data from the stream directly into the locked buffer
|
||||
_codec->decompress(_file.readStream(_file.size()), lpBuf, _dwBufferSize / 2);
|
||||
|
||||
/* Unlock the buffer */
|
||||
lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL);
|
||||
// Unlock the buffer
|
||||
#ifdef REFACTOR_ME
|
||||
lpDSBuffer->unlock(lpBuf, _dwBufferSize / 2, NULL, NULL);
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
// Create a thread to play the stream
|
||||
_hThreadEnd = CoroScheduler.createEvent(false, false);
|
||||
_hPlayThread = CoroScheduler.createProcess(playThread, this, sizeof(FPStream *));
|
||||
|
||||
/* Start to play the buffer */
|
||||
lpDSBuffer->SetCurrentPosition(0);
|
||||
bIsPlaying = true;
|
||||
// Start to play the buffer
|
||||
#ifdef REFACTOR_ME
|
||||
lpDSBuffer->setCurrentPosition(0);
|
||||
#endif
|
||||
_bIsPlaying = true;
|
||||
|
||||
dspnHot[0].dwOffset = 32;
|
||||
dspnHot[0].hEventNotify = hHot1;
|
||||
#ifdef REFACTOR_ME
|
||||
_dspnHot[0].dwOffset = 32;
|
||||
_dspnHot[0].hEventNotify = _hHot1;
|
||||
|
||||
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
||||
dspnHot[1].hEventNotify = hHot2;
|
||||
_dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
||||
_dspnHot[1].hEventNotify = _hHot2;
|
||||
|
||||
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
||||
dspnHot[2].hEventNotify = hHot3;
|
||||
_dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
||||
_dspnHot[2].hEventNotify = _hHot3;
|
||||
|
||||
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
|
||||
int a = 1;
|
||||
|
@ -748,11 +1124,11 @@ bool FPStream::play() {
|
|||
|
||||
switch (dwCodec) {
|
||||
case FPCODEC_RAW:
|
||||
lpCodec = new CODECRAW(bLoop);
|
||||
_codec = new CODECRAW(_bLoop);
|
||||
break;
|
||||
|
||||
case FPCODEC_ADPCM:
|
||||
lpCodec = new CODECADPCMSTEREO(bLoop);
|
||||
_codec = new CODECADPCMSTEREO(_bLoop);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -770,7 +1146,7 @@ bool FPStream::play() {
|
|||
}
|
||||
|
||||
/* Uncompress the data from the stream directly into the locked buffer */
|
||||
lpCodec->Decompress(hFile, lpBuf, dwBufferSize / 2);
|
||||
_codec->Decompress(hFile, lpBuf, dwBufferSize / 2);
|
||||
|
||||
/* Unlock the buffer */
|
||||
lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL);
|
||||
|
@ -846,7 +1222,7 @@ bool FPStream::stop(bool bSync) {
|
|||
GlobalFree(lpTempBuffer);
|
||||
|
||||
/* Close and free the CODEC */
|
||||
delete lpCodec;
|
||||
delete _codec;
|
||||
|
||||
bIsPlaying = false;
|
||||
bPaused = false;
|
||||
|
@ -882,7 +1258,7 @@ void FPStream::waitForSync(FPStream *toplay) {
|
|||
GlobalFree(lpTempBuffer);
|
||||
|
||||
/* Close and free the CODEC */
|
||||
delete lpCodec;
|
||||
delete _codec;
|
||||
#endif
|
||||
_bIsPlaying = false;
|
||||
}
|
||||
|
@ -892,129 +1268,110 @@ void FPStream::waitForSync(FPStream *toplay) {
|
|||
*
|
||||
*/
|
||||
|
||||
void FPStream::playThread(FPStream *This) {
|
||||
#ifdef REFACTOR_ME
|
||||
void FPStream::playThread(CORO_PARAM, const void *param) {
|
||||
CORO_BEGIN_CONTEXT;
|
||||
byte *lpLockBuf;
|
||||
uint32 dwResult;
|
||||
byte *lpLockBuf2;
|
||||
uint32 dwResult2;
|
||||
bool cicla = true;
|
||||
bool cicla;
|
||||
uint32 countEnd;
|
||||
bool bPrecache;
|
||||
char buf[1024];
|
||||
uint32 hList[5];
|
||||
CORO_END_CONTEXT(_ctx);
|
||||
|
||||
/* Events that signal when you need to do something */
|
||||
HANDLE hList[5] = { This->hThreadEnd, This->hHot1, This->hHot2, This->hHot3, This->hPlayThread_PlayFast };
|
||||
// FPStream *This = *(FPStream **)param;
|
||||
|
||||
bPrecache = true;
|
||||
countEnd = 0;
|
||||
while (cicla) {
|
||||
if (This->lpCodec->EndOfStream() && This->lpCodec->bLoop == false) {
|
||||
countEnd++;
|
||||
if (countEnd == 3)
|
||||
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 (bPrecache)
|
||||
This->lpCodec->Decompress(This->_file, This->lpTempBuffer, This->dwBufferSize / 2);
|
||||
// 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);
|
||||
|
||||
bPrecache = false;
|
||||
_ctx->bPrecache = false;
|
||||
|
||||
/* Waits for an event. Since they are all in automatic reset, there is no need to reset it after */
|
||||
// Waits for an event. Since they are all in automatic reset, there is no need to reset it after
|
||||
|
||||
// uint32 dwBufStatus;
|
||||
// This->lpDSBuffer->GetStatus(&dwBufStatus);
|
||||
uint32 dwBufStatus;
|
||||
|
||||
CORO_INVOKE_4(CoroScheduler.waitForMultipleObjects, 5, _ctx->hList, false, CORO_INFINITE, &_ctx->dwResult);
|
||||
|
||||
// sprintf(buf, "WFMO: %x (buf status: %x) MyThread: 0x%x\n", This->lpDSBuffer, dwBufStatus, GetCurrentThreadId());
|
||||
// warning(buf);
|
||||
dwResult = WaitForMultipleObjects(5, hList, false, CORO_INFINITE);
|
||||
|
||||
/* uint32 dwPlay, dwWrite;
|
||||
This->lpDSBuffer->GetCurrentPosition(&dwPlay, &dwWrite);
|
||||
sprintf(buf, "CP Play: %u, Write: %u\n", dwPlay, dwWrite);
|
||||
warning(buf); */
|
||||
|
||||
/* Make a switch to determine which event has been set */
|
||||
switch (dwResult - WAIT_OBJECT_0) {
|
||||
case 0:
|
||||
// Check to determine which event has been set
|
||||
if (CoroScheduler.getEvent(This->_hThreadEnd)->signalled) {
|
||||
/* Must leave the thread */
|
||||
cicla = false;
|
||||
break;
|
||||
_ctx->cicla = false;
|
||||
|
||||
case 1:
|
||||
/* Must fill the second half of the buffer */
|
||||
// if (dwPlay >= This->dspnHot[0].dwOffset && dwPlay <= This->dspnHot[0].dwOffset+1024 )
|
||||
{
|
||||
// sprintf(buf, "Prima metà buffer: %x\n", This->lpDSBuffer);
|
||||
// warning(buf);
|
||||
This->lpDSBuffer->Lock(This->dwBufferSize / 2, This->dwBufferSize / 2, (void **)&lpLockBuf, &dwResult, (void **)&lpLockBuf2, &dwResult2, 0);
|
||||
// sprintf(buf, "LockedBuf: dwResult=%x, dwBufferSize/2=%x, lpLockBuf2=%x, dwResult2=%x\n", dwResult, This->dwBufferSize/2, lpLockBuf2, dwResult2);
|
||||
// warning(buf);
|
||||
copyMemory(lpLockBuf, This->lpTempBuffer, This->dwBufferSize / 2);
|
||||
This->lpDSBuffer->Unlock(lpLockBuf, This->dwBufferSize / 2, lpLockBuf2, 0);
|
||||
bPrecache = true;
|
||||
}
|
||||
break;
|
||||
} 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);
|
||||
|
||||
case 2:
|
||||
/* Must fill the first half of the buffer */
|
||||
// if (dwPlay >= This->dspnHot[1].dwOffset && dwPlay <= This->dspnHot[1].dwOffset+1024 )
|
||||
{
|
||||
// sprintf(buf, "Seconda metà buffer: %x\n", This->lpDSBuffer);
|
||||
// warning(buf);
|
||||
This->lpDSBuffer->Lock(0, This->dwBufferSize / 2, (void **)&lpLockBuf, &dwResult, NULL, NULL, 0);
|
||||
copyMemory(lpLockBuf, This->lpTempBuffer, This->dwBufferSize / 2);
|
||||
This->lpDSBuffer->Unlock(lpLockBuf, This->dwBufferSize / 2, NULL, NULL);
|
||||
bPrecache = true;
|
||||
}
|
||||
break;
|
||||
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);
|
||||
|
||||
case 3: {
|
||||
// sprintf(buf, "End of buffer %x (SyncToPlay [%x]=%x, SyncExit: [%x]=%d)\n", This->lpDSBuffer, &This->SyncToPlay, This->SyncToPlay, &This->bSyncExit, This->bSyncExit);
|
||||
// warning(buf);
|
||||
if (This->bSyncExit) {
|
||||
// sprintf(buf, "Go with sync (Buffer: %x) MyThread: %x!\n", This->SyncToPlay->lpDSBuffer, GetCurrentThreadId());
|
||||
// warning(buf);
|
||||
//This->SyncToPlay->PlayFast();
|
||||
SetEvent(This->SyncToPlay->hPlayThread_PlayFast);
|
||||
// Transfer immediatly control to the other threads
|
||||
Sleep(0);
|
||||
This->bSyncExit = false;
|
||||
cicla = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
CORO_SLEEP(1);
|
||||
|
||||
case 4:
|
||||
This->PlayFast();
|
||||
This->_bSyncExit = false;
|
||||
_ctx->cicla = false;
|
||||
break;
|
||||
}
|
||||
} else if (CoroScheduler.getEvent(This->_hPlayThreadPlayFast)->signalled) {
|
||||
This->playFast();
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the DirectSound buffer */
|
||||
// sprintf(buf, "Exiting thread. Buffer = %x, MyThread = 0x%x\n", This->lpDSBuffer, GetCurrentThreadId());
|
||||
// warning(buf);
|
||||
// Close the DirectSound buffer
|
||||
This->lpDSBuffer->Stop();
|
||||
|
||||
ExitThread(0);
|
||||
#endif
|
||||
|
||||
CORO_END_CODE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unables or disables stream loop.
|
||||
*
|
||||
* @param bLoop True enable loop, False disables it
|
||||
* @param _bLoop True enable loop, False disables it
|
||||
*
|
||||
* @remarks The loop must be activated BEFORE the stream starts
|
||||
* playing. Any changes made during the play will have no
|
||||
* effect until the stream is stopped then played again.
|
||||
*/
|
||||
|
||||
void FPStream::setLoop(bool loop) {
|
||||
_bLoop = loop;
|
||||
}
|
||||
|
@ -1025,38 +1382,38 @@ void FPStream::setLoop(bool loop) {
|
|||
*
|
||||
* @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;
|
||||
|
||||
if (bFileLoaded) {
|
||||
if (bPause && bIsPlaying) {
|
||||
lpDSBuffer->Stop();
|
||||
bIsPlaying = false;
|
||||
bPaused = true;
|
||||
} else if (!bPause && bPaused) {
|
||||
dspnHot[0].dwOffset = 32;
|
||||
dspnHot[0].hEventNotify = hHot1;
|
||||
_dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
||||
_dspnHot[1].hEventNotify = hHot2;
|
||||
|
||||
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
||||
dspnHot[1].hEventNotify = hHot2;
|
||||
|
||||
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
||||
dspnHot[2].hEventNotify = hHot3;
|
||||
_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);
|
||||
bIsPlaying = true;
|
||||
bPaused = false;
|
||||
lpDSBuffer->Play(0, 0, _bLoop);
|
||||
#endif
|
||||
_bIsPlaying = true;
|
||||
_bPaused = false;
|
||||
|
||||
// Trick to reset the volume after a possible new sound configuration
|
||||
SetVolume(lastVolume);
|
||||
setVolume(_lastVolume);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -245,6 +245,24 @@ public:
|
|||
bool endOfBuffer() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Codec base class
|
||||
*/
|
||||
class CODEC {
|
||||
protected:
|
||||
bool _bEndReached;
|
||||
|
||||
public:
|
||||
bool _bLoop;
|
||||
|
||||
CODEC(bool _bLoop = true);
|
||||
virtual ~CODEC();
|
||||
virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize) = 0;
|
||||
virtual void loopReset() = 0;
|
||||
bool endOfStream();
|
||||
};
|
||||
|
||||
|
||||
class FPStream {
|
||||
private:
|
||||
// HWND hwnd;
|
||||
|
@ -258,12 +276,12 @@ private:
|
|||
uint32 _dwSize; // Stream size (bytes)
|
||||
uint32 _dwCodec; // CODEC used
|
||||
|
||||
HANDLE _hThreadEnd; // Event used to close thread
|
||||
uint32 _hThreadEnd; // Event used to close thread
|
||||
Common::File _file; // File handle used for the stream
|
||||
HANDLE _hPlayThread; // Handle of the Play thread
|
||||
HANDLE _hHot1, _hHot2, _hHot3; // Events set by DirectSoundNotify
|
||||
HANDLE _hPlayThreadPlayFast;
|
||||
HANDLE _hPlayThreadPlayNormal;
|
||||
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
|
||||
|
@ -273,6 +291,7 @@ private:
|
|||
bool _bPaused;
|
||||
int _lastVolume;
|
||||
FPStream *_syncToPlay;
|
||||
CODEC *_codec;
|
||||
|
||||
// DSBPOSITIONNOTIFY dspnHot[3];
|
||||
|
||||
|
@ -286,7 +305,7 @@ private:
|
|||
* Thread playing the stream
|
||||
*
|
||||
*/
|
||||
static void playThread(FPStream *This);
|
||||
static void playThread(CORO_PARAM, const void *param);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -321,13 +340,13 @@ public:
|
|||
/**
|
||||
* Opens a file stream
|
||||
*
|
||||
* @param lpszFile Filename to be opened
|
||||
* @param fileName Filename to be opened
|
||||
* @param dwCodec CODEC to be used to uncompress samples
|
||||
*
|
||||
* @returns True is everything is OK, False otherwise
|
||||
*/
|
||||
|
||||
bool loadFile(const char *lpszFileName, uint32 dwCodec = FPCODEC_RAW, int nSync = 2000);
|
||||
bool loadFile(const Common::String &fileName, uint32 dwCodec = FPCODEC_RAW, int nSync = 2000);
|
||||
|
||||
/**
|
||||
* Closes a file stream (opened or not).
|
||||
|
|
|
@ -187,10 +187,7 @@ void TonyEngine::GUIError(const Common::String &msg) {
|
|||
GUIErrorMessage(msg);
|
||||
}
|
||||
|
||||
void TonyEngine::playMusic(int nChannel, const char *fn, int nFX, bool bLoop, int nSync) {
|
||||
warning("TODO: TonyEngine::playMusic");
|
||||
// g_system->lockMutex(csMusic);
|
||||
|
||||
void TonyEngine::playMusic(int nChannel, const Common::String &fname, int nFX, bool bLoop, int nSync) {
|
||||
if (nChannel < 4)
|
||||
if (GLOBALS._flipflop)
|
||||
nChannel = nChannel + 1;
|
||||
|
@ -207,64 +204,78 @@ void TonyEngine::playMusic(int nChannel, const char *fn, int nFX, bool bLoop, in
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef REFACTOR_ME
|
||||
// Mette il path giusto
|
||||
if (nChannel < 4)
|
||||
GetDataDirectory(DD_MUSIC, path_buffer);
|
||||
else
|
||||
GetDataDirectory(DD_LAYER, path_buffer);
|
||||
_splitpath(path_buffer, drive, dir, NULL, NULL);
|
||||
_splitpath(fn, NULL, NULL, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, fname, ext);
|
||||
|
||||
_makepath(path_buffer, drive, dir, fname, ext);
|
||||
|
||||
if (nFX == 22) { // Sync a tempo
|
||||
curChannel = nChannel;
|
||||
strcpy(nextMusic, path_buffer);
|
||||
nextLoop = bLoop;
|
||||
nextSync = nSync;
|
||||
if (flipflop)
|
||||
nextChannel = nChannel - 1;
|
||||
GLOBALS._curChannel = nChannel;
|
||||
GLOBALS._nextLoop = bLoop;
|
||||
GLOBALS._nextSync = nSync;
|
||||
if (GLOBALS._flipflop)
|
||||
GLOBALS._nextChannel = nChannel - 1;
|
||||
else
|
||||
nextChannel = nChannel + 1;
|
||||
DWORD id;
|
||||
HANDLE hThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)DoNextMusic, _stream, 0, &id);
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
||||
GLOBALS._nextChannel = nChannel + 1;
|
||||
|
||||
uint32 hThread = CoroScheduler.createProcess(doNextMusic, &_stream, sizeof(FPStream ***));
|
||||
assert(hThread != CORO_INVALID_PID_VALUE);
|
||||
|
||||
} else if (nFX == 44) { // Cambia canale e lascia finire il primo
|
||||
if (flipflop)
|
||||
nextChannel = nChannel - 1;
|
||||
if (GLOBALS._flipflop)
|
||||
GLOBALS._nextChannel = nChannel - 1;
|
||||
else
|
||||
nextChannel = nChannel + 1;
|
||||
GLOBALS._nextChannel = nChannel + 1;
|
||||
|
||||
_stream[nextChannel]->Stop();
|
||||
_stream[nextChannel]->UnloadFile();
|
||||
_stream[GLOBALS._nextChannel]->stop();
|
||||
_stream[GLOBALS._nextChannel]->unloadFile();
|
||||
|
||||
if (!getIsDemo()) {
|
||||
if (!_stream[nextChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync))
|
||||
theGame.Abort();
|
||||
if (!_stream[GLOBALS._nextChannel]->loadFile(fname, FPCODEC_ADPCM, nSync))
|
||||
_vm->abortGame();
|
||||
} else {
|
||||
_stream[nextChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync);
|
||||
_stream[GLOBALS._nextChannel]->loadFile(fname, FPCODEC_ADPCM, nSync);
|
||||
}
|
||||
|
||||
_stream[nextChannel]->SetLoop(bLoop);
|
||||
_stream[nextChannel]->Play();
|
||||
_stream[GLOBALS._nextChannel]->setLoop(bLoop);
|
||||
_stream[GLOBALS._nextChannel]->play();
|
||||
|
||||
flipflop = 1 - flipflop;
|
||||
GLOBALS._flipflop = 1 - GLOBALS._flipflop;
|
||||
} else {
|
||||
if (!getIsDemo()) {
|
||||
if (!_stream[nChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync))
|
||||
theGame.Abort();
|
||||
if (!_stream[nChannel]->loadFile(fname, FPCODEC_ADPCM, nSync))
|
||||
_vm->abortGame();
|
||||
} else {
|
||||
_stream[nChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync);
|
||||
_stream[nChannel]->loadFile(fname, FPCODEC_ADPCM, nSync);
|
||||
}
|
||||
|
||||
_stream[nChannel]->SetLoop(bLoop);
|
||||
_stream[nChannel]->Play();
|
||||
_stream[nChannel]->setLoop(bLoop);
|
||||
_stream[nChannel]->play();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// g_system->unlockMutex(csMusic);
|
||||
void TonyEngine::doNextMusic(CORO_PARAM, const void *param) {
|
||||
CORO_BEGIN_CONTEXT;
|
||||
Common::String fn;
|
||||
CORO_END_CONTEXT(_ctx);
|
||||
|
||||
FPStream **streams = *(FPStream ***)param;
|
||||
|
||||
CORO_BEGIN_CODE(_ctx);
|
||||
|
||||
if (!_vm->getIsDemo()) {
|
||||
if (!streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, FPCODEC_ADPCM, GLOBALS._nextSync))
|
||||
_vm->abortGame();
|
||||
} else {
|
||||
streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, FPCODEC_ADPCM, GLOBALS._nextSync);
|
||||
}
|
||||
|
||||
streams[GLOBALS._nextChannel]->setLoop(GLOBALS._nextLoop);
|
||||
streams[GLOBALS._nextChannel]->prefetch();
|
||||
|
||||
streams[GLOBALS._curChannel]->stop(true);
|
||||
streams[GLOBALS._curChannel]->waitForSync(streams[GLOBALS._nextChannel]);
|
||||
|
||||
streams[GLOBALS._curChannel]->unloadFile();
|
||||
|
||||
GLOBALS._flipflop = 1 - GLOBALS._flipflop;
|
||||
|
||||
CORO_END_CODE;
|
||||
}
|
||||
|
||||
void TonyEngine::playSFX(int nChannel, int nFX) {
|
||||
|
|
|
@ -87,6 +87,8 @@ private:
|
|||
void closeVoiceDatabase();
|
||||
void initCustomFunctionMap();
|
||||
static void playProcess(CORO_PARAM, const void *param);
|
||||
static void doNextMusic(CORO_PARAM, const void *param);
|
||||
|
||||
protected:
|
||||
// Engine APIs
|
||||
virtual Common::Error run();
|
||||
|
@ -183,7 +185,7 @@ public:
|
|||
|
||||
// Music
|
||||
// ******
|
||||
void playMusic(int nChannel, const char *fn, int nFX, bool bLoop, int nSync);
|
||||
void playMusic(int nChannel, const Common::String &fn, int nFX, bool bLoop, int nSync);
|
||||
void stopMusic(int nChannel);
|
||||
|
||||
void playSFX(int nSfx, int nFX = 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue