backports from uhexen2 source, preparing for streaming music support:

* snd_mix.c: Increased PAINTBUFFER_SIZE from 512 to 2048.
* snd_mix.c: snd_vol is static now. it is calculated in S_PaintChannels and
  only used in SND_PaintChannelFrom16. all its other uses are removed from
  Snd_WriteLinearBlastStereo16, S_TransferStereo16, S_TransferPaintBuffer.
  The way it was, the sound volume was applied to the whole final contents
  of the paint buffer, but with this new quake2+ way we can add raw samples
  to the paint buffer with its own volume, such as bgmvolume. However, this
  makes the snd_scaletable to be recalculated everytime the sfxvolume is,
  changed, therefore it is adjusted that way to incorporate sfxvolume.
* snd_mix.c: In S_PaintChannels, check against s_rawend and copy from the
  streaming sound source if necessary.
* snd_dma.c: Added old_volume to detect sfxvolume changes. Made S_Update to
  compare it to sfxvolume.value and call SND_InitScaletable() if it changed.
* snd_dma.c: Add new globals s_rawsamples and s_rawend. Reset s_rawend to 0
  in S_ClearBuffer. Add new function S_RawSamples, adapted from quake2 with
  its 8 bit stereo playback fixed.
* snd_dma.c (S_FileExtension): Add new function which returns the given
  sound file's extension including the dot, or NULL.
* q_sound.h: Add new macro MAX_RAW_SAMPLES, defined as 8192. Add externs
  for new globals s_rawsamples and s_rawend. Add prototype for the new
  S_RawSamples and S_FileExtension functions.


git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@355 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Ozkan Sezer 2010-12-30 17:11:28 +00:00
parent 94767a4e6d
commit bcef8e85f0
3 changed files with 188 additions and 14 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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++)