|
|
@ -16,204 +16,6 @@ GNU General Public License for more details. |
|
|
|
#include "common.h" |
|
|
|
#include "common.h" |
|
|
|
#include "sound.h" |
|
|
|
#include "sound.h" |
|
|
|
|
|
|
|
|
|
|
|
// hardcoded macros to test for zero crossing
|
|
|
|
|
|
|
|
#define ZERO_X_8( b ) (( b ) < 2 && ( b ) > -2 ) |
|
|
|
|
|
|
|
#define ZERO_X_16( b ) (( b ) < 512 && ( b ) > -512 ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Purpose: Search backward for a zero crossing starting at sample
|
|
|
|
|
|
|
|
// Input : sample - starting point
|
|
|
|
|
|
|
|
// Output : position of zero crossing
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( pWaveData == NULL ) |
|
|
|
|
|
|
|
return sample; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->type == WF_PCMDATA ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int sampleSize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleSize = pWaveData->width * pWaveData->channels; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this can never be zero -- other functions divide by this.
|
|
|
|
|
|
|
|
// This should never happen, but avoid crashing
|
|
|
|
|
|
|
|
if( sampleSize <= 0 ) sampleSize = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->width == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
signed char *pData = (signed char *)(pWaveData->buffer + sample * sampleSize); |
|
|
|
|
|
|
|
qboolean zero = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->channels == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample > 0 && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_8( *pData )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sample--; |
|
|
|
|
|
|
|
pData--; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample > 0 && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_8( *pData ) && ZERO_X_8( pData[1] )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sample--; |
|
|
|
|
|
|
|
pData--; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
short *pData = (short *)(pWaveData->buffer + sample * sampleSize); |
|
|
|
|
|
|
|
qboolean zero = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->channels == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample > 0 && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_16(*pData )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pData--; |
|
|
|
|
|
|
|
sample--; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample > 0 && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_16( *pData ) && ZERO_X_16( pData[1] )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sample--; |
|
|
|
|
|
|
|
pData--; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return sample; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Purpose: Search forward for a zero crossing
|
|
|
|
|
|
|
|
// Input : sample - starting point
|
|
|
|
|
|
|
|
// Output : position of found zero crossing
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( pWaveData == NULL ) |
|
|
|
|
|
|
|
return sample; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->type == WF_PCMDATA ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int sampleSize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleSize = pWaveData->width * pWaveData->channels; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this can never be zero -- other functions divide by this.
|
|
|
|
|
|
|
|
// This should never happen, but avoid crashing
|
|
|
|
|
|
|
|
if( sampleSize <= 0 ) sampleSize = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->width == 1 ) // 8-bit
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
signed char *pData = (signed char *)(pWaveData->buffer + sample * sampleSize); |
|
|
|
|
|
|
|
qboolean zero = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->channels == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample < pWaveData->samples && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_8( *pData )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sample++; |
|
|
|
|
|
|
|
pData++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample < pWaveData->samples && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_8( *pData ) && ZERO_X_8( pData[1] )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sample++; |
|
|
|
|
|
|
|
pData++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
short *pData = (short *)(pWaveData->buffer + sample * sampleSize); |
|
|
|
|
|
|
|
qboolean zero = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pWaveData->channels == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample > 0 && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_16( *pData )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pData++; |
|
|
|
|
|
|
|
sample++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while( sample > 0 && !zero ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ZERO_X_16( *pData ) && ZERO_X_16( pData[1] )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zero = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sample++; |
|
|
|
|
|
|
|
pData++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return sample; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: wrap the position wrt looping
|
|
|
|
// Purpose: wrap the position wrt looping
|
|
|
|
// Input : samplePosition - absolute position
|
|
|
|
// Input : samplePosition - absolute position
|
|
|
@ -279,28 +81,3 @@ int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int s |
|
|
|
|
|
|
|
|
|
|
|
return sampleCount; |
|
|
|
return sampleCount; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// move the current position to newPosition
|
|
|
|
|
|
|
|
void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( pSource ) |
|
|
|
|
|
|
|
newPosition = S_ZeroCrossingAfter( pSource, newPosition ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pChan->pMixer.sample = newPosition; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// end playback at newEndPosition
|
|
|
|
|
|
|
|
void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// forced end of zero means play the whole sample
|
|
|
|
|
|
|
|
if( !newEndPosition ) newEndPosition = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pSource ) |
|
|
|
|
|
|
|
newEndPosition = S_ZeroCrossingBefore( pSource, newEndPosition ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// past current position? limit.
|
|
|
|
|
|
|
|
if( newEndPosition < pChan->pMixer.sample ) |
|
|
|
|
|
|
|
newEndPosition = pChan->pMixer.sample; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pChan->pMixer.forcedEndSample = newEndPosition; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|