From 1a86229538ebb375bd5fdf2ad4b5127529593e9c Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 15 Dec 2013 00:18:29 -0600 Subject: [PATCH] Fix playback of stereo sounds in Base sound system Already works correctly in OpenAL. --- code/client/snd_local.h | 1 + code/client/snd_mem.c | 82 ++++++++++++++++++++++------------------- code/client/snd_mix.c | 68 ++++++++++++++++++++++++++-------- 3 files changed, 98 insertions(+), 53 deletions(-) diff --git a/code/client/snd_local.h b/code/client/snd_local.h index 66f3bcde..e0f5b1d0 100644 --- a/code/client/snd_local.h +++ b/code/client/snd_local.h @@ -56,6 +56,7 @@ typedef struct sfx_s { qboolean soundCompressed; // not in Memory int soundCompressionMethod; int soundLength; + int soundChannels; char soundName[MAX_QPATH]; int lastTimeUsed; struct sfx_s *next; diff --git a/code/client/snd_mem.c b/code/client/snd_mem.c index 1031f34c..655ae420 100644 --- a/code/client/snd_mem.c +++ b/code/client/snd_mem.c @@ -113,47 +113,51 @@ ResampleSfx 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 srcsample; float stepscale; - int i; + int i, j; int sample, samplefrac, fracstep; int part; sndBuffer *chunk; stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 - outcount = sfx->soundLength / stepscale; - sfx->soundLength = outcount; + outcount = samples / stepscale; samplefrac = 0; - fracstep = stepscale * 256; + fracstep = stepscale * 256 * channels; chunk = sfx->soundData; for (i=0 ; i> 8; samplefrac += fracstep; - if( inwidth == 2 ) { - sample = ( ((short *)data)[srcsample] ); - } else { - sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; - } - part = (i&(SND_CHUNK_SIZE-1)); - if (part == 0) { - sndBuffer *newchunk; - newchunk = SND_malloc(); - if (chunk == NULL) { - sfx->soundData = newchunk; + for (j=0 ; jnext = 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 ================ */ -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 srcsample; float stepscale; - int i; + int i, j; int sample, samplefrac, fracstep; 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; samplefrac = 0; - fracstep = stepscale * 256; + fracstep = stepscale * 256 * channels; for (i=0 ; i> 8; samplefrac += fracstep; - if( inwidth == 2 ) { - sample = LittleShort ( ((short *)data)[srcsample] ); - } else { - sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; + for (j=0 ; jsoundName); } - samples = Hunk_AllocateTempMemory(info.samples * sizeof(short) * 2); + samples = Hunk_AllocateTempMemory(info.channels * info.samples * sizeof(short) * 2); 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 // sound in as needed - if( sfx->soundCompressed == qtrue) { + if( info.channels == 1 && sfx->soundCompressed == qtrue) { sfx->soundCompressionMethod = 1; 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); #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->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); - } 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->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); #endif } else { sfx->soundCompressionMethod = 0; - sfx->soundLength = info.samples; 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(data); diff --git a/code/client/snd_mix.c b/code/client/snd_mix.c index fca5e15f..38bd0aae 100644 --- a/code/client/snd_mix.c +++ b/code/client/snd_mix.c @@ -234,7 +234,7 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co portable_samplepair_t *samp; sndBuffer *chunk; short *samples; - float ooff, fdata, fdiv, fleftvol, frightvol; + float ooff, fdata[2], fdiv, fleftvol, frightvol; 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; } + if ( sc->soundChannels == 2 ) { + sampleOffset *= sc->soundChannels; + + if ( sampleOffset & 1 ) { + sampleOffset &= ~1; + } + } + chunk = sc->soundData; while (sampleOffset>=SND_CHUNK_SIZE) { 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))) { data = samples[sampleOffset++]; samp[i].left += (data * leftvol)>>8; + + if ( sc->soundChannels == 2 ) { + data = samples[sampleOffset++]; + } samp[i].right += (data * rightvol)>>8; 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 ; idopplerScale; + ooff = ooff + ch->dopplerScale * sc->soundChannels; boff = ooff; - fdata = 0; - for (j=aoff; jsoundChannels) { if (j == SND_CHUNK_SIZE) { chunk = chunk->next; if (!chunk) { @@ -385,11 +397,17 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co samples = chunk->sndChunk; 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); - samp[i].left += (fdata * fleftvol)/fdiv; - samp[i].right += (fdata * frightvol)/fdiv; + fdiv = 256 * (boff-aoff) / sc->soundChannels; + samp[i].left += (fdata[0] * fleftvol)/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; sndBuffer *chunk; short *samples; - float ooff, fdata, fdiv, fleftvol, frightvol; + float ooff, fdata[2], fdiv, fleftvol, frightvol; 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; } + if ( sc->soundChannels == 2 ) { + sampleOffset *= sc->soundChannels; + + if ( sampleOffset & 1 ) { + sampleOffset &= ~1; + } + } + chunk = sc->soundData; while (sampleOffset>=SND_CHUNK_SIZE) { 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>8; + + if ( sc->soundChannels == 2 ) { + data = samples[sampleOffset++]; + } samp[i].right += (data * rightvol)>>8; 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 ; idopplerScale; + ooff = ooff + ch->dopplerScale * sc->soundChannels; boff = ooff; - fdata = 0; - for (j=aoff; jsoundChannels) { if (j == SND_CHUNK_SIZE) { chunk = chunk->next; if (!chunk) { @@ -459,11 +489,17 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou samples = chunk->sndChunk; 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); - samp[i].left += (fdata * fleftvol)/fdiv; - samp[i].right += (fdata * frightvol)/fdiv; + fdiv = 256 * (boff-aoff) / sc->soundChannels; + samp[i].left += (fdata[0] * fleftvol)/fdiv; + samp[i].right += (fdata[1] * frightvol)/fdiv; } } }