2007-05-30 21:56:52 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
2003-09-24 06:56:30 +00:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2005-10-18 01:30:26 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2003-09-24 06:56:30 +00:00
*
2006-02-11 09:55:41 +00:00
* $ URL $
* $ Id $
2003-09-24 06:56:30 +00:00
*
*/
2005-06-24 15:23:51 +00:00
# include "common/stdafx.h"
2006-09-23 00:42:35 +00:00
# include "engines/engine.h"
2003-10-03 18:33:57 +00:00
# include "scumm/player_v2a.h"
# include "scumm/scumm.h"
namespace Scumm {
2003-09-24 06:56:30 +00:00
2003-09-27 19:43:06 +00:00
# define BASE_FREQUENCY 3579545
2004-01-08 12:14:48 +00:00
static uint32 CRCtable [ 256 ] ;
2007-09-01 19:13:04 +00:00
2004-01-08 12:14:48 +00:00
2007-09-10 13:17:20 +00:00
static void InitCRC ( void ) {
2003-09-24 06:56:30 +00:00
const uint32 poly = 0xEDB88320 ;
int i , j ;
uint32 n ;
2004-01-08 12:14:48 +00:00
2007-09-10 13:17:20 +00:00
for ( i = 0 ; i < 256 ; i + + ) {
2003-09-24 06:56:30 +00:00
n = i ;
for ( j = 0 ; j < 8 ; j + + )
n = ( n & 1 ) ? ( ( n > > 1 ) ^ poly ) : ( n > > 1 ) ;
CRCtable [ i ] = n ;
}
}
2003-10-03 23:34:06 +00:00
2007-09-10 13:17:20 +00:00
static uint32 GetCRC ( byte * data , int len ) {
2003-09-24 06:56:30 +00:00
uint32 CRC = 0xFFFFFFFF ;
int i ;
for ( i = 0 ; i < len ; i + + )
CRC = ( CRC > > 8 ) ^ CRCtable [ ( CRC ^ data [ i ] ) & 0xFF ] ;
return CRC ^ 0xFFFFFFFF ;
}
class V2A_Sound {
public :
V2A_Sound ( ) : _id ( 0 ) , _mod ( NULL ) { }
2007-04-25 19:31:23 +00:00
virtual ~ V2A_Sound ( ) { }
2003-09-27 19:43:06 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) = 0 ;
virtual bool update ( ) = 0 ;
virtual void stop ( ) = 0 ;
protected :
int _id ;
Player_MOD * _mod ;
} ;
2005-02-09 00:36:15 +00:00
// unsupported sound effect, print warning message to console
2003-09-27 19:43:06 +00:00
class V2A_Sound_Unsupported : public V2A_Sound {
public :
2003-10-09 05:27:52 +00:00
V2A_Sound_Unsupported ( ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
warning ( " player_v2a - sound %i not supported yet " , id ) ;
}
virtual bool update ( ) { return false ; }
virtual void stop ( ) { }
2003-09-27 19:43:06 +00:00
} ;
2005-02-09 00:36:15 +00:00
// template, automatically stops all channels when a sound is silenced
2003-09-27 19:43:06 +00:00
template < int numChan >
class V2A_Sound_Base : public V2A_Sound {
public :
V2A_Sound_Base ( ) : _offset ( 0 ) , _size ( 0 ) , _data ( 0 ) { }
V2A_Sound_Base ( uint16 offset , uint16 size ) : _offset ( offset ) , _size ( size ) , _data ( 0 ) { }
virtual void stop ( ) {
assert ( _id ) ;
for ( int i = 0 ; i < numChan ; i + + )
_mod - > stopChannel ( _id | ( i < < 8 ) ) ;
_id = 0 ;
free ( _data ) ;
_data = 0 ;
}
2003-09-24 06:56:30 +00:00
protected :
2003-09-27 19:43:06 +00:00
const uint16 _offset ;
const uint16 _size ;
char * _data ;
2003-09-24 06:56:30 +00:00
} ;
2005-02-09 00:36:15 +00:00
// plays a music track
2003-09-27 06:33:22 +00:00
class V2A_Sound_Music : public V2A_Sound {
2003-09-24 06:56:30 +00:00
public :
2003-09-27 06:33:22 +00:00
V2A_Sound_Music ( uint16 instoff , uint16 voloff , uint16 chan1off , uint16 chan2off , uint16 chan3off , uint16 chan4off , uint16 sampoff , bool looped ) :
_instoff ( instoff ) , _voloff ( voloff ) , _chan1off ( chan1off ) , _chan2off ( chan2off ) , _chan3off ( chan3off ) , _chan4off ( chan4off ) , _sampoff ( sampoff ) , _looped ( looped ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_data = ( char * ) malloc ( READ_LE_UINT16 ( data ) ) ;
2003-09-27 22:53:09 +00:00
memcpy ( _data , data , READ_LE_UINT16 ( data ) ) ;
2003-09-24 06:56:30 +00:00
2003-09-27 06:33:22 +00:00
_chan [ 0 ] . dataptr_i = _chan1off ;
_chan [ 1 ] . dataptr_i = _chan2off ;
_chan [ 2 ] . dataptr_i = _chan3off ;
_chan [ 3 ] . dataptr_i = _chan4off ;
for ( int i = 0 ; i < 4 ; i + + ) {
_chan [ i ] . dataptr = _chan [ i ] . dataptr_i ;
_chan [ i ] . volbase = 0 ;
_chan [ i ] . volptr = 0 ;
_chan [ i ] . chan = 0 ;
_chan [ i ] . dur = 0 ;
_chan [ i ] . ticks = 0 ;
}
2003-09-24 06:56:30 +00:00
update ( ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
int i , j = 0 ;
for ( i = 0 ; i < 4 ; i + + ) {
2003-09-27 06:33:22 +00:00
if ( _chan [ i ] . dur ) {
if ( ! - - _chan [ i ] . dur ) {
_mod - > stopChannel ( _id | ( _chan [ i ] . chan < < 8 ) ) ;
} else {
_mod - > setChannelVol ( _id | ( _chan [ i ] . chan < < 8 ) ,
READ_BE_UINT16 ( _data + _chan [ i ] . volbase + ( _chan [ i ] . volptr + + < < 1 ) ) ) ;
if ( _chan [ i ] . volptr = = 0 ) {
_mod - > stopChannel ( _id | ( _chan [ i ] . chan < < 8 ) ) ;
_chan [ i ] . dur = 0 ;
}
}
}
if ( ! _chan [ i ] . dataptr ) {
2003-09-24 06:56:30 +00:00
j + + ;
continue ;
}
2003-09-27 06:33:22 +00:00
if ( READ_BE_UINT16 ( _data + _chan [ i ] . dataptr ) < = _chan [ i ] . ticks ) {
if ( READ_BE_UINT16 ( _data + _chan [ i ] . dataptr + 2 ) = = 0xFFFF ) {
if ( _looped ) {
_chan [ i ] . dataptr = _chan [ i ] . dataptr_i ;
_chan [ i ] . ticks = 0 ;
if ( READ_BE_UINT16 ( _data + _chan [ i ] . dataptr ) > 0 ) {
_chan [ i ] . ticks + + ;
continue ;
}
} else {
_chan [ i ] . dataptr = 0 ;
j + + ;
continue ;
}
2003-09-24 06:56:30 +00:00
}
2003-09-27 19:43:06 +00:00
int freq = BASE_FREQUENCY / READ_BE_UINT16 ( _data + _chan [ i ] . dataptr + 2 ) ;
2003-09-27 06:33:22 +00:00
int inst = READ_BE_UINT16 ( _data + _chan [ i ] . dataptr + 8 ) ;
_chan [ i ] . volbase = _voloff + ( READ_BE_UINT16 ( _data + _instoff + ( inst < < 5 ) ) < < 9 ) ;
_chan [ i ] . volptr = 0 ;
_chan [ i ] . chan = READ_BE_UINT16 ( _data + _chan [ i ] . dataptr + 6 ) & 0x3 ;
if ( _chan [ i ] . dur ) // if there's something playing, stop it
_mod - > stopChannel ( _id | ( _chan [ i ] . chan < < 8 ) ) ;
_chan [ i ] . dur = READ_BE_UINT16 ( _data + _chan [ i ] . dataptr + 4 ) ;
int vol = READ_BE_UINT16 ( _data + _chan [ i ] . volbase + ( _chan [ i ] . volptr + + < < 1 ) ) ;
2003-09-24 06:56:30 +00:00
int pan ;
2003-09-27 06:33:22 +00:00
if ( ( _chan [ i ] . chan = = 0 ) | | ( _chan [ i ] . chan = = 3 ) )
2003-09-24 06:56:30 +00:00
pan = - 127 ;
else pan = 127 ;
2003-09-27 06:33:22 +00:00
int offset = READ_BE_UINT16 ( _data + _instoff + ( inst < < 5 ) + 0x14 ) ;
int len = READ_BE_UINT16 ( _data + _instoff + ( inst < < 5 ) + 0x18 ) ;
int loopoffset = READ_BE_UINT16 ( _data + _instoff + ( inst < < 5 ) + 0x16 ) ;
int looplen = READ_BE_UINT16 ( _data + _instoff + ( inst < < 5 ) + 0x10 ) ;
int size = len + looplen ;
2003-09-24 06:56:30 +00:00
char * data = ( char * ) malloc ( size ) ;
2003-09-27 06:33:22 +00:00
memcpy ( data , _data + _sampoff + offset , len ) ;
memcpy ( data + len , _data + _sampoff + loopoffset , looplen ) ;
_mod - > startChannel ( _id | ( _chan [ i ] . chan < < 8 ) , data , size , freq , vol , len , looplen + len , pan ) ;
_chan [ i ] . dataptr + = 16 ;
2003-09-24 06:56:30 +00:00
}
2003-09-27 06:33:22 +00:00
_chan [ i ] . ticks + + ;
2003-09-24 06:56:30 +00:00
}
if ( j = = 4 )
return false ;
return true ;
}
virtual void stop ( ) {
assert ( _id ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
2003-09-27 06:33:22 +00:00
if ( _chan [ i ] . dur )
_mod - > stopChannel ( _id | ( _chan [ i ] . chan < < 8 ) ) ;
2003-09-24 06:56:30 +00:00
}
free ( _data ) ;
_id = 0 ;
}
private :
const uint16 _instoff ;
2003-09-27 06:33:22 +00:00
const uint16 _voloff ;
2003-09-24 06:56:30 +00:00
const uint16 _chan1off ;
const uint16 _chan2off ;
const uint16 _chan3off ;
const uint16 _chan4off ;
const uint16 _sampoff ;
2003-09-27 06:33:22 +00:00
const bool _looped ;
2003-09-24 06:56:30 +00:00
char * _data ;
2003-09-27 06:33:22 +00:00
struct tchan {
uint16 dataptr_i ;
uint16 dataptr ;
uint16 volbase ;
uint8 volptr ;
uint16 chan ;
uint16 dur ;
uint16 ticks ;
} _chan [ 4 ] ;
2003-09-24 06:56:30 +00:00
} ;
2005-02-09 00:36:15 +00:00
// plays a single waveform
2003-09-27 19:43:06 +00:00
class V2A_Sound_Single : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
V2A_Sound_Single ( uint16 offset , uint16 size , uint16 freq , uint8 vol ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq ( freq ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
int vol = ( _vol < < 2 ) | ( _vol > > 4 ) ;
2003-09-27 19:43:06 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _freq , vol , 0 , 0 ) ;
_ticks = 1 + ( 60 * _size * _freq ) / BASE_FREQUENCY ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
_ticks - - ;
if ( ! _ticks ) {
return false ;
}
return true ;
}
private :
const uint16 _freq ;
const uint8 _vol ;
int _ticks ;
} ;
2003-09-27 23:11:25 +00:00
2005-02-09 00:36:15 +00:00
// plays a single looped waveform
2003-09-27 19:43:06 +00:00
class V2A_Sound_SingleLooped : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2003-09-27 19:43:06 +00:00
V2A_Sound_SingleLooped ( uint16 offset , uint16 size , uint16 freq , uint8 vol , uint16 loopoffset , uint16 loopsize ) :
2003-09-30 17:03:36 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _loopoffset ( loopoffset ) , _loopsize ( loopsize ) , _freq ( freq ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
V2A_Sound_SingleLooped ( uint16 offset , uint16 size , uint16 freq , uint8 vol ) :
2003-09-30 17:03:36 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _loopoffset ( 0 ) , _loopsize ( size ) , _freq ( freq ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
int vol = ( _vol < < 2 ) | ( _vol > > 4 ) ;
2003-09-27 19:43:06 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _freq , vol , _loopoffset , _loopoffset + _loopsize ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
return true ;
}
private :
const uint16 _loopoffset ;
const uint16 _loopsize ;
const uint16 _freq ;
const uint8 _vol ;
} ;
2003-09-27 23:11:25 +00:00
2005-02-09 00:36:15 +00:00
// plays two looped waveforms
2003-09-27 19:43:06 +00:00
class V2A_Sound_MultiLooped : public V2A_Sound_Base < 2 > {
2003-09-24 06:56:30 +00:00
public :
V2A_Sound_MultiLooped ( uint16 offset , uint16 size , uint16 freq1 , uint8 vol1 , uint16 freq2 , uint8 vol2 ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 2 > ( offset , size ) , _freq1 ( freq1 ) , _vol1 ( vol1 ) , _freq2 ( freq2 ) , _vol2 ( vol2 ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 22:27:12 +00:00
char * tmp_data1 = ( char * ) malloc ( _size ) ;
char * tmp_data2 = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data1 , data + _offset , _size ) ;
memcpy ( tmp_data2 , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
int vol1 = ( _vol1 < < 1 ) | ( _vol1 > > 5 ) ;
int vol2 = ( _vol2 < < 1 ) | ( _vol2 > > 5 ) ;
2003-09-27 22:27:12 +00:00
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _freq1 , vol1 , 0 , _size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _freq2 , vol2 , 0 , _size , 127 ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
return true ;
}
private :
const uint16 _freq1 ;
const uint8 _vol1 ;
const uint16 _freq2 ;
const uint8 _vol2 ;
} ;
2003-09-27 23:11:25 +00:00
2005-02-09 00:36:15 +00:00
// plays two looped waveforms for a fixed number of frames
2003-09-27 22:53:09 +00:00
class V2A_Sound_MultiLoopedDuration : public V2A_Sound_MultiLooped {
2003-09-24 06:56:30 +00:00
public :
V2A_Sound_MultiLoopedDuration ( uint16 offset , uint16 size , uint16 freq1 , uint8 vol1 , uint16 freq2 , uint8 vol2 , uint16 numframes ) :
2003-09-27 22:53:09 +00:00
V2A_Sound_MultiLooped ( offset , size , freq1 , vol1 , freq2 , vol2 ) , _duration ( numframes ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
2003-09-27 22:53:09 +00:00
V2A_Sound_MultiLooped : : start ( mod , id , data ) ;
2003-09-24 06:56:30 +00:00
_ticks = 0 ;
}
virtual bool update ( ) {
assert ( _id ) ;
_ticks + + ;
2003-09-27 22:53:09 +00:00
if ( _ticks > = _duration )
2003-09-24 06:56:30 +00:00
return false ;
return true ;
}
private :
const uint16 _duration ;
int _ticks ;
} ;
2003-09-27 23:11:25 +00:00
2005-02-09 00:36:15 +00:00
// plays a single looped waveform which starts at one frequency and bends to another frequency, where it remains until stopped
2003-09-27 19:43:06 +00:00
class V2A_Sound_SingleLoopedPitchbend : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
V2A_Sound_SingleLoopedPitchbend ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint8 vol , uint8 step ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _vol ( vol ) , _step ( step ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
int vol = ( _vol < < 2 ) | ( _vol > > 4 ) ;
_curfreq = _freq1 ;
2003-09-27 19:43:06 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , vol , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
if ( _freq1 < _freq2 ) {
_curfreq + = _step ;
if ( _curfreq > _freq2 )
_curfreq = _freq2 ;
else
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
} else {
_curfreq - = _step ;
if ( _curfreq < _freq2 )
_curfreq = _freq2 ;
else
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
}
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint8 _vol ;
const uint16 _step ;
uint16 _curfreq ;
} ;
2003-09-27 23:11:25 +00:00
2005-02-09 00:36:15 +00:00
// plays a single looped waveform starting at a specific frequency/volume, dropping in frequency and fading volume to zero
2005-03-23 06:06:07 +00:00
// used when Maniac Mansion explodes
class V2A_Sound_Special_ManiacNuclear : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacNuclear ( uint16 offset , uint16 size , uint16 freq , uint8 vol ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq ( freq ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
_curvol = ( _vol < < 3 ) | ( _vol > > 3 ) ;
_curfreq = _freq ;
2005-02-09 00:36:15 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , _curvol > > 1 , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
_curfreq + = 2 ;
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
_curvol - - ;
if ( _curvol = = 0 )
return false ;
_mod - > setChannelVol ( _id , _curvol > > 1 ) ;
return true ;
}
private :
const uint16 _freq ;
const uint8 _vol ;
uint16 _curfreq ;
uint16 _curvol ;
} ;
2005-02-09 00:36:15 +00:00
// plays a single looped waveform, fading the volume from zero to maximum at one rate, then back to zero at another rate
2005-03-23 06:06:07 +00:00
// used when a microwave oven goes 'Ding'
class V2A_Sound_Special_ManiacDing : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacDing ( uint16 offset , uint16 size , uint16 freq , uint8 fadeinrate , uint8 fadeoutrate ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq ( freq ) , _fade1 ( fadeinrate ) , _fade2 ( fadeoutrate ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
_curvol = 1 ;
_dir = 0 ;
2005-02-09 00:36:15 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _freq , _curvol , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
if ( _dir = = 0 ) {
_curvol + = _fade1 ;
if ( _curvol > 0x3F ) {
_curvol = 0x3F ;
_dir = 1 ;
}
} else {
_curvol - = _fade2 ;
if ( _curvol < 1 )
return false ;
}
_mod - > setChannelVol ( _id , ( _curvol < < 2 ) | ( _curvol > > 4 ) ) ;
return true ;
}
private :
const uint16 _freq ;
const uint16 _fade1 ;
const uint16 _fade2 ;
int _curvol ;
int _dir ;
} ;
2005-02-09 00:36:15 +00:00
// plays two looped waveforms, fading the volume from zero to maximum at one rate, then back to zero at another rate
2005-03-23 06:06:07 +00:00
// used in Zak McKracken for several stereo 'Ding' sounds
class V2A_Sound_Special_ZakStereoDing : public V2A_Sound_Base < 2 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ZakStereoDing ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint8 fadeinrate , uint8 fadeoutrate ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 2 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _fade1 ( fadeinrate ) , _fade2 ( fadeoutrate ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 22:27:12 +00:00
char * tmp_data1 = ( char * ) malloc ( _size ) ;
char * tmp_data2 = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data1 , data + _offset , _size ) ;
memcpy ( tmp_data2 , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
_curvol = 1 ;
_dir = 0 ;
2003-09-27 22:27:12 +00:00
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _freq1 , 1 , 0 , _size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _freq2 , 1 , 0 , _size , 127 ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
if ( _dir = = 0 ) {
_curvol + = _fade1 ;
if ( _curvol > 0x3F ) {
_curvol = 0x3F ;
_dir = 1 ;
}
} else {
_curvol - = _fade2 ;
if ( _curvol < 1 )
return false ;
}
_mod - > setChannelVol ( _id | 0x000 , ( _curvol < < 1 ) | ( _curvol > > 5 ) ) ;
_mod - > setChannelVol ( _id | 0x100 , ( _curvol < < 1 ) | ( _curvol > > 5 ) ) ;
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint16 _fade1 ;
const uint16 _fade2 ;
int _curvol ;
int _dir ;
} ;
2005-02-09 00:36:15 +00:00
// plays a single looped waveform, starting at one frequency and at full volume, bending down to another frequency, and then fading volume to zero
2005-03-23 06:06:07 +00:00
// used in Maniac Mansion for the tentacle sounds
class V2A_Sound_Special_ManiacTentacle : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacTentacle ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint16 step ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _step ( step ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
_curfreq = _freq1 ;
_curvol = 0x3F ;
2003-09-27 19:43:06 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , ( _curvol < < 2 ) | ( _curvol > > 4 ) , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
if ( _curfreq > _freq2 )
_curvol = 0x3F + _freq2 - _curfreq ;
if ( _curvol < 1 )
return false ;
_curfreq + = _step ;
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
_mod - > setChannelVol ( _id , ( _curvol < < 2 ) | ( _curvol > > 4 ) ) ;
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint16 _step ;
uint16 _curfreq ;
int _curvol ;
} ;
2005-02-09 00:36:15 +00:00
// plays a single looped waveform, starting at one frequency, bending down to another frequency, and then back up to the original frequency
2005-03-23 06:06:07 +00:00
// used for electronic noises
class V2A_Sound_Special_ManiacElectric : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacElectric ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint16 step , uint8 vol ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _step ( step ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
int vol = ( _vol < < 2 ) | ( _vol > > 4 ) ;
_curfreq = _freq1 ;
_dir = 2 ;
2003-09-27 19:43:06 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , vol , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
if ( _dir = = 2 ) {
_curfreq + = _step ;
if ( _curfreq > _freq2 ) {
_curfreq = _freq2 ;
_dir = 1 ;
}
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
} else if ( _dir = = 1 ) {
_curfreq - = _step ;
if ( _curfreq < _freq1 ) {
_curfreq = _freq1 ;
_dir = 0 ;
}
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
}
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint16 _step ;
const uint8 _vol ;
uint16 _curfreq ;
int _dir ;
} ;
2005-02-09 00:36:15 +00:00
// plays a single looped waveform, simultaneously bending the frequency downward and slowly fading volume to zero
2005-03-23 06:06:07 +00:00
// don't remember where this one is used
// old name: SlowPitchbendDownAndFadeout
class V2A_Sound_Special_Maniac61 : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_Maniac61 ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
_curfreq = _freq1 ;
2003-09-27 22:27:12 +00:00
_curvol = 0x3F ;
2003-09-27 19:43:06 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , ( _curvol < < 2 ) | ( _curvol > > 4 ) , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
_curfreq + + ;
if ( ! ( _curfreq & 3 ) )
_curvol - - ;
if ( ( _curfreq = = _freq2 ) | | ( _curvol = = 0 ) )
return false ;
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
2003-09-24 06:56:30 +00:00
_mod - > setChannelVol ( _id , ( _curvol < < 2 ) | ( _curvol > > 4 ) ) ;
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
uint16 _curfreq ;
uint8 _curvol ;
} ;
2005-03-23 10:17:52 +00:00
// intermittently plays two looped waveforms for a specific duration
2005-03-23 06:06:07 +00:00
// used for ringing telephones
class V2A_Sound_Special_ManiacPhone : public V2A_Sound_Base < 2 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacPhone ( uint16 offset , uint16 size , uint16 freq1 , uint8 vol1 , uint16 freq2 , uint8 vol2 , uint16 numframes , uint8 playwidth , uint8 loopwidth ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 2 > ( offset , size ) , _freq1 ( freq1 ) , _vol1 ( vol1 ) , _freq2 ( freq2 ) , _vol2 ( vol2 ) , _duration ( numframes ) , _playwidth ( playwidth ) , _loopwidth ( loopwidth ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_data = ( char * ) malloc ( READ_LE_UINT16 ( data ) ) ;
2003-09-27 22:53:09 +00:00
memcpy ( _data , data , READ_LE_UINT16 ( data ) ) ;
2003-09-24 06:56:30 +00:00
soundon ( ) ;
_ticks = 0 ;
_loop = 0 ;
}
virtual bool update ( ) {
assert ( _id ) ;
2003-09-27 22:53:09 +00:00
if ( _loop = = _playwidth ) {
_mod - > stopChannel ( _id | 0x000 ) ;
_mod - > stopChannel ( _id | 0x100 ) ;
}
2003-09-24 06:56:30 +00:00
if ( _loop = = _loopwidth ) {
_loop = 0 ;
soundon ( ) ;
}
_loop + + ;
_ticks + + ;
2003-09-27 22:53:09 +00:00
if ( _ticks > = _duration )
2003-09-24 06:56:30 +00:00
return false ;
return true ;
}
private :
const uint16 _freq1 ;
const uint8 _vol1 ;
const uint16 _freq2 ;
const uint8 _vol2 ;
const uint16 _duration ;
const uint8 _playwidth ;
const uint8 _loopwidth ;
int _ticks ;
int _loop ;
void soundon ( ) {
2003-09-27 22:27:12 +00:00
char * tmp_data1 = ( char * ) malloc ( _size ) ;
char * tmp_data2 = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data1 , _data + _offset , _size ) ;
memcpy ( tmp_data2 , _data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
int vol1 = ( _vol1 < < 1 ) | ( _vol1 > > 5 ) ;
int vol2 = ( _vol2 < < 1 ) | ( _vol2 > > 5 ) ;
2003-09-27 22:27:12 +00:00
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _freq1 , vol1 , 0 , _size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _freq2 , vol2 , 0 , _size , 127 ) ;
2003-09-24 06:56:30 +00:00
}
} ;
2005-03-23 06:06:07 +00:00
// intermittently plays a single waveform for a specified duration
// used when applying a wrench to a pipe
class V2A_Sound_Special_ManiacWrench : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacWrench ( uint16 offset , uint16 size , uint16 freq , uint8 vol , uint8 loopwidth , uint8 numloops ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq ( freq ) , _vol ( vol ) , _loopwidth ( loopwidth ) , _numloops ( numloops ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_data = ( char * ) malloc ( READ_LE_UINT16 ( data ) ) ;
2003-09-27 22:53:09 +00:00
memcpy ( _data , data , READ_LE_UINT16 ( data ) ) ;
2003-09-24 06:56:30 +00:00
soundon ( ) ;
_loop = 0 ;
_loopctr = 0 ;
}
virtual bool update ( ) {
assert ( _id ) ;
_loop + + ;
if ( _loop = = _loopwidth ) {
_loop = 0 ;
_loopctr + + ;
if ( _loopctr = = _numloops )
return false ;
2003-09-27 22:53:09 +00:00
_mod - > stopChannel ( _id ) ;
2003-09-24 06:56:30 +00:00
soundon ( ) ;
}
return true ;
}
private :
const uint16 _freq ;
const uint8 _vol ;
const uint8 _loopwidth ;
const uint8 _numloops ;
int _loop ;
int _loopctr ;
void soundon ( ) {
2003-09-27 22:53:09 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , _data + _offset , _size ) ;
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _freq , ( _vol < < 2 ) | ( _vol > > 4 ) , 0 , 0 ) ;
2003-09-24 06:56:30 +00:00
}
} ;
2005-03-23 06:06:07 +00:00
// plays a single waveform at irregular intervals for a specified number of frames, possibly looped
// used for typewriter noises, as well as tapping on the bus in Zak McKracken
class V2A_Sound_Special_ManiacTypewriter : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacTypewriter ( uint16 offset , uint16 size , uint16 freq , uint8 vol , uint8 numdurs , const uint8 * durations , bool looped ) :
2003-09-27 22:27:12 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq ( freq ) , _vol ( vol ) , _numdurs ( numdurs ) , _durations ( durations ) , _looped ( looped ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_data = ( char * ) malloc ( READ_LE_UINT16 ( data ) ) ;
2003-09-27 22:53:09 +00:00
memcpy ( _data , data , READ_LE_UINT16 ( data ) ) ;
2003-09-24 06:56:30 +00:00
soundon ( ) ;
_curdur = 0 ;
2003-09-27 22:27:12 +00:00
_ticks = _durations [ _curdur + + ] ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
_ticks - - ;
if ( ! _ticks ) {
2003-09-27 22:27:12 +00:00
if ( _curdur = = _numdurs ) {
if ( _looped )
_curdur = 0 ;
else
return false ;
}
2003-09-27 22:53:09 +00:00
_mod - > stopChannel ( _id ) ;
2003-09-24 06:56:30 +00:00
soundon ( ) ;
_ticks = _durations [ _curdur + + ] ;
}
return true ;
}
private :
const uint16 _freq ;
const uint8 _vol ;
const uint8 _numdurs ;
const uint8 * _durations ;
2003-09-27 22:27:12 +00:00
const bool _looped ;
2003-09-24 06:56:30 +00:00
int _ticks ;
int _curdur ;
void soundon ( ) {
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , _data + _offset , _size ) ;
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _freq , ( _vol < < 2 ) | ( _vol > > 4 ) , 0 , 0 ) ;
2003-09-24 06:56:30 +00:00
}
} ;
2005-03-23 06:06:07 +00:00
// plays two looped waveforms pitch bending up at various predefined rates
// used for some sort of siren-like noise in Maniac Mansion
// old name: TwinSirenMulti
class V2A_Sound_Special_Maniac44 : public V2A_Sound_Base < 2 > {
2003-09-27 23:11:25 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_Maniac44 ( uint16 offset1 , uint16 size1 , uint16 offset2 , uint16 size2 , uint16 freq1 , uint16 freq2 , uint8 vol ) :
2003-09-27 23:11:25 +00:00
_offset1 ( offset1 ) , _size1 ( size1 ) , _offset2 ( offset2 ) , _size2 ( size2 ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _vol ( vol ) { }
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_data = ( char * ) malloc ( READ_LE_UINT16 ( data ) ) ;
memcpy ( _data , data , READ_LE_UINT16 ( data ) ) ;
2003-11-08 21:59:32 +00:00
2003-09-27 23:11:25 +00:00
_loopnum = 1 ;
_step = 2 ;
_curfreq = _freq1 ;
soundon ( _data + _offset1 , _size1 ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / _curfreq ) ;
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / ( _curfreq + 3 ) ) ;
_curfreq - = _step ;
if ( _loopnum = = 7 ) {
if ( ( BASE_FREQUENCY / _curfreq ) > = 65536 )
return false ;
else
return true ;
}
if ( _curfreq > = _freq2 )
return true ;
2003-11-08 21:59:32 +00:00
const char steps [ 8 ] = { 0 , 2 , 2 , 3 , 4 , 8 , 15 , 2 } ;
2003-09-27 23:11:25 +00:00
_curfreq = _freq1 ;
_step = steps [ + + _loopnum ] ;
if ( _loopnum = = 7 ) {
_mod - > stopChannel ( _id | 0x000 ) ;
_mod - > stopChannel ( _id | 0x100 ) ;
soundon ( _data + _offset2 , _size2 ) ;
}
return true ;
}
private :
const uint16 _offset1 ;
const uint16 _size1 ;
const uint16 _offset2 ;
const uint16 _size2 ;
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint8 _vol ;
int _curfreq ;
uint16 _loopnum ;
uint16 _step ;
void soundon ( const char * data , int size ) {
char * tmp_data1 = ( char * ) malloc ( size ) ;
char * tmp_data2 = ( char * ) malloc ( size ) ;
memcpy ( tmp_data1 , data , size ) ;
memcpy ( tmp_data2 , data , size ) ;
int vol = ( _vol < < 1 ) | ( _vol > > 5 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , size , BASE_FREQUENCY / _curfreq , vol , 0 , size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , size , BASE_FREQUENCY / ( _curfreq + 3 ) , vol , 0 , size , 127 ) ;
}
} ;
2005-03-23 06:06:07 +00:00
// plays 4 looped waveforms, each at modulating frequencies
// used for the siren noise in Maniac Mansion
class V2A_Sound_Special_ManiacSiren : public V2A_Sound_Base < 4 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ManiacSiren ( uint16 offset1 , uint16 size1 , uint16 offset2 , uint16 size2 , uint8 vol ) :
2003-09-24 06:56:30 +00:00
_offset1 ( offset1 ) , _size1 ( size1 ) , _offset2 ( offset2 ) , _size2 ( size2 ) , _vol ( vol ) { }
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_freq1 = 0x02D0 ;
_step1 = - 0x000A ;
_freq2 = 0x0122 ;
_step2 = 0x000A ;
_freq3 = 0x02BC ;
_step3 = - 0x0005 ;
_freq4 = 0x010E ;
_step4 = 0x0007 ;
2003-09-27 22:53:09 +00:00
char * tmp_data1 = ( char * ) malloc ( _size1 ) ;
char * tmp_data2 = ( char * ) malloc ( _size2 ) ;
char * tmp_data3 = ( char * ) malloc ( _size1 ) ;
char * tmp_data4 = ( char * ) malloc ( _size2 ) ;
memcpy ( tmp_data1 , data + _offset1 , _size1 ) ;
memcpy ( tmp_data2 , data + _offset2 , _size2 ) ;
memcpy ( tmp_data3 , data + _offset1 , _size1 ) ;
memcpy ( tmp_data4 , data + _offset2 , _size2 ) ;
2003-09-27 22:27:12 +00:00
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size1 , BASE_FREQUENCY / _freq1 , _vol , 0 , _size1 , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size2 , BASE_FREQUENCY / _freq2 , _vol , 0 , _size2 , 127 ) ;
2003-09-27 22:53:09 +00:00
_mod - > startChannel ( _id | 0x200 , tmp_data3 , _size1 , BASE_FREQUENCY / _freq3 , _vol , 0 , _size1 , 127 ) ;
_mod - > startChannel ( _id | 0x300 , tmp_data4 , _size2 , BASE_FREQUENCY / _freq4 , _vol , 0 , _size2 , - 127 ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
2003-11-08 21:59:32 +00:00
updatefreq ( _freq1 , _step1 , 0x00AA , 0x00FA ) ;
updatefreq ( _freq2 , _step2 , 0x019A , 0x03B6 ) ;
updatefreq ( _freq3 , _step3 , 0x00AA , 0x00FA ) ;
updatefreq ( _freq4 , _step4 , 0x019A , 0x03B6 ) ;
2003-09-27 19:43:06 +00:00
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / _freq1 ) ;
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / _freq2 ) ;
_mod - > setChannelFreq ( _id | 0x200 , BASE_FREQUENCY / _freq3 ) ;
_mod - > setChannelFreq ( _id | 0x300 , BASE_FREQUENCY / _freq4 ) ;
2003-09-24 06:56:30 +00:00
return true ;
}
private :
const uint16 _offset1 ;
const uint16 _size1 ;
const uint16 _offset2 ;
const uint16 _size2 ;
const uint8 _vol ;
uint16 _freq1 ;
int16 _step1 ;
uint16 _freq2 ;
int16 _step2 ;
uint16 _freq3 ;
int16 _step3 ;
uint16 _freq4 ;
int16 _step4 ;
void updatefreq ( uint16 & freq , int16 & step , uint16 min , uint16 max ) {
freq + = step ;
if ( freq < = min ) {
freq = min ;
step = - step ;
}
if ( freq > = max ) {
freq = max ;
step = - step ;
}
}
} ;
2005-02-09 00:36:15 +00:00
// plays 4 looped waveforms
2005-03-23 06:06:07 +00:00
// some sort of laserbeam-like sound effect in Zak
// old name: QuadFreqLooped
class V2A_Sound_Special_Zak70 : public V2A_Sound_Base < 4 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_Zak70 ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint16 freq3 , uint16 freq4 , uint8 vol ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 4 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _freq3 ( freq3 ) , _freq4 ( freq4 ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2005-07-30 21:11:48 +00:00
2003-09-27 22:27:12 +00:00
char * tmp_data1 = ( char * ) malloc ( _size ) ;
char * tmp_data2 = ( char * ) malloc ( _size ) ;
2003-09-27 22:53:09 +00:00
char * tmp_data3 = ( char * ) malloc ( _size ) ;
char * tmp_data4 = ( char * ) malloc ( _size ) ;
2003-09-27 22:27:12 +00:00
memcpy ( tmp_data1 , data + _offset , _size ) ;
memcpy ( tmp_data2 , data + _offset , _size ) ;
2003-09-27 22:53:09 +00:00
memcpy ( tmp_data3 , data + _offset , _size ) ;
memcpy ( tmp_data4 , data + _offset , _size ) ;
2003-09-27 22:27:12 +00:00
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _freq1 , _vol , 0 , _size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _freq2 , _vol , 0 , _size , 127 ) ;
2003-09-27 22:53:09 +00:00
_mod - > startChannel ( _id | 0x200 , tmp_data3 , _size , BASE_FREQUENCY / _freq3 , _vol , 0 , _size , 127 ) ;
_mod - > startChannel ( _id | 0x300 , tmp_data4 , _size , BASE_FREQUENCY / _freq4 , _vol , 0 , _size , - 127 ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
return true ;
}
2003-09-27 22:53:09 +00:00
protected :
2003-09-24 06:56:30 +00:00
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint16 _freq3 ;
const uint16 _freq4 ;
const uint8 _vol ;
} ;
2005-02-09 00:36:15 +00:00
// plays 4 looped waveforms and fades volume to zero after a specific delay
2005-03-23 06:06:07 +00:00
// some whooshing-type sound in Zak
// old name: QuadFreqFadeout
class V2A_Sound_Special_Zak101 : public V2A_Sound_Special_Zak70 {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_Zak101 ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint16 freq3 , uint16 freq4 , uint8 vol , uint16 dur ) :
V2A_Sound_Special_Zak70 ( offset , size , freq1 , freq2 , freq3 , freq4 , vol ) , _dur ( dur ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_Zak70 : : start ( mod , id , data ) ;
2003-09-24 06:56:30 +00:00
_ticks = _dur ;
}
virtual bool update ( ) {
assert ( _id ) ;
if ( ! - - _ticks )
return false ;
if ( _ticks < _vol ) {
_mod - > setChannelVol ( _id | 0x000 , _ticks ) ;
_mod - > setChannelVol ( _id | 0x100 , _ticks ) ;
_mod - > setChannelVol ( _id | 0x200 , _ticks ) ;
_mod - > setChannelVol ( _id | 0x300 , _ticks ) ;
}
return true ;
}
private :
const uint16 _dur ;
int _ticks ;
} ;
2005-02-09 00:36:15 +00:00
// plays a single looped waveform and slowly fades volume to zero
2005-03-23 06:06:07 +00:00
// another whooshing-type noise in Zak
// old name: SingleFadeout
class V2A_Sound_Special_Zak37 : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_Zak37 ( uint16 offset , uint16 size , uint16 freq , uint8 vol ) :
2003-09-27 19:43:06 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq ( freq ) , _vol ( vol ) { }
2003-09-24 06:56:30 +00:00
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
2003-09-27 19:43:06 +00:00
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
2003-09-24 06:56:30 +00:00
_curvol = _vol < < 2 ;
2005-02-09 00:36:15 +00:00
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _freq , _curvol , 0 , _size ) ;
2003-09-24 06:56:30 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
if ( ! - - _curvol )
return false ;
_mod - > setChannelVol ( _id , _curvol ) ;
return true ;
}
private :
const uint16 _freq ;
const uint8 _vol ;
int _curvol ;
} ;
2005-02-09 00:36:15 +00:00
// plays a single looped waveform, slowly bending from one frequency to another and then slowly fading volume from max to zero
2005-03-23 06:06:07 +00:00
// used in Zak for airplane taking off and landing
class V2A_Sound_Special_ZakAirplane : public V2A_Sound_Base < 1 > {
2003-09-27 22:27:12 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ZakAirplane ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 ) :
2003-09-27 22:27:12 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) { }
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
_curfreq = _freq1 ;
_curvol = 0x3F ;
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , ( _curvol < < 2 ) | ( _curvol > > 4 ) , 0 , _size ) ;
_ticks = 0 ;
}
virtual bool update ( ) {
assert ( _id ) ;
_ticks + + ;
if ( _ticks < 4 )
return true ;
_ticks = 0 ;
if ( _curfreq = = _freq2 ) {
_curvol - - ;
if ( _curvol = = 0 )
return false ;
_mod - > setChannelVol ( _id , ( _curvol < < 2 ) | ( _curvol > > 4 ) ) ;
}
else {
if ( _freq1 < _freq2 )
_curfreq + + ;
else
_curfreq - - ;
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
}
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
uint16 _curfreq ;
int _curvol ;
int _ticks ;
} ;
2005-02-09 00:25:43 +00:00
// plays 4 looped waveforms, starting at specific frequencies and bending at different rates while fading volume to zero
2005-03-23 06:06:07 +00:00
// used for some weird sound effect
2005-02-09 00:25:43 +00:00
class V2A_Sound_Special_Zak71 : public V2A_Sound_Base < 4 > {
public :
V2A_Sound_Special_Zak71 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_freq1 = 0x00C8 ;
_freq2 = 0x0190 ;
_freq3 = 0x0320 ;
_freq4 = 0x0640 ;
_vol = 0x78 ;
char * tmp_data1 = ( char * ) malloc ( _size ) ;
char * tmp_data2 = ( char * ) malloc ( _size ) ;
char * tmp_data3 = ( char * ) malloc ( _size ) ;
char * tmp_data4 = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data1 , data + _offset , _size ) ;
memcpy ( tmp_data2 , data + _offset , _size ) ;
memcpy ( tmp_data3 , data + _offset , _size ) ;
memcpy ( tmp_data4 , data + _offset , _size ) ;
2005-02-09 03:26:08 +00:00
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _freq1 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) , 0 , _size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _freq2 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) , 0 , _size , 127 ) ;
_mod - > startChannel ( _id | 0x200 , tmp_data3 , _size , BASE_FREQUENCY / _freq3 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) , 0 , _size , 127 ) ;
_mod - > startChannel ( _id | 0x300 , tmp_data4 , _size , BASE_FREQUENCY / _freq4 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) , 0 , _size , - 127 ) ;
2005-02-09 00:25:43 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
_freq1 + = 0x14 ;
_freq2 + = 0x1E ;
_freq3 + = 0x32 ;
_freq4 + = 0x50 ;
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / _freq1 ) ;
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / _freq2 ) ;
_mod - > setChannelFreq ( _id | 0x200 , BASE_FREQUENCY / _freq3 ) ;
_mod - > setChannelFreq ( _id | 0x300 , BASE_FREQUENCY / _freq4 ) ;
_vol - - ;
if ( _vol = = 0 )
return false ;
2005-02-09 03:26:08 +00:00
_mod - > setChannelVol ( _id | 0x000 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) ) ;
_mod - > setChannelVol ( _id | 0x100 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) ) ;
_mod - > setChannelVol ( _id | 0x200 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) ) ;
_mod - > setChannelVol ( _id | 0x300 , MIN ( ( _vol > > 1 ) + 3 , 0x32 ) ) ;
2005-02-09 00:25:43 +00:00
return true ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _freq1 ;
uint16 _freq2 ;
uint16 _freq3 ;
uint16 _freq4 ;
uint8 _vol ;
} ;
2005-03-23 06:06:07 +00:00
// plays a single looped waveform, bending the frequency upward at a varying rate
// used in Zak for the tram on Mars (?)
class V2A_Sound_Special_ZakTram : public V2A_Sound_Base < 1 > {
2003-12-14 08:57:53 +00:00
public :
2005-03-23 06:06:07 +00:00
V2A_Sound_Special_ZakTram ( uint16 offset , uint16 size , uint16 freq1 , uint16 freq2 , uint8 vol ) :
2003-12-14 08:57:53 +00:00
V2A_Sound_Base < 1 > ( offset , size ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) , _vol ( vol ) { }
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , data + _offset , _size ) ;
_curfreq = _freq1 ;
_mod - > startChannel ( _id , tmp_data , _size , BASE_FREQUENCY / _curfreq , ( _vol < < 2 ) | ( _vol > > 4 ) , 0 , _size ) ;
_bendrate = 8 ;
_bendctr = 100 ;
_holdctr = 30 ;
}
virtual bool update ( ) {
assert ( _id ) ;
2007-09-10 13:17:20 +00:00
if ( _curfreq > = _freq2 ) {
2003-12-14 08:57:53 +00:00
_mod - > setChannelFreq ( _id , BASE_FREQUENCY / _curfreq ) ;
_curfreq - = _bendrate ;
if ( - - _bendctr )
return true ;
_bendrate - - ;
if ( _bendrate < 2 )
_bendrate = 2 ;
2007-09-10 13:17:20 +00:00
} else {
2003-12-14 08:57:53 +00:00
if ( ! - - _holdctr )
return false ;
}
return true ;
}
private :
const uint16 _freq1 ;
const uint16 _freq2 ;
const uint16 _vol ;
uint16 _curfreq ;
uint16 _bendrate ;
uint16 _bendctr ;
uint16 _holdctr ;
} ;
2005-02-09 00:25:43 +00:00
// plays one waveform, then switches to a different looped waveform and slowly fades volume to zero
2005-03-23 06:06:07 +00:00
// used for some odd sound effect
2005-02-09 00:25:43 +00:00
class V2A_Sound_Special_Zak54 : public V2A_Sound_Base < 1 > {
public :
V2A_Sound_Special_Zak54 ( uint16 offset1 , uint16 size1 , uint16 offset2 , uint16 size2 , uint16 freq ) :
_offset1 ( offset1 ) , _size1 ( size1 ) , _offset2 ( offset2 ) , _size2 ( size2 ) , _freq ( freq ) { }
virtual void start ( Player_MOD * mod , int id , const byte * data ) {
_mod = mod ;
_id = id ;
_data = ( char * ) malloc ( READ_LE_UINT16 ( data ) ) ;
memcpy ( _data , data , READ_LE_UINT16 ( data ) ) ;
char * tmp_data = ( char * ) malloc ( _size1 ) ;
memcpy ( tmp_data , data + _offset1 , _size1 ) ;
_vol = 0xFC ;
_mod - > startChannel ( _id , tmp_data , _size1 , BASE_FREQUENCY / _freq , _vol , 0 , _size1 ) ;
_loop = _size1 * _freq * 60 / BASE_FREQUENCY ;
}
virtual bool update ( ) {
assert ( _id ) ;
2007-09-10 13:17:20 +00:00
if ( ! _loop ) {
2005-02-09 00:25:43 +00:00
_vol - - ;
if ( _vol )
_mod - > setChannelVol ( _id , _vol ) ;
else return false ;
2007-09-10 13:17:20 +00:00
} else if ( ! - - _loop ) {
2005-02-09 00:25:43 +00:00
_mod - > stopChannel ( _id ) ;
char * tmp_data = ( char * ) malloc ( _size2 ) ;
memcpy ( tmp_data , _data + _offset2 , _size2 ) ;
_mod - > startChannel ( _id , tmp_data , _size2 , BASE_FREQUENCY / _freq , _vol , 0 , _size2 ) ;
}
return true ;
}
private :
const uint16 _offset1 ;
const uint16 _offset2 ;
const uint16 _size1 ;
const uint16 _size2 ;
const uint16 _freq ;
int _vol ;
int _loop ;
} ;
2003-11-08 21:59:32 +00:00
# define CRCToSound(CRC, SOUND) \
if ( crc = = CRC ) \
return new SOUND
2003-09-24 06:56:30 +00:00
static V2A_Sound * findSound ( unsigned long crc ) {
2003-10-09 15:03:01 +00:00
CRCToSound ( 0x8FAB08C4 , V2A_Sound_SingleLooped ( 0x006C , 0x2B58 , 0x016E , 0x3F ) ) ; // Maniac 17
CRCToSound ( 0xB673160A , V2A_Sound_SingleLooped ( 0x006C , 0x1E78 , 0x01C2 , 0x1E ) ) ; // Maniac 38
CRCToSound ( 0x4DB1D0B2 , V2A_Sound_MultiLooped ( 0x0072 , 0x1BC8 , 0x023D , 0x3F , 0x0224 , 0x3F ) ) ; // Maniac 20
CRCToSound ( 0x754D75EF , V2A_Sound_Single ( 0x0076 , 0x0738 , 0x01FC , 0x3F ) ) ; // Maniac 10
CRCToSound ( 0x6E3454AF , V2A_Sound_Single ( 0x0076 , 0x050A , 0x017C , 0x3F ) ) ; // Maniac 12
CRCToSound ( 0x92F0BBB6 , V2A_Sound_Single ( 0x0076 , 0x3288 , 0x012E , 0x3F ) ) ; // Maniac 41
CRCToSound ( 0xE1B13982 , V2A_Sound_MultiLoopedDuration ( 0x0078 , 0x0040 , 0x007C , 0x3F , 0x007B , 0x3F , 0x001E ) ) ; // Maniac 21
CRCToSound ( 0x288B16CF , V2A_Sound_MultiLoopedDuration ( 0x007A , 0x0040 , 0x007C , 0x3F , 0x007B , 0x3F , 0x000A ) ) ; // Maniac 11
CRCToSound ( 0xA7565268 , V2A_Sound_MultiLoopedDuration ( 0x007A , 0x0040 , 0x00F8 , 0x3F , 0x00F7 , 0x3F , 0x000A ) ) ; // Maniac 19
CRCToSound ( 0x7D419BFC , V2A_Sound_MultiLoopedDuration ( 0x007E , 0x0040 , 0x012C , 0x3F , 0x0149 , 0x3F , 0x001E ) ) ; // Maniac 22
CRCToSound ( 0x1B52280C , V2A_Sound_Single ( 0x0098 , 0x0A58 , 0x007F , 0x32 ) ) ; // Maniac 6
CRCToSound ( 0x38D4A810 , V2A_Sound_Single ( 0x0098 , 0x2F3C , 0x0258 , 0x32 ) ) ; // Maniac 7
CRCToSound ( 0x09F98FC2 , V2A_Sound_Single ( 0x0098 , 0x0A56 , 0x012C , 0x32 ) ) ; // Maniac 16
CRCToSound ( 0x90440A65 , V2A_Sound_Single ( 0x0098 , 0x0208 , 0x0078 , 0x28 ) ) ; // Maniac 28
CRCToSound ( 0x985C76EF , V2A_Sound_Single ( 0x0098 , 0x0D6E , 0x00C8 , 0x32 ) ) ; // Maniac 30
CRCToSound ( 0x76156137 , V2A_Sound_Single ( 0x0098 , 0x2610 , 0x017C , 0x39 ) ) ; // Maniac 39
CRCToSound ( 0x5D95F88C , V2A_Sound_Single ( 0x0098 , 0x0A58 , 0x007F , 0x1E ) ) ; // Maniac 65
CRCToSound ( 0x92D704EA , V2A_Sound_SingleLooped ( 0x009C , 0x29BC , 0x012C , 0x3F , 0x1BD4 , 0x0DE8 ) ) ; // Maniac 15
CRCToSound ( 0x92F5513C , V2A_Sound_Single ( 0x009E , 0x0DD4 , 0x01F4 , 0x3F ) ) ; // Maniac 13
CRCToSound ( 0xCC2F3B5A , V2A_Sound_Single ( 0x009E , 0x00DE , 0x01AC , 0x3F ) ) ; // Maniac 43
CRCToSound ( 0x153207D3 , V2A_Sound_Single ( 0x009E , 0x0E06 , 0x02A8 , 0x3F ) ) ; // Maniac 67
CRCToSound ( 0xC4F370CE , V2A_Sound_Single ( 0x00AE , 0x0330 , 0x01AC , 0x3F ) ) ; // Maniac 8
CRCToSound ( 0x928C4BAC , V2A_Sound_Single ( 0x00AE , 0x08D6 , 0x01AC , 0x3F ) ) ; // Maniac 9
CRCToSound ( 0x62D5B11F , V2A_Sound_Single ( 0x00AE , 0x165C , 0x01CB , 0x3F ) ) ; // Maniac 27
CRCToSound ( 0x3AB22CB5 , V2A_Sound_Single ( 0x00AE , 0x294E , 0x012A , 0x3F ) ) ; // Maniac 62
CRCToSound ( 0x2D70BBE9 , V2A_Sound_SingleLoopedPitchbend ( 0x00B4 , 0x1702 , 0x03E8 , 0x0190 , 0x3F , 5 ) ) ; // Maniac 64
2005-03-23 06:06:07 +00:00
CRCToSound ( 0xFA4C1B1C , V2A_Sound_Special_ManiacNuclear ( 0x00B2 , 0x1702 , 0x0190 , 0x3F ) ) ; // Maniac 69
CRCToSound ( 0x19D50D67 , V2A_Sound_Special_ManiacDing ( 0x00B6 , 0x0020 , 0x00C8 , 16 , 2 ) ) ; // Maniac 14
CRCToSound ( 0x3E6FBE15 , V2A_Sound_Special_ManiacTentacle ( 0x00B2 , 0x0010 , 0x007C , 0x016D , 1 ) ) ; // Maniac 25
CRCToSound ( 0x5305753C , V2A_Sound_Special_ManiacTentacle ( 0x00B2 , 0x0010 , 0x007C , 0x016D , 7 ) ) ; // Maniac 36
CRCToSound ( 0x28895106 , V2A_Sound_Special_ManiacElectric ( 0x00C0 , 0x00FE , 0x00E9 , 0x0111 , 4 , 0x0A ) ) ; // Maniac 59
CRCToSound ( 0xB641ACF6 , V2A_Sound_Special_Maniac61 ( 0x00C8 , 0x0100 , 0x00C8 , 0x01C2 ) ) ; // Maniac 61
CRCToSound ( 0xE1A91583 , V2A_Sound_Special_ManiacPhone ( 0x00D0 , 0x0040 , 0x007C , 0x3F , 0x007B , 0x3F , 0x3C , 5 , 6 ) ) ; // Maniac 23
CRCToSound ( 0x64816ED5 , V2A_Sound_Special_ManiacPhone ( 0x00D0 , 0x0040 , 0x00BE , 0x37 , 0x00BD , 0x37 , 0x3C , 5 , 6 ) ) ; // Maniac 24
CRCToSound ( 0x639D72C2 , V2A_Sound_Special_ManiacWrench ( 0x00D0 , 0x10A4 , 0x0080 , 0x3F , 0x28 , 3 ) ) ; // Maniac 46
CRCToSound ( 0xE8826D92 , V2A_Sound_Special_ManiacTypewriter ( 0x00EC , 0x025A , 0x023C , 0x3F , 8 , ( const uint8 * ) " \x20 \x41 \x04 \x21 \x08 \x10 \x13 \x07 " , true ) ) ; // Maniac 45
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xEDFF3D41 , V2A_Sound_Single ( 0x00F8 , 0x2ADE , 0x01F8 , 0x3F ) ) ; // Maniac 42 (this should echo, but it's barely noticeable and I don't feel like doing it)
2005-03-23 06:06:07 +00:00
CRCToSound ( 0x15606D06 , V2A_Sound_Special_ManiacSiren ( 0x0148 , 0x0020 , 0x0168 , 0x0020 , 0x3F ) ) ; // Maniac 32
CRCToSound ( 0x753EAFE3 , V2A_Sound_Special_Maniac44 ( 0x017C , 0x0010 , 0x018C , 0x0020 , 0x00C8 , 0x0080 , 0x3F ) ) ; // Maniac 44
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xB1AB065C , V2A_Sound_Music ( 0x0032 , 0x00B2 , 0x08B2 , 0x1222 , 0x1A52 , 0x23C2 , 0x3074 , false ) ) ; // Maniac 50
CRCToSound ( 0x091F5D9C , V2A_Sound_Music ( 0x0032 , 0x0132 , 0x0932 , 0x1802 , 0x23D2 , 0x3EA2 , 0x4F04 , false ) ) ; // Maniac 58
CRCToSound ( 0x8E2C8AB3 , V2A_Sound_SingleLooped ( 0x005C , 0x0F26 , 0x0168 , 0x3C ) ) ; // Zak 41
CRCToSound ( 0x3792071F , V2A_Sound_SingleLooped ( 0x0060 , 0x1A18 , 0x06A4 , 0x3F ) ) ; // Zak 88
CRCToSound ( 0xF192EDE9 , V2A_Sound_SingleLooped ( 0x0062 , 0x0054 , 0x01FC , 0x1E ) ) ; // Zak 68
2005-03-23 06:06:07 +00:00
CRCToSound ( 0xC43B0245 , V2A_Sound_Special_Zak70 ( 0x006C , 0x166E , 0x00C8 , 0x0190 , 0x0320 , 0x0640 , 0x32 ) ) ; // Zak 70
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xCEB51670 , V2A_Sound_SingleLooped ( 0x00AC , 0x26DC , 0x012C , 0x3F ) ) ; // Zak 42
CRCToSound ( 0x10347B51 , V2A_Sound_SingleLooped ( 0x006C , 0x00E0 , 0x0594 , 0x3F ) ) ; // Zak 18
CRCToSound ( 0x9D2FADC0 , V2A_Sound_MultiLooped ( 0x0072 , 0x1FC8 , 0x016A , 0x3F , 0x01CE , 0x3F ) ) ; // Zak 80
CRCToSound ( 0xFAD2C676 , V2A_Sound_MultiLooped ( 0x0076 , 0x0010 , 0x0080 , 0x3F , 0x0090 , 0x3B ) ) ; // Zak 40
CRCToSound ( 0x01508B48 , V2A_Sound_Single ( 0x0076 , 0x0D8C , 0x017C , 0x3F ) ) ; // Zak 90
CRCToSound ( 0x9C18DC46 , V2A_Sound_Single ( 0x0076 , 0x0D8C , 0x015E , 0x3F ) ) ; // Zak 91
CRCToSound ( 0xF98F7EAC , V2A_Sound_Single ( 0x0076 , 0x0D8C , 0x0140 , 0x3F ) ) ; // Zak 92
CRCToSound ( 0xC925FBEF , V2A_Sound_MultiLoopedDuration ( 0x0080 , 0x0010 , 0x0080 , 0x3F , 0x0090 , 0x3B , 0x0168 ) ) ; // Zak 53
2005-03-23 06:06:07 +00:00
CRCToSound ( 0xCAB35257 , V2A_Sound_Special_Zak101 ( 0x00DA , 0x425C , 0x023C , 0x08F0 , 0x0640 , 0x0478 , 0x3F , 0x012C ) ) ; // Zak 101
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xA31FE4FD , V2A_Sound_Single ( 0x0094 , 0x036A , 0x00E1 , 0x3F ) ) ; // Zak 97
CRCToSound ( 0x0A1AE0F5 , V2A_Sound_Single ( 0x009E , 0x0876 , 0x0168 , 0x3F ) ) ; // Zak 5
CRCToSound ( 0xD01A66CB , V2A_Sound_Single ( 0x009E , 0x04A8 , 0x0168 , 0x3F ) ) ; // Zak 47
CRCToSound ( 0x5497B912 , V2A_Sound_Single ( 0x009E , 0x0198 , 0x01F4 , 0x3F ) ) ; // Zak 39
CRCToSound ( 0x2B50362F , V2A_Sound_Single ( 0x009E , 0x09B6 , 0x023D , 0x3F ) ) ; // Zak 67
CRCToSound ( 0x7BFB6E72 , V2A_Sound_Single ( 0x009E , 0x0D14 , 0x0078 , 0x3F ) ) ; // Zak 69
CRCToSound ( 0xB803A792 , V2A_Sound_Single ( 0x009E , 0x2302 , 0x02BC , 0x3F ) ) ; // Zak 78
CRCToSound ( 0x7AB82E39 , V2A_Sound_SingleLooped ( 0x00A0 , 0x2A3C , 0x016E , 0x3F , 0x1018 , 0x1A24 ) ) ; // Zak 100
CRCToSound ( 0x28057CEC , V2A_Sound_Single ( 0x0098 , 0x0FEC , 0x0140 , 0x32 ) ) ; // Zak 63
CRCToSound ( 0x1180A2FC , V2A_Sound_Single ( 0x0098 , 0x0F06 , 0x0190 , 0x32 ) ) ; // Zak 64
CRCToSound ( 0x12616755 , V2A_Sound_Single ( 0x0098 , 0x14C8 , 0x023C , 0x14 ) ) ; // Zak 9
2005-03-23 06:06:07 +00:00
CRCToSound ( 0x642723AA , V2A_Sound_Special_Zak37 ( 0x00A2 , 0x1702 , 0x01F4 , 0x3F ) ) ; // Zak 37
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xDEE56848 , V2A_Sound_Single ( 0x009A , 0x0F86 , 0x0100 , 0x3F ) ) ; // Zak 93
2005-03-23 06:06:07 +00:00
CRCToSound ( 0xF9BE27B8 , V2A_Sound_Special_Zak37 ( 0x011C , 0x1704 , 0x0228 , 0x3F ) ) ; // Zak 113
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xC73487B2 , V2A_Sound_Single ( 0x00B0 , 0x18BA , 0x0478 , 0x3F ) ) ; // Zak 81
CRCToSound ( 0x32D8F925 , V2A_Sound_Single ( 0x00B0 , 0x2E46 , 0x00F0 , 0x3F ) ) ; // Zak 94
CRCToSound ( 0x988C83A5 , V2A_Sound_Single ( 0x00B0 , 0x0DE0 , 0x025B , 0x3F ) ) ; // Zak 106
CRCToSound ( 0x8F1E3B3D , V2A_Sound_Single ( 0x00B0 , 0x05FE , 0x04E2 , 0x3F ) ) ; // Zak 107
CRCToSound ( 0x0A2A7646 , V2A_Sound_Single ( 0x00B0 , 0x36FE , 0x016E , 0x3F ) ) ; // Zak 43
CRCToSound ( 0x6F1FC435 , V2A_Sound_Single ( 0x00B0 , 0x2808 , 0x044C , 0x3F ) ) ; // Zak 108
2003-12-05 05:57:28 +00:00
CRCToSound ( 0x870EFC29 , V2A_Sound_SingleLoopedPitchbend ( 0x00BA , 0x0100 , 0x03E8 , 0x00C8 , 0x3F , 3 ) ) ; // Zak 55
2005-03-23 06:06:07 +00:00
CRCToSound ( 0xED773699 , V2A_Sound_Special_ManiacDing ( 0x00B4 , 0x0020 , 0x012C , 8 , 4 ) ) ; // Zak 3
CRCToSound ( 0x0BF59774 , V2A_Sound_Special_ZakStereoDing ( 0x00BE , 0x0020 , 0x00F8 , 0x00F7 , 8 , 1 ) ) ; // Zak 72
CRCToSound ( 0x656FFEDE , V2A_Sound_Special_ZakStereoDing ( 0x00BE , 0x0020 , 0x00C4 , 0x00C3 , 8 , 1 ) ) ; // Zak 73
CRCToSound ( 0xFC4D41E5 , V2A_Sound_Special_ZakStereoDing ( 0x00BE , 0x0020 , 0x00A5 , 0x00A4 , 8 , 1 ) ) ; // Zak 74
CRCToSound ( 0xC0DD2089 , V2A_Sound_Special_ZakStereoDing ( 0x00BE , 0x0020 , 0x009C , 0x009B , 8 , 1 ) ) ; // Zak 75
CRCToSound ( 0x627DFD92 , V2A_Sound_Special_ZakStereoDing ( 0x00BE , 0x0020 , 0x008B , 0x008A , 8 , 1 ) ) ; // Zak 76
CRCToSound ( 0x703E05C1 , V2A_Sound_Special_ZakStereoDing ( 0x00BE , 0x0020 , 0x007C , 0x007B , 8 , 1 ) ) ; // Zak 77
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xB0F77006 , V2A_Sound_Unsupported ( ) ) ; // Zak 52
2005-03-23 06:06:07 +00:00
CRCToSound ( 0x5AE9D6A7 , V2A_Sound_Special_ZakAirplane ( 0x00CA , 0x22A4 , 0x0113 , 0x0227 ) ) ; // Zak 109
CRCToSound ( 0xABE0D3B0 , V2A_Sound_Special_ZakAirplane ( 0x00CE , 0x22A4 , 0x0227 , 0x0113 ) ) ; // Zak 105
2005-02-09 00:25:43 +00:00
CRCToSound ( 0x788CC749 , V2A_Sound_Special_Zak71 ( 0x00C8 , 0x0B37 ) ) ; // Zak 71
2005-03-23 06:06:07 +00:00
CRCToSound ( 0x2E2AB1FA , V2A_Sound_Special_ZakTram ( 0x00D4 , 0x04F0 , 0x0FE3 , 0x0080 , 0x3F ) ) ; // Zak 99
CRCToSound ( 0x1304CF20 , V2A_Sound_Special_ManiacTypewriter ( 0x00DC , 0x0624 , 0x023C , 0x3C , 2 , ( const uint8 * ) " \x14 \x11 " , false ) ) ; // Zak 79
2005-02-09 00:25:43 +00:00
CRCToSound ( 0xAE68ED91 , V2A_Sound_Special_Zak54 ( 0x00D4 , 0x1A25 , 0x1E1E , 0x0B80 , 0x01F4 ) ) ; // Zak 54
2003-10-09 15:03:01 +00:00
CRCToSound ( 0xA4F40F97 , V2A_Sound_Unsupported ( ) ) ; // Zak 61
CRCToSound ( 0x348F85CE , V2A_Sound_Unsupported ( ) ) ; // Zak 62
2005-03-23 06:06:07 +00:00
CRCToSound ( 0xD473AB86 , V2A_Sound_Special_ManiacTypewriter ( 0x0122 , 0x03E8 , 0x00BE , 0x3F , 7 , ( const uint8 * ) " \x0F \x0B \x04 \x0F \x1E \x0F \x66 " , false ) ) ; // Zak 46
2003-10-09 15:03:01 +00:00
CRCToSound ( 0x84A0BA90 , V2A_Sound_Unsupported ( ) ) ; // Zak 110
CRCToSound ( 0x92680D9F , V2A_Sound_Unsupported ( ) ) ; // Zak 32
CRCToSound ( 0xABFFDB02 , V2A_Sound_Unsupported ( ) ) ; // Zak 86
CRCToSound ( 0x41045447 , V2A_Sound_Unsupported ( ) ) ; // Zak 98
CRCToSound ( 0xC8EEBD34 , V2A_Sound_Unsupported ( ) ) ; // Zak 82
CRCToSound ( 0x42F9469F , V2A_Sound_Music ( 0x05F6 , 0x0636 , 0x0456 , 0x0516 , 0x05D6 , 0x05E6 , 0x0A36 , true ) ) ; // Zak 96
CRCToSound ( 0x038BBD78 , V2A_Sound_Music ( 0x054E , 0x05CE , 0x044E , 0x04BE , 0x052E , 0x053E , 0x0BCE , true ) ) ; // Zak 85
CRCToSound ( 0x06FFADC5 , V2A_Sound_Music ( 0x0626 , 0x0686 , 0x0446 , 0x04F6 , 0x0606 , 0x0616 , 0x0C86 , true ) ) ; // Zak 87
CRCToSound ( 0xCE20ECF0 , V2A_Sound_Music ( 0x0636 , 0x0696 , 0x0446 , 0x0576 , 0x0616 , 0x0626 , 0x0E96 , true ) ) ; // Zak 114
CRCToSound ( 0xBDA01BB6 , V2A_Sound_Music ( 0x0678 , 0x06B8 , 0x0458 , 0x0648 , 0x0658 , 0x0668 , 0x0EB8 , false ) ) ; // Zak 33
CRCToSound ( 0x59976529 , V2A_Sound_Music ( 0x088E , 0x092E , 0x048E , 0x05EE , 0x074E , 0x07EE , 0x112E , true ) ) ; // Zak 49
CRCToSound ( 0xED1EED02 , V2A_Sound_Music ( 0x08D0 , 0x0950 , 0x0440 , 0x07E0 , 0x08B0 , 0x08C0 , 0x1350 , false ) ) ; // Zak 112
CRCToSound ( 0x5A16C037 , V2A_Sound_Music ( 0x634A , 0x64CA , 0x049A , 0x18FA , 0x398A , 0x511A , 0x6CCA , false ) ) ; // Zak 95
2003-09-24 06:56:30 +00:00
return NULL ;
}
2006-10-21 12:44:10 +00:00
Player_V2A : : Player_V2A ( ScummEngine * scumm , Audio : : Mixer * mixer ) {
2003-09-24 06:56:30 +00:00
int i ;
2004-01-08 20:37:26 +00:00
_vm = scumm ;
2003-09-24 06:56:30 +00:00
InitCRC ( ) ;
for ( i = 0 ; i < V2A_MAXSLOTS ; i + + ) {
_slot [ i ] . id = 0 ;
_slot [ i ] . sound = NULL ;
}
2006-10-21 12:44:10 +00:00
_mod = new Player_MOD ( mixer ) ;
2003-09-24 06:56:30 +00:00
_mod - > setUpdateProc ( update_proc , this , 60 ) ;
}
Player_V2A : : ~ Player_V2A ( ) {
delete _mod ;
}
2004-11-28 21:24:02 +00:00
void Player_V2A : : setMusicVolume ( int vol ) {
_mod - > setMusicVolume ( vol ) ;
2003-09-24 06:56:30 +00:00
}
int Player_V2A : : getSoundSlot ( int id ) const {
int i ;
for ( i = 0 ; i < V2A_MAXSLOTS ; i + + ) {
if ( _slot [ i ] . id = = id )
break ;
}
if ( i = = V2A_MAXSLOTS ) {
if ( id = = 0 )
warning ( " player_v2a - out of sound slots " ) ;
return - 1 ;
}
return i ;
}
void Player_V2A : : stopAllSounds ( ) {
for ( int i = 0 ; i < V2A_MAXSLOTS ; i + + ) {
if ( ! _slot [ i ] . id )
continue ;
_slot [ i ] . sound - > stop ( ) ;
2003-10-09 05:27:52 +00:00
delete _slot [ i ] . sound ;
2003-09-24 06:56:30 +00:00
_slot [ i ] . sound = NULL ;
_slot [ i ] . id = 0 ;
}
}
void Player_V2A : : stopSound ( int nr ) {
int i ;
if ( nr = = 0 )
return ;
i = getSoundSlot ( nr ) ;
if ( i = = - 1 )
return ;
_slot [ i ] . sound - > stop ( ) ;
2003-10-09 05:27:52 +00:00
delete _slot [ i ] . sound ;
2003-09-24 06:56:30 +00:00
_slot [ i ] . sound = NULL ;
_slot [ i ] . id = 0 ;
}
void Player_V2A : : startSound ( int nr ) {
2004-01-08 20:37:26 +00:00
assert ( _vm ) ;
byte * data = _vm - > getResourceAddress ( rtSound , nr ) ;
2003-09-24 06:56:30 +00:00
assert ( data ) ;
2003-11-08 21:59:32 +00:00
uint32 crc = GetCRC ( data + 0x0A , READ_BE_UINT16 ( data + 0x08 ) ) ;
2003-09-24 06:56:30 +00:00
V2A_Sound * snd = findSound ( crc ) ;
if ( snd = = NULL ) {
warning ( " player_v2a - sound %i not recognized yet (crc %08X) " , nr , crc ) ;
return ;
}
stopSound ( nr ) ;
int i = getSoundSlot ( ) ;
if ( i = = - 1 )
return ;
_slot [ i ] . id = nr ;
2003-10-09 15:03:01 +00:00
_slot [ i ] . sound = snd ;
2003-09-24 06:56:30 +00:00
_slot [ i ] . sound - > start ( _mod , nr , data ) ;
}
void Player_V2A : : update_proc ( void * param ) {
( ( Player_V2A * ) param ) - > updateSound ( ) ;
}
void Player_V2A : : updateSound ( ) {
int i ;
for ( i = 0 ; i < V2A_MAXSLOTS ; i + + ) {
if ( ( _slot [ i ] . id ) & & ( ! _slot [ i ] . sound - > update ( ) ) ) {
_slot [ i ] . sound - > stop ( ) ;
2003-10-09 05:27:52 +00:00
delete _slot [ i ] . sound ;
2003-09-24 06:56:30 +00:00
_slot [ i ] . sound = NULL ;
_slot [ i ] . id = 0 ;
}
}
}
int Player_V2A : : getMusicTimer ( ) const {
return 0 ; // FIXME - need to keep track of playing music resources
}
int Player_V2A : : getSoundStatus ( int nr ) const {
for ( int i = 0 ; i < V2A_MAXSLOTS ; i + + ) {
if ( _slot [ i ] . id = = nr )
return 1 ;
}
return 0 ;
}
2003-10-03 18:33:57 +00:00
2005-07-30 21:11:48 +00:00
} // End of namespace Scumm