diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp index df633e3be2d..450384b3418 100644 --- a/engines/tony/sound.cpp +++ b/engines/tony/sound.cpp @@ -37,693 +37,8 @@ namespace Tony { * Defines \****************************************************************************/ -/* Massimo numero di bytes da decodificare in una singola chiamata a CODEC */ -#define MAXDECODESIZE (44100 * 2 * 2) - #define RELEASE(x) {if ((x) != NULL) { (x)->Release(); x = NULL; }} -/****************************************************************************\ -***************************************************************************** -* class CODEC (ABSTRACT) -* ----------- -* Description: classe base per CODEC. -***************************************************************************** -\****************************************************************************/ - -class CODEC { -protected: - bool bEndReached; - -public: - bool bLoop; - CODEC(bool bLoop = true); - virtual ~CODEC(); - virtual uint32 Decompress(HANDLE hStream, void *lpBuf, uint32 dwSize) = 0; - virtual uint32 Decompress(Common::File &fp, void *lpBuf, uint32 dwSize) = 0; - virtual void LoopReset() = 0; - bool EndOfStream(); -}; - - -/****************************************************************************\ -***************************************************************************** -* class CODECRAW -* -------------- -* Description: CODEC di play da disco di campioni puri -***************************************************************************** -\****************************************************************************/ - -class CODECRAW : public CODEC { -public: - CODECRAW(bool bLoop = true); - virtual ~CODECRAW(); - virtual uint32 Decompress(HANDLE hStream, void *lpBuf, uint32 dwSize); - virtual uint32 Decompress(Common::File &fp, void *lpBuf, uint32 dwSize); - virtual void LoopReset(); -}; - - -/****************************************************************************\ -***************************************************************************** -* class CODECADPCM -* ---------------- -* Description: CODEC per play di compressione ADPCM -***************************************************************************** -\****************************************************************************/ - -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(HANDLE hStream, void *lpBuf, uint32 dwSize) = 0; - virtual uint32 Decompress(Common::File &fp, 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(HANDLE hStream, void *lpBuf, uint32 dwSize); - virtual uint32 Decompress(Common::File &fp, 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(HANDLE hStream, void *lpBuf, uint32 dwSize); - virtual uint32 Decompress(Common::File &fp, void *lpBuf, uint32 dwSize); - virtual void LoopReset(); -}; - -/****************************************************************************\ -* Metodi per CODEC -\****************************************************************************/ - - -/****************************************************************************\ -* -* Function: CODEC::CODEC(bool loop = true); -* -* Description: Costruttore standard. E' possibile specificare se si vuole -* attivare o disattivare il loop (che di default e' attivo). -* -* Input: bool loop true se si vuole attivare il loop, -* false per disattivarlo -* -\****************************************************************************/ - -CODEC::CODEC(bool loop) { - bLoop = loop; - bEndReached = false; -} - -CODEC::~CODEC() { - -} - -/****************************************************************************\ -* -* Function: bool CODEC::EndOfStream() -* -* Description: Informa se abbiamo raggiunto la fine dello stream -* -* Return: true se siamo arrivati alla fine, false altrimenti -* -\****************************************************************************/ - -bool CODEC::EndOfStream() { - return bEndReached; -} - - -/****************************************************************************\ -* Metodi per CODECRAW -\****************************************************************************/ - -/****************************************************************************\ -* -* Function: CODECRAW::CODECRAW(bool loop = true); -* -* Description: Costruttore standard. Richiama solamente il costruttore della -* classe astratta CODEC. -* -* Input: bool loop true se si vuole attivare il loop, -* false per disattivarlo -* -\****************************************************************************/ - -CODECRAW::CODECRAW(bool loop) : CODEC(loop) { -} - -CODECRAW::~CODECRAW() { - -} - -/****************************************************************************\ -* -* Function: CODECRAW::LoopReset(); -* -* Description: Resetta il playing prima di iniziare di nuovo il file. -* Nel caso dei file RAW non fa nulla. -* -\****************************************************************************/ - -void CODECRAW::LoopReset() { -} - -/****************************************************************************\ -* -* Function: uint32 CODECRAW::Decompress(HANDLE hStream, void *lpBuf, -* uint32 dwSize) -* -* Description: Gestisce il formato RAW: semplicemente copia dal file -* stream nel buffer. -* -* Return: Se e' stata raggiunta la fine del file, indica quale byte, -* tra quelli letti, e' l'inizio del nuovo loop. Altrimenti -* il valore non e' determinato. -* -\****************************************************************************/ - -uint32 CODECRAW::Decompress(HANDLE hStream, void *buf, uint32 dwSize) { -#if 0 - byte *lpBuf = (byte *)buf; - uint32 dwRead; - uint32 dwEOF; - - bEndReached = false; - dwEOF = 0; - ReadFile(hStream, lpBuf, dwSize, &dwRead, NULL); - - if (dwRead < dwSize) { - dwEOF = dwRead; - bEndReached = true; - - if (!bLoop) { - ZeroMemory(lpBuf + dwRead, dwSize - dwRead); - } else { - SetFilePointer(hStream, 0, NULL, FILE_BEGIN); - ReadFile(hStream, lpBuf + dwRead, dwSize - dwRead, &dwRead, NULL); - } - } - - return dwEOF; -#endif - return 0; -} - -uint32 CODECRAW::Decompress(Common::File &fp, void *buf, uint32 dwSize) { - byte *lpBuf = (byte *)buf; - uint32 dwRead; - uint32 dwEOF; - - bEndReached = false; - dwEOF = 0; - - dwRead = fp.read(lpBuf, dwSize); - - if (dwRead < dwSize) { - dwEOF = dwRead; - bEndReached = true; - - if (!bLoop) { - Common::fill(lpBuf + dwRead, lpBuf + dwRead + (dwSize - dwRead), 0); - } else { - fp.seek(0); - fp.read(lpBuf + dwRead, dwSize - dwRead); - } - } - - return dwEOF; -} - -/****************************************************************************\ -* Metodi per CODECADPCM -\****************************************************************************/ - -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 -}; - - -/****************************************************************************\ -* -* Function: CODECADPCM::CODECADPCM() -* -* Description: Costruttore. Inizializza le tabelle e alloca la memoria -* temporanea. -* -\****************************************************************************/ - -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) { - /* Inizializza per il playing */ - LoopReset(); -} - -CODECADPCMSTEREO::~CODECADPCMSTEREO() { - -} - -/****************************************************************************\ -* -* Function: CODECADPCM::~CODECADPCM() -* -* Description: Distruttore. Libera la memoria temporanea. -* -\****************************************************************************/ - -CODECADPCM::~CODECADPCM() { - globalFree(lpTemp); -} - - -/****************************************************************************\ -* -* Function: CODECADPCM::LoopReset() -* -* Description: Resetta il player prima di ogni play o loop. -* -\****************************************************************************/ - -void CODECADPCMSTEREO::LoopReset() { - valpred[0] = 0; - valpred[1] = 0; - index[0] = 0; - index[1] = 0; -} - -void CODECADPCMMONO::LoopReset() { - valpred = 0; - index = 0; -} - -/****************************************************************************\ -* -* Function: CODECADPCM::Decompress(HANDLE hStream, void *lpBuf, -* uint32 dwSize); -* -* Description: Gestisce il formato ADPCM 16:4. La routine dovrebbe essere -* ottimizzata in Assembler per garantire migliori performance. -* -\****************************************************************************/ - -uint32 CODECADPCMMONO::Decompress(HANDLE hFile, void *buf, uint32 dwSize) { -#if 0 - uint16 *lpBuf = (uint16 *)buf; - byte *inp; - int bufferstep; - int cache; - int delta; - int sign; - int vpdiff; - uint32 eof, i; - int step; - uint32 dwRead; - - bufferstep = 1; - step = stepSizeTable[index]; - - /* Richiama il CODEC RAW per leggere da disco lo stream con loop. La - chiamata e' possibile perche' abbiamo ereditato CODECADPCM da CODECRAW, - e non semplicemente da CODEC. */ - eof = CODECRAW::Decompress(hFile, lpTemp, dwSize / 4); - inp = lpTemp; - - eof *= 2; - /* Se bisogna loopare subito lo fa */ - if (EndOfStream() && eof == 0) { - LoopReset(); - bufferstep = 1; - step = stepSizeTable[index]; - } else if (!EndOfStream()) - eof = 0; - - dwSize /= 2; - for (i = 0; i < dwSize; i++) { - /* Controlla se siamo alla fine del file, e bisogna loopare */ - if (eof != 0 && i == eof) { - LoopReset(); - bufferstep = 1; - step = stepSizeTable[index]; - } - - /* Legge il delta (4 bit) */ - if (bufferstep) { - cache = *inp++; - delta = (cache >> 4) & 0xF; - } else - delta = cache & 0xF; - - /* Trova il nuovo indice */ - index += indexTable[delta]; - if (index < 0) index = 0; - if (index > 88) index = 88; - - /* Legge il segno e lo separa dall'ampliamento */ - sign = delta & 8; - delta = delta & 7; - - /* Trova la differenza dal valore precedente */ - 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; - - /* Controlla i limiti del valore trovato */ - if (valpred > 32767) - valpred = 32767; - else if (valpred < -32768) - valpred = -32768; - - /* Aggiorna lo step */ - step = stepSizeTable[index]; - - /* Scrive il valore trovato */ - *lpBuf++ = (signed short)valpred; - - bufferstep = !bufferstep; - } - - return eof / 2; -#endif - return 0; -} - -uint32 CODECADPCMMONO::Decompress(Common::File &fp, 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]; - - /* Richiama il CODEC RAW per leggere da disco lo stream con loop. La - chiamata e' possibile perche' abbiamo ereditato CODECADPCM da CODECRAW, - e non semplicemente da CODEC. */ - eof = CODECRAW::Decompress(fp, lpTemp, dwSize / 4); - inp = lpTemp; - - eof *= 2; - - /* Se bisogna loopare subito lo fa */ - if (EndOfStream() && eof == 0) { - LoopReset(); - bufferstep = 1; - step = stepSizeTable[index]; - } else if (!EndOfStream()) - eof = 0; - - dwSize /= 2; - for (i = 0; i < dwSize; i++) { - /* Controlla se siamo alla fine del file, e bisogna loopare */ - if (eof != 0 && i == eof) { - LoopReset(); - bufferstep = 1; - step = stepSizeTable[index]; - } - - /* Legge il delta (4 bit) */ - if (bufferstep) { - cache = *inp++; - delta = (cache >> 4) & 0xF; - } else - delta = cache & 0xF; - - /* Trova il nuovo indice */ - index += indexTable[delta]; - if (index < 0) index = 0; - if (index > 88) index = 88; - - /* Legge il segno e lo separa dall'ampliamento */ - sign = delta & 8; - delta = delta & 7; - - /* Trova la differenza dal valore precedente */ - 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; - - /* Controlla i limiti del valore trovato */ - if (valpred > 32767) - valpred = 32767; - else if (valpred < -32768) - valpred = - 32768; - - /* Aggiorna lo step */ - step = stepSizeTable[index]; - - /* Scrive il valore trovato */ - *lpBuf ++ = (signed short)valpred; - - bufferstep = !bufferstep; - } - - return eof / 2; -} - -uint32 CODECADPCMSTEREO::Decompress(HANDLE hFile, 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]]; - - /* Richiama il CODEC RAW per leggere da disco lo stream con loop. La - chiamata e' possibile perche' abbiamo ereditato CODECADPCM da CODECRAW, - e non semplicemente da CODEC. */ - eof = CODECRAW::Decompress(hFile, lpTemp, dwSize / 4); - inp = lpTemp; - - eof *= 2; - - /* Se bisogna loopare subito lo fa */ - 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++) { - /* Controlla se siamo alla fine del file, e bisogna loopare */ - if (eof != 0 && i == eof) { - LoopReset(); - bufferstep = 1; - step[0] = stepSizeTable[index[0]]; - step[1] = stepSizeTable[index[1]]; - } - - /* Legge il delta (4 bit) */ - if (bufferstep) { - cache = *inp++; - delta = cache & 0xF; - } else - delta = (cache >> 4) & 0xF; - - /* Trova il nuovo indice */ - index[bufferstep] += indexTable[delta]; - if (index[bufferstep] < 0) index[bufferstep] = 0; - if (index[bufferstep] > 88) index[bufferstep] = 88; - - /* Legge il segno e lo separa dall'ampliamento */ - sign = delta & 8; - delta = delta & 7; - - /* Trova la differenza dal valore precedente */ - 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; - - /* Controlla i limiti del valore trovato */ - if (valpred[bufferstep] > 32767) - valpred[bufferstep] = 32767; - else if (valpred[bufferstep] < -32768) - valpred[bufferstep] = -32768; - - /* Aggiorna lo step */ - step[bufferstep] = stepSizeTable[index[bufferstep]]; - - /* Scrive il valore trovato */ - *lpBuf ++ = (signed short)valpred[bufferstep]; - - bufferstep = !bufferstep; - } - - return eof / 2; -} - - -uint32 CODECADPCMSTEREO::Decompress(Common::File &fp, 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]]; - - /* Richiama il CODEC RAW per leggere da disco lo stream con loop. La - chiamata e' possibile perche' abbiamo ereditato CODECADPCM da CODECRAW, - e non semplicemente da CODEC. */ - eof = CODECRAW::Decompress(fp, lpTemp, dwSize / 4); - inp = lpTemp; - - eof *= 2; - /* Se bisogna loopare subito lo fa */ - 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++) { - /* Controlla se siamo alla fine del file, e bisogna loopare */ - if (eof != 0 && i == eof) { - LoopReset(); - bufferstep = 1; - step[0] = stepSizeTable[index[0]]; - step[1] = stepSizeTable[index[1]]; - } - - /* Legge il delta (4 bit) */ - if (bufferstep) { - cache = *inp++; - delta = cache & 0xF; - } else - delta = (cache >> 4) & 0xF; - - /* Trova il nuovo indice */ - index[bufferstep] += indexTable[delta]; - if (index[bufferstep] < 0) index[bufferstep] = 0; - if (index[bufferstep] > 88) index[bufferstep] = 88; - - /* Legge il segno e lo separa dall'ampliamento */ - sign = delta & 8; - delta = delta & 7; - - /* Trova la differenza dal valore precedente */ - 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; - - /* Controlla i limiti del valore trovato */ - if (valpred[bufferstep] > 32767) - valpred[bufferstep] = 32767; - else if (valpred[bufferstep] < -32768) - valpred[bufferstep] = -32768; - - /* Aggiorna lo step */ - step[bufferstep] = stepSizeTable[index[bufferstep]]; - - /* Scrive il valore trovato */ - *lpBuf ++ = (signed short)valpred[bufferstep]; - - bufferstep = !bufferstep; - } - - return eof / 2; -} - - /****************************************************************************\ * Metodi per FPSOUND \****************************************************************************/