Reformat the sound system code

caedes and some other people will probably kill me for this, but I'm the
idiot who has to maintain the code. And that's much easier if it's in a
readable und writeable state.
This commit is contained in:
Yamagi Burmeister 2012-06-06 11:13:07 +02:00
parent 51cc3369b1
commit d8e35b82c7
8 changed files with 1374 additions and 1143 deletions

View File

@ -27,89 +27,97 @@
#ifndef CL_SOUND_LOCAL_H
#define CL_SOUND_LOCAL_H
typedef struct {
int left;
int right;
typedef struct
{
int left;
int right;
} portable_samplepair_t;
typedef struct {
int length;
int loopstart;
int speed; /* not needed, because converted on load? */
int width;
typedef struct
{
int length;
int loopstart;
int speed; /* not needed, because converted on load? */
int width;
#if USE_OPENAL
int size;
int bufnum;
int size;
int bufnum;
#endif
int stereo;
byte data[1]; /* variable sized */
int stereo;
byte data[1]; /* variable sized */
} sfxcache_t;
typedef struct sfx_s {
char name[MAX_QPATH];
int registration_sequence;
sfxcache_t *cache;
char *truename;
typedef struct sfx_s
{
char name[MAX_QPATH];
int registration_sequence;
sfxcache_t *cache;
char *truename;
} sfx_t;
/* a playsound_t will be generated by each call to S_StartSound,
when the mixer reaches playsound->begin, the playsound will
be assigned to a channel */
typedef struct playsound_s {
struct playsound_s *prev, *next;
sfx_t *sfx;
float volume;
float attenuation;
int entnum;
int entchannel;
qboolean fixed_origin; /* use origin field instead of entnum's origin */
vec3_t origin;
unsigned begin; /* begin on this sample */
* when the mixer reaches playsound->begin, the playsound will
* be assigned to a channel */
typedef struct playsound_s
{
struct playsound_s *prev, *next;
sfx_t *sfx;
float volume;
float attenuation;
int entnum;
int entchannel;
qboolean fixed_origin; /* use origin field instead of entnum's origin */
vec3_t origin;
unsigned begin; /* begin on this sample */
} playsound_t;
typedef struct {
int channels;
int samples; /* mono samples in buffer */
int submission_chunk; /* don't mix less than this */
int samplepos; /* in mono samples */
int samplebits;
int speed;
byte *buffer;
typedef struct
{
int channels;
int samples; /* mono samples in buffer */
int submission_chunk; /* don't mix less than this */
int samplepos; /* in mono samples */
int samplebits;
int speed;
byte *buffer;
} dma_t;
typedef struct {
sfx_t *sfx; /* sfx number */
int leftvol; /* 0-255 volume */
int rightvol; /* 0-255 volume */
int end; /* end time in global paintsamples */
int pos; /* sample position in sfx */
int looping; /* where to loop, -1 = no looping */
int entnum; /* to allow overriding a specific sound */
int entchannel;
vec3_t origin; /* only use if fixed_origin is set */
vec_t dist_mult; /* distance multiplier (attenuation/clipK) */
int master_vol; /* 0-255 master volume */
qboolean fixed_origin; /* use origin instead of fetching entnum's origin */
qboolean autosound; /* from an entity->sound, cleared each frame */
typedef struct
{
sfx_t *sfx; /* sfx number */
int leftvol; /* 0-255 volume */
int rightvol; /* 0-255 volume */
int end; /* end time in global paintsamples */
int pos; /* sample position in sfx */
int looping; /* where to loop, -1 = no looping */
int entnum; /* to allow overriding a specific sound */
int entchannel;
vec3_t origin; /* only use if fixed_origin is set */
vec_t dist_mult; /* distance multiplier (attenuation/clipK) */
int master_vol; /* 0-255 master volume */
qboolean fixed_origin; /* use origin instead of fetching entnum's origin */
qboolean autosound; /* from an entity->sound, cleared each frame */
#if USE_OPENAL
int autoframe;
int srcnum;
int autoframe;
int srcnum;
#endif
} channel_t;
typedef struct {
int rate;
int width;
int channels;
int loopstart;
int samples;
int dataofs; /* chunk starts this many bytes from file start */
typedef struct
{
int rate;
int width;
int channels;
int loopstart;
int samples;
int dataofs; /* chunk starts this many bytes from file start */
} wavinfo_t;
typedef enum {
SS_NOT = 0, // soundsystem not started
SS_DMA, // soundsystem started, using DMA/SDL
SS_OAL // soundsystem started, using OpenAL
typedef enum
{
SS_NOT = 0, /* soundsystem not started */
SS_DMA, /* soundsystem started, using DMA/SDL */
SS_OAL /* soundsystem started, using OpenAL */
} sndstarted_t;
extern sndstarted_t sound_started;
@ -119,42 +127,42 @@ extern sndstarted_t sound_started;
qboolean SNDDMA_Init(void);
/* gets the current DMA position */
int SNDDMA_GetDMAPos(void);
int SNDDMA_GetDMAPos(void);
/* shutdown the DMA xfer. */
void SNDDMA_Shutdown(void);
void SNDDMA_BeginPainting (void);
void SNDDMA_Submit(void);
void SNDDMA_Shutdown(void);
void SNDDMA_BeginPainting(void);
void SNDDMA_Submit(void);
#define MAX_CHANNELS 32
extern channel_t channels[MAX_CHANNELS];
extern int s_numchannels;
#define MAX_CHANNELS 32
extern channel_t channels[MAX_CHANNELS];
extern int s_numchannels;
extern int paintedtime;
extern int s_rawend;
extern vec3_t listener_origin;
extern vec3_t listener_forward;
extern vec3_t listener_right;
extern vec3_t listener_up;
extern dma_t dma;
extern playsound_t s_pendingplays;
extern int paintedtime;
extern int s_rawend;
extern vec3_t listener_origin;
extern vec3_t listener_forward;
extern vec3_t listener_right;
extern vec3_t listener_up;
extern dma_t dma;
extern playsound_t s_pendingplays;
#define MAX_RAW_SAMPLES 8192
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
#define MAX_RAW_SAMPLES 8192
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
extern cvar_t *s_volume;
extern cvar_t *s_nosound;
extern cvar_t *s_loadas8bit;
extern cvar_t *s_khz;
extern cvar_t *s_show;
extern cvar_t *s_mixahead;
extern cvar_t *s_testsound;
extern cvar_t *s_ambient;
extern cvar_t *s_volume;
extern cvar_t *s_nosound;
extern cvar_t *s_loadas8bit;
extern cvar_t *s_khz;
extern cvar_t *s_show;
extern cvar_t *s_mixahead;
extern cvar_t *s_testsound;
extern cvar_t *s_ambient;
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength);
void S_InitScaletable (void);
sfxcache_t *S_LoadSound (sfx_t *s);
void S_IssuePlaysound (playsound_t *ps);
wavinfo_t GetWavinfo(char *name, byte *wav, int wavlength);
void S_InitScaletable(void);
sfxcache_t *S_LoadSound(sfx_t *s);
void S_IssuePlaysound(playsound_t *ps);
void S_PaintChannels(int endtime);
/* picks a channel based on priorities, empty slots, number of channels */
@ -163,28 +171,30 @@ channel_t *S_PickChannel(int entnum, int entchannel);
/* spatializes a channel */
void S_Spatialize(channel_t *ch);
void S_BuildSoundList( int *sounds );
void S_BuildSoundList(int *sounds);
#if USE_OPENAL
// this stuff was taken from Q2Pro
// only begin attenuating sound volumes when outside the FULLVOLUME range
#define SOUND_FULLVOLUME 80
#define SOUND_LOOPATTENUATE 0.003
/* Only begin attenuating sound volumes
when outside the FULLVOLUME range */
#define SOUND_FULLVOLUME 80
#define SOUND_LOOPATTENUATE 0.003
// number of buffers in flight (needed for ogg)
/* number of buffers in flight (needed for ogg) */
extern int active_buffers;
// for snd_al.c - copied from Q2Pro and adapted
void AL_SoundInfo( void );
qboolean AL_Init( void );
void AL_Shutdown( void );
sfxcache_t *AL_UploadSfx( sfx_t *s, wavinfo_t *s_info, byte *data );
void AL_DeleteSfx( sfx_t *s );
void AL_StopChannel( channel_t *ch );
void AL_PlayChannel( channel_t *ch );
void AL_StopAllChannels( void );
void AL_Update( void );
void AL_RawSamples( int samples, int rate, int width, int channels, byte *data, float volume );
#endif
/* for snd_al.c - copied from Q2Pro and adapted */
void AL_SoundInfo(void);
qboolean AL_Init(void);
void AL_Shutdown(void);
sfxcache_t *AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data);
void AL_DeleteSfx(sfx_t *s);
void AL_StopChannel(channel_t *ch);
void AL_PlayChannel(channel_t *ch);
void AL_StopAllChannels(void);
void AL_Update(void);
void AL_RawSamples(int samples, int rate, int width,
int channels, byte *data, float volume);
#endif
#endif

View File

@ -30,24 +30,29 @@
struct sfx_s;
void S_Init (void);
void S_Shutdown (void);
void S_Init(void);
void S_Shutdown(void);
/* if origin is NULL, the sound will be dynamically sourced from the entity */
void S_StartSound (vec3_t origin, int entnum, int entchannel, struct sfx_s *sfx, float fvol, float attenuation, float timeofs);
/* if origin is NULL, the sound will be
dynamically sourced from the entity */
void S_StartSound(vec3_t origin, int entnum, int entchannel,
struct sfx_s *sfx, float fvol, float attenuation,
float timeofs);
void S_StartLocalSound (char *s);
void S_RawSamples (int samples, int rate, int width, int channels, byte *data, float volume);
void S_StartLocalSound(char *s);
void S_RawSamples(int samples, int rate, int width, int channels,
byte *data, float volume);
void S_StopAllSounds(void);
void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
void S_Activate (qboolean active);
void S_BeginRegistration (void);
struct sfx_s *S_RegisterSound (char *sample);
void S_EndRegistration (void);
struct sfx_s *S_FindName (char *name, qboolean create);
void S_Update(vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
void S_Activate(qboolean active);
void S_BeginRegistration(void);
struct sfx_s *S_RegisterSound(char *sample);
void S_EndRegistration(void);
struct sfx_s *S_FindName(char *name, qboolean create);
/* the sound code makes callbacks to the client for entitiy position
information, so entities can be dynamically re-spatialized */
void CL_GetEntitySoundOrigin (int ent, vec3_t org);
/* the sound code makes callbacks to the client for
entitiy position information, so entities can be
dynamically re-spatialized */
void CL_GetEntitySoundOrigin(int ent, vec3_t org);
#endif

View File

@ -25,49 +25,51 @@
#ifdef OGG
#ifndef CL_SOUND_VORBIS_H
#define CL_SOUND_VORBIS_H
#define CL_SOUND_VORBIS_H
/* The OGG codec can return the samples in a number
of different formats, we use the standard signed
short format. */
#define OGG_SAMPLEWIDTH 2
* of different formats, we use the standard signed
* short format. */
#define OGG_SAMPLEWIDTH 2
#define OGG_DIR "music"
#define OGG_DIR "music"
typedef enum {
typedef enum
{
PLAY,
PAUSE,
STOP
} ogg_status_t;
typedef enum {
typedef enum
{
ABS,
REL
} ogg_seek_t;
void OGG_Init (void);
void OGG_Shutdown(void);
void OGG_Reinit(void);
qboolean OGG_Check(char *name);
void OGG_Seek (ogg_seek_t type, double offset);
void OGG_LoadFileList(void);
void OGG_LoadPlaylist(char *name);
qboolean OGG_Open(ogg_seek_t type, int offset);
qboolean OGG_OpenName(char *filename);
int OGG_Read (void);
void OGG_Sequence(void);
void OGG_Stop (void);
void OGG_Stream(void);
void S_RawSamplesVol(int samples, int rate, int width, int channels, byte * data, float volume);
void OGG_Init(void);
void OGG_Shutdown(void);
void OGG_Reinit(void);
qboolean OGG_Check(char *name);
void OGG_Seek(ogg_seek_t type, double offset);
void OGG_LoadFileList(void);
void OGG_LoadPlaylist(char *name);
qboolean OGG_Open(ogg_seek_t type, int offset);
qboolean OGG_OpenName(char *filename);
int OGG_Read(void);
void OGG_Sequence(void);
void OGG_Stop(void);
void OGG_Stream(void);
void S_RawSamplesVol(int samples, int rate, int width,
int channels, byte *data, float volume);
/* Console commands. */
void OGG_ListCmd(void);
void OGG_ParseCmd(char *arg);
void OGG_PauseCmd(void);
void OGG_PlayCmd(void);
void OGG_ResumeCmd(void);
void OGG_SeekCmd(void);
void OGG_StatusCmd(void);
void OGG_ListCmd(void);
void OGG_ParseCmd(char *arg);
void OGG_PauseCmd(void);
void OGG_PlayCmd(void);
void OGG_ResumeCmd(void);
void OGG_SeekCmd(void);
void OGG_StatusCmd(void);
#endif
#endif

View File

@ -21,10 +21,9 @@
*
* =======================================================================
*
* Most of these functions are from the Q2Pro project, and some are from
* zeq2. We adapted them to work with Yamagi Quake II
*
* This is an OpenAL backend for the Quake II Soundsystem.
* This is an OpenAL backend for the Quake II Soundsystem. Most of these
* functions are from the Q2Pro project, and some are from zeq2. We
* adapted them to work with Yamagi Quake II.
*
* =======================================================================
*/
@ -36,11 +35,12 @@
#include "header/local.h"
#include "header/vorbis.h"
// translates from AL coordinate system to quake
#define AL_UnpackVector(v) -v[1],v[2],-v[0]
#define AL_CopyVector(a,b) ((b)[0]=-(a)[1],(b)[1]=(a)[2],(b)[2]=-(a)[0])
/* translates from AL coordinate system to quake */
#define AL_UnpackVector(v) - v[1], v[2], -v[0]
#define AL_CopyVector(a, b) ((b)[0] = -(a)[1], (b)[1] = (a)[2], (b)[2] = \
-(a)[0])
// OpenAL implementation should support at least this number of sources
/* OpenAL implementation should support at least this number of sources */
#define MIN_CHANNELS 16
qboolean streamPlaying;
@ -49,27 +49,31 @@ int active_buffers;
static ALuint streamSource;
static ALuint underwaterFilter;
static ALuint s_srcnums[MAX_CHANNELS-1];
static ALuint s_srcnums[MAX_CHANNELS - 1];
static int s_framecount;
// Forward Declarations
static void S_AL_StreamUpdate( void );
static void S_AL_StreamDie( void );
// /Forward Declarations
/* Forward Declarations */
static void S_AL_StreamUpdate(void);
static void S_AL_StreamDie(void);
static void AL_InitStreamSource() {
qalSourcei (streamSource, AL_BUFFER, 0 );
qalSourcei (streamSource, AL_LOOPING, AL_FALSE );
qalSource3f(streamSource, AL_POSITION, 0.0, 0.0, 0.0);
qalSource3f(streamSource, AL_VELOCITY, 0.0, 0.0, 0.0);
qalSource3f(streamSource, AL_DIRECTION, 0.0, 0.0, 0.0);
qalSourcef (streamSource, AL_ROLLOFF_FACTOR, 0.0 );
qalSourcei (streamSource, AL_SOURCE_RELATIVE, AL_TRUE );
/* /Forward Declarations */
static void
AL_InitStreamSource()
{
qalSourcei(streamSource, AL_BUFFER, 0);
qalSourcei(streamSource, AL_LOOPING, AL_FALSE);
qalSource3f(streamSource, AL_POSITION, 0.0, 0.0, 0.0);
qalSource3f(streamSource, AL_VELOCITY, 0.0, 0.0, 0.0);
qalSource3f(streamSource, AL_DIRECTION, 0.0, 0.0, 0.0);
qalSourcef(streamSource, AL_ROLLOFF_FACTOR, 0.0);
qalSourcei(streamSource, AL_SOURCE_RELATIVE, AL_TRUE);
}
static void AL_InitUnderwaterFilter()
static void
AL_InitUnderwaterFilter()
{
// Generate a filter
/* Generate a filter */
qalGenFilters(1, &underwaterFilter);
if (qalGetError() != AL_NO_ERROR)
@ -78,7 +82,7 @@ static void AL_InitUnderwaterFilter()
return;
}
// Low pass filter for underwater effect
/* Low pass filter for underwater effect */
qalFilteri(underwaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
if (qalGetError() != AL_NO_ERROR)
@ -87,44 +91,55 @@ static void AL_InitUnderwaterFilter()
return;
}
// The effect
/* The effect */
qalFilterf(underwaterFilter, AL_LOWPASS_GAIN, 1.5);
qalFilterf(underwaterFilter, AL_LOWPASS_GAINHF, 0.25);
}
qboolean AL_Init( void ) {
qboolean
AL_Init(void)
{
int i;
if( !QAL_Init() ) {
Com_Printf( "ERROR: OpenAL failed to initialize.\n" );
if (!QAL_Init())
{
Com_Printf("ERROR: OpenAL failed to initialize.\n");
return false;
}
// check for linear distance extension
if( !qalIsExtensionPresent( "AL_EXT_LINEAR_DISTANCE" ) ) {
Com_Printf( "ERROR: Required AL_EXT_LINEAR_DISTANCE extension is missing.\n" );
/* check for linear distance extension */
if (!qalIsExtensionPresent("AL_EXT_LINEAR_DISTANCE"))
{
Com_Printf("ERROR: Required AL_EXT_LINEAR_DISTANCE extension is missing.\n");
goto fail;
}
// generate source names
/* generate source names */
qalGetError();
qalGenSources( 1, &streamSource );
if( qalGetError() != AL_NO_ERROR )
{
Com_Printf( "ERROR: Couldn't get a single Source.\n" );
goto fail;
qalGenSources(1, &streamSource);
} else {
// -1 because we already got one channel for streaming
for( i = 0; i < MAX_CHANNELS - 1; i++ ) {
qalGenSources( 1, &s_srcnums[i] );
if( qalGetError() != AL_NO_ERROR ) {
if (qalGetError() != AL_NO_ERROR)
{
Com_Printf("ERROR: Couldn't get a single Source.\n");
goto fail;
}
else
{
/* -1 because we already got one channel for streaming */
for (i = 0; i < MAX_CHANNELS - 1; i++)
{
qalGenSources(1, &s_srcnums[i]);
if (qalGetError() != AL_NO_ERROR)
{
break;
}
}
if( i < MIN_CHANNELS - 1 ) {
Com_Printf( "ERROR: Required at least %d sources, but got %d.\n", MIN_CHANNELS, i+1 );
if (i < MIN_CHANNELS - 1)
{
Com_Printf("ERROR: Required at least %d sources, but got %d.\n",
MIN_CHANNELS, i + 1);
goto fail;
}
}
@ -142,44 +157,53 @@ fail:
return false;
}
void AL_Shutdown( void ) {
Com_Printf( "Shutting down OpenAL.\n" );
void
AL_Shutdown(void)
{
Com_Printf("Shutting down OpenAL.\n");
S_AL_StreamDie();
qalDeleteSources(1, &streamSource);
qalDeleteFilters(1, &underwaterFilter);
if( s_numchannels ) {
// delete source names
qalDeleteSources( s_numchannels, s_srcnums );
memset( s_srcnums, 0, sizeof( s_srcnums ) );
if (s_numchannels)
{
/* delete source names */
qalDeleteSources(s_numchannels, s_srcnums);
memset(s_srcnums, 0, sizeof(s_srcnums));
s_numchannels = 0;
}
QAL_Shutdown();
}
sfxcache_t *AL_UploadSfx( sfx_t *s, wavinfo_t *s_info, byte *data ) {
sfxcache_t *
AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data)
{
sfxcache_t *sc;
ALsizei size = s_info->samples * s_info->width;
ALenum format = s_info->width == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
ALuint name;
if( !size ) {
if (!size)
{
return NULL;
}
qalGetError();
qalGenBuffers( 1, &name );
qalBufferData( name, format, data, size, s_info->rate );
qalGenBuffers(1, &name);
qalBufferData(name, format, data, size, s_info->rate);
active_buffers++;
if( qalGetError() != AL_NO_ERROR ) {
if (qalGetError() != AL_NO_ERROR)
{
return NULL;
}
// allocate placeholder sfxcache
/* allocate placeholder sfxcache */
sc = s->cache = Z_TagMalloc(sizeof(*sc), 0);
sc->length = s_info->samples * 1000 / s_info->rate; // in msec
sc->length = s_info->samples * 1000 / s_info->rate; /* in msec */
sc->loopstart = s_info->loopstart;
sc->width = s_info->width;
sc->size = size;
@ -188,147 +212,212 @@ sfxcache_t *AL_UploadSfx( sfx_t *s, wavinfo_t *s_info, byte *data ) {
return sc;
}
void AL_DeleteSfx( sfx_t *s ) {
void
AL_DeleteSfx(sfx_t *s)
{
sfxcache_t *sc;
ALuint name;
sc = s->cache;
if( !sc ) {
if (!sc)
{
return;
}
name = sc->bufnum;
qalDeleteBuffers( 1, &name );
qalDeleteBuffers(1, &name);
active_buffers--;
}
void AL_StopChannel( channel_t *ch ) {
void
AL_StopChannel(channel_t *ch)
{
if (s_show->value > 1)
Com_Printf("%s: %s\n", __func__, ch->sfx->name );
// stop it
qalSourceStop( ch->srcnum );
qalSourcei( ch->srcnum, AL_BUFFER, AL_NONE );
memset (ch, 0, sizeof(*ch));
}
static void AL_Spatialize( channel_t *ch ) {
vec3_t origin;
// anything coming from the view entity will always be full volume
// no attenuation = no spatialization
if( ch->entnum == -1 || ch->entnum == cl.playernum + 1 || !ch->dist_mult ) {
VectorCopy( listener_origin, origin );
} else if( ch->fixed_origin ) {
VectorCopy( ch->origin, origin );
} else {
CL_GetEntitySoundOrigin( ch->entnum, origin );
{
Com_Printf("%s: %s\n", __func__, ch->sfx->name);
}
qalSource3f( ch->srcnum, AL_POSITION, AL_UnpackVector( origin ) );
/* stop it */
qalSourceStop(ch->srcnum);
qalSourcei(ch->srcnum, AL_BUFFER, AL_NONE);
memset(ch, 0, sizeof(*ch));
}
void AL_PlayChannel( channel_t *ch ) {
static void
AL_Spatialize(channel_t *ch)
{
vec3_t origin;
/* anything coming from the view entity
will always be full volume. no
attenuation = no spatialization */
if ((ch->entnum == -1) || (ch->entnum == cl.playernum + 1) ||
!ch->dist_mult)
{
VectorCopy(listener_origin, origin);
}
else if (ch->fixed_origin)
{
VectorCopy(ch->origin, origin);
}
else
{
CL_GetEntitySoundOrigin(ch->entnum, origin);
}
qalSource3f(ch->srcnum, AL_POSITION, AL_UnpackVector(origin));
}
void
AL_PlayChannel(channel_t *ch)
{
sfxcache_t *sc = ch->sfx->cache;
if (s_show->value > 1)
Com_Printf("%s: %s\n", __func__, ch->sfx->name );
{
Com_Printf("%s: %s\n", __func__, ch->sfx->name);
}
ch->srcnum = s_srcnums[ch - channels];
qalGetError();
qalSourcei( ch->srcnum, AL_BUFFER, sc->bufnum );
qalSourcei( ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE );
qalSourcef( ch->srcnum, AL_GAIN, ch->master_vol );
qalSourcef( ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME );
qalSourcef( ch->srcnum, AL_MAX_DISTANCE, 8192 );
qalSourcef( ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * ( 8192 - SOUND_FULLVOLUME ) );
qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum);
qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE);
qalSourcef(ch->srcnum, AL_GAIN, ch->master_vol);
qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME);
qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192);
qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult *
(8192 - SOUND_FULLVOLUME));
AL_Spatialize( ch );
AL_Spatialize(ch);
// play it
qalSourcePlay( ch->srcnum );
if( qalGetError() != AL_NO_ERROR ) {
AL_StopChannel( ch );
/* play it */
qalSourcePlay(ch->srcnum);
if (qalGetError() != AL_NO_ERROR)
{
AL_StopChannel(ch);
}
}
void AL_StopAllChannels( void ) {
int i;
channel_t *ch;
void
AL_StopAllChannels(void)
{
int i;
channel_t *ch;
ch = channels;
for( i = 0; i < s_numchannels; i++, ch++ ) {
for (i = 0; i < s_numchannels; i++, ch++)
{
if (!ch->sfx)
{
continue;
AL_StopChannel( ch );
}
AL_StopChannel(ch);
}
s_rawend = 0;
S_AL_StreamDie();
}
static channel_t *AL_FindLoopingSound( int entnum, sfx_t *sfx ) {
int i;
channel_t *ch;
static channel_t *
AL_FindLoopingSound(int entnum, sfx_t *sfx)
{
int i;
channel_t *ch;
ch = channels;
for( i = 0; i < s_numchannels; i++, ch++ ) {
if( !ch->sfx )
for (i = 0; i < s_numchannels; i++, ch++)
{
if (!ch->sfx)
{
continue;
if( !ch->autosound )
}
if (!ch->autosound)
{
continue;
if( ch->entnum != entnum )
}
if (ch->entnum != entnum)
{
continue;
if( ch->sfx != sfx )
}
if (ch->sfx != sfx)
{
continue;
}
return ch;
}
return NULL;
}
static void AL_AddLoopSounds( void ) {
int i;
int sounds[MAX_EDICTS];
channel_t *ch;
sfx_t *sfx;
sfxcache_t *sc;
int num;
entity_state_t *ent;
static void
AL_AddLoopSounds(void)
{
int i;
int sounds[MAX_EDICTS];
channel_t *ch;
sfx_t *sfx;
sfxcache_t *sc;
int num;
entity_state_t *ent;
if( cls.state != ca_active || cl_paused->value || !s_ambient->value ) {
if ((cls.state != ca_active) || cl_paused->value || !s_ambient->value)
{
return;
}
S_BuildSoundList( sounds );
S_BuildSoundList(sounds);
for( i = 0; i < cl.frame.num_entities; i++ ) {
for (i = 0; i < cl.frame.num_entities; i++)
{
if (!sounds[i])
{
continue;
}
sfx = cl.sound_precache[sounds[i]];
if (!sfx)
continue; // bad sound effect
{
continue; /* bad sound effect */
}
sc = sfx->cache;
if (!sc)
{
continue;
}
num = ( cl.frame.parse_entities + i ) & ( MAX_PARSE_ENTITIES - 1 );
ent = &cl_parse_entities [ num ];
num = (cl.frame.parse_entities + i) & (MAX_PARSE_ENTITIES - 1);
ent = &cl_parse_entities[num];
ch = AL_FindLoopingSound( ent->number, sfx );
if( ch ) {
ch = AL_FindLoopingSound(ent->number, sfx);
if (ch)
{
ch->autoframe = s_framecount;
ch->end = paintedtime + sc->length;
continue;
}
// allocate a channel
/* allocate a channel */
ch = S_PickChannel(0, 0);
if (!ch)
continue;
ch->autosound = true; // remove next frame
if (!ch)
{
continue;
}
ch->autosound = true; /* remove next frame */
ch->autoframe = s_framecount;
ch->sfx = sfx;
ch->entnum = ent->number;
@ -336,116 +425,145 @@ static void AL_AddLoopSounds( void ) {
ch->dist_mult = SOUND_LOOPATTENUATE;
ch->end = paintedtime + sc->length;
AL_PlayChannel( ch );
AL_PlayChannel(ch);
}
}
static void AL_IssuePlaysounds( void ) {
static void
AL_IssuePlaysounds(void)
{
playsound_t *ps;
// start any playsounds
while (1) {
/* start any playsounds */
while (1)
{
ps = s_pendingplays.next;
if (ps == &s_pendingplays)
break; // no more pending sounds
{
break; /* no more pending sounds */
}
if (ps->begin > paintedtime)
{
break;
S_IssuePlaysound (ps);
}
S_IssuePlaysound(ps);
}
}
void AL_Update( void ) {
int i;
channel_t *ch;
vec_t orientation[6];
void
AL_Update(void)
{
int i;
channel_t *ch;
vec_t orientation[6];
paintedtime = cl.time;
// set listener parameters
qalListener3f( AL_POSITION, AL_UnpackVector( listener_origin ) );
AL_CopyVector( listener_forward, orientation );
AL_CopyVector( listener_up, orientation + 3 );
qalListenerfv( AL_ORIENTATION, orientation );
qalListenerf( AL_GAIN, s_volume->value );
qalDistanceModel( AL_LINEAR_DISTANCE_CLAMPED );
/* set listener parameters */
qalListener3f(AL_POSITION, AL_UnpackVector(listener_origin));
AL_CopyVector(listener_forward, orientation);
AL_CopyVector(listener_up, orientation + 3);
qalListenerfv(AL_ORIENTATION, orientation);
qalListenerf(AL_GAIN, s_volume->value);
qalDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
// update spatialization for dynamic sounds
/* update spatialization for dynamic sounds */
ch = channels;
for( i = 0; i < s_numchannels; i++, ch++ ) {
if( !ch->sfx )
continue;
if( ch->autosound ) {
// autosounds are regenerated fresh each frame
if( ch->autoframe != s_framecount ) {
AL_StopChannel( ch );
for (i = 0; i < s_numchannels; i++, ch++)
{
if (!ch->sfx)
{
continue;
}
if (ch->autosound)
{
/* autosounds are regenerated fresh each frame */
if (ch->autoframe != s_framecount)
{
AL_StopChannel(ch);
continue;
}
} else {
}
else
{
ALenum state;
qalGetError();
qalGetSourcei( ch->srcnum, AL_SOURCE_STATE, &state );
if( qalGetError() != AL_NO_ERROR || state == AL_STOPPED ) {
AL_StopChannel( ch );
qalGetSourcei(ch->srcnum, AL_SOURCE_STATE, &state);
if ((qalGetError() != AL_NO_ERROR) || (state == AL_STOPPED))
{
AL_StopChannel(ch);
continue;
}
}
if (s_show->value) {
Com_Printf ("%3i %s\n", ch->master_vol, ch->sfx->name);
if (s_show->value)
{
Com_Printf("%3i %s\n", ch->master_vol, ch->sfx->name);
}
AL_Spatialize(ch); // respatialize channel
AL_Spatialize(ch); /* respatialize channel */
}
s_framecount++;
// add loopsounds
AL_AddLoopSounds ();
/* add loopsounds */
AL_AddLoopSounds();
// add music
/* add music */
OGG_Stream();
S_AL_StreamUpdate();
AL_IssuePlaysounds();
}
void AL_Underwater()
void
AL_Underwater()
{
int i;
if(sound_started != SS_OAL) {
if (sound_started != SS_OAL)
{
return;
}
// Apply to all sources
/* Apply to all sources */
for (i = 0; i < s_numchannels; i++)
{
qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, underwaterFilter);
}
}
void AL_Overwater()
void
AL_Overwater()
{
int i;
// Apply to all sources
/* Apply to all sources */
for (i = 0; i < s_numchannels; i++)
{
qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, 0);
}
}
static void S_AL_StreamDie( void )
static void
S_AL_StreamDie(void)
{
int numBuffers;
int numBuffers;
streamPlaying = false;
qalSourceStop(streamSource);
// Un-queue any buffers, and delete them
qalGetSourcei( streamSource, AL_BUFFERS_QUEUED, &numBuffers );
while( numBuffers-- )
/* Un-queue any buffers, and delete them */
qalGetSourcei(streamSource, AL_BUFFERS_QUEUED, &numBuffers);
while (numBuffers--)
{
ALuint buffer;
qalSourceUnqueueBuffers(streamSource, 1, &buffer);
@ -454,14 +572,16 @@ static void S_AL_StreamDie( void )
}
}
static void S_AL_StreamUpdate( void )
static void
S_AL_StreamUpdate(void)
{
int numBuffers;
ALint state;
int numBuffers;
ALint state;
// Un-queue any buffers, and delete them
qalGetSourcei( streamSource, AL_BUFFERS_PROCESSED, &numBuffers );
while( numBuffers-- )
/* Un-queue any buffers, and delete them */
qalGetSourcei(streamSource, AL_BUFFERS_PROCESSED, &numBuffers);
while (numBuffers--)
{
ALuint buffer;
qalSourceUnqueueBuffers(streamSource, 1, &buffer);
@ -469,70 +589,84 @@ static void S_AL_StreamUpdate( void )
active_buffers--;
}
// Start the streamSource playing if necessary
qalGetSourcei( streamSource, AL_BUFFERS_QUEUED, &numBuffers );
/* Start the streamSource playing if necessary */
qalGetSourcei(streamSource, AL_BUFFERS_QUEUED, &numBuffers);
qalGetSourcei(streamSource, AL_SOURCE_STATE, &state);
if(state == AL_STOPPED)
if (state == AL_STOPPED)
{
streamPlaying = false;
}
if( !streamPlaying && numBuffers )
if (!streamPlaying && numBuffers)
{
qalSourcePlay( streamSource );
qalSourcePlay(streamSource);
streamPlaying = true;
}
}
static ALuint S_AL_Format(int width, int channels)
static ALuint
S_AL_Format(int width, int channels)
{
ALuint format = AL_FORMAT_MONO16;
// Work out format
if(width == 1)
/* Work out format */
if (width == 1)
{
if(channels == 1)
if (channels == 1)
{
format = AL_FORMAT_MONO8;
else if(channels == 2)
}
else if (channels == 2)
{
format = AL_FORMAT_STEREO8;
}
}
else if(width == 2)
else if (width == 2)
{
if(channels == 1)
if (channels == 1)
{
format = AL_FORMAT_MONO16;
else if(channels == 2)
}
else if (channels == 2)
{
format = AL_FORMAT_STEREO16;
}
}
return format;
}
void AL_RawSamples( int samples, int rate, int width, int channels, byte *data, float volume )
void
AL_RawSamples(int samples, int rate, int width, int channels,
byte *data, float volume)
{
ALuint buffer;
ALuint format;
format = S_AL_Format( width, channels );
format = S_AL_Format(width, channels);
// Create a buffer, and stuff the data into it
/* Create a buffer, and stuff the data into it */
qalGenBuffers(1, &buffer);
qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate);
qalBufferData(buffer, format, (ALvoid *)data,
(samples * width * channels), rate);
active_buffers++;
// set volume
qalSourcef( streamSource, AL_GAIN, volume );
/* set volume */
qalSourcef(streamSource, AL_GAIN, volume);
// Shove the data onto the streamSource
/* Shove the data onto the streamSource */
qalSourceQueueBuffers(streamSource, 1, &buffer);
// emulate behavior of S_RawSamples for s_rawend
/* emulate behavior of S_RawSamples for s_rawend */
s_rawend += samples;
}
void AL_UnqueueRawSamples()
void
AL_UnqueueRawSamples()
{
S_AL_StreamDie();
}
#endif // USE_OPENAL
#endif /* USE_OPENAL */

File diff suppressed because it is too large Load Diff

View File

@ -19,8 +19,9 @@
*
* =======================================================================
*
* The sound caching. This file contains support functions for loading
* the sound samples into the memory.
* The sound caching. This file contains support functions for
* processing the soundsamples, load them into the memory and
* provide them to the SDL or OpenAL sound backend.
*
* =======================================================================
*/
@ -29,7 +30,7 @@
#include "header/local.h"
void
ResampleSfx ( sfx_t *sfx, int inrate, int inwidth, byte *data )
ResampleSfx(sfx_t *sfx, int inrate, int inwidth, byte *data)
{
int outcount;
int srcsample;
@ -37,37 +38,38 @@ ResampleSfx ( sfx_t *sfx, int inrate, int inwidth, byte *data )
int i;
int sample;
unsigned int samplefrac, fracstep;
sfxcache_t *sc;
sfxcache_t *sc;
sc = sfx->cache;
if ( !sc )
if (!sc)
{
return;
}
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 = (int) ( sc->length / stepscale );
outcount = (int)(sc->length / stepscale);
if ( outcount == 0 )
if (outcount == 0)
{
Com_Printf( "ResampleSfx: Invalid sound file '%s' (zero length)\n", sfx->name );
Z_Free( sfx->cache );
Com_Printf("ResampleSfx: Invalid sound file '%s' (zero length)\n",
sfx->name);
Z_Free(sfx->cache);
sfx->cache = NULL;
return;
}
sc->length = outcount;
if ( sc->loopstart != -1 )
if (sc->loopstart != -1)
{
sc->loopstart = (int) ( sc->loopstart / stepscale );
sc->loopstart = (int)(sc->loopstart / stepscale);
}
sc->speed = dma.speed;
if ( s_loadas8bit->value )
if (s_loadas8bit->value)
{
sc->width = 1;
}
@ -81,62 +83,62 @@ ResampleSfx ( sfx_t *sfx, int inrate, int inwidth, byte *data )
/* resample / decimate to the current source rate */
samplefrac = 0;
fracstep = (int) ( stepscale * 256 );
fracstep = (int)(stepscale * 256);
for ( i = 0; i < outcount; i++ )
for (i = 0; i < outcount; i++)
{
srcsample = samplefrac >> 8;
samplefrac += fracstep;
if ( inwidth == 2 )
if (inwidth == 2)
{
sample = LittleShort( ( (short *) data ) [ srcsample ] );
sample = LittleShort(((short *)data)[srcsample]);
}
else
{
sample = (int) ( (unsigned char) ( data [ srcsample ] ) - 128 ) << 8;
sample = (int)((unsigned char)(data[srcsample]) - 128) << 8;
}
if ( sc->width == 2 )
if (sc->width == 2)
{
( (short *) sc->data ) [ i ] = sample;
((short *)sc->data)[i] = sample;
}
else
{
( (signed char *) sc->data ) [ i ] = sample >> 8;
((signed char *)sc->data)[i] = sample >> 8;
}
}
}
sfxcache_t *
S_LoadSound ( sfx_t *s )
S_LoadSound(sfx_t *s)
{
char namebuffer [ MAX_QPATH ];
byte *data;
char namebuffer[MAX_QPATH];
byte *data;
wavinfo_t info;
int len;
float stepscale;
sfxcache_t *sc;
sfxcache_t *sc;
int size;
char *name;
char *name;
if ( s->name [ 0 ] == '*' )
if (s->name[0] == '*')
{
return ( NULL );
return NULL;
}
/* see if still in memory */
sc = s->cache;
if ( sc )
if (sc)
{
return ( sc );
return sc;
}
/* load it in */
if ( s->truename )
if (s->truename)
{
name = s->truename;
}
@ -146,48 +148,52 @@ S_LoadSound ( sfx_t *s )
name = s->name;
}
if ( name [ 0 ] == '#' )
if (name[0] == '#')
{
strcpy( namebuffer, &name [ 1 ] );
} else {
Com_sprintf( namebuffer, sizeof ( namebuffer ), "sound/%s", name );
strcpy(namebuffer, &name[1]);
}
else
{
Com_sprintf(namebuffer, sizeof(namebuffer), "sound/%s", name);
}
size = FS_LoadFile( namebuffer, (void **) &data );
size = FS_LoadFile(namebuffer, (void **)&data);
if ( !data )
if (!data)
{
s->cache = NULL;
Com_DPrintf( "Couldn't load %s\n", namebuffer );
return ( NULL );
Com_DPrintf("Couldn't load %s\n", namebuffer);
return NULL;
}
info = GetWavinfo( s->name, data, size );
info = GetWavinfo(s->name, data, size);
if ( info.channels != 1 )
if (info.channels != 1)
{
Com_Printf( "%s is a stereo sample\n", s->name );
FS_FreeFile( data );
return ( NULL );
Com_Printf("%s is a stereo sample\n", s->name);
FS_FreeFile(data);
return NULL;
}
if (sound_started != SS_OAL) {
stepscale = (float) info.rate / dma.speed;
len = (int) ( info.samples / stepscale );
if ( ( info.samples == 0 ) || ( len == 0 ) )
if (sound_started != SS_OAL)
{
stepscale = (float)info.rate / dma.speed;
len = (int)(info.samples / stepscale);
if ((info.samples == 0) || (len == 0))
{
Com_Printf( "WARNING: Zero length sound encountered: %s\n", s->name );
FS_FreeFile( data );
return ( NULL );
Com_Printf("WARNING: Zero length sound encountered: %s\n", s->name);
FS_FreeFile(data);
return NULL;
}
len = len * info.width * info.channels;
sc = s->cache = Z_Malloc( len + sizeof ( sfxcache_t ) );
sc = s->cache = Z_Malloc(len + sizeof(sfxcache_t));
if ( !sc )
if (!sc)
{
FS_FreeFile( data );
return ( NULL );
FS_FreeFile(data);
return NULL;
}
sc->length = info.samples;
@ -199,12 +205,17 @@ S_LoadSound ( sfx_t *s )
#if USE_OPENAL
if (sound_started == SS_OAL)
{
sc = AL_UploadSfx(s, &info, data + info.dataofs);
}
else
#endif
ResampleSfx( s, sc->speed, sc->width, data + info.dataofs );
{
ResampleSfx(s, sc->speed, sc->width, data + info.dataofs);
}
FS_FreeFile( data );
FS_FreeFile(data);
return ( sc );
return sc;
}

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
*
* =======================================================================
*
* This file implements a subset of the WAVE audio file format
* This file implements a subset of the WAVE audio file format.
*
* =======================================================================
*/
@ -27,48 +27,45 @@
#include "../header/client.h"
#include "header/local.h"
// FIXME: this code is really fucked up, those global variables make me sick.
// someone should clean this up one day..
byte *data_p;
byte *iff_end;
byte *last_chunk;
byte *iff_data;
int iff_chunk_len;
byte *data_p;
byte *iff_end;
byte *last_chunk;
byte *iff_data;
int iff_chunk_len;
short
GetLittleShort ( void )
GetLittleShort(void)
{
short val = 0;
val = *data_p;
val = val + ( *( data_p + 1 ) << 8 );
val = val + (*(data_p + 1) << 8);
data_p += 2;
return ( val );
return val;
}
int
GetLittleLong ( void )
GetLittleLong(void)
{
int val = 0;
val = *data_p;
val = val + ( *( data_p + 1 ) << 8 );
val = val + ( *( data_p + 2 ) << 16 );
val = val + ( *( data_p + 3 ) << 24 );
val = val + (*(data_p + 1) << 8);
val = val + (*(data_p + 2) << 16);
val = val + (*(data_p + 3) << 24);
data_p += 4;
return ( val );
return val;
}
void
FindNextChunk ( char *name )
FindNextChunk(char *name)
{
while ( 1 )
while (1)
{
data_p = last_chunk;
data_p += 4;
if ( data_p >= iff_end )
if (data_p >= iff_end)
{
data_p = NULL;
return;
@ -76,16 +73,16 @@ FindNextChunk ( char *name )
iff_chunk_len = GetLittleLong();
if ( iff_chunk_len < 0 )
if (iff_chunk_len < 0)
{
data_p = NULL;
return;
}
data_p -= 8;
last_chunk = data_p + 8 + ( ( iff_chunk_len + 1 ) & ~1 );
last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
if ( !strncmp( (const char *) data_p, name, 4 ) )
if (!strncmp((const char *)data_p, name, 4))
{
return;
}
@ -93,57 +90,57 @@ FindNextChunk ( char *name )
}
void
FindChunk ( char *name )
FindChunk(char *name)
{
last_chunk = iff_data;
FindNextChunk( name );
FindNextChunk(name);
}
wavinfo_t
GetWavinfo ( char *name, byte *wav, int wavlength )
GetWavinfo(char *name, byte *wav, int wavlength)
{
wavinfo_t info;
int i;
int format;
int samples;
memset( &info, 0, sizeof ( info ) );
memset(&info, 0, sizeof(info));
if ( !wav )
if (!wav)
{
return ( info );
return info;
}
iff_data = wav;
iff_end = wav + wavlength;
/* find "RIFF" chunk */
FindChunk( "RIFF" );
FindChunk("RIFF");
if ( !( data_p && !strncmp( (const char *) data_p + 8, "WAVE", 4 ) ) )
if (!(data_p && !strncmp((const char *)data_p + 8, "WAVE", 4)))
{
Com_Printf( "Missing RIFF/WAVE chunks\n" );
return ( info );
Com_Printf("Missing RIFF/WAVE chunks\n");
return info;
}
/* get "fmt " chunk */
iff_data = data_p + 12;
FindChunk( "fmt " );
FindChunk("fmt ");
if ( !data_p )
if (!data_p)
{
Com_Printf( "Missing fmt chunk\n" );
return ( info );
Com_Printf("Missing fmt chunk\n");
return info;
}
data_p += 8;
format = GetLittleShort();
if ( format != 1 )
if (format != 1)
{
Com_Printf( "Microsoft PCM format only\n" );
return ( info );
Com_Printf("Microsoft PCM format only\n");
return info;
}
info.channels = GetLittleShort();
@ -152,21 +149,24 @@ GetWavinfo ( char *name, byte *wav, int wavlength )
info.width = GetLittleShort() / 8;
/* get cue chunk */
FindChunk( "cue " );
FindChunk("cue ");
if ( data_p )
if (data_p)
{
data_p += 32;
info.loopstart = GetLittleLong();
/* if the next chunk is a LIST chunk, look for a cue length marker */
FindNextChunk( "LIST" );
/* if the next chunk is a LIST chunk,
look for a cue length marker */
FindNextChunk("LIST");
if ( data_p )
if (data_p)
{
if ( ( ( data_p - wav ) + 32 <= wavlength ) && !strncmp( (const char *) data_p + 28, "mark", 4 ) )
if (((data_p - wav) + 32 <= wavlength) &&
!strncmp((const char *)data_p + 28, "mark", 4))
{
/* this is not a proper parse, but it works with cooledit... */
/* this is not a proper parse,
but it works with cooledit... */
data_p += 24;
i = GetLittleLong(); /* samples in loop */
info.samples = info.loopstart + i;
@ -179,22 +179,22 @@ GetWavinfo ( char *name, byte *wav, int wavlength )
}
/* find data chunk */
FindChunk( "data" );
FindChunk("data");
if ( !data_p )
if (!data_p)
{
Com_Printf( "Missing data chunk\n" );
return ( info );
Com_Printf("Missing data chunk\n");
return info;
}
data_p += 4;
samples = GetLittleLong() / info.width;
if ( info.samples )
if (info.samples)
{
if ( samples < info.samples )
if (samples < info.samples)
{
Com_Error( ERR_DROP, "Sound %s has a bad loop length", name );
Com_Error(ERR_DROP, "Sound %s has a bad loop length", name);
}
}
else
@ -202,7 +202,8 @@ GetWavinfo ( char *name, byte *wav, int wavlength )
info.samples = samples;
}
info.dataofs = (int) ( data_p - wav );
info.dataofs = (int)(data_p - wav);
return ( info );
return info;
}