diff --git a/Quake/q_sound.h b/Quake/q_sound.h index 203e6e8c..c100b66c 100644 --- a/Quake/q_sound.h +++ b/Quake/q_sound.h @@ -121,6 +121,12 @@ channel_t *SND_PickChannel(int entnum, int entchannel); // spatializes a channel void SND_Spatialize(channel_t *ch); +// music stream support +void S_RawSamples(int samples, int rate, int width, int channels, byte * data, float volume); + +// returns file's extension including the dot, or NULL +const char *S_FileExtension (const char *name); + // initializes cycling through a DMA buffer and returns information on it qboolean SNDDMA_Init(void); @@ -166,6 +172,7 @@ extern int total_channels; extern qboolean fakedma; extern int fakedma_updates; extern int paintedtime; +extern int s_rawend; extern vec3_t listener_origin; extern vec3_t listener_forward; extern vec3_t listener_right; @@ -173,6 +180,9 @@ extern vec3_t listener_up; extern volatile dma_t *shm; extern volatile dma_t sn; +#define MAX_RAW_SAMPLES 8192 +extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; + extern cvar_t loadas8bit; extern cvar_t bgmvolume; extern cvar_t sfxvolume; diff --git a/Quake/snd_dma.c b/Quake/snd_dma.c index df8f687f..4cff70f3 100644 --- a/Quake/snd_dma.c +++ b/Quake/snd_dma.c @@ -53,6 +53,9 @@ vec3_t listener_up; int soundtime; // sample PAIRS int paintedtime; // sample PAIRS +int s_rawend; +portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; + #define MAX_SFX 512 sfx_t *known_sfx; // hunk allocated [MAX_SFX] @@ -62,6 +65,8 @@ sfx_t *ambient_sfx[NUM_AMBIENTS]; qboolean sound_started = false; +static float oldvolume = -1.0; + cvar_t bgmvolume = {"bgmvolume", "1", true}; cvar_t sfxvolume = {"volume", "0.7", true}; @@ -251,6 +256,29 @@ sfx_t *S_FindName (const char *name) } +/* +================= +S_FileExtension + +return file's extension including the dot, or NULL +================= +*/ +const char *S_FileExtension (const char *name) +{ + const char *ptr = name + strlen(name) - 1; + + while (ptr > name && + (*ptr != '/' && *ptr != '\\')) + { + if (*ptr == '.') + return ptr; + ptr--; + } + + return NULL; +} + + /* ================== S_TouchSound @@ -511,6 +539,8 @@ void S_ClearBuffer (void) if (! shm->buffer) return; + s_rawend = 0; + if (shm->samplebits == 8) clear = 0x80; else @@ -622,6 +652,106 @@ void S_UpdateAmbientSounds (void) } +/* +=================== +S_RawSamples (from QuakeII) + +Streaming music support. Byte swapping +of data must be handled by the codec. +=================== +*/ +void S_RawSamples (int samples, int rate, int width, int channels, byte *data, float volume) +{ + int i; + int src, dst; + float scale; + int intVolume; + + if (s_rawend < paintedtime) + { + s_rawend = paintedtime; + } + + scale = (float) rate / shm->speed; + intVolume = (int) (256 * volume); + + if (channels == 2 && width == 2) + { + for (i = 0; ; i++) + { + src = i * scale; + + if (src >= samples) + { + break; + } + + dst = s_rawend & (MAX_RAW_SAMPLES - 1); + s_rawend++; + s_rawsamples [dst].left = ((short *) data)[src * 2] * intVolume; + s_rawsamples [dst].right = ((short *) data)[src * 2 + 1] * intVolume; + } + } + else if (channels == 1 && width == 2) + { + for (i = 0; ; i++) + { + src = i * scale; + + if (src >= samples) + { + break; + } + + dst = s_rawend & (MAX_RAW_SAMPLES - 1); + s_rawend++; + s_rawsamples [dst].left = ((short *) data)[src] * intVolume; + s_rawsamples [dst].right = ((short *) data)[src] * intVolume; + } + } + else if (channels == 2 && width == 1) + { + intVolume *= 256; + + for (i = 0; ; i++) + { + src = i * scale; + + if (src >= samples) + { + break; + } + + dst = s_rawend & (MAX_RAW_SAMPLES - 1); + s_rawend++; + // s_rawsamples [dst].left = ((char *) data)[src * 2] * intVolume; + // s_rawsamples [dst].right = ((char *) data)[src * 2 + 1] * intVolume; + /* the above doesn't work for me with U8, only the unsigned ones below do */ + s_rawsamples [dst].left = (((byte *) data)[src * 2] - 128) * intVolume; + s_rawsamples [dst].right = (((byte *) data)[src * 2 + 1] - 128) * intVolume; + } + } + else if (channels == 1 && width == 1) + { + intVolume *= 256; + + for (i = 0; ; i++) + { + src = i * scale; + + if (src >= samples) + { + break; + } + + dst = s_rawend & (MAX_RAW_SAMPLES - 1); + s_rawend++; + s_rawsamples [dst].left = (((byte *) data)[src] - 128) * intVolume; + s_rawsamples [dst].right = (((byte *) data)[src] - 128) * intVolume; + } + } +} + /* ============ S_Update @@ -639,6 +769,12 @@ void S_Update (vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) if (!sound_started || (snd_blocked > 0)) return; + if (sfxvolume.value != oldvolume) + { + oldvolume = sfxvolume.value; + SND_InitScaletable (); + } + VectorCopy(origin, listener_origin); VectorCopy(forward, listener_forward); VectorCopy(right, listener_right); diff --git a/Quake/snd_mix.c b/Quake/snd_mix.c index 5aa52d18..c92bb644 100644 --- a/Quake/snd_mix.c +++ b/Quake/snd_mix.c @@ -23,12 +23,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#define PAINTBUFFER_SIZE 512 +#define PAINTBUFFER_SIZE 2048 portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; int snd_scaletable[32][256]; -int *snd_p, snd_linear_count, snd_vol; +int *snd_p, snd_linear_count; short *snd_out; +static int snd_vol; + void Snd_WriteLinearBlastStereo16 (void); void Snd_WriteLinearBlastStereo16 (void) @@ -38,7 +40,7 @@ void Snd_WriteLinearBlastStereo16 (void) for (i = 0; i < snd_linear_count; i += 2) { - val = (snd_p[i]*snd_vol) >> 8; + val = snd_p[i] >> 8; if (val > 0x7fff) snd_out[i] = 0x7fff; else if (val < (short)0x8000) @@ -46,7 +48,7 @@ void Snd_WriteLinearBlastStereo16 (void) else snd_out[i] = val; - val = (snd_p[i+1]*snd_vol) >> 8; + val = snd_p[i+1] >> 8; if (val > 0x7fff) snd_out[i+1] = 0x7fff; else if (val < (short)0x8000) @@ -61,8 +63,6 @@ void S_TransferStereo16 (int endtime) int lpos; int lpaintedtime; - snd_vol = sfxvolume.value * 256; - snd_p = (int *) paintbuffer; lpaintedtime = paintedtime; @@ -104,14 +104,13 @@ void S_TransferPaintBuffer(int endtime) out_mask = shm->samples - 1; out_idx = paintedtime * shm->channels & out_mask; step = 3 - shm->channels; - snd_vol = sfxvolume.value * 256; if (shm->samplebits == 16) { short *out = (short *)shm->buffer; while (count--) { - val = (*p * snd_vol) >> 8; + val = *p >> 8; p+= step; if (val > 0x7fff) val = 0x7fff; @@ -126,7 +125,7 @@ void S_TransferPaintBuffer(int endtime) unsigned char *out = shm->buffer; while (count--) { - val = (*p * snd_vol) >> 8; + val = *p >> 8; p+= step; if (val > 0x7fff) val = 0x7fff; @@ -157,6 +156,8 @@ void S_PaintChannels (int endtime) channel_t *ch; sfxcache_t *sc; + snd_vol = sfxvolume.value * 256; + while (paintedtime < endtime) { // if paintbuffer is smaller than DMA buffer @@ -165,7 +166,32 @@ void S_PaintChannels (int endtime) end = paintedtime + PAINTBUFFER_SIZE; // clear the paint buffer - memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); + if (s_rawend < paintedtime) + { // clear + memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); + } + else + { // copy from the streaming sound source + int s; + int stop; + + stop = (end < s_rawend) ? end : s_rawend; + + for (i = paintedtime; i < stop; i++) + { + s = i & (MAX_RAW_SAMPLES - 1); + paintbuffer[i - paintedtime] = s_rawsamples[s]; + } + // if (i != end) + // Con_Printf ("partial stream\n"); + // else + // Con_Printf ("full stream\n"); + for ( ; i < end; i++) + { + paintbuffer[i - paintedtime].left = + paintbuffer[i - paintedtime].right = 0; + } + } // paint in the channels. ch = snd_channels; @@ -224,9 +250,11 @@ void S_PaintChannels (int endtime) void SND_InitScaletable (void) { int i, j; + int scale; for (i = 0; i < 32; i++) { + scale = i * 8 * 256 * sfxvolume.value; for (j = 0; j < 256; j++) /* When compiling with gcc-4.1.0 at optimisations O1 and higher, the tricky signed char type conversion is not @@ -234,8 +262,8 @@ void SND_InitScaletable (void) value from the index as required. From Kevin Shanahan. See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26719 */ - // snd_scaletable[i][j] = ((signed char)j) * i * 8; - snd_scaletable[i][j] = ((j < 128) ? j : j - 0xff) * i * 8; + // snd_scaletable[i][j] = ((signed char)j) * scale; + snd_scaletable[i][j] = ((j < 128) ? j : j - 0xff) * scale; } } @@ -274,8 +302,8 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) signed short *sfx; int i; - leftvol = ch->leftvol; - rightvol = ch->rightvol; + leftvol = ch->leftvol * snd_vol; + rightvol = ch->rightvol * snd_vol; sfx = (signed short *)sc->data + ch->pos; for (i = 0; i < count; i++)