Fix playback of stereo sounds in Base sound system

Already works correctly in OpenAL.
This commit is contained in:
Zack Middleton 2013-12-15 00:18:29 -06:00
parent 623d107f42
commit 1a86229538
3 changed files with 98 additions and 53 deletions

View file

@ -56,6 +56,7 @@ typedef struct sfx_s {
qboolean soundCompressed; // not in Memory qboolean soundCompressed; // not in Memory
int soundCompressionMethod; int soundCompressionMethod;
int soundLength; int soundLength;
int soundChannels;
char soundName[MAX_QPATH]; char soundName[MAX_QPATH];
int lastTimeUsed; int lastTimeUsed;
struct sfx_s *next; struct sfx_s *next;

View file

@ -113,47 +113,51 @@ ResampleSfx
resample / decimate to the current source rate resample / decimate to the current source rate
================ ================
*/ */
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) { static int ResampleSfx( sfx_t *sfx, int channels, int inrate, int inwidth, int samples, byte *data, qboolean compressed ) {
int outcount; int outcount;
int srcsample; int srcsample;
float stepscale; float stepscale;
int i; int i, j;
int sample, samplefrac, fracstep; int sample, samplefrac, fracstep;
int part; int part;
sndBuffer *chunk; sndBuffer *chunk;
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
outcount = sfx->soundLength / stepscale; outcount = samples / stepscale;
sfx->soundLength = outcount;
samplefrac = 0; samplefrac = 0;
fracstep = stepscale * 256; fracstep = stepscale * 256 * channels;
chunk = sfx->soundData; chunk = sfx->soundData;
for (i=0 ; i<outcount ; i++) for (i=0 ; i<outcount ; i++)
{ {
srcsample = samplefrac >> 8; srcsample = samplefrac >> 8;
samplefrac += fracstep; samplefrac += fracstep;
if( inwidth == 2 ) { for (j=0 ; j<channels ; j++)
sample = ( ((short *)data)[srcsample] ); {
} else { if( inwidth == 2 ) {
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; sample = ( ((short *)data)[srcsample+j] );
}
part = (i&(SND_CHUNK_SIZE-1));
if (part == 0) {
sndBuffer *newchunk;
newchunk = SND_malloc();
if (chunk == NULL) {
sfx->soundData = newchunk;
} else { } else {
chunk->next = newchunk; sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
}
part = (i*channels+j)&(SND_CHUNK_SIZE-1);
if (part == 0) {
sndBuffer *newchunk;
newchunk = SND_malloc();
if (chunk == NULL) {
sfx->soundData = newchunk;
} else {
chunk->next = newchunk;
}
chunk = newchunk;
} }
chunk = newchunk;
}
chunk->sndChunk[part] = sample; chunk->sndChunk[part] = sample;
}
} }
return outcount;
} }
/* /*
@ -163,11 +167,11 @@ ResampleSfx
resample / decimate to the current source rate resample / decimate to the current source rate
================ ================
*/ */
static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byte *data ) { static int ResampleSfxRaw( short *sfx, int channels, int inrate, int inwidth, int samples, byte *data ) {
int outcount; int outcount;
int srcsample; int srcsample;
float stepscale; float stepscale;
int i; int i, j;
int sample, samplefrac, fracstep; int sample, samplefrac, fracstep;
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
@ -175,18 +179,21 @@ static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byt
outcount = samples / stepscale; outcount = samples / stepscale;
samplefrac = 0; samplefrac = 0;
fracstep = stepscale * 256; fracstep = stepscale * 256 * channels;
for (i=0 ; i<outcount ; i++) for (i=0 ; i<outcount ; i++)
{ {
srcsample = samplefrac >> 8; srcsample = samplefrac >> 8;
samplefrac += fracstep; samplefrac += fracstep;
if( inwidth == 2 ) { for (j=0 ; j<channels ; j++)
sample = LittleShort ( ((short *)data)[srcsample] ); {
} else { if( inwidth == 2 ) {
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; sample = LittleShort ( ((short *)data)[srcsample+j] );
} else {
sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
}
sfx[i*channels+j] = sample;
} }
sfx[i] = sample;
} }
return outcount; return outcount;
} }
@ -221,7 +228,7 @@ qboolean S_LoadSound( sfx_t *sfx )
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz audio file\n", sfx->soundName); Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz audio file\n", sfx->soundName);
} }
samples = Hunk_AllocateTempMemory(info.samples * sizeof(short) * 2); samples = Hunk_AllocateTempMemory(info.channels * info.samples * sizeof(short) * 2);
sfx->lastTimeUsed = Com_Milliseconds()+1; sfx->lastTimeUsed = Com_Milliseconds()+1;
@ -231,29 +238,30 @@ qboolean S_LoadSound( sfx_t *sfx )
// manager to do the right thing for us and page // manager to do the right thing for us and page
// sound in as needed // sound in as needed
if( sfx->soundCompressed == qtrue) { if( info.channels == 1 && sfx->soundCompressed == qtrue) {
sfx->soundCompressionMethod = 1; sfx->soundCompressionMethod = 1;
sfx->soundData = NULL; sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, data + info.dataofs ); sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, data + info.dataofs );
S_AdpcmEncodeSound(sfx, samples); S_AdpcmEncodeSound(sfx, samples);
#if 0 #if 0
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) { } else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
sfx->soundCompressionMethod = 3; sfx->soundCompressionMethod = 3;
sfx->soundData = NULL; sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) ); sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
encodeMuLaw( sfx, samples); encodeMuLaw( sfx, samples);
} else if (info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) { } else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
sfx->soundCompressionMethod = 2; sfx->soundCompressionMethod = 2;
sfx->soundData = NULL; sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) ); sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
encodeWavelet( sfx, samples); encodeWavelet( sfx, samples);
#endif #endif
} else { } else {
sfx->soundCompressionMethod = 0; sfx->soundCompressionMethod = 0;
sfx->soundLength = info.samples;
sfx->soundData = NULL; sfx->soundData = NULL;
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs, qfalse ); sfx->soundLength = ResampleSfx( sfx, info.channels, info.rate, info.width, info.samples, data + info.dataofs, qfalse );
} }
sfx->soundChannels = info.channels;
Hunk_FreeTempMemory(samples); Hunk_FreeTempMemory(samples);
Hunk_FreeTempMemory(data); Hunk_FreeTempMemory(data);

View file

@ -234,7 +234,7 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
portable_samplepair_t *samp; portable_samplepair_t *samp;
sndBuffer *chunk; sndBuffer *chunk;
short *samples; short *samples;
float ooff, fdata, fdiv, fleftvol, frightvol; float ooff, fdata[2], fdiv, fleftvol, frightvol;
samp = &paintbuffer[ bufferOffset ]; samp = &paintbuffer[ bufferOffset ];
@ -242,6 +242,14 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
sampleOffset = sampleOffset*ch->oldDopplerScale; sampleOffset = sampleOffset*ch->oldDopplerScale;
} }
if ( sc->soundChannels == 2 ) {
sampleOffset *= sc->soundChannels;
if ( sampleOffset & 1 ) {
sampleOffset &= ~1;
}
}
chunk = sc->soundData; chunk = sc->soundData;
while (sampleOffset>=SND_CHUNK_SIZE) { while (sampleOffset>=SND_CHUNK_SIZE) {
chunk = chunk->next; chunk = chunk->next;
@ -274,6 +282,10 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) { while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
data = samples[sampleOffset++]; data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8; samp[i].left += (data * leftvol)>>8;
if ( sc->soundChannels == 2 ) {
data = samples[sampleOffset++];
}
samp[i].right += (data * rightvol)>>8; samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) { if (sampleOffset == SND_CHUNK_SIZE) {
@ -373,10 +385,10 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
for ( i=0 ; i<count ; i++ ) { for ( i=0 ; i<count ; i++ ) {
aoff = ooff; aoff = ooff;
ooff = ooff + ch->dopplerScale; ooff = ooff + ch->dopplerScale * sc->soundChannels;
boff = ooff; boff = ooff;
fdata = 0; fdata[0] = fdata[1] = 0;
for (j=aoff; j<boff; j++) { for (j=aoff; j<boff; j += sc->soundChannels) {
if (j == SND_CHUNK_SIZE) { if (j == SND_CHUNK_SIZE) {
chunk = chunk->next; chunk = chunk->next;
if (!chunk) { if (!chunk) {
@ -385,11 +397,17 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
samples = chunk->sndChunk; samples = chunk->sndChunk;
ooff -= SND_CHUNK_SIZE; ooff -= SND_CHUNK_SIZE;
} }
fdata += samples[j&(SND_CHUNK_SIZE-1)]; if ( sc->soundChannels == 2 ) {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
} else {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
}
} }
fdiv = 256 * (boff-aoff); fdiv = 256 * (boff-aoff) / sc->soundChannels;
samp[i].left += (fdata * fleftvol)/fdiv; samp[i].left += (fdata[0] * fleftvol)/fdiv;
samp[i].right += (fdata * frightvol)/fdiv; samp[i].right += (fdata[1] * frightvol)/fdiv;
} }
} }
} }
@ -402,7 +420,7 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
portable_samplepair_t *samp; portable_samplepair_t *samp;
sndBuffer *chunk; sndBuffer *chunk;
short *samples; short *samples;
float ooff, fdata, fdiv, fleftvol, frightvol; float ooff, fdata[2], fdiv, fleftvol, frightvol;
samp = &paintbuffer[ bufferOffset ]; samp = &paintbuffer[ bufferOffset ];
@ -410,6 +428,14 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
sampleOffset = sampleOffset*ch->oldDopplerScale; sampleOffset = sampleOffset*ch->oldDopplerScale;
} }
if ( sc->soundChannels == 2 ) {
sampleOffset *= sc->soundChannels;
if ( sampleOffset & 1 ) {
sampleOffset &= ~1;
}
}
chunk = sc->soundData; chunk = sc->soundData;
while (sampleOffset>=SND_CHUNK_SIZE) { while (sampleOffset>=SND_CHUNK_SIZE) {
chunk = chunk->next; chunk = chunk->next;
@ -426,6 +452,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
for ( i=0 ; i<count ; i++ ) { for ( i=0 ; i<count ; i++ ) {
data = samples[sampleOffset++]; data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8; samp[i].left += (data * leftvol)>>8;
if ( sc->soundChannels == 2 ) {
data = samples[sampleOffset++];
}
samp[i].right += (data * rightvol)>>8; samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) { if (sampleOffset == SND_CHUNK_SIZE) {
@ -447,10 +477,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
for ( i=0 ; i<count ; i++ ) { for ( i=0 ; i<count ; i++ ) {
aoff = ooff; aoff = ooff;
ooff = ooff + ch->dopplerScale; ooff = ooff + ch->dopplerScale * sc->soundChannels;
boff = ooff; boff = ooff;
fdata = 0; fdata[0] = fdata[1] = 0;
for (j=aoff; j<boff; j++) { for (j=aoff; j<boff; j += sc->soundChannels) {
if (j == SND_CHUNK_SIZE) { if (j == SND_CHUNK_SIZE) {
chunk = chunk->next; chunk = chunk->next;
if (!chunk) { if (!chunk) {
@ -459,11 +489,17 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
samples = chunk->sndChunk; samples = chunk->sndChunk;
ooff -= SND_CHUNK_SIZE; ooff -= SND_CHUNK_SIZE;
} }
fdata += samples[j&(SND_CHUNK_SIZE-1)]; if ( sc->soundChannels == 2 ) {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
} else {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
}
} }
fdiv = 256 * (boff-aoff); fdiv = 256 * (boff-aoff) / sc->soundChannels;
samp[i].left += (fdata * fleftvol)/fdiv; samp[i].left += (fdata[0] * fleftvol)/fdiv;
samp[i].right += (fdata * frightvol)/fdiv; samp[i].right += (fdata[1] * frightvol)/fdiv;
} }
} }
} }