Initial revision.

This commit is contained in:
curt
1998-07-16 17:48:11 +00:00
parent 1175179da1
commit fca7a8fa47
22 changed files with 3172 additions and 0 deletions

12
src/Makefile.am Normal file
View File

@@ -0,0 +1,12 @@
libdir = ${exec_prefix}/lib
lib_LTLIBRARIES = libsl.la libsm.la
libsl_la_SOURCES = \
sl.h slPortability.h \
slDSP.cxx slSample.cxx slEnvelope.cxx \
slSamplePlayer.cxx slScheduler.cxx
libsm_la_SOURCES = sm.h slPortability.h smMixer.cxx
INCLUDES += -I$(top_builddir) -I.

635
src/sl.h Normal file
View File

@@ -0,0 +1,635 @@
#ifndef __SL_H__
#define __SL_H__ 1
#include "slPortability.h"
#ifdef SL_USING_OSS_AUDIO
#define SLDSP_DEFAULT_DEVICE "/dev/dsp"
#elif defined(WIN32)
#define SLDSP_DEFAULT_DEVICE "dsp"
#elif defined(__OpenBSD__)
#define SLDSP_DEFAULT_DEVICE "/dev/audio"
#elif defined(sgi)
#define SLDSP_DEFAULT_DEVICE "dsp" // dummy ...
#else
#error "Port me !"
#endif
# define SL_TRUE 1
# define SL_FALSE 0
typedef unsigned char Uchar ;
typedef unsigned short Ushort ;
#define SL_DEFAULT_SAMPLING_RATE 11025
class slSample ;
class slSamplePlayer ;
class slEnvelope ;
class slScheduler ;
class slDSP ;
class slDSP
{
private:
int stereo ;
int rate ;
int bps ;
int error ;
int fd ;
#ifdef __OpenBSD__
audio_info_t ainfo; // ioctl structure
audio_offset_t audio_offset; // offset in audiostream
long counter; // counter-written packets
#elif defined(SL_USING_OSS_AUDIO)
audio_buf_info buff_info ;
#elif defined(sgi)
ALconfig config; // configuration stuff
ALport port; // .. we are here
#endif
#ifndef WIN32
int ioctl ( int cmd, int param = 0 )
{
if ( error ) return param ;
if ( ::ioctl ( fd, cmd, & param ) == -1 )
{
perror ( "slDSP: ioctl" ) ;
error = SL_TRUE ;
}
return param ;
}
#elif defined(WIN32)
HWAVEOUT hWaveOut; // device handle
WAVEFORMATEX Format; // open needs this
MMTIME mmt; // timing
WAVEHDR wavehdr[ 3 ]; // for round robin ..
int curr_header; // index of actual wavehdr
long counter; // counter-written packets
#endif
void open ( char *device, int _rate, int _stereo, int _bps ) ;
void close () ;
void getBufferInfo () ;
void write ( void *buffer, size_t length ) ;
protected:
void setError () { error = SL_TRUE ; }
int getDriverBufferSize () ;
public:
slDSP ( int _rate = SL_DEFAULT_SAMPLING_RATE,
int _stereo = SL_FALSE, int _bps = 8 )
{
open ( SLDSP_DEFAULT_DEVICE, _rate, _stereo, _bps ) ;
}
slDSP ( char *device, int _rate = SL_DEFAULT_SAMPLING_RATE,
int _stereo = SL_FALSE, int _bps = 8 )
{
open ( device, _rate, _stereo, _bps ) ;
}
~slDSP () { close () ; }
float secondsRemaining () ;
float secondsUsed () ;
void play ( void *buffer, size_t length ) { write ( buffer, length ) ; }
int not_working () { return error ; }
int getBps () { return bps ; }
int getRate () { return rate ; }
int getStereo() { return stereo ; }
void sync () ;
void stop () ;
} ;
class slSample
{
int ref_count ;
protected:
char *comment;
int rate ;
int bps ;
int stereo ;
Uchar *buffer ;
int length ;
void init ()
{
ref_count = 0 ;
comment = NULL ;
buffer = NULL ;
length = 0 ;
rate = SL_DEFAULT_SAMPLING_RATE ;
bps = 8 ;
stereo = SL_FALSE ;
}
public:
slSample () { init () ; }
slSample ( Uchar *buff, int leng )
{
init () ;
setBuffer ( buff, leng ) ;
}
slSample ( char *fname, class slDSP *dsp = NULL )
{
init () ;
loadFile ( fname ) ;
autoMatch ( dsp ) ;
}
~slSample ()
{
if ( ref_count != 0 )
{
fprintf ( stderr,
"slSample: FATAL ERROR - Application deleted a sample while it was playing.\n" ) ;
exit ( 1 ) ;
}
delete buffer ;
}
void ref () { ref_count++ ; }
void unRef () { ref_count-- ; }
int getPlayCount () { return ref_count ; }
char *getComment () { return comment ; }
void setComment ( char *nc )
{
delete comment ;
comment = new char [ strlen ( nc ) + 1 ] ;
strcpy ( comment, nc ) ;
}
Uchar *getBuffer () { return buffer ; }
int getLength () { return length ; }
void autoMatch ( slDSP *dsp ) ;
void setBuffer ( Uchar *buff, int leng )
{
delete buffer ;
buffer = new Uchar [ leng ] ;
if ( buff != NULL )
memcpy ( buffer, buff, leng ) ;
length = leng ;
}
/* These routines only set flags - use changeXXX () to convert a sound */
void setRate ( int r ) { rate = r ; }
void setBps ( int b ) { bps = b ; }
void setStereo ( int s ) { stereo = s ; }
int getRate () { return rate ; }
int getBps () { return bps ; }
int getStereo () { return stereo ; }
float getDuration () { return (float) getLength() /
(float) ( (getStereo()?2.0f:1.0f)*
(getBps()/8.0f)*getRate() ) ; }
int loadFile ( char *fname ) ;
int loadRawFile ( char *fname ) ;
int loadAUFile ( char *fname ) ;
int loadWavFile ( char *fname ) ;
void changeRate ( int r ) ;
void changeBps ( int b ) ;
void changeStereo ( int s ) ;
void adjustVolume ( float vol ) ;
void print ( FILE *fd )
{
if ( buffer == NULL )
{
fprintf ( fd, "Empty sample buffer\n" ) ;
}
else
{
fprintf ( fd, "\"%s\"\n",(getComment() == NULL ||
getComment()[0]=='\0') ? "Sample" : comment ) ;
fprintf ( fd, "%s, %d bits per sample.\n",
getStereo() ? "Stereo" : "Mono", getBps() ) ;
fprintf ( fd, "%gKHz sample rate.\n", (float) getRate() / 1000.0f ) ;
fprintf ( fd, "%d bytes of samples == %g seconds duration.\n", getLength(), getDuration() ) ;
}
}
} ;
enum slSampleStatus
{
SL_SAMPLE_WAITING, /* Sound hasn't started playing yet */
SL_SAMPLE_RUNNING, /* Sound has started playing */
SL_SAMPLE_DONE , /* Sound is complete */
SL_SAMPLE_PAUSED /* Sound hasn't started playing yet */
} ;
enum slPreemptMode
{
SL_SAMPLE_CONTINUE, /* Don't allow yourself to be preempted */
SL_SAMPLE_ABORT , /* Abort playing the sound when preempted */
SL_SAMPLE_RESTART , /* Restart the sound when load permits */
SL_SAMPLE_MUTE , /* Continue silently until load permits */
SL_SAMPLE_DELAY /* Pause until load permits */
} ;
enum slReplayMode
{
SL_SAMPLE_LOOP, /* Loop sound so that it plays forever */
SL_SAMPLE_ONE_SHOT /* Play sound just once */
} ;
enum slEvent
{
SL_EVENT_COMPLETE, /* Sound finished playing */
SL_EVENT_LOOPED, /* Sound looped back to the start */
SL_EVENT_PREEMPTED /* Sound was preempted */
} ;
typedef void (*slCallBack) ( slSample *, slEvent, int ) ;
class slEnvelope
{
float *time ;
float *value ;
int nsteps ;
int ref_count ;
slReplayMode replay_mode ;
int getStepDelta ( float *_time, float *delta ) ;
public:
slEnvelope ( int _nsteps, slReplayMode _rm, float *_times, float *_values )
{
ref_count = 0 ;
nsteps = _nsteps ;
time = new float [ nsteps ] ;
value = new float [ nsteps ] ;
memcpy ( time , _times , sizeof(float) * nsteps ) ;
memcpy ( value, _values, sizeof(float) * nsteps ) ;
replay_mode = _rm ;
}
slEnvelope ( int _nsteps = 1, slReplayMode _rm = SL_SAMPLE_ONE_SHOT )
{
ref_count = 0 ;
nsteps = _nsteps ;
time = new float [ nsteps ] ;
value = new float [ nsteps ] ;
for ( int i = 0 ; i < nsteps ; i++ )
time [ i ] = value [ i ] = 0.0 ;
replay_mode = _rm ;
}
~slEnvelope ()
{
if ( ref_count != 0 )
{
fprintf ( stderr,
"slEnvelope: FATAL ERROR - Application deleted an envelope while it was playing.\n" ) ;
exit ( 1 ) ;
}
delete time ;
delete value ;
}
void ref () { ref_count++ ; }
void unRef () { ref_count-- ; }
int getPlayCount () { return ref_count ; }
void setStep ( int n, float _time, float _value )
{
if ( n >= 0 && n < nsteps )
{
time [ n ] = _time ;
value [ n ] = _value ;
}
}
float getStepValue ( int s ) { return value [ s ] ; }
float getStepTime ( int s ) { return time [ s ] ; }
int getNumSteps () { return nsteps ; }
float getValue ( float _time ) ;
void applyToVolume ( Uchar *dst, Uchar *src, int nframes, int start ) ;
void applyToInvVolume ( Uchar *dst, Uchar *src, int nframes, int start ) ;
} ;
#define SL_MAX_PRIORITY 16
#define SL_MAX_SAMPLES 16
#define SL_MAX_CALLBACKS (SL_MAX_SAMPLES * 2)
#define SL_MAX_ENVELOPES 4
enum slEnvelopeType
{
SL_PITCH_ENVELOPE , SL_INVERSE_PITCH_ENVELOPE ,
SL_VOLUME_ENVELOPE, SL_INVERSE_VOLUME_ENVELOPE,
SL_FILTER_ENVELOPE, SL_INVERSE_FILTER_ENVELOPE,
SL_PAN_ENVELOPE , SL_INVERSE_PAN_ENVELOPE ,
SL_ECHO_ENVELOPE , SL_INVERSE_ECHO_ENVELOPE ,
SL_NULL_ENVELOPE
} ;
struct slPendingCallBack
{
slCallBack callback ;
slSample *sample ;
slEvent event ;
int magic ;
} ;
class slSamplePlayer
{
int lengthRemaining ;
Uchar *bufferPos ;
slSample *sample ;
slEnvelope *env [ SL_MAX_ENVELOPES ] ;
slEnvelopeType env_type [ SL_MAX_ENVELOPES ] ;
int env_start_time [ SL_MAX_ENVELOPES ] ;
slReplayMode replay_mode ;
slPreemptMode preempt_mode ;
slSampleStatus status ;
int priority ;
slCallBack callback ;
int magic ;
public:
slSamplePlayer ( slSample *s, slReplayMode rp_mode = SL_SAMPLE_ONE_SHOT,
int pri = 0, slPreemptMode pr_mode = SL_SAMPLE_DELAY,
int _magic = 0, slCallBack cb = NULL )
{
magic = _magic ;
sample = s ;
callback = cb ;
for ( int i = 0 ; i < SL_MAX_ENVELOPES ; i++ )
{
env [ i ] = NULL ;
env_type [ i ] = SL_NULL_ENVELOPE ;
}
if ( sample ) sample -> ref () ;
reset () ;
replay_mode = rp_mode ;
preempt_mode = pr_mode ;
priority = pri ;
}
~slSamplePlayer () ;
int getAmountLeft ()
{
return lengthRemaining ;
}
slPreemptMode getPreemptMode () { return preempt_mode ; }
int getPriority ()
{
return ( isRunning() &&
preempt_mode == SL_SAMPLE_CONTINUE ) ? (SL_MAX_PRIORITY+1) :
priority ;
}
int preempt ( int delay ) ;
void addEnvelope ( int i, slEnvelope *_env, slEnvelopeType _type ) ;
void pause ()
{
if ( status != SL_SAMPLE_DONE )
status = SL_SAMPLE_PAUSED ;
}
void resume ()
{
if ( status == SL_SAMPLE_PAUSED )
status = SL_SAMPLE_RUNNING ;
}
void reset ()
{
status = SL_SAMPLE_WAITING ;
lengthRemaining = sample->getLength () ;
bufferPos = sample->getBuffer () ;
}
void start ()
{
status = SL_SAMPLE_RUNNING ;
lengthRemaining = sample->getLength () ;
bufferPos = sample->getBuffer () ;
}
void stop ()
{
status = SL_SAMPLE_DONE ;
lengthRemaining = 0 ;
bufferPos = NULL ;
}
int getMagic () { return magic ; }
slSample *getSample () { return sample ; }
int isWaiting () { return status == SL_SAMPLE_WAITING ; }
int isPaused () { return status == SL_SAMPLE_PAUSED ; }
int isRunning () { return status == SL_SAMPLE_RUNNING ; }
int isDone () { return status == SL_SAMPLE_DONE ; }
void skip ( int nframes ) ;
Uchar *read ( int nframes, Uchar *spare1, Uchar *spare2 ) ;
} ;
class slScheduler : public slDSP
{
slPendingCallBack pending_callback [ SL_MAX_CALLBACKS ] ;
int num_pending_callbacks ;
float safety_margin ;
int mixer_buffer_size ;
Uchar *mixer_buffer ;
Uchar *mixer ;
int amount_left ;
slSamplePlayer *samplePlayer [ SL_MAX_SAMPLES ] ;
Uchar *spare_buffer1 [ 3 ] ;
Uchar *spare_buffer2 [ 3 ] ;
void init () ;
Uchar *mergeBlock ( Uchar *d ) ;
Uchar *mergeBlock ( Uchar *d, slSamplePlayer *spa ) ;
Uchar *mergeBlock ( Uchar *d, slSamplePlayer *spa,
slSamplePlayer *spb ) ;
Uchar *mergeBlock ( Uchar *d, slSamplePlayer *spa,
slSamplePlayer *spb,
slSamplePlayer *spc ) ;
void mixBuffer () ;
void mixBuffer ( slSamplePlayer *a ) ;
void mixBuffer ( slSamplePlayer *a,
slSamplePlayer *b ) ;
void mixBuffer ( slSamplePlayer *a,
slSamplePlayer *b,
slSamplePlayer *c ) ;
Uchar mix ( Uchar a, Uchar b )
{
register int r = a + b - 0x80 ;
return ( r > 255 ) ? 255 :
( r < 0 ) ? 0 : r ;
}
Uchar mix ( Uchar a, Uchar b, Uchar c )
{
register int r = a + b + c - 0x80 - 0x80 ;
return ( r > 255 ) ? 255 :
( r < 0 ) ? 0 : r ;
}
void realUpdate ( int dump_first = SL_FALSE ) ;
void initBuffers () ;
int now ;
static slScheduler *current ;
public:
slScheduler ( int _rate = SL_DEFAULT_SAMPLING_RATE ) : slDSP ( _rate, SL_FALSE, 8 ) { init () ; }
slScheduler ( char *device,
int _rate = SL_DEFAULT_SAMPLING_RATE ) : slDSP ( device, _rate, SL_FALSE, 8 ) { init () ; }
~slScheduler () ;
static slScheduler *getCurrent () { return current ; }
int getTimeNow () { return now ; }
float getElapsedTime ( int then ) { return (float)(now-then)/(float)getRate() ; }
void flushCallBacks () ;
void addCallBack ( slCallBack c, slSample *s, slEvent e, int m ) ;
void update () { realUpdate ( SL_FALSE ) ; }
void dumpUpdate () { realUpdate ( SL_TRUE ) ; }
void addSampleEnvelope ( slSample *s = NULL, int magic = 0,
int slot = 1, slEnvelope *e = NULL,
slEnvelopeType t = SL_VOLUME_ENVELOPE )
{
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
if ( samplePlayer [ i ] != NULL &&
( s == NULL || samplePlayer [ i ] -> getSample () == s ) &&
( magic == 0 || samplePlayer [ i ] -> getMagic () == magic ) )
samplePlayer [ i ] -> addEnvelope ( slot, e, t ) ;
}
void resumeSample ( slSample *s = NULL, int magic = 0 )
{
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
if ( samplePlayer [ i ] != NULL &&
( s == NULL || samplePlayer [ i ] -> getSample () == s ) &&
( magic == 0 || samplePlayer [ i ] -> getMagic () == magic ) )
samplePlayer [ i ] -> resume () ;
}
void pauseSample ( slSample *s = NULL, int magic = 0 )
{
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
if ( samplePlayer [ i ] != NULL &&
( s == NULL || samplePlayer [ i ] -> getSample () == s ) &&
( magic == 0 || samplePlayer [ i ] -> getMagic () == magic ) )
samplePlayer [ i ] -> pause () ;
}
void stopSample ( slSample *s = NULL, int magic = 0 )
{
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
if ( samplePlayer [ i ] != NULL &&
( s == NULL || samplePlayer [ i ] -> getSample () == s ) &&
( magic == 0 || samplePlayer [ i ] -> getMagic () == magic ) )
samplePlayer [ i ] -> stop () ;
}
int loopSample ( slSample *s, int pri = 0, slPreemptMode mode = SL_SAMPLE_MUTE, int magic = 0, slCallBack cb = NULL )
{
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
if ( samplePlayer [ i ] == NULL )
{
samplePlayer [ i ] = new slSamplePlayer ( s, SL_SAMPLE_LOOP, pri, mode, magic, cb ) ;
return i ;
}
return -1 ;
}
int playSample ( slSample *s, int pri = 1, slPreemptMode mode = SL_SAMPLE_ABORT, int magic = 0, slCallBack cb = NULL )
{
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
if ( samplePlayer [ i ] == NULL )
{
samplePlayer [ i ] = new slSamplePlayer ( s, SL_SAMPLE_ONE_SHOT, pri, mode, magic, cb ) ;
return SL_TRUE ;
}
return SL_FALSE ;
}
void setSafetyMargin ( float seconds ) { safety_margin = seconds ; }
} ;
#endif

663
src/slDSP.cxx Normal file
View File

@@ -0,0 +1,663 @@
#include "sl.h"
static int init_bytes ;
#ifdef SL_USING_OSS_AUDIO
/* ------------------------------------------------------------ */
/* OSSAUDIO - Linux, FreeBSD, etc */
/* ------------------------------------------------------------ */
void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
{
fd = ::open ( device, O_WRONLY ) ;
if ( fd < 0 )
{
perror ( "slDSP: open" ) ;
error = SL_TRUE ;
stereo = SL_FALSE ;
bps = 1 ;
rate = 8000 ;
init_bytes = 0 ;
}
else
{
error = SL_FALSE ;
/* Set up a driver fragment size of 1024 (ie 2^10) */
ioctl ( SNDCTL_DSP_SETFRAGMENT, 0x7FFF000A ) ;
stereo = ioctl ( SOUND_PCM_WRITE_CHANNELS, _stereo ? 2 : 1 ) >= 2 ;
bps = ioctl ( SOUND_PCM_WRITE_BITS, _bps ) ;
rate = ioctl ( SOUND_PCM_WRITE_RATE, _rate ) ;
getBufferInfo () ;
init_bytes = buff_info.bytes ;
}
}
void slDSP::close ()
{
if ( fd >= 0 )
::close ( fd ) ;
}
int slDSP::getDriverBufferSize ()
{
if ( error )
return 0 ;
getBufferInfo () ;
return buff_info.fragsize ;
}
void slDSP::getBufferInfo ()
{
if ( error )
return ;
if ( ::ioctl ( fd, SNDCTL_DSP_GETOSPACE, & buff_info ) < 0 )
{
perror ( "slDSP: getBufferInfo" ) ;
error = SL_TRUE ;
return ;
}
}
void slDSP::write ( void *buffer, size_t length )
{
if ( error || length <= 0 )
return ;
int nwritten = ::write ( fd, (const char *) buffer, length ) ;
if ( nwritten < 0 )
perror ( "slDSP: write" ) ;
else
if ( nwritten != length )
perror ( "slDSP: short write" ) ;
}
float slDSP::secondsRemaining ()
{
if ( error )
return 0.0f ;
getBufferInfo () ;
int samples_left = buff_info.fragments * buff_info.fragsize ;
if ( stereo ) samples_left /= 2 ;
if ( bps == 16 ) samples_left /= 2 ;
return (float) samples_left / (float) rate ;
}
float slDSP::secondsUsed ()
{
if ( error )
return 0.0f ;
getBufferInfo () ;
int samples_used = init_bytes - buff_info.bytes ;
if ( stereo ) samples_used /= 2 ;
if ( bps == 16 ) samples_used /= 2 ;
return (float) samples_used / (float) rate ;
}
void slDSP::sync ()
{
if ( !error) ::ioctl ( fd, SOUND_PCM_SYNC , 0 ) ;
}
void slDSP::stop ()
{
if ( !error) ::ioctl ( fd, SOUND_PCM_RESET, 0 ) ;
}
#endif
#ifdef WIN32
/* ------------------------------------------------------------ */
/* win32 */
/* ------------------------------------------------------------ */
static void wperror(MMRESULT num)
{
char buffer[0xff]; // yes, this is hardcoded :-)
waveOutGetErrorText( num, buffer, sizeof(buffer)-1);
fprintf( stderr, "SlDSP: %s\n", buffer );
fflush ( stderr );
}
void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
switch( uMsg )
{
case WOM_CLOSE:
break;
case WOM_OPEN:
break;
case WOM_DONE:
waveOutUnprepareHeader( (HWAVEOUT)dwParam1,
(LPWAVEHDR)dwParam2, sizeof( WAVEHDR ));
break;
}
}
void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
{
MMRESULT result;
hWaveOut = NULL;
curr_header = 0;
counter = 0;
Format.wFormatTag = WAVE_FORMAT_PCM;
Format.nChannels = _stereo ? 2 : 1;
Format.nSamplesPerSec = _rate;
Format.wBitsPerSample = _bps;
Format.nBlockAlign = 1;
Format.nAvgBytesPerSec = _rate * Format.nChannels;
Format.cbSize = 0;
result = waveOutOpen( & hWaveOut, WAVE_MAPPER, & Format, NULL,
0L, WAVE_FORMAT_QUERY );
if ( result != MMSYSERR_NOERROR )
{
wperror( result);
error = SL_TRUE ;
stereo = SL_FALSE ;
bps = _bps ;
rate = _rate ;
init_bytes = 0 ;
return;
}
// Now the hwaveouthandle "should" be valid
if ( ( result = waveOutOpen( & hWaveOut, WAVE_MAPPER,
(WAVEFORMATEX *)& Format, (DWORD)waveOutProc,
0L, CALLBACK_FUNCTION )) != MMSYSERR_NOERROR )
{
wperror( result);
error = SL_TRUE ;
stereo = SL_FALSE ;
bps = _bps ;
rate = _rate ;
init_bytes = 0 ;
return;
}
else
{
error = SL_FALSE ;
stereo = _stereo;
bps = _bps;
rate = _rate;
/* hmm ?! */
init_bytes = 1024*8;
}
}
void slDSP::close ()
{
if ( hWaveOut != NULL )
{
waveOutClose( hWaveOut );
hWaveOut = NULL;
}
}
int slDSP::getDriverBufferSize ()
{
if ( error )
return 0 ;
/* hmm ?! */
return 1024*8;
}
void slDSP::getBufferInfo ()
{
return ;
}
void slDSP::write ( void *buffer, size_t length )
{
MMRESULT result;
if ( error || length <= 0 )
return ;
wavehdr[curr_header].lpData = (LPSTR) buffer;
wavehdr[curr_header].dwBufferLength = (long) length;
wavehdr[curr_header].dwBytesRecorded = 0L;
wavehdr[curr_header].dwUser = NULL;
wavehdr[curr_header].dwFlags = 0;
wavehdr[curr_header].dwLoops = 0;
wavehdr[curr_header].lpNext = NULL;
wavehdr[curr_header].reserved = 0;
result = waveOutPrepareHeader( hWaveOut, & wavehdr[curr_header],
sizeof(WAVEHDR));
if ( result != MMSYSERR_NOERROR )
{
wperror ( result );
error = SL_TRUE;
}
result = waveOutWrite(hWaveOut, & wavehdr[curr_header],
sizeof(WAVEHDR));
if ( result != MMSYSERR_NOERROR )
{
wperror ( result );
error = SL_TRUE;
}
counter ++;
curr_header = ( curr_header + 1 ) % 3;
}
float slDSP::secondsRemaining ()
{
if ( error )
return 0.0f ;
return 0.0f ;
}
float slDSP::secondsUsed ()
{
int samples_used;
MMRESULT result;
float samp_time;
if ( error )
return 0.0f ;
mmt.wType = TIME_BYTES;
result = waveOutGetPosition( hWaveOut, &mmt, sizeof( mmt ));
if ( mmt.u.cb == 0 || counter == 0)
return (float)0.0;
samples_used = ( init_bytes * counter ) - mmt.u.cb;
if ( stereo ) samples_used /= 2 ;
if ( bps == 16 ) samples_used /= 2 ;
samp_time = (float) samples_used / (float) rate ;
//printf("%0.2f position=%ld total written=%ld\n",
// samp_time, mmt.u.cb, init_bytes * counter );
return samp_time;
}
void slDSP::sync ()
{
}
void slDSP::stop ()
{
waveOutReset( hWaveOut );
}
/* ------------------------------------------------------------ */
/* OpenBSD 2.3 this should be very close to SUN Audio */
/* ------------------------------------------------------------ */
#elif defined(__OpenBSD__)
void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
{
counter = 0;
fd = ::open ( device, O_RDWR ) ;
if ( fd < 0 )
{
perror ( "slDSP: open" ) ;
error = SL_TRUE ;
}
else
{
if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) == -1)
{
perror("slDSP: open - getinfo");
stereo = SL_FALSE ;
bps = 8 ;
rate = 8000 ;
init_bytes = 0 ;
return;
}
ainfo.play.sample_rate = _rate;
ainfo.play.precision = _bps;
ainfo.play.channels = _stereo ? 2 : 1;
ainfo.play.encoding = AUDIO_ENCODING_ULINEAR;
if( :: ioctl(fd, AUDIO_SETINFO, &ainfo) == -1)
{
perror("slDSP: open - setinfo");
stereo = SL_FALSE ;
bps = 8 ;
rate = 8000 ;
init_bytes = 0 ;
return;
}
rate = _rate;
stereo = _stereo;
bps = _bps;
error = SL_FALSE ;
getBufferInfo ();
// I could not change the size,
// so let's try this ...
init_bytes = 1024 * 8;
}
}
void slDSP::close ()
{
if ( fd >= 0 )
::close ( fd ) ;
}
int slDSP::getDriverBufferSize ()
{
if ( error )
return 0 ;
getBufferInfo () ;
// HW buffer is 0xffff on my box
//return ainfo.play.buffer_size;
return 1024 * 8;
}
void slDSP::getBufferInfo ()
{
if ( error )
return ;
if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) < 0)
{
perror ( "slDSP: getBufferInfo" ) ;
error = SL_TRUE ;
return ;
}
if( ::ioctl( fd, AUDIO_GETOOFFS, &audio_offset ) < 0)
{
perror ( "slDSP: getBufferInfo" ) ;
error = SL_TRUE ;
return ;
}
}
void slDSP::write ( void *buffer, size_t length )
{
if ( error || length <= 0 )
return ;
int nwritten = ::write ( fd, (const char *) buffer, length ) ;
if ( nwritten < 0 )
perror ( "slDSP: write" ) ;
else if ( nwritten != length )
perror ( "slDSP: short write" ) ;
counter ++; /* hmmm */
}
float slDSP::secondsRemaining ()
{
return 0.0f ;
}
float slDSP::secondsUsed ()
{
/*
* original formula from Steve:
* -----------------------------
*
* int samples_used = init_bytes - buff_info.bytes ;
* | |
* | +--- current available
* | space in bytes !
* +---------------- available space
* when empty;
*
* sample_used contains the number of bytes which are
* "used" or in the DSP "pipeline".
*/
int samples_used;
if ( error )
return 0.0f ;
getBufferInfo () ;
//This is wrong: this is the hw queue in the kernel !
//samples_used = ainfo.play.buffer_size - audio_offset.offset ;
// This is: all data written minus where we are now in the queue
if ( counter == 0 )
return 0.0;
samples_used = ( counter * init_bytes ) - audio_offset.samples;
if ( stereo ) samples_used /= 2 ;
if ( bps == 16 ) samples_used /= 2 ;
return (float) samples_used / (float) rate ;
}
void slDSP::sync ()
{
if ( !error) ::ioctl ( fd, AUDIO_FLUSH , 0 ) ;
}
void slDSP::stop ()
{
// nothing found yet
}
/* ------------------------------------------------------------ */
/* SGI IRIX audio */
/* ------------------------------------------------------------ */
#elif defined(sgi)
void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
{
if ( _bps != 8 )
{
perror ( "slDSP: supports only 8bit audio for sgi" ) ;
error = SL_TRUE;
return;
}
init_bytes = 1024 * 8;
config = ALnewconfig();
ALsetchannels ( config, _stereo ? AL_STEREO : AL_MONO );
ALsetwidth ( config, _bps == 8 ? AL_SAMPLE_8 : AL_SAMPLE_16 );
ALsetqueuesize( config, init_bytes );
port = ALopenport( device, "w", config );
if ( port == NULL )
{
perror ( "slDSP: open" ) ;
error = SL_TRUE ;
}
else
{
long params[2] = {AL_OUTPUT_RATE, 0 };
params[1] = _rate;
if ( ALsetparams(AL_DEFAULT_DEVICE, params, 2) != 0 )
{
perror ( "slDSP: open - ALsetparams" ) ;
error = SL_TRUE ;
return;
}
rate = _rate;
stereo = _stereo;
bps = _bps;
error = SL_FALSE ;
}
}
void slDSP::close ()
{
if ( port != NULL )
{
ALcloseport ( port );
ALfreeconfig( config );
port = NULL;
}
}
int slDSP::getDriverBufferSize ()
{
if ( error )
return 0 ;
return ALgetqueuesize( config );
}
void slDSP::getBufferInfo ()
{
if ( error )
return ;
}
void slDSP::write ( void *buffer, size_t length )
{
char *buf = (char *)buffer;
int i;
if ( error || length <= 0 )
return ;
// Steve: is this a problem ??
for ( i = 0; i < length; i ++ )
buf[i] = buf[i] >> 1;
ALwritesamps(port, (void *)buf, length );
}
float slDSP::secondsRemaining ()
{
int samples_remain;
if ( error )
return 0.0f ;
samples_remain = ALgetfillable(port);
if ( stereo ) samples_remain /= 2 ;
if ( bps == 16 ) samples_remain /= 2 ;
return (float) samples_remain / (float) rate ;
}
float slDSP::secondsUsed ()
{
int samples_used;
if ( error )
return 0.0f ;
samples_used = ALgetfilled(port);
if ( stereo ) samples_used /= 2 ;
if ( bps == 16 ) samples_used /= 2 ;
return (float) samples_used / (float) rate ;
}
void slDSP::sync ()
{
/* found this in the header file - but no description
* or example for the long parameter.
*/
// ALflush(ALport, long);
}
void slDSP::stop ()
{
}
#endif

92
src/slEnvelope.cxx Normal file
View File

@@ -0,0 +1,92 @@
#include "sl.h"
float slEnvelope::getValue ( float _time )
{
float delta ;
int step = getStepDelta ( &_time, &delta ) ;
return delta * (_time - time[step]) + value[step] ;
}
int slEnvelope::getStepDelta ( float *_time, float *delta )
{
float tt ;
if ( replay_mode == SL_SAMPLE_LOOP )
{
tt = floor ( *_time / time [ nsteps-1 ] ) ;
*_time -= tt * time [ nsteps-1 ] ;
}
tt = *_time ;
if ( tt <= time[ 0 ] ) { *delta = 0.0f ; return 0 ; }
if ( tt >= time[nsteps-1] ) { *delta = 0.0f ; return nsteps-1 ; }
for ( int i = 1 ; i <= nsteps-1 ; i++ )
if ( tt <= time[i] )
{
float t1 = time[i-1] ; float v1 = value[i-1] ;
float t2 = time[ i ] ; float v2 = value[ i ] ;
if ( t1 == t2 )
{
*delta = 0.0f ;
return i ;
}
*delta = (v2-v1) / (t2-t1) ;
return i-1 ;
}
*delta = 0.0f ;
return nsteps - 1 ;
}
void slEnvelope::applyToVolume ( Uchar *dst, Uchar *src,
int nframes, int start )
{
float delta ;
float _time = slScheduler::getCurrent() -> getElapsedTime ( start ) ;
int step = getStepDelta ( &_time, &delta ) ;
float _value = delta * (_time - time[step]) + value[step] ;
delta /= (float) slScheduler::getCurrent() -> getRate () ;
while ( nframes-- )
{
register int res = (int)( (float)((int)*(src++)-0x80) * _value ) + 0x80 ;
_value += delta ;
*(dst++) = ( res > 255 ) ? 255 : ( res < 0 ) ? 0 : res ;
}
}
void slEnvelope::applyToInvVolume ( Uchar *dst, Uchar *src,
int nframes, int start )
{
float delta ;
float _time = slScheduler::getCurrent() -> getElapsedTime ( start ) ;
int step = getStepDelta ( &_time, &delta ) ;
float _value = delta * (_time - time[step]) + value[step] ;
delta /= (float) slScheduler::getCurrent() -> getRate () ;
delta = - delta ;
_value = 1.0 - _value ;
while ( nframes-- )
{
register int res = (int)( (float)((int)*(src++)-0x80) * _value ) + 0x80 ;
_value += delta ;
*(dst++) = ( res > 255 ) ? 255 : ( res < 0 ) ? 0 : res ;
}
}

72
src/slPortability.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef __SLPORTABILITY_H__
#define __SLPORTABILITY_H__ 1
/* ------------------------------------------------------------- */
/* OS specific includes and defines ... */
/* ------------------------------------------------------------- */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#undef VERSION
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#include <sys/ioctl.h>
#else
#include <windows.h>
#ifdef __CYGWIN32__
# define NEAR /* */
# define FAR /* */
# define WHERE_EVER_YOU_ARE /* Curt: optional, but it reminds me of a song */
#endif
#include <mmsystem.h>
#endif
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <math.h>
#ifdef __linux__
#define SL_USING_OSS_AUDIO 1
#endif
#ifdef SL_USING_OSS_AUDIO
#if defined(__linux__)
#include <linux/soundcard.h>
#elif defined(__FreeBSD__)
#include <machine/soundcard.h>
#else
/*
Tom thinks this file may be <sys/soundcard.h> under some
unixen - but that isn't where the OSS manuals say it
should be.
If you ever find out the truth, please email me:
Steve Baker <sjbaker1@airmail.net>
*/
#include <soundcard.h>
#endif
#endif
#ifdef __OpenBSD__
#include <sys/audioio.h>
#endif
#ifdef WIN32
#define strcasecmp stricmp /* Yes, Steve really does *HATE* Windoze */
#endif
/* Tom */
#ifdef sgi
#include <audio.h>
#endif
#endif

505
src/slSample.cxx Normal file
View File

@@ -0,0 +1,505 @@
#include "sl.h"
#include <math.h>
void slSample::autoMatch ( slDSP *dsp )
{
if ( dsp == NULL ) return ;
changeRate ( dsp->getRate () ) ;
changeBps ( dsp->getBps () ) ;
changeStereo ( dsp->getStereo () ) ;
}
void slSample::adjustVolume ( float vol )
{
for ( int i = 0 ; i < length ; i++ )
{
int s = (int)(((float) buffer[i] - (float) 0x80) * vol) + 0x80 ;
buffer [ i ] = ( s > 255 ) ? 255 :
( s < 0 ) ? 0 : s ;
}
}
void slSample::changeRate ( int r )
{
if ( r == rate ) return ;
int length1 = length / (getBps ()/8) ;
int length2 = (int) ( (float) length1 * ( (float) r / (float) rate ) ) ;
Uchar *buffer2 = new Uchar [ length2 ] ;
float step = (float) length1 / (float) length2 ;
for ( int i = 0 ; i < length2 / (getBps()/8); i++ )
{
float pos = (float) i * step ;
int p1 = (int) floor ( pos ) ;
int p2 = (int) ceil ( pos ) ;
if ( stereo )
{
if ( ( p1 & 1 ) != ( i & 1 ) ) { pos++ ; p1++ ; p2++ ; }
p2++ ;
}
float ratio = pos - (float) p1 ;
float b1 = (getBps()==8) ?
(float) buffer [(p1<0)?0:(p1>=length1)?length1-1:p1] :
(float) ((Ushort*)buffer)[(p1<0)?0:(p1>=length1)?length1-1:p1] ;
float b2 = (getBps()==8) ?
(float) buffer [(p2<0)?0:(p2>=length1)?length1-1:p2] :
(float) ((Ushort*)buffer)[(p2<0)?0:(p2>=length1)?length1-1:p2] ;
float res = b1 * (1.0-ratio) + b2 * ratio ;
if ( getBps () == 8 )
buffer2 [ i ] = (Uchar) ( (res < 0) ? 0 : (res > 255) ? 255 : res ) ;
else
((Ushort *) buffer2 ) [ i ] =
(Ushort) ( (res < 0) ? 0 : (res > 65535) ? 65535 : res ) ;
}
rate = r ;
length = length2 ;
delete buffer ;
buffer = buffer2 ;
}
#ifdef 0
void slSample::changeToUnsigned ()
{
if ( getBps() == 16 )
{
int length2 = length / 2 ;
Ushort *buffer2 = (Ushort *) buffer ;
for ( int i = 0 ; i < length2 ; i++ )
buffer2 [ i ] = buffer2 [ i ] + 32768 ;
}
else
{
for ( int i = 0 ; i < length ; i++ )
buffer [ i ] = (buffer [ i ]>0x80) ? (buffer[i]-0x80) :
(0xFF-buffer[i]) ;
}
}
#endif
void slSample::changeBps ( int b )
{
if ( b == getBps () ) return ;
if ( b == 8 && getBps() == 16 )
{
length /= 2 ;
Uchar *buffer2 = new Uchar [ length ] ;
for ( int i = 0 ; i < length ; i++ )
buffer2 [ i ] = ((Ushort *)buffer) [ i ] >> 8 ;
delete buffer ;
buffer = buffer2 ;
setBps ( b ) ;
}
else
if ( b == 16 && getBps() == 8 )
{
Ushort *buffer2 = new Ushort [ length ] ;
for ( int i = 0 ; i < length ; i++ )
buffer2 [ i ] = buffer [ i ] << 8 ;
delete buffer ;
buffer = (Uchar *) buffer2 ;
length *= 2 ;
setBps ( b ) ;
}
}
void slSample::changeStereo ( int s )
{
if ( s == getStereo () )
return ;
if ( s && ! getStereo () )
{
if ( getBps () == 8 )
{
Uchar *buffer2 = new Uchar [ length * 2 ] ;
for ( int i = 0 ; i < length ; i++ )
buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = buffer [ i ] ;
delete buffer ;
buffer = buffer2 ;
length *= 2 ;
setStereo ( SL_TRUE ) ;
}
else
{
Ushort *buffer2 = new Ushort [ length ] ;
for ( int i = 0 ; i < length / 2 ; i++ )
buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = ((Ushort *) buffer) [ i ] ;
delete buffer ;
buffer = (Uchar *)buffer2 ;
length *= 2 ;
setStereo ( SL_TRUE ) ;
}
}
else
{
if ( getBps () == 8 )
{
Uchar *buffer2 = new Uchar [ length / 2 ] ;
for ( int i = 0 ; i < length ; i++ )
buffer2 [ i ] = ((int)buffer [ i*2 ] + (int)buffer [ i*2 + 1 ] ) / 2 ;
delete buffer ;
buffer = buffer2 ;
length /= 2 ;
setStereo ( SL_FALSE ) ;
}
else
{
Ushort *buffer2 = new Ushort [ length / 4 ] ;
for ( int i = 0 ; i < length / 4 ; i++ )
buffer2 [ i ] = ((int)((Ushort *)buffer) [ i*2 ] +
(int)((Ushort *)buffer) [ i*2 + 1 ] ) / 2 ;
delete buffer ;
buffer = (Uchar *)buffer2 ;
length /= 2 ;
setStereo ( SL_FALSE ) ;
}
}
}
static void swap_Ushort ( Ushort *i )
{
*i = ((*i << 8) & 0xFF00) +
((*i >> 8) & 0x00FF) ;
}
static void swap_int ( int *i )
{
*i = ((*i << 24) & 0xFF000000) +
((*i << 8) & 0x00FF0000) +
((*i >> 8) & 0x0000FF00) +
((*i >> 24) & 0x000000FF) ;
}
int slSample::loadFile ( char *fname )
{
if ( strcasecmp ( & fname [ strlen ( fname ) - 4 ], ".wav" ) == 0 )
return loadWavFile ( fname ) ;
if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".au" ) == 0 )
return loadAUFile ( fname ) ;
if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".ub" ) == 0 )
return loadRawFile ( fname ) ;
fprintf ( stderr, "slSample:loadFile: Unknown file type for '%s'.\n",
fname ) ;
return SL_FALSE ;
}
int slSample::loadWavFile ( char *fname )
{
int found_header = SL_FALSE ;
int needs_swabbing = SL_FALSE ;
delete buffer ;
buffer = NULL ;
length = 0 ;
FILE *fd = fopen ( fname, "rb" ) ;
if ( fd == NULL )
{
fprintf ( stderr,
"slSample: loadWavFile: Cannot open '%s' for reading.\n",
fname ) ;
return SL_FALSE ;
}
char magic [ 8 ] ;
if ( fread ( magic, 4, 1, fd ) == -1 ||
magic[0] != 'R' || magic[1] != 'I' ||
magic[2] != 'F' || magic[3] != 'F' )
{
fprintf ( stderr, "slWavSample: File '%s' has wrong magic number\n", fname ) ;
fprintf ( stderr, " - it probably isn't in '.wav' format.\n" ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
int leng1 ;
if ( fread ( & leng1, sizeof(int), 1, fd ) == -1 )
{
fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
fread ( magic, 4, 1, fd ) ;
if ( magic[0] != 'W' || magic[1] != 'A' ||
magic[2] != 'V' || magic[3] != 'E' )
{
fprintf ( stderr, "slSample: File '%s' has no WAVE tag.\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
while ( ! feof ( fd ) )
{
fread ( magic, 4, 1, fd ) ;
if ( magic[0] == 'f' && magic[1] == 'm' &&
magic[2] == 't' && magic[3] == ' ' )
{
found_header = SL_TRUE ;
if ( fread ( & leng1, sizeof(int), 1, fd ) == -1 )
{
fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
if ( leng1 > 65536 )
{
needs_swabbing = SL_TRUE ;
swap_int ( & leng1 ) ;
}
Ushort header [ 8 ] ;
if ( leng1 != sizeof ( header ) )
fprintf ( stderr,
"slSample: File '%s' has unexpectedly long (%d byte) header\n",
fname, leng1 ) ;
fread ( & header, sizeof(header), 1, fd ) ;
for ( int junk = sizeof(header) ; junk < leng1 ; junk++ )
fgetc ( fd ) ;
if ( needs_swabbing )
{
swap_Ushort ( & header[0] ) ;
swap_Ushort ( & header[1] ) ;
swap_int ( (int *) & header[2] ) ;
swap_int ( (int *) & header[4] ) ;
swap_Ushort ( & header[6] ) ;
swap_Ushort ( & header[7] ) ;
}
if ( header [ 0 ] != 0x0001 )
{
fprintf ( stderr, "slSample: File '%s' is not WAVE_FORMAT_PCM!\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
setStereo ( header[1] > 1 ) ;
setRate ( *((int *) (& header[2])) ) ;
setBps ( header[7] ) ;
}
else
if ( magic[0] == 'd' && magic[1] == 'a' &&
magic[2] == 't' && magic[3] == 'a' )
{
if ( ! found_header )
{
fprintf ( stderr, "slSample: File '%s' has no data section\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
if ( fread ( & length, sizeof(int), 1, fd ) == -1 )
{
fprintf ( stderr, "slSample: File '%s' has premature EOF in data\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
if ( needs_swabbing )
swap_int ( & length ) ;
buffer = new Uchar [ length ] ;
fread ( buffer, 1, length, fd ) ;
if ( getBps () == 16 )
{
Ushort *b = (Ushort*) buffer ;
for ( int i = 0 ; i < length/2 ; i++ )
b [ i ] = (Ushort) ( (int)((short) b [ i ]) + 32768 ) ;
}
fclose ( fd ) ;
return SL_TRUE ;
}
}
fclose ( fd ) ;
return SL_FALSE ;
}
int slSample::loadAUFile ( char *fname )
{
delete buffer ;
buffer = NULL ;
length = 0 ;
FILE *fd = fopen ( fname, "rb" ) ;
if ( fd == NULL )
{
fprintf ( stderr,
"slSample: loadAUFile: Cannot open '%s' for reading.\n",
fname ) ;
return SL_FALSE ;
}
char magic [ 4 ] ;
if ( fread ( magic, 4, 1, fd ) == -1 ||
magic[0] != '.' || magic[1] != 's' ||
magic[2] != 'n' || magic[3] != 'd' )
{
fprintf ( stderr, "slSample: File '%s' has wrong magic number\n", fname ) ;
fprintf ( stderr, " - it probably isn't in '.au' format.\n" ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
int hdr_length ;
int dat_length ;
int nbytes ;
int irate ;
int nchans ;
if ( fread ( & hdr_length, sizeof(int), 1, fd ) == -1 ||
fread ( & dat_length, sizeof(int), 1, fd ) == -1 ||
fread ( & nbytes , sizeof(int), 1, fd ) == -1 ||
fread ( & irate , sizeof(int), 1, fd ) == -1 ||
fread ( & nchans , sizeof(int), 1, fd ) == -1 )
{
fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
if ( hdr_length > 65536 )
{
swap_int ( & hdr_length ) ;
swap_int ( & dat_length ) ;
swap_int ( & nbytes ) ;
swap_int ( & irate ) ;
swap_int ( & nchans ) ;
}
bps = nbytes * 8 ;
stereo = (nchans>1) ;
rate = irate ;
if ( nbytes > 2 || nbytes <= 0 || hdr_length > 512 || hdr_length < 24 ||
irate > 65526 || irate <= 1000 || nchans < 1 || nchans > 2 )
{
fprintf ( stderr, "slSample: File '%s' has a very strange header\n", fname ) ;
fprintf ( stderr, " Header Length = %d\n", hdr_length ) ;
fprintf ( stderr, " Data Length = %d\n", dat_length ) ;
fprintf ( stderr, " Bytes/sample = %d\n", nbytes ) ;
fprintf ( stderr, " Sampling Rate = %dHz\n",irate ) ;
fprintf ( stderr, " Num Channels = %d\n", nchans ) ;
fprintf ( stderr, "\n" ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
if ( hdr_length > 24 )
{
delete comment ;
comment = new char [ hdr_length - 24 + 1 ] ;
fread ( comment, 1, hdr_length - 24, fd ) ;
}
if ( dat_length > 0 )
{
buffer = new Uchar [ dat_length ] ;
length = fread ( buffer, 1, dat_length, fd ) ;
if ( length != dat_length )
fprintf ( stderr, "slAUSample: File '%s' has premature EOF in data.\n", fname ) ;
}
fclose ( fd ) ;
return SL_TRUE ;
}
int slSample::loadRawFile ( char *fname )
{
delete buffer ;
buffer = NULL ;
length = 0 ;
FILE *fd = fopen ( fname, "rb" ) ;
if ( fd == NULL )
{
fprintf ( stderr,
"slSample: loadRawFile: Cannot open '%s' for reading.\n",
fname ) ;
return SL_FALSE ;
}
struct stat stat_buf ;
if ( fstat ( fileno ( fd ), & stat_buf ) != 0 )
{
fprintf ( stderr,
"slSample: loadRawFile: Cannot get status for '%s'.\n",
fname ) ;
fclose ( fd ) ;
return SL_FALSE ;
}
length = stat_buf . st_size ;
if ( length > 0 )
{
buffer = new Uchar [ length ] ;
length = fread ( buffer, 1, length, fd ) ;
}
bps = 8 ;
stereo = SL_FALSE ;
rate = 8000 ; /* Guess */
fclose ( fd ) ;
return SL_TRUE ;
}

150
src/slSamplePlayer.cxx Normal file
View File

@@ -0,0 +1,150 @@
#include "sl.h"
void slSamplePlayer::addEnvelope ( int i, slEnvelope *_env, slEnvelopeType _type )
{
if ( i < 0 || i >= SL_MAX_ENVELOPES ) return ;
if ( env [ i ] != NULL )
env [ i ] -> unRef () ;
env [ i ] = _env ;
if ( _env != NULL )
env [ i ] -> ref () ;
env_type [ i ] = _type ;
env_start_time [ i ] = slScheduler::getCurrent() -> getTimeNow () ;
}
int slSamplePlayer::preempt ( int delay )
{
slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_PREEMPTED, magic ) ;
switch ( preempt_mode )
{
case SL_SAMPLE_CONTINUE: if ( isRunning() )
return SL_FALSE ;
/* FALLTHROUGH! */
case SL_SAMPLE_DELAY : break ;
case SL_SAMPLE_MUTE : skip ( delay ) ; break ;
case SL_SAMPLE_ABORT : stop () ; break ;
case SL_SAMPLE_RESTART : reset () ; break ;
}
return SL_TRUE ;
}
slSamplePlayer::~slSamplePlayer ()
{
if ( sample )
sample -> unRef () ;
slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_COMPLETE, magic ) ;
}
void slSamplePlayer::skip ( int nframes )
{
if ( nframes < lengthRemaining )
{
lengthRemaining -= nframes ;
bufferPos += nframes ;
}
else
if ( replay_mode == SL_SAMPLE_LOOP )
{
slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
nframes -= lengthRemaining ;
while ( nframes >= sample->getLength () )
nframes -= sample->getLength () ;
lengthRemaining = sample->getLength() - nframes ;
bufferPos = & ( sample->getBuffer() [ nframes ] ) ;
}
else
stop () ;
}
Uchar *slSamplePlayer::read ( int nframes, Uchar *spare1, Uchar *spare2 )
{
if ( isWaiting() ) start () ;
if ( nframes > lengthRemaining ) /* This is an error */
{
fprintf ( stderr, "slSamplePlayer: FATAL ERROR - Mixer Requested too much data.\n" ) ;
abort () ;
}
Uchar *src = bufferPos ;
Uchar *dst = spare1 ;
for ( int i = 0 ; i < SL_MAX_ENVELOPES ; i++ )
{
if ( env[i] )
{
switch ( env_type [ i ] )
{
case SL_INVERSE_PITCH_ENVELOPE :
case SL_PITCH_ENVELOPE :
memcpy ( dst, src, nframes ) /* Tricky! */ ;
break ;
case SL_INVERSE_VOLUME_ENVELOPE:
env[i]->applyToInvVolume ( dst,src,nframes,env_start_time[i] ) ;
break ;
case SL_VOLUME_ENVELOPE :
env[i]->applyToVolume ( dst,src,nframes,env_start_time[i] ) ;
break ;
case SL_INVERSE_FILTER_ENVELOPE:
case SL_FILTER_ENVELOPE :
memcpy ( dst, src, nframes ) /* Tricky! */ ;
break ;
case SL_INVERSE_PAN_ENVELOPE :
case SL_PAN_ENVELOPE :
memcpy ( dst, src, nframes ) /* Tricky! */ ;
break ;
case SL_INVERSE_ECHO_ENVELOPE :
case SL_ECHO_ENVELOPE :
memcpy ( dst, src, nframes ) /* Tricky! */ ;
break ;
}
if ( dst == spare1 )
{
src = spare1 ;
dst = spare2 ;
}
else
{
dst = spare1 ;
src = spare2 ;
}
}
}
if ( nframes < lengthRemaining ) /* Less data than there is left... */
{
lengthRemaining -= nframes ;
bufferPos += nframes ;
}
else /* Read it all */
{
if ( replay_mode == SL_SAMPLE_ONE_SHOT )
stop () ;
else
{
slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
start () ;
}
}
return src ;
}

370
src/slScheduler.cxx Normal file
View File

@@ -0,0 +1,370 @@
#include "sl.h"
slScheduler *slScheduler::current = NULL ;
void slScheduler::init ()
{
current = this ;
if ( not_working () )
{
fprintf ( stderr, "slScheduler: soundcard init failed.\n" ) ;
setError () ;
return ;
}
if ( getBps() != 8 )
{
fprintf ( stderr, "slScheduler: Needs a sound card that supports 8 bits per sample.\n" ) ;
setError () ;
return ;
}
if ( getStereo() )
{
fprintf ( stderr, "slScheduler: Needs a sound card that supports monophonic replay.\n" ) ;
setError () ;
return ;
}
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
samplePlayer [ i ] = NULL ;
amount_left = 0 ;
now = 0 ;
num_pending_callbacks = 0 ;
safety_margin = 1.0 ;
mixer = NULL ;
mixer_buffer = NULL ;
spare_buffer1 [ 0 ] = NULL ;
spare_buffer1 [ 1 ] = NULL ;
spare_buffer1 [ 2 ] = NULL ;
spare_buffer2 [ 0 ] = NULL ;
spare_buffer2 [ 1 ] = NULL ;
spare_buffer2 [ 2 ] = NULL ;
initBuffers () ;
}
void slScheduler::initBuffers ()
{
if ( not_working () ) return ;
delete mixer_buffer ;
delete spare_buffer1 [ 0 ] ;
delete spare_buffer1 [ 1 ] ;
delete spare_buffer1 [ 2 ] ;
delete spare_buffer2 [ 0 ] ;
delete spare_buffer2 [ 1 ] ;
delete spare_buffer2 [ 2 ] ;
mixer_buffer_size = getDriverBufferSize () ;
mixer_buffer = new Uchar [ mixer_buffer_size ] ;
memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
spare_buffer1 [ 0 ] = new Uchar [ mixer_buffer_size ] ;
spare_buffer1 [ 1 ] = new Uchar [ mixer_buffer_size ] ;
spare_buffer1 [ 2 ] = new Uchar [ mixer_buffer_size ] ;
spare_buffer2 [ 0 ] = new Uchar [ mixer_buffer_size ] ;
spare_buffer2 [ 1 ] = new Uchar [ mixer_buffer_size ] ;
spare_buffer2 [ 2 ] = new Uchar [ mixer_buffer_size ] ;
}
slScheduler::~slScheduler ()
{
if ( current == this )
current = NULL ;
delete mixer_buffer ;
delete spare_buffer1 [ 0 ] ;
delete spare_buffer1 [ 1 ] ;
delete spare_buffer1 [ 2 ] ;
delete spare_buffer2 [ 0 ] ;
delete spare_buffer2 [ 1 ] ;
delete spare_buffer2 [ 2 ] ;
}
Uchar *slScheduler::mergeBlock ( Uchar *d )
{
register int l = amount_left ;
amount_left = 0 ;
memset ( d, 0x80, l ) ;
return d + l ;
}
Uchar *slScheduler::mergeBlock ( Uchar *d, slSamplePlayer *spa )
{
register int l = spa -> getAmountLeft () ;
if ( l > amount_left )
l = amount_left ;
amount_left -= l ;
memcpy ( d, spa->read(l, spare_buffer1[0], spare_buffer2[0]), l ) ;
return d + l ;
}
Uchar *slScheduler::mergeBlock ( Uchar *d, slSamplePlayer *spa, slSamplePlayer *spb )
{
int la = spa -> getAmountLeft () ;
int lb = spb -> getAmountLeft () ;
register int l = ( la < lb ) ? la : lb ;
if ( l > amount_left )
l = amount_left ;
amount_left -= l ;
register Uchar *a = spa -> read ( l, spare_buffer1[0], spare_buffer2[0] ) ;
register Uchar *b = spb -> read ( l, spare_buffer1[1], spare_buffer2[1] ) ;
while ( l-- ) *d++ = mix ( *a++, *b++ ) ;
return d ;
}
Uchar *slScheduler::mergeBlock ( Uchar *d, slSamplePlayer *spa, slSamplePlayer *spb, slSamplePlayer *spc )
{
int la = spa -> getAmountLeft () ;
int lb = spb -> getAmountLeft () ;
int lc = spc -> getAmountLeft () ;
register int l = ( la < lb ) ?
(( la < lc ) ? la : lc ) :
(( lb < lc ) ? lb : lc ) ;
if ( l > amount_left )
l = amount_left ;
amount_left -= l ;
register Uchar *a = spa -> read ( l, spare_buffer1[0], spare_buffer2[0] ) ;
register Uchar *b = spb -> read ( l, spare_buffer1[1], spare_buffer2[1] ) ;
register Uchar *c = spc -> read ( l, spare_buffer1[2], spare_buffer2[2] ) ;
while ( l-- ) *d++ = mix ( *a++, *b++, *c++ ) ;
return d ;
}
void slScheduler::mixBuffer ()
{
register Uchar *d = mixer_buffer ;
amount_left = mixer_buffer_size ;
while ( amount_left > 0 )
d = mergeBlock ( d ) ;
}
void slScheduler::mixBuffer ( slSamplePlayer *spa )
{
register Uchar *d = mixer_buffer ;
amount_left = mixer_buffer_size ;
while ( amount_left > 0 )
{
int la = spa -> getAmountLeft () ;
if ( la > 0 ) /* Buffer has data left... */
d = mergeBlock ( d, spa ) ;
else /* Buffer is empty */
d = mergeBlock ( d ) ;
}
}
void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb )
{
register Uchar *d = mixer_buffer ;
amount_left = mixer_buffer_size ;
while ( amount_left > 0 )
{
int la = spa -> getAmountLeft () ;
int lb = spb -> getAmountLeft () ;
if ( la > 0 && lb > 0 ) /* Both buffers have data left... */
d = mergeBlock ( d, spa, spb ) ;
else
if ( la > 0 && lb <= 0 ) /* Only the A buffer has data left... */
d = mergeBlock ( d, spa ) ;
else
if ( la <= 0 && lb > 0 ) /* Only the B buffer has data left... */
d = mergeBlock ( d, spb ) ;
else /* Both buffers are empty */
d = mergeBlock ( d ) ;
}
}
void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb,
slSamplePlayer *spc )
{
register Uchar *d = mixer_buffer ;
amount_left = mixer_buffer_size ;
while ( amount_left > 0 )
{
int la = spa -> getAmountLeft () ;
int lb = spb -> getAmountLeft () ;
int lc = spc -> getAmountLeft () ;
if ( lc > 0 ) /* C buffer has data left... */
{
if ( la > 0 && lb > 0 ) /* All three buffers have data left... */
d = mergeBlock ( d, spa, spb, spc ) ;
else
if ( la > 0 && lb <= 0 ) /* Only the A&C buffers have data left... */
d = mergeBlock ( d, spa, spc ) ;
else
if ( la <= 0 && lb > 0 ) /* Only the B&C buffers have data left... */
d = mergeBlock ( d, spb, spc ) ;
else /* Only the C buffer has data left */
d = mergeBlock ( d, spc ) ;
}
else
{
if ( la > 0 && lb > 0 ) /* Only the A&B buffers have data left... */
d = mergeBlock ( d, spa, spb ) ;
else
if ( la > 0 && lb <= 0 ) /* Only the A buffer has data left... */
d = mergeBlock ( d, spa ) ;
else
if ( la <= 0 && lb > 0 ) /* Only the B buffer has data left... */
d = mergeBlock ( d, spb ) ;
else /* All three buffers are empty */
d = mergeBlock ( d ) ;
}
}
}
void slScheduler::realUpdate ( int dump_first )
{
int i ;
if ( not_working () )
return ;
while ( secondsUsed() <= safety_margin )
{
slSamplePlayer *psp [ 3 ] ;
int pri [ 3 ] ;
pri [ 0 ] = pri [ 1 ] = pri [ 2 ] = -1 ;
for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
{
if ( samplePlayer [ i ] == NULL )
continue ;
/* Clean up dead sample players */
if ( samplePlayer [ i ] -> isDone () )
{
delete samplePlayer [ i ] ;
samplePlayer [ i ] = NULL ;
continue ;
}
if ( samplePlayer [ i ] -> isPaused () )
continue ;
int lowest = ( pri [0] <= pri [2] ) ?
(( pri [0] <= pri [1] ) ? 0 : 1 ) :
(( pri [1] <= pri [2] ) ? 1 : 2 ) ;
if ( samplePlayer[i]->getPriority() > pri[lowest] )
{
psp[lowest] = samplePlayer[i] ;
pri[lowest] = samplePlayer[i]->getPriority() ;
}
}
for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
{
if ( samplePlayer [ i ] == NULL )
continue ;
if ( ! samplePlayer [ i ] -> isPaused () &&
samplePlayer [ i ] != psp[0] &&
samplePlayer [ i ] != psp[1] &&
samplePlayer [ i ] != psp[2] )
{
samplePlayer [ i ] -> preempt ( mixer_buffer_size ) ;
}
}
if ( pri[0] < 0 ) mixBuffer () ; else
if ( pri[1] < 0 ) mixBuffer ( psp[0] ) ; else
if ( pri[2] < 0 ) mixBuffer ( psp[0], psp[1] ) ; else
mixBuffer ( psp[0], psp[1], psp[2] ) ;
if ( dump_first )
{
stop () ;
dump_first = SL_FALSE ;
}
play ( mixer_buffer, mixer_buffer_size ) ;
now += mixer_buffer_size ;
}
flushCallBacks () ;
}
void slScheduler::addCallBack ( slCallBack c, slSample *s, slEvent e, int m )
{
if ( num_pending_callbacks >= SL_MAX_CALLBACKS )
{
fprintf ( stderr, "slScheduler: Too many pending callback events!\n" ) ;
return ;
}
slPendingCallBack *p = & ( pending_callback [ num_pending_callbacks++ ] ) ;
p -> callback = c ;
p -> sample = s ;
p -> event = e ;
p -> magic = m ;
}
void slScheduler::flushCallBacks ()
{
/*
Execute all the callbacks that we accumulated
in this iteration.
This is done at the end of 'update' to reduce the risk
of nasty side-effects caused by 'unusual' activities
in the application's callback function.
*/
while ( num_pending_callbacks > 0 )
{
slPendingCallBack *p = & ( pending_callback [ --num_pending_callbacks ] ) ;
if ( p -> callback )
(*(p->callback))( p->sample, p->event, p->magic ) ;
}
}

88
src/sm.h Normal file
View File

@@ -0,0 +1,88 @@
#ifndef __SM_H__
#define __SM_H__ 1
#include "slPortability.h"
#ifdef SL_USING_OSS_AUDIO
#define SMMIXER_DEFAULT_DEVICE "/dev/mixer"
#elif defined(WIN32)
#define SMMIXER_DEFAULT_DEVICE "mixer"
#else
#endif
# define SM_TRUE 1
# define SM_FALSE 0
typedef unsigned char Uchar ;
typedef unsigned short Ushort ;
class smMixer
{
private:
int devices ;
int error ;
int fd ;
#ifdef SL_USING_OSS_AUDIO
static char *labels [] = SOUND_DEVICE_LABELS ;
int ioctl ( int cmd, int param = 0 )
{
if ( error ) return param ;
if ( ::ioctl ( fd, cmd, & param ) == -1 )
{
perror ( "smMixer: ioctl" ) ;
error = SM_TRUE ;
}
return param ;
}
#endif
void open ( char *device ) ;
void close () ;
public:
/* Tom */
smMixer ();
smMixer ( char *device );
~smMixer ();
int not_working ();
/* Volume controls are in integer percentages */
int getVolume ( int channel );
void setVolume ( int channel, int volume );
void getVolume ( int channel, int *left, int *right );
void setVolume ( int channel, int left, int right );
void setTreble ( int treble );
void setBass ( int bass );
void setMasterVolume ( int volume );
void setSynthVolume ( int volume );
void setPCMVolume ( int volume );
void setSpeakerVolume( int volume );
void setLineVolume ( int volume );
void setMicVolume ( int volume );
void setCDVolume ( int volume );
void setMasterVolume ( int left, int right );
void setSynthVolume ( int left, int right );
void setPCMVolume ( int left, int right );
void setSpeakerVolume( int left, int right );
void setLineVolume ( int left, int right );
void setMicVolume ( int left, int right );
void setCDVolume ( int left, int right );
} ;
#endif

258
src/smMixer.cxx Normal file
View File

@@ -0,0 +1,258 @@
#include "sm.h"
#ifdef SL_USING_OSS_AUDIO
/* ------------------------------------------------------------ */
/* OSSAUDIO - Linux, FreeBSD */
/* ------------------------------------------------------------ */
void smMixer::open ( char *device )
{
fd = ::open ( device, O_WRONLY ) ;
if ( fd < 0 )
{
perror ( "smMixer: open" ) ;
error = SM_TRUE ;
}
else
error = SM_FALSE ;
devices = ioctl ( SOUND_MIXER_READ_DEVMASK ) ;
}
void smMixer::close ()
{
if ( fd >= 0 )
::close ( fd ) ;
}
smMixer::smMixer ()
{
open ( SMMIXER_DEFAULT_DEVICE ) ;
}
smMixer::smMixer ( char *device )
{
open ( device ) ;
}
smMixer::~smMixer ()
{
close () ;
}
int smMixer::not_working ()
{
return error ;
}
/* Volume controls are in integer percentages */
int smMixer::getVolume ( int channel )
{
return ioctl ( MIXER_READ ( channel ) ) & 0xFF ;
}
void smMixer::setVolume ( int channel, int volume )
{
ioctl ( MIXER_WRITE ( channel ), (( volume & 255 ) << 8 ) |
( volume & 255 ) ) ;
}
void smMixer::getVolume ( int channel, int *left, int *right )
{
int vv = ioctl ( MIXER_READ ( channel ) ) ;
if ( left ) *left = vv & 0xFF ;
if ( right ) *right = (vv>>8) & 0xFF ;
}
void smMixer::setVolume ( int channel, int left, int right )
{
ioctl ( MIXER_WRITE ( channel ), (( right & 255 ) << 8 ) |
( left & 255 ) ) ;
}
void smMixer::setTreble ( int treble )
{
setVolume ( SOUND_MIXER_TREBLE , treble ) ;
}
void smMixer::setBass ( int bass )
{
setVolume ( SOUND_MIXER_TREBLE , bass ) ;
}
void smMixer::setMasterVolume ( int volume )
{
setVolume ( SOUND_MIXER_VOLUME , volume ) ;
}
void smMixer::setSynthVolume ( int volume )
{
setVolume ( SOUND_MIXER_SYNTH , volume ) ;
}
void smMixer::setPCMVolume ( int volume )
{
setVolume ( SOUND_MIXER_PCM , volume ) ;
}
void smMixer::setSpeakerVolume( int volume )
{
setVolume ( SOUND_MIXER_SPEAKER, volume ) ;
}
void smMixer::setLineVolume ( int volume )
{
setVolume ( SOUND_MIXER_LINE , volume ) ;
}
void smMixer::setMicVolume ( int volume )
{
setVolume ( SOUND_MIXER_MIC , volume ) ;
}
void smMixer::setCDVolume ( int volume )
{
setVolume ( SOUND_MIXER_CD , volume ) ;
}
void smMixer::setMasterVolume ( int left, int right )
{
setVolume ( SOUND_MIXER_VOLUME , left, right ) ;
}
void smMixer::setSynthVolume ( int left, int right )
{
setVolume ( SOUND_MIXER_SYNTH , left, right ) ;
}
void smMixer::setPCMVolume ( int left, int right )
{
setVolume ( SOUND_MIXER_PCM , left, right ) ;
}
void smMixer::setSpeakerVolume( int left, int right )
{
setVolume ( SOUND_MIXER_SPEAKER, left, right ) ;
}
void smMixer::setLineVolume ( int left, int right )
{
setVolume ( SOUND_MIXER_LINE , left, right ) ;
}
void smMixer::setMicVolume ( int left, int right )
{
setVolume ( SOUND_MIXER_MIC , left, right ) ;
}
void smMixer::setCDVolume ( int left, int right )
{
setVolume ( SOUND_MIXER_CD , left, right ) ;
}
#elif defined(__OpenBSD__)
/* ------------------------------------------------------------ */
/* OpenBSD 2.3 */
/* ------------------------------------------------------------ */
void smMixer::open ( char *device )
{
}
void smMixer::close (){}
smMixer::smMixer () { }
smMixer::smMixer ( char *device ) { }
smMixer::~smMixer () {}
int smMixer::not_working ()
{
return error ;
}
/* Volume controls are in integer percentages */
int smMixer::getVolume ( int channel ) { return 50 ; }
void smMixer::getVolume ( int channel, int *left, int *right )
{
if ( left ) *left = 50 ;
if ( right ) *right = 50 ;
}
void smMixer::setVolume ( int channel, int volume ) {}
void smMixer::setVolume ( int channel, int left, int right ){}
void smMixer::setTreble ( int treble ) {}
void smMixer::setBass ( int bass ) {}
void smMixer::setMasterVolume ( int volume ) {}
void smMixer::setSynthVolume ( int volume ) {}
void smMixer::setPCMVolume ( int volume ) {}
void smMixer::setSpeakerVolume( int volume ) {}
void smMixer::setLineVolume ( int volume ) {}
void smMixer::setMicVolume ( int volume ) {}
void smMixer::setCDVolume ( int volume ) {}
void smMixer::setMasterVolume ( int left, int right ) {}
void smMixer::setSynthVolume ( int left, int right ) {}
void smMixer::setPCMVolume ( int left, int right ) {}
void smMixer::setSpeakerVolume( int left, int right ) {}
void smMixer::setLineVolume ( int left, int right ) {}
void smMixer::setMicVolume ( int left, int right ) {}
void smMixer::setCDVolume ( int left, int right ) {}
#else
/* ------------------------------------------------------------ */
/* win32 */
/* ------------------------------------------------------------ */
void smMixer::open ( char *device )
{
}
void smMixer::close (){}
smMixer::smMixer () { }
smMixer::smMixer ( char *device ) { }
smMixer::~smMixer () {}
int smMixer::not_working ()
{
return error ;
}
/* Volume controls are in integer percentages */
int smMixer::getVolume ( int channel ) { return 50 ; }
void smMixer::getVolume ( int channel, int *left, int *right )
{
if ( left ) *left = 50 ;
if ( right ) *right = 50 ;
}
void smMixer::setVolume ( int channel, int volume ) {}
void smMixer::setVolume ( int channel, int left, int right ){}
void smMixer::setTreble ( int treble ) {}
void smMixer::setBass ( int bass ) {}
void smMixer::setMasterVolume ( int volume ) {}
void smMixer::setSynthVolume ( int volume ) {}
void smMixer::setPCMVolume ( int volume ) {}
void smMixer::setSpeakerVolume( int volume ) {}
void smMixer::setLineVolume ( int volume ) {}
void smMixer::setMicVolume ( int volume ) {}
void smMixer::setCDVolume ( int volume ) {}
void smMixer::setMasterVolume ( int left, int right ) {}
void smMixer::setSynthVolume ( int left, int right ) {}
void smMixer::setPCMVolume ( int left, int right ) {}
void smMixer::setSpeakerVolume( int left, int right ) {}
void smMixer::setLineVolume ( int left, int right ) {}
void smMixer::setMicVolume ( int left, int right ) {}
void smMixer::setCDVolume ( int left, int right ) {}
#endif