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-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
2011-11-01 15:03:29 +00:00
static void InitCRC ( ) {
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
2011-11-01 15:03:29 +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 ) {
2009-05-31 10:02:16 +00:00
warning ( " player_v2a - sound %i not supported " , id ) ;
2003-09-24 06:56:30 +00:00
}
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 ) ,
2011-11-01 15:03:29 +00:00
READ_BE_UINT16 ( _data + _chan [ i ] . volbase + ( _chan [ i ] . volptr + + < < 1 ) ) ) ;
2003-09-27 06:33:22 +00:00
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 ;
2011-11-01 15:03:29 +00:00
if ( _chan [ i ] . dur ) // if there's something playing, stop it
2003-09-27 06:33:22 +00:00
_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 ;
2011-11-01 15:03:29 +00:00
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
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Maniac69 : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2008-02-16 03:12:34 +00:00
V2A_Sound_Special_Maniac69 ( 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
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Maniac59 : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2008-02-16 03:12:34 +00:00
V2A_Sound_Special_Maniac59 ( 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
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
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Maniac46 : public V2A_Sound_Base < 1 > {
2003-09-24 06:56:30 +00:00
public :
2008-02-16 03:12:34 +00:00
V2A_Sound_Special_Maniac46 ( 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
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
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Maniac32 : public V2A_Sound_Base < 4 > {
2003-09-24 06:56:30 +00:00
public :
2008-02-16 03:12:34 +00:00
V2A_Sound_Special_Maniac32 ( 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 ;
2011-11-01 15:03:29 +00:00
void updatefreq ( uint16 & freq , int16 & step , uint16 min , uint16 max ) {
2003-09-24 06:56:30 +00:00
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
2008-02-19 00:36:47 +00:00
// used in the white crystal chamber
2005-03-23 06:06:07 +00:00
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
2008-02-19 00:36:47 +00:00
// used when the Mindbender disappears
2005-03-23 06:06:07 +00:00
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
2008-02-19 00:36:47 +00:00
// used when refilling oxygen
2005-03-23 06:06:07 +00:00
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 ) ) ;
2011-11-01 15:03:29 +00:00
} else {
2003-09-27 22:27:12 +00:00
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
2008-02-19 00:36:47 +00:00
// used when the white crystal machine turns off
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 ) ;
2010-04-28 20:18:56 +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 ;
2010-04-28 20:18:56 +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
2008-02-19 00:36:47 +00:00
// used when the Skolarian device activates
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak99 : public V2A_Sound_Base < 1 > {
2003-12-14 08:57:53 +00:00
public :
2008-02-16 03:12:34 +00:00
V2A_Sound_Special_Zak99 ( 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
2008-02-19 00:36:47 +00:00
// used when depressurizing the hostel
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 ) ;
2008-02-16 03:12:34 +00:00
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 ;
} ;
2008-02-16 03:12:34 +00:00
// plays 2 looped waveforms at different frequencies, pulsing at different frequencies and ramping the volume up and down once
2008-02-19 00:36:47 +00:00
// used when abducted at the Bermuda Triangle
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak110 : public V2A_Sound_Base < 2 > {
public :
V2A_Sound_Special_Zak110 ( uint16 offset1 , uint16 size1 , uint16 offset2 , uint16 size2 , uint16 freq1 , uint16 freq2 ) :
_offset1 ( offset1 ) , _size1 ( size1 ) , _offset2 ( offset2 ) , _size2 ( size2 ) , _freq1 ( freq1 ) , _freq2 ( freq2 ) { }
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 ) ) ;
_loopnum = 0 ;
_vol = 0x1500 ;
_beepcount = 0 ;
}
virtual bool update ( ) {
char * tmp_data ;
assert ( _id ) ;
int vol = ( ( ( _vol > > 7 ) & 0x7E ) | ( ( _vol > > 15 ) & 0x01 ) ) ;
_beepcount + + ;
switch ( _beepcount & 0x3 ) {
case 0 :
_mod - > stopChannel ( _id | 0x000 ) ;
break ;
case 1 :
tmp_data = ( char * ) malloc ( _size1 ) ;
memcpy ( tmp_data , _data + _offset1 , _size1 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data , _size1 , BASE_FREQUENCY / _freq1 , vol , 0 , _size1 , - 127 ) ;
break ;
default :
_mod - > setChannelVol ( _id | 0x000 , vol ) ;
break ;
}
switch ( _beepcount & 0x7 ) {
case 0 :
_mod - > stopChannel ( _id | 0x100 ) ;
break ;
case 1 :
tmp_data = ( char * ) malloc ( _size2 ) ;
memcpy ( tmp_data , _data + _offset2 , _size2 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data , _size2 , BASE_FREQUENCY / _freq2 , vol , 0 , _size2 , 127 ) ;
break ;
default :
_mod - > setChannelVol ( _id | 0x100 , vol ) ;
break ;
}
if ( _loopnum = = 0 ) {
_vol + = 0x80 ;
if ( _vol = = 0x4000 ) {
_vol = 0x3F00 ;
_loopnum = 1 ;
}
} else if ( _loopnum = = 1 ) {
_vol - = 0x20 ;
if ( _vol = = 0x2000 )
_loopnum = 2 ;
}
return true ;
}
private :
const uint16 _offset1 ;
const uint16 _size1 ;
const uint16 _offset2 ;
const uint16 _size2 ;
const uint16 _freq1 ;
const uint16 _freq2 ;
uint16 _loopnum ;
uint16 _vol ;
uint16 _beepcount ;
} ;
// plays a stereo siren, sweeping up and down quickly several times before sweeping up slowly, stopping, and then going silent
2008-02-19 00:36:47 +00:00
// door orb sound in the Mars Face
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak32 : public V2A_Sound_Base < 2 > {
public :
V2A_Sound_Special_Zak32 ( uint16 offset1 , uint16 offset2 , uint16 size1 , uint16 size2 ) :
_offset1 ( offset1 ) , _offset2 ( offset2 ) , _size1 ( size1 ) , _size2 ( size2 ) { }
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 ) ) ;
_loopnum = 1 ;
_freqmod = - 4 ;
_freq = 0x00C8 ;
char * tmp_data1 = ( char * ) malloc ( _size1 ) ;
char * tmp_data2 = ( char * ) malloc ( _size1 ) ;
memcpy ( tmp_data1 , _data + _offset1 , _size1 ) ;
memcpy ( tmp_data2 , _data + _offset1 , _size1 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size1 , BASE_FREQUENCY / _freq , 0x7F , 0 , _size1 , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size1 , BASE_FREQUENCY / ( _freq + 3 ) , 0x7F , 0 , _size1 , 127 ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
if ( _loopnum < 7 ) {
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / _freq ) ;
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / ( _freq + 3 ) ) ;
_freq + = _freqmod ;
if ( _freq < = 0x80 )
_freqmod = - _freqmod ;
else if ( _freq > = 0xC8 ) {
_freqmod = - _freqmod ;
_loopnum + + ;
if ( _loopnum = = 7 ) {
_freq = 0x00C8 ;
_freqmod = 2 ;
}
}
return true ;
} else {
if ( _loopnum = = 7 ) {
_mod - > stopChannel ( _id | 0x000 ) ;
_mod - > stopChannel ( _id | 0x100 ) ;
char * tmp_data1 = ( char * ) malloc ( _size2 ) ;
char * tmp_data2 = ( char * ) malloc ( _size2 ) ;
memcpy ( tmp_data1 , _data + _offset2 , _size2 ) ;
memcpy ( tmp_data2 , _data + _offset2 , _size2 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size2 , BASE_FREQUENCY / ( _freq ) , 0x7F , 0 , _size2 , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size2 , BASE_FREQUENCY / ( _freq + 3 ) , 0x7F , 0 , _size2 , 127 ) ;
_loopnum + + ;
} else {
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / _freq ) ;
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / ( _freq + 3 ) ) ;
}
_freq - = _freqmod ;
if ( _freq > 0 )
return true ;
else
return false ;
}
}
private :
const uint16 _offset1 ;
const uint16 _offset2 ;
const uint16 _size1 ;
const uint16 _size2 ;
uint16 _loopnum ;
int16 _freqmod ;
uint16 _freq ;
} ;
// plays a looped waveform, increasing frequency and reducing volume once the frequency reaches a certain point
// probably used for some sort of vehicle sound
class V2A_Sound_Special_Zak52 : public V2A_Sound_Base < 1 > {
public :
V2A_Sound_Special_Zak52 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
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 ) ) ;
_curfreq = 0x0312 ;
char * tmp_data = ( char * ) malloc ( _size ) ;
memcpy ( tmp_data , _data + _offset , _size ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data , _size , BASE_FREQUENCY / _curfreq , 0xFF , 0 , _size , - 127 ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
int vol = ( _curfreq - 0xC8 ) > > 3 ;
if ( vol > 0x3F )
vol = 0x3F ;
vol = ( vol < < 2 ) | ( vol > > 4 ) ;
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / _curfreq ) ;
_mod - > setChannelVol ( _id | 0x000 , vol ) ;
_curfreq - - ;
if ( _curfreq > = 0x107 )
return true ;
else
return false ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _curfreq ;
} ;
// plays a looped waveform, sweeping the frequency up while modulating it (alternating which channel updates) and fading volume out
2008-02-19 00:36:47 +00:00
// used when teleporting out with the yellow crystal
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak61 : public V2A_Sound_Base < 2 > {
public :
V2A_Sound_Special_Zak61 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
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 ) ) ;
_loop = 1 ;
_curfreq = 0x01F4 ;
2010-04-28 20:18:56 +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 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _curfreq , 0x7F , 0 , _size , - 127 ) ;
2008-02-16 03:12:34 +00:00
// start 2nd channel silent
2010-04-28 20:18:56 +00:00
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _curfreq , 0 , 0 , _size , 127 ) ;
2008-02-16 03:12:34 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
int freq = ( _loop < < 4 ) + _curfreq ;
int vol = freq - 0x76 ;
if ( vol > 0x3F )
vol = 0x3F ;
vol = ( vol < < 1 ) | ( vol > > 5 ) ;
switch ( _loop ) {
case 0 :
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / freq ) ;
_mod - > setChannelVol ( _id | 0x000 , vol ) ;
break ;
case 1 :
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / freq ) ;
_mod - > setChannelVol ( _id | 0x100 , vol ) ;
break ;
}
_loop = ( _loop + 1 ) & 3 ;
if ( ! _loop ) {
_curfreq - = 4 ;
if ( _curfreq < = 0x80 )
return false ;
}
return true ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _loop ;
uint16 _curfreq ;
} ;
// just like Zak61, but sweeps frequency in the other direction
2008-02-19 00:36:47 +00:00
// used when teleporting in with the yellow crystal
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak62 : public V2A_Sound_Base < 2 > {
public :
V2A_Sound_Special_Zak62 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
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 ) ) ;
_loop = 1 ;
_curfreq = 0x0080 ;
2010-04-28 20:18:56 +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 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _curfreq , 0x7F , 0 , _size , - 127 ) ;
2008-02-16 03:12:34 +00:00
// start 2nd channel silent
2010-04-28 20:18:56 +00:00
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _curfreq , 0 , 0 , _size , 127 ) ;
2008-02-16 03:12:34 +00:00
}
virtual bool update ( ) {
assert ( _id ) ;
int freq = ( _loop < < 4 ) + _curfreq ;
int vol = 0x0200 - freq ;
if ( vol > 0x3F )
vol = 0x3F ;
vol = ( vol < < 1 ) | ( vol > > 5 ) ;
switch ( _loop ) {
case 0 :
_mod - > setChannelFreq ( _id | 0x000 , BASE_FREQUENCY / freq ) ;
_mod - > setChannelVol ( _id | 0x000 , vol ) ;
break ;
case 1 :
_mod - > setChannelFreq ( _id | 0x100 , BASE_FREQUENCY / freq ) ;
_mod - > setChannelVol ( _id | 0x100 , vol ) ;
break ;
}
_loop = ( _loop + 1 ) & 3 ;
if ( ! _loop ) {
_curfreq + = 4 ;
if ( _curfreq > = 0x01F4 )
return false ;
}
return true ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _loop ;
uint16 _curfreq ;
} ;
2009-01-01 15:06:43 +00:00
// plays a series of double-looped sounds at varying frequencies and delays, very specialized
2008-02-19 00:36:47 +00:00
// Guardian of the Sphinx, perhaps?
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak82 : public V2A_Sound_Base < 4 > {
public :
V2A_Sound_Special_Zak82 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
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 ) ) ;
// Wait values were to insure playing an integral number of loops on each sample
// and have been adjusted to reflect the actual duration spent playing
_loop = 0 ;
_playctr = 240 ;
_wait1 = 76 ; // was 39, extended to loop twice
_wait2 = 10000 ;
_wait3 = 10000 ;
_wait4 = 10000 ;
int size = 2000 ;
int offset = _offset ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
char * tmp_data = ( char * ) malloc ( size ) ;
memcpy ( tmp_data , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data , size , BASE_FREQUENCY / 0x0479 , 0xFF , 0 , size ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
char * tmp_data1 , * tmp_data2 ;
int size , offset = _offset ;
if ( ! - - _wait1 ) {
_wait1 = 10000 ;
_mod - > stopChannel ( _id | 0x000 ) ;
} else if ( ! - - _wait2 ) {
_wait2 = 10000 ;
_mod - > stopChannel ( _id | 0x000 ) ;
} else if ( ! - - _wait3 ) {
_wait3 = 10000 ;
_mod - > stopChannel ( _id | 0x200 ) ;
} else if ( ! - - _wait4 ) {
_wait4 = 10000 ;
_mod - > stopChannel ( _id | 0x100 ) ;
_mod - > stopChannel ( _id | 0x300 ) ;
}
if ( - - _playctr )
return true ;
switch ( + + _loop ) {
case 1 :
size = 6300 ;
offset + = 0x07D0 ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
tmp_data1 = ( char * ) malloc ( size ) ;
memcpy ( tmp_data1 , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , size , BASE_FREQUENCY / 0x0479 , 0x7F , 0 , size , - 127 ) ;
_wait2 = 241 ; // was 120, extended to loop twice
_playctr = 10 ;
break ;
case 2 :
size = 6292 ;
offset + = 0x206C ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
tmp_data1 = ( char * ) malloc ( size ) ;
memcpy ( tmp_data1 , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x200 , tmp_data1 , size , BASE_FREQUENCY / 0x0384 , 0x7F , 0 , size , 127 ) ;
_wait3 = 189 ; // was 94, extended to loop twice
_playctr = 20 ;
break ;
case 3 :
size = 6300 ;
offset + = 0x07D0 ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
tmp_data1 = ( char * ) malloc ( size ) ;
tmp_data2 = ( char * ) malloc ( size ) ;
memcpy ( tmp_data1 , _data + offset , size ) ;
memcpy ( tmp_data2 , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data1 , size , BASE_FREQUENCY / 0x01E0 , 0x7F , 0 , size , 127 ) ;
_mod - > startChannel ( _id | 0x300 , tmp_data2 , size , BASE_FREQUENCY / 0x01E0 , 0x7F , 0 , size , - 127 ) ;
_wait4 = 101 ; // was 50, extended to loop twice
_playctr = 120 ;
break ;
default :
return false ;
}
return true ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _loop ;
uint16 _playctr ;
uint16 _wait1 ;
uint16 _wait2 ;
uint16 _wait3 ;
uint16 _wait4 ;
} ;
// plays a "ding" (volume 0-max-0) followed by a sound sample, a pause, then loops again
2008-02-19 00:36:47 +00:00
// Mars Tram about to depart
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak86 : public V2A_Sound_Base < 1 > {
public :
V2A_Sound_Special_Zak86 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
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 ) ) ;
_mode = 0 ;
_vol = 0 ;
_volmod = 16 ;
int size = 32 ;
int offset = _offset + 0x2B8E ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
char * tmp_data = ( char * ) malloc ( size ) ;
memcpy ( tmp_data , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data , size , BASE_FREQUENCY / 0x0096 , 0 , 0 , size , 0 ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
int size , offset ;
char * tmp_data ;
switch ( _mode ) {
case 0 :
_mod - > setChannelVol ( _id | 0x000 , ( _vol < < 2 ) | ( _vol > > 4 ) ) ;
if ( _vol + _volmod > 0 ) {
_vol + = _volmod ;
if ( _vol > 0x3F ) {
_vol = 0x3F ;
_volmod = - 4 ;
}
return true ;
}
_mod - > stopChannel ( _id | 0x000 ) ;
_mode = 1 ;
2009-01-01 15:06:43 +00:00
2008-02-16 03:12:34 +00:00
size = 0x2B8E ;
offset = _offset ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
tmp_data = ( char * ) malloc ( size ) ;
memcpy ( tmp_data , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data , size , BASE_FREQUENCY / 0x0152 , 0x3F ) ;
_volmod = 100 ;
break ;
case 1 :
if ( ! - - _volmod ) {
size = 32 ;
offset = _offset + 0x2B8E ;
2008-02-19 00:36:47 +00:00
assert ( offset + size < = _offset + _size ) ;
2008-02-16 03:12:34 +00:00
tmp_data = ( char * ) malloc ( size ) ;
memcpy ( tmp_data , _data + offset , size ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data , size , BASE_FREQUENCY / 0x0096 , 0 , 0 , size , 0 ) ;
_mode = 0 ;
_vol = 0 ;
_volmod = 16 ;
}
break ;
}
return true ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _mode ;
uint16 _vol ;
int16 _volmod ;
} ;
// modulates volume on 4 samples, frequency on only 2 of them
2008-02-19 00:36:47 +00:00
// Skolarian device pedestal activated without any parts
2008-02-16 03:12:34 +00:00
class V2A_Sound_Special_Zak98 : public V2A_Sound_Base < 4 > {
public :
V2A_Sound_Special_Zak98 ( uint16 offset , uint16 size ) :
_offset ( offset ) , _size ( size ) { }
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 ) ) ;
_freq [ 0 ] = 0x1E0 ;
_freq [ 1 ] = 0x3E8 ;
_freq [ 2 ] = 0x200 ;
_freq [ 3 ] = 0x408 ;
_vol [ 0 ] = 0x3F ;
_vol [ 1 ] = 0x3F ;
_vol [ 2 ] = 0x3F ;
_vol [ 3 ] = 0x3F ;
_freqmod = 4 ;
_volmod [ 0 ] = - 2 ;
_volmod [ 1 ] = - 1 ;
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 ) ;
_mod - > startChannel ( _id | 0x000 , tmp_data1 , _size , BASE_FREQUENCY / _freq [ 0 ] , _vol [ 0 ] , 0 , _size , - 127 ) ;
_mod - > startChannel ( _id | 0x100 , tmp_data2 , _size , BASE_FREQUENCY / _freq [ 1 ] , _vol [ 1 ] , 0 , _size , 127 ) ;
_mod - > startChannel ( _id | 0x200 , tmp_data3 , _size , BASE_FREQUENCY / _freq [ 2 ] , _vol [ 2 ] , 0 , _size , 127 ) ;
_mod - > startChannel ( _id | 0x300 , tmp_data4 , _size , BASE_FREQUENCY / _freq [ 3 ] , _vol [ 3 ] , 0 , _size , - 127 ) ;
}
virtual bool update ( ) {
assert ( _id ) ;
2010-04-28 20:18:56 +00:00
const uint16 _minvol [ 2 ] = { 0x2E , 0x32 } ;
2008-02-16 03:12:34 +00:00
int i ;
2011-11-01 15:03:29 +00:00
for ( i = 0 ; i < 4 ; i + + ) {
2008-02-16 03:12:34 +00:00
_mod - > setChannelFreq ( _id | ( i < < 8 ) , BASE_FREQUENCY / _freq [ i ] ) ;
_mod - > setChannelVol ( _id | ( i < < 8 ) , _vol [ i ] ) ;
}
for ( i = 0 ; i < 2 ; i + + ) {
_vol [ i ] + = _volmod [ i ] ;
if ( _vol [ i ] > 0x3F ) {
_vol [ i ] = 0x3F ;
_volmod [ i ] = - _volmod [ i ] ;
} else if ( _vol [ i ] < _minvol [ i ] ) {
_vol [ i ] = _minvol [ i ] ;
_volmod [ i ] = - _volmod [ i ] ;
}
2011-11-01 15:03:29 +00:00
_vol [ i + 2 ] = _vol [ i ] ;
2008-02-16 03:12:34 +00:00
}
_freq [ 0 ] + = _freqmod ;
if ( _freq [ 0 ] > 0x2BC ) {
_freq [ 0 ] = 0x2BC ;
_freqmod = - _freqmod ;
} else if ( _freq [ 0 ] < 0x1E0 ) {
_freq [ 0 ] = 0x1E0 ;
_freqmod = - _freqmod ;
}
_freq [ 2 ] = _freq [ 0 ] + 0x20 ;
return true ;
}
private :
const uint16 _offset ;
const uint16 _size ;
uint16 _freq [ 4 ] ;
uint16 _vol [ 4 ] ;
int16 _freqmod ;
int16 _volmod [ 2 ] ;
} ;
# define CRCToSound(CRC, SOUND) \
if ( crc = = CRC ) \
2003-11-08 21:59:32 +00:00
return new SOUND
2003-09-24 06:56:30 +00:00
2011-11-01 15:03:29 +00:00
static V2A_Sound * findSound ( unsigned long crc ) {
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
CRCToSound ( 0xFA4C1B1C , V2A_Sound_Special_Maniac69 ( 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_Maniac59 ( 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_Maniac46 ( 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
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)
CRCToSound ( 0x15606D06 , V2A_Sound_Special_Maniac32 ( 0x0148 , 0x0020 , 0x0168 , 0x0020 , 0x3F ) ) ; // Maniac 32
CRCToSound ( 0x753EAFE3 , V2A_Sound_Special_Maniac44 ( 0x017C , 0x0010 , 0x018C , 0x0020 , 0x00C8 , 0x0080 , 0x3F ) ) ; // Maniac 44
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
CRCToSound ( 0xC43B0245 , V2A_Sound_Special_Zak70 ( 0x006C , 0x166E , 0x00C8 , 0x0190 , 0x0320 , 0x0640 , 0x32 ) ) ; // Zak 70
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
CRCToSound ( 0xCAB35257 , V2A_Sound_Special_Zak101 ( 0x00DA , 0x425C , 0x023C , 0x08F0 , 0x0640 , 0x0478 , 0x3F , 0x012C ) ) ; // Zak 101
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
CRCToSound ( 0x642723AA , V2A_Sound_Special_Zak37 ( 0x00A2 , 0x1702 , 0x01F4 , 0x3F ) ) ; // Zak 37
CRCToSound ( 0xDEE56848 , V2A_Sound_Single ( 0x009A , 0x0F86 , 0x0100 , 0x3F ) ) ; // Zak 93
CRCToSound ( 0xF9BE27B8 , V2A_Sound_Special_Zak37 ( 0x011C , 0x1704 , 0x0228 , 0x3F ) ) ; // Zak 113
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
CRCToSound ( 0x870EFC29 , V2A_Sound_SingleLoopedPitchbend ( 0x00BA , 0x0100 , 0x03E8 , 0x00C8 , 0x3F , 3 ) ) ; // Zak 55
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
CRCToSound ( 0xB0F77006 , V2A_Sound_Special_Zak52 ( 0x00B0 , 0x01BC ) ) ; // Zak 52
CRCToSound ( 0x5AE9D6A7 , V2A_Sound_Special_ZakAirplane ( 0x00CA , 0x22A4 , 0x0113 , 0x0227 ) ) ; // Zak 109
CRCToSound ( 0xABE0D3B0 , V2A_Sound_Special_ZakAirplane ( 0x00CE , 0x22A4 , 0x0227 , 0x0113 ) ) ; // Zak 105
CRCToSound ( 0x788CC749 , V2A_Sound_Special_Zak71 ( 0x00C8 , 0x0B37 ) ) ; // Zak 71
CRCToSound ( 0x2E2AB1FA , V2A_Sound_Special_Zak99 ( 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
CRCToSound ( 0xAE68ED91 , V2A_Sound_Special_Zak54 ( 0x00D4 , 0x1A25 , 0x1E1E , 0x0B80 , 0x01F4 ) ) ; // Zak 54
CRCToSound ( 0xA4F40F97 , V2A_Sound_Special_Zak61 ( 0x00E4 , 0x0020 ) ) ; // Zak 61
CRCToSound ( 0x348F85CE , V2A_Sound_Special_Zak62 ( 0x00E4 , 0x0020 ) ) ; // Zak 62
CRCToSound ( 0xD473AB86 , V2A_Sound_Special_ManiacTypewriter ( 0x0122 , 0x03E8 , 0x00BE , 0x3F , 7 , ( const uint8 * ) " \x0F \x0B \x04 \x0F \x1E \x0F \x66 " , false ) ) ; // Zak 46
CRCToSound ( 0x84A0BA90 , V2A_Sound_Special_Zak110 ( 0x0126 , 0x0040 , 0x0136 , 0x0080 , 0x007C , 0x0087 ) ) ; // Zak 110
CRCToSound ( 0x92680D9F , V2A_Sound_Special_Zak32 ( 0x0140 , 0x0150 , 0x0010 , 0x0010 ) ) ; // Zak 32
CRCToSound ( 0xABFFDB02 , V2A_Sound_Special_Zak86 ( 0x01A2 , 0x2BAE ) ) ; // Zak 86
CRCToSound ( 0x41045447 , V2A_Sound_Special_Zak98 ( 0x017A , 0x0020 ) ) ; // Zak 98
CRCToSound ( 0xC8EEBD34 , V2A_Sound_Special_Zak82 ( 0x01A6 , 0x3900 ) ) ; // 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 ;
}
2011-11-01 15:03:29 +00:00
void Player_V2A : : setMusicVolume ( int vol ) {
2004-11-28 21:24:02 +00:00
_mod - > setMusicVolume ( vol ) ;
2003-09-24 06:56:30 +00:00
}
2011-11-01 15:03:29 +00:00
int Player_V2A : : getSoundSlot ( int id ) const {
2003-09-24 06:56:30 +00:00
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 ) {
2010-04-28 20:18:56 +00:00
warning ( " player_v2a - sound %i not recognized yet (crc %08X) " , nr , crc ) ;
2003-09-24 06:56:30 +00:00
return ;
}
stopSound ( nr ) ;
int i = getSoundSlot ( ) ;
2011-11-01 14:56:22 +00:00
if ( i = = - 1 ) {
delete snd ;
2003-09-24 06:56:30 +00:00
return ;
2011-11-01 14:56:22 +00:00
}
2003-09-24 06:56:30 +00:00
_slot [ i ] . id = nr ;
2003-10-09 15:03:01 +00:00
_slot [ i ] . sound = snd ;
2010-04-28 20:18:56 +00:00
_slot [ i ] . sound - > start ( _mod , nr , data ) ;
2003-09-24 06:56:30 +00:00
}
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 ;
}
}
}
2009-11-26 00:31:19 +00:00
int Player_V2A : : getMusicTimer ( ) {
2011-11-01 15:03:29 +00:00
return 0 ; // FIXME - need to keep track of playing music resources
2003-09-24 06:56:30 +00:00
}
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