Files
simgear/src/slSamplePlayer.cxx
curt 1b99b2a25d Incorporated Steve's latest version of his audio library. This version
allows pitch and volume changes so we should be able tie this to the
throttle now.
1998-09-24 19:36:25 +00:00

189 lines
4.3 KiB
C++

#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 () ;
}
void slSamplePlayer::read ( int nframes, Uchar *dst, int next_env )
{
/*
WARNING:
CO-RECURSIVE!
*/
/* Find the next envelope */
while ( next_env < SL_MAX_ENVELOPES && env [ next_env ] == NULL )
next_env++ ;
/*
If there are no fancy envelopes to process then return
the raw data.
*/
if ( next_env >= SL_MAX_ENVELOPES ) /* No fancy envelopes left */
{
low_read ( nframes, dst ) ;
return ;
}
/*
Envelope processing required...
Process the next envelope using data read recursively through
the remaining envelopes.
*/
switch ( env_type [ next_env ] )
{
/* For Volume envelopes, SRC and DST can be the same buffer */
case SL_INVERSE_VOLUME_ENVELOPE:
read ( nframes, dst, next_env+1 ) ;
env[ next_env ]->applyToInvVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
break ;
case SL_VOLUME_ENVELOPE :
read ( nframes, dst, next_env+1 ) ;
env[ next_env ]->applyToVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
break ;
case SL_INVERSE_PITCH_ENVELOPE :
env[ next_env ]->applyToInvPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
break ;
case SL_PITCH_ENVELOPE :
env[ next_env ]->applyToPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
break ;
case SL_INVERSE_FILTER_ENVELOPE:
case SL_FILTER_ENVELOPE :
read ( nframes, dst, next_env+1 ) ;
break ;
case SL_INVERSE_PAN_ENVELOPE :
case SL_PAN_ENVELOPE :
read ( nframes, dst, next_env+1 ) ;
break ;
case SL_INVERSE_ECHO_ENVELOPE :
case SL_ECHO_ENVELOPE :
read ( nframes, dst, next_env+1 ) ;
break ;
}
}
void slSamplePlayer::low_read ( int nframes, Uchar *dst )
{
if ( isWaiting() ) start () ;
if ( bufferPos == NULL ) /* Run out of sample & no repeats */
{
memset ( dst, 0x80, nframes ) ;
return ;
}
while ( SL_TRUE )
{
/*
If we can satisfy this request in one read (with data left in
the sample buffer ready for next time around) - then we are done...
*/
if ( nframes < lengthRemaining )
{
memcpy ( dst, bufferPos, nframes ) ;
bufferPos += nframes ;
lengthRemaining -= nframes ;
return ;
}
memcpy ( dst, bufferPos, lengthRemaining ) ;
bufferPos += lengthRemaining ;
dst += lengthRemaining ;
nframes -= lengthRemaining ;
lengthRemaining = 0 ;
if ( replay_mode == SL_SAMPLE_ONE_SHOT )
{
stop () ;
memset ( dst, 0x80, nframes ) ;
return ;
}
else
{
slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
start () ;
}
}
}