weitere Dateien des Soundsystems neu formatiert und kommentiert

This commit is contained in:
Yamagi Burmeister 2010-06-19 17:04:32 +00:00
parent 0c4a7d291f
commit fe587b7148
6 changed files with 604 additions and 721 deletions

View file

@ -190,7 +190,7 @@ void S_Shutdown(void) {
}
/*
* Returns the name of sound
* Returns the name of a sound
*/
sfx_t *S_FindName (char *name, qboolean create) {
int i;
@ -296,7 +296,7 @@ void S_EndRegistration (void) {
if (sfx->registration_sequence != s_registration_sequence) {
/* don't need this sound */
if (sfx->cache) /* it is possible to have a leftover */
Z_Free (sfx->cache); /* from a server that didn't finish loading */
Z_Free (sfx->cache); /* from a server that didn't finish loading */
memset (sfx, 0, sizeof(*sfx));
@ -383,9 +383,9 @@ void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *
dist -= SOUND_FULLVOLUME;
if (dist < 0)
dist = 0; /* close enough to be at full volume */
dist = 0; /* close enough to be at full volume */
dist *= dist_mult; /* different attenuation levels */
dist *= dist_mult; /* different attenuation levels */
dot = DotProduct(listener_right, source_vec);
@ -796,7 +796,7 @@ void S_AddLoopSounds (void) {
ch->leftvol = left_total;
ch->rightvol = right_total;
ch->autosound = true; /* remove next frame */
ch->autosound = true; /* remove next frame */
ch->sfx = sfx;
/* Sometimes, the sc->length argument can become 0,
@ -952,7 +952,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) {
continue;
}
S_Spatialize(ch); /* respatialize channel */
S_Spatialize(ch); /* respatialize channel */
if (!ch->leftvol && !ch->rightvol) {
memset (ch, 0, sizeof(*ch));
@ -1107,3 +1107,4 @@ void S_SoundList(void) {
Com_Printf ("Total resident: %i\n", total);
}

View file

@ -1,128 +1,113 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Local defines of the sound system
*
* =======================================================================
*/
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// snd_loc.h -- private sound functions
// !!! if this is changed, the asm code must change !!!
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;
int stereo;
byte data[1]; // variable sized
typedef struct {
int length;
int loopstart;
int speed; /* not needed, because converted on load? */
int width;
int stereo;
byte data[1]; /* variable sized */
} sfxcache_t;
typedef struct sfx_s
{
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
{
/* 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
qboolean fixed_origin; /* use origin field instead of entnum's origin */
vec3_t origin;
unsigned begin; // begin on this sample
unsigned begin; /* begin on this sample */
} playsound_t;
typedef struct
{
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 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;
// !!! if this is changed, the asm code must change !!!
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 OBSOLETE?
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 */
} channel_t;
typedef struct
{
typedef struct {
int rate;
int width;
int channels;
int loopstart;
int samples;
int dataofs; // chunk starts this many bytes from file start
int dataofs; /* chunk starts this many bytes from file start */
} wavinfo_t;
/*
====================================================================
SYSTEM SPECIFIC FUNCTIONS
====================================================================
*/
// initializes cycling through a DMA buffer and returns information on it
/* initializes cycling through a DMA
buffer and returns information on it */
qboolean SNDDMA_Init(void);
// gets the current DMA position
/* gets the current DMA position */
int SNDDMA_GetDMAPos(void);
// shutdown the DMA xfer.
/* shutdown the DMA xfer. */
void SNDDMA_Shutdown(void);
void SNDDMA_BeginPainting (void);
void SNDDMA_Submit(void);
//====================================================================
#define MAX_CHANNELS 32
extern channel_t channels[MAX_CHANNELS];
@ -148,17 +133,13 @@ extern cvar_t *s_testsound;
extern cvar_t *s_primary;
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
/* picks a channel based on priorities, empty slots, number of channels */
channel_t *S_PickChannel(int entnum, int entchannel);
// spatializes a channel
/* spatializes a channel */
void S_Spatialize(channel_t *ch);

View file

@ -1,38 +1,39 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// snd_mem.c: sound caching
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* The sound caching. This files manages a double linked list (a circle
* buffer) which caches the sound samples and provides their memory
* adresses to the low level sound backend. It also implements the WAV
* fileformat and functions for loading the samples into the list.
*
* =======================================================================
*/
#include "../header/client.h"
#include "snd_loc.h"
int cache_full_cycle;
int cache_full_cycle;
byte *S_Alloc (int size);
/*
================
ResampleSfx
================
*/
void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data)
{
void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) {
int outcount;
int srcsample;
float stepscale;
@ -40,65 +41,63 @@ void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data)
int sample;
unsigned int samplefrac, fracstep;
sfxcache_t *sc;
sc = sfx->cache;
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);
sc->length = outcount;
if (sc->loopstart != -1)
sc->loopstart = (int)(sc->loopstart / stepscale);
sc->speed = dma.speed;
if (s_loadas8bit->value)
sc->width = 1;
else
sc->width = inwidth;
sc->stereo = 0;
// resample / decimate to the current source rate
if (stepscale == 1 && inwidth == 1 && sc->width == 1)
{
// fast special case
/* resample / decimate to the current source rate */
if (stepscale == 1 && inwidth == 1 && sc->width == 1) {
/* fast special case */
for (i=0 ; i<outcount ; i++)
((signed char *)sc->data)[i]
= (int)( (unsigned char)(data[i]) - 128);
}
else
{
// general case
} else {
/* general case */
samplefrac = 0;
fracstep = (int)(stepscale*256);
for (i=0 ; i<outcount ; i++)
{
for (i=0 ; i<outcount ; i++) {
srcsample = samplefrac >> 8;
samplefrac += fracstep;
if (inwidth == 2)
sample = LittleShort ( ((short *)data)[srcsample] );
else
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
if (sc->width == 2)
((short *)sc->data)[i] = sample;
else
((signed char *)sc->data)[i] = sample >> 8;
}
}
}
//=============================================================================
/*
==============
S_LoadSound
==============
*/
sfxcache_t *S_LoadSound (sfx_t *s)
{
char namebuffer[MAX_QPATH];
sfxcache_t *S_LoadSound (sfx_t *s) {
char namebuffer[MAX_QPATH];
byte *data;
wavinfo_t info;
int len;
@ -110,58 +109,59 @@ sfxcache_t *S_LoadSound (sfx_t *s)
if (s->name[0] == '*')
return NULL;
// see if still in memory
/* see if still in memory */
sc = s->cache;
if (sc)
return sc;
// load it in
/* load it in */
if (s->truename)
name = s->truename;
else
name = s->name;
if (name[0] == '#')
strcpy(namebuffer, &name[1]);
else
Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name);
size = FS_LoadFile (namebuffer, (void **)&data);
if (!data)
{
if (!data) {
s->cache = NULL;
Com_DPrintf ("Couldn't load %s\n", namebuffer);
return NULL;
}
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;
}
stepscale = (float)info.rate / dma.speed;
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;
}
if (info.samples == 0 || len == 0) {
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));
if (!sc)
{
if (!sc) {
FS_FreeFile (data);
return NULL;
}
sc->length = info.samples;
sc->loopstart = info.loopstart;
sc->speed = info.rate;
@ -175,23 +175,13 @@ sfxcache_t *S_LoadSound (sfx_t *s)
return sc;
}
/*
===============================================================================
WAV loading
===============================================================================
*/
byte *data_p;
byte *iff_end;
byte *last_chunk;
byte *iff_data;
int iff_chunk_len;
short GetLittleShort(void)
{
short GetLittleShort(void) {
short val = 0;
val = *data_p;
val = val + (*(data_p+1)<<8);
@ -199,8 +189,7 @@ short GetLittleShort(void)
return val;
}
int GetLittleLong(void)
{
int GetLittleLong(void) {
int val = 0;
val = *data_p;
val = val + (*(data_p+1)<<8);
@ -210,46 +199,44 @@ int GetLittleLong(void)
return val;
}
void FindNextChunk(char *name)
{
while (1)
{
void FindNextChunk(char *name) {
while (1) {
data_p=last_chunk;
if (data_p >= iff_end)
{ // didn't find the chunk
if (data_p >= iff_end) {
/* didn't find the chunk */
data_p = NULL;
return;
}
data_p += 4;
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 );
if (!strncmp((const char *)data_p, name, 4))
return;
}
}
void FindChunk(char *name)
{
void FindChunk(char *name) {
last_chunk = iff_data;
FindNextChunk (name);
}
void DumpChunks(void)
{
void DumpChunks(void) {
char str[5];
str[4] = 0;
data_p=iff_data;
do
{
do {
memcpy (str, data_p, 4);
data_p += 4;
iff_chunk_len = GetLittleLong();
@ -258,13 +245,7 @@ void DumpChunks(void)
} while (data_p < iff_end);
}
/*
============
GetWavinfo
============
*/
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
{
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) {
wavinfo_t info;
int i;
int format;
@ -274,31 +255,32 @@ wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
if (!wav)
return info;
iff_data = wav;
iff_end = wav + wavlength;
// find "RIFF" chunk
/* find "RIFF" chunk */
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;
}
// get "fmt " chunk
/* get "fmt " chunk */
iff_data = data_p + 12;
FindChunk("fmt ");
if (!data_p)
{
if (!data_p) {
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;
}
@ -308,32 +290,32 @@ wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
data_p += 4+2;
info.width = GetLittleShort() / 8;
// get cue chunk
/* get cue chunk */
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
/* if the next chunk is a LIST chunk, look for a cue length marker */
FindNextChunk ("LIST");
if (data_p)
{
if (!strncmp ((const char *)data_p + 28, "mark", 4))
{ // this is not a proper parse, but it works with cooledit...
if (data_p) {
if (!strncmp ((const char *)data_p + 28, "mark", 4)) {
/* this is not a proper parse, but it works with cooledit... */
data_p += 24;
i = GetLittleLong (); // samples in loop
i = GetLittleLong (); /* samples in loop */
info.samples = info.loopstart + i;
}
}
}
else
} else
info.loopstart = -1;
// find data chunk
/* find data chunk */
FindChunk("data");
if (!data_p)
{
if (!data_p) {
Com_Printf("Missing data chunk\n");
return info;
}
@ -341,16 +323,14 @@ wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
data_p += 4;
samples = GetLittleLong () / info.width;
if (info.samples)
{
if (info.samples) {
if (samples < info.samples)
Com_Error (ERR_DROP, "Sound %s has a bad loop length", name);
}
else
} else
info.samples = samples;
info.dataofs = data_p - wav;
return info;
}

View file

@ -1,80 +1,91 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// snd_mix.c -- portable code to mix sounds for snd_dma.c
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* This code mixes two or more sound samples into one. It also
* implements sample rate changing and per channel extraction.
* It's called by the upper level sound framework, snd_dma.c
*
* =======================================================================
*/
#include "../header/client.h"
#include "snd_loc.h"
#define PAINTBUFFER_SIZE 8192
#define PAINTBUFFER_SIZE 8192
portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
int snd_scaletable[32][256];
int *snd_p, snd_linear_count, snd_vol;
short *snd_out;
void S_WriteLinearBlastStereo16 (void)
{
void S_WriteLinearBlastStereo16 (void) {
int i;
int val;
for (i=0 ; i<snd_linear_count ; i+=2)
{
for (i=0 ; i<snd_linear_count ; i+=2) {
val = snd_p[i]>>8;
if (val > 0x7fff)
snd_out[i] = 0x7fff;
else if (val < (short)0x8000)
snd_out[i] = (short)0x8000;
else
snd_out[i] = val;
val = snd_p[i+1]>>8;
if (val > 0x7fff)
snd_out[i+1] = 0x7fff;
else if (val < (short)0x8000)
snd_out[i+1] = (short)0x8000;
else
snd_out[i+1] = val;
}
}
void S_TransferStereo16 (unsigned long *pbuf, int endtime)
{
void S_TransferStereo16 (unsigned long *pbuf, int endtime) {
int lpos;
int lpaintedtime;
snd_p = (int *) paintbuffer;
lpaintedtime = paintedtime;
while (lpaintedtime < endtime)
{
// handle recirculating buffer issues
while (lpaintedtime < endtime) {
/* handle recirculating buffer issues */
lpos = lpaintedtime & ((dma.samples>>1)-1);
snd_out = (short *) pbuf + (lpos<<1);
snd_linear_count = (dma.samples>>1) - lpos;
if (lpaintedtime + snd_linear_count > endtime)
snd_linear_count = endtime - lpaintedtime;
snd_linear_count <<= 1;
// write a linear blast of samples
/* write a linear blast of samples */
S_WriteLinearBlastStereo16 ();
snd_p += snd_linear_count;
@ -82,14 +93,7 @@ void S_TransferStereo16 (unsigned long *pbuf, int endtime)
}
}
/*
===================
S_TransferPaintBuffer
===================
*/
void S_TransferPaintBuffer(int endtime)
{
void S_TransferPaintBuffer(int endtime) {
int out_idx;
int count;
int out_mask;
@ -100,64 +104,69 @@ void S_TransferPaintBuffer(int endtime)
pbuf = (unsigned long *)dma.buffer;
if (s_testsound->value)
{
if (s_testsound->value) {
static float x = 0.05;
static float y = 0.0001;
int i;
int count;
x += y;
if (x > 0.15)
y = -0.0001;
else if (x < 0.0005)
y = 0.0001;
// write a fixed sine wave
/* write a fixed sine wave */
count = (endtime - paintedtime);
for (i=0 ; i<count ; i++)
paintbuffer[i].left = paintbuffer[i].right = (int)((float)sin((paintedtime+i)*0.1f)*20000*256);
}
if (dma.samplebits == 16 && dma.channels == 2)
{ // optimized case
if (dma.samplebits == 16 && dma.channels == 2) {
/* optimized case */
S_TransferStereo16 (pbuf, endtime);
}
else
{ // general case
} else {
/* general case */
p = (int *) paintbuffer;
count = (endtime - paintedtime) * dma.channels;
out_mask = dma.samples - 1;
out_mask = dma.samples - 1;
out_idx = paintedtime * dma.channels & out_mask;
step = 3 - dma.channels;
if (dma.samplebits == 16)
{
if (dma.samplebits == 16) {
short *out = (short *) pbuf;
while (count--)
{
while (count--) {
val = *p >> 8;
p+= step;
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short)0x8000)
val = (short)0x8000;
out[out_idx] = val;
out_idx = (out_idx + 1) & out_mask;
}
}
else if (dma.samplebits == 8)
{
} else if (dma.samplebits == 8) {
unsigned char *out = (unsigned char *) pbuf;
while (count--)
{
while (count--) {
val = *p >> 8;
p+= step;
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short)0x8000)
val = (short)0x8000;
out[out_idx] = (val>>8) + 128;
out_idx = (out_idx + 1) & out_mask;
}
@ -165,20 +174,10 @@ void S_TransferPaintBuffer(int endtime)
}
}
/*
===============================================================================
CHANNEL MIXING
===============================================================================
*/
void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime, int offset);
void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime, int offset);
void S_PaintChannels(int endtime)
{
void S_PaintChannels(int endtime) {
int i;
int end;
channel_t *ch;
@ -188,135 +187,129 @@ void S_PaintChannels(int endtime)
snd_vol = s_volume->value*256;
while (paintedtime < endtime)
{
// if paintbuffer is smaller than DMA buffer
while (paintedtime < endtime) {
/* if paintbuffer is smaller than DMA buffer */
end = endtime;
if (endtime - paintedtime > PAINTBUFFER_SIZE)
end = paintedtime + PAINTBUFFER_SIZE;
// start any playsounds
while (1)
{
/* start any playsounds */
while (1) {
ps = s_pendingplays.next;
if (ps == NULL)
break;
if (ps == &s_pendingplays)
break; // no more pending sounds
if (ps->begin <= paintedtime)
{
break; /* no more pending sounds */
if (ps->begin <= paintedtime) {
S_IssuePlaysound (ps);
continue;
}
if (ps->begin < end)
end = ps->begin; // stop here
end = ps->begin; /* stop here */
break;
}
// clear the paint buffer
if (s_rawend < paintedtime)
{
/* clear the paint buffer */
if (s_rawend < paintedtime) {
memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
}
else
{ // copy from the streaming sound source
} else {
/* copy from the streaming sound source */
int s;
int stop;
stop = (end < s_rawend) ? end : s_rawend;
for (i=paintedtime ; i<stop ; i++)
{
for (i=paintedtime ; i<stop ; i++) {
s = i&(MAX_RAW_SAMPLES-1);
paintbuffer[i-paintedtime] = s_rawsamples[s];
}
for ( ; i<end ; i++)
{
for ( ; i<end ; i++) {
paintbuffer[i-paintedtime].left =
paintbuffer[i-paintedtime].right = 0;
paintbuffer[i-paintedtime].right = 0;
}
}
// paint in the channels.
/* paint in the channels. */
ch = channels;
for (i=0; i<MAX_CHANNELS ; i++, ch++)
{
for (i=0; i<MAX_CHANNELS ; i++, ch++) {
ltime = paintedtime;
while (ltime < end)
{
while (ltime < end) {
if (!ch->sfx || (!ch->leftvol && !ch->rightvol) )
break;
// max painting is to the end of the buffer
/* max painting is to the end of the buffer */
count = end - ltime;
// might be stopped by running out of data
/* might be stopped by running out of data */
if (ch->end - ltime < count)
count = ch->end - ltime;
sc = S_LoadSound (ch->sfx);
if (!sc)
break;
if (count > 0 && ch->sfx)
{
if (sc->width == 1)// FIXME; 8 bit asm is wrong now
if (count > 0 && ch->sfx) {
if (sc->width == 1)
S_PaintChannelFrom8(ch, sc, count, ltime - paintedtime);
else
S_PaintChannelFrom16(ch, sc, count, ltime - paintedtime);
ltime += count;
}
// if at end of loop, restart
if (ltime >= ch->end)
{
if (ch->autosound)
{ // autolooping sounds always go back to start
/* if at end of loop, restart */
if (ltime >= ch->end) {
if (ch->autosound) {
/* autolooping sounds always go back to start */
ch->pos = 0;
ch->end = ltime + sc->length;
}
else if (sc->loopstart >= 0)
{
} else if (sc->loopstart >= 0) {
ch->pos = sc->loopstart;
ch->end = ltime + sc->length - ch->pos;
}
else
{ // channel just stopped
} else {
/* channel just stopped */
ch->sfx = NULL;
}
}
}
}
// transfer out according to DMA format
/* transfer out according to DMA format */
S_TransferPaintBuffer(end);
paintedtime = end;
}
}
void S_InitScaletable (void)
{
void S_InitScaletable (void) {
int i, j;
int scale;
s_volume->modified = false;
for (i=0 ; i<32 ; i++)
{
for (i=0 ; i<32 ; i++) {
scale = (int)(i * 8 * 256 * s_volume->value);
for (j=0 ; j<256 ; j++)
snd_scaletable[i][j] = ((signed char)j) * scale;
}
}
void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset)
{
void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset) {
int data;
int *lscale, *rscale;
unsigned char *sfx;
@ -325,29 +318,26 @@ void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset)
if (ch->leftvol > 255)
ch->leftvol = 255;
if (ch->rightvol > 255)
ch->rightvol = 255;
//ZOID-- >>11 has been changed to >>3, >>11 didn't make much sense
//as it would always be zero.
lscale = snd_scaletable[ ch->leftvol >> 3];
rscale = snd_scaletable[ ch->rightvol >> 3];
sfx = sc->data + ch->pos;
samp = &paintbuffer[offset];
for (i=0 ; i<count ; i++, samp++)
{
for (i=0 ; i<count ; i++, samp++) {
data = sfx[i];
samp->left += lscale[data];
samp->right += rscale[data];
}
ch->pos += count;
}
void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset)
{
void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset) {
int data;
int left, right;
int leftvol, rightvol;
@ -360,8 +350,8 @@ void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset)
sfx = (signed short *)sc->data + ch->pos;
samp = &paintbuffer[offset];
for (i=0 ; i<count ; i++, samp++)
{
for (i=0 ; i<count ; i++, samp++) {
data = sfx[i];
left = (data * leftvol)>>8;
right = (data * rightvol)>>8;
@ -371,4 +361,3 @@ void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset)
ch->pos += count;
}

View file

@ -1,27 +1,32 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or(at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
==========================================================
OGG Vorbis decoding
==========================================================
*/
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* This file implements an interface to libvorbis for decoding
* OGG/Vorbis files. Strongly spoken this file isn't part of the
* sound system but part of the main client. It justs converts
* Vorbis streams into normal, raw Wave stream which are injected
* into snd_mem.c as if they were normal wave files. At this moment
* only background music playback and in theory .cin movie file
* playback is supported.
*
* =======================================================================
*/
#include <sys/time.h>
#include <errno.h>
@ -31,35 +36,30 @@
#include "snd_loc.h"
#include "snd_ogg.h"
extern int sound_started; /* Sound initialization flag. */
extern cvar_t *fs_basedir; /* Path to "music". */
extern int sound_started; /* Sound initialization flag. */
extern cvar_t *fs_basedir; /* Path to "music". */
qboolean ogg_first_init = true; /* First initialization flag. */
qboolean ogg_started = false; /* Initialization flag. */
byte *ogg_buffer; /* File buffer. */
char **ogg_filelist; /* List of Ogg Vorbis files. */
char ovBuf[4096]; /* Buffer for sound. */
int ogg_curfile; /* Index of currently played file. */
int ogg_numfiles; /* Number of Ogg Vorbis files. */
int ovSection; /* Position in Ogg Vorbis file. */
ogg_status_t ogg_status; /* Status indicator. */
cvar_t *ogg_autoplay; /* Play this song when started. */
cvar_t *ogg_check; /* Check Ogg files or not. */
cvar_t *ogg_playlist; /* Playlist. */
cvar_t *ogg_sequence; /* Sequence play indicator. */
cvar_t *ogg_volume; /* Music volume. */
OggVorbis_File ovFile; /* Ogg Vorbis file. */
qboolean ogg_first_init = true; /* First initialization flag. */
qboolean ogg_started = false; /* Initialization flag. */
byte *ogg_buffer; /* File buffer. */
char **ogg_filelist; /* List of Ogg Vorbis files. */
char ovBuf[4096]; /* Buffer for sound. */
int ogg_curfile; /* Index of currently played file. */
int ogg_numfiles; /* Number of Ogg Vorbis files. */
int ovSection; /* Position in Ogg Vorbis file. */
ogg_status_t ogg_status; /* Status indicator. */
cvar_t *ogg_autoplay; /* Play this song when started. */
cvar_t *ogg_check; /* Check Ogg files or not. */
cvar_t *ogg_playlist; /* Playlist. */
cvar_t *ogg_sequence; /* Sequence play indicator. */
cvar_t *ogg_volume; /* Music volume. */
OggVorbis_File ovFile; /* Ogg Vorbis file. */
/*
==========
OGG_Init
Initialize the Ogg Vorbis subsystem.
==========
*/
void OGG_Init(void)
{
cvar_t *cv; /* Cvar pointer. */
* Initialize the Ogg Vorbis subsystem.
*/
void OGG_Init(void) {
cvar_t *cv; /* Cvar pointer. */
if (ogg_started)
return;
@ -68,6 +68,7 @@ void OGG_Init(void)
/* Skip initialization if disabled. */
cv = Cvar_Get ("ogg_enable", "0", CVAR_ARCHIVE);
if (cv->value != 1) {
Com_Printf ("Ogg Vorbis not initializing.\n");
return;
@ -92,8 +93,10 @@ void OGG_Init(void)
/* Build list of files. */
ogg_numfiles = 0;
if (ogg_playlist->string[0] != '\0')
OGG_LoadPlaylist(ogg_playlist->string);
if (ogg_numfiles == 0)
OGG_LoadFileList();
@ -124,14 +127,9 @@ void OGG_Init(void)
}
/*
==========
OGG_Shutdown
Shutdown the Ogg Vorbis subsystem.
==========
*/
void OGG_Shutdown(void)
{
* Shutdown the Ogg Vorbis subsystem.
*/
void OGG_Shutdown(void) {
if (!ogg_started)
return;
@ -157,42 +155,34 @@ void OGG_Shutdown(void)
}
/*
==========
OGG_Reinit
Reinitialize the Ogg Vorbis subsystem.
==========
*/
void OGG_Reinit(void)
{
* Reinitialize the Ogg Vorbis subsystem.
*/
void OGG_Reinit(void) {
OGG_Shutdown();
OGG_Init();
}
/*
==========
OGG_Check
Check if the file is a valid Ogg Vorbis file.
==========
*/
qboolean OGG_Check(char *name)
{
qboolean res; /* Return value. */
byte *buffer; /* File buffer. */
int size; /* File size. */
OggVorbis_File ovf; /* Ogg Vorbis file. */
* Check if the file is a valid Ogg Vorbis file.
*/
qboolean OGG_Check(char *name) {
qboolean res; /* Return value. */
byte *buffer; /* File buffer. */
int size; /* File size. */
OggVorbis_File ovf; /* Ogg Vorbis file. */
if (ogg_check->value == 0)
return (true);
res = false;
if ((size = FS_LoadFile(name, (void**)&buffer)) > 0) {
if (ov_test(NULL, &ovf, (char *)buffer, size) == 0) {
res = true;
ov_clear(&ovf);
}
FS_FreeFile(buffer);
}
@ -200,16 +190,11 @@ qboolean OGG_Check(char *name)
}
/*
==========
OGG_Seek
Change position in the file.
==========
*/
void OGG_Seek(ogg_seek_t type, double offset)
{
double pos; /* Position in file (in seconds). */
double total; /* Length of file (in seconds). */
* Change position in the file.
*/
void OGG_Seek(ogg_seek_t type, double offset) {
double pos; /* Position in file (in seconds). */
double total; /* Length of file (in seconds). */
/* Check if the file is seekable. */
if (ov_seekable(&ovFile) == 0) {
@ -222,43 +207,46 @@ void OGG_Seek(ogg_seek_t type, double offset)
total = ov_time_total(&ovFile, -1);
switch (type) {
case ABS:
if (offset >= 0 && offset <= total) {
if (ov_time_seek(&ovFile, offset) != 0)
Com_Printf("OGG_Seek: could not seek.\n");
else
Com_Printf("%0.2f -> %0.2f of %0.2f.\n", pos, offset, total);
} else
Com_Printf("OGG_Seek: invalid offset.\n");
break;
case REL:
if (pos + offset >= 0 && pos + offset <= total) {
if (ov_time_seek(&ovFile, pos + offset) != 0)
Com_Printf("OGG_Seek: could not seek.\n");
else
Com_Printf("%0.2f -> %0.2f of %0.2f.\n", pos, pos + offset, total);
} else
Com_Printf("OGG_Seek: invalid offset.\n");
break;
case ABS:
if (offset >= 0 && offset <= total) {
if (ov_time_seek(&ovFile, offset) != 0)
Com_Printf("OGG_Seek: could not seek.\n");
else
Com_Printf("%0.2f -> %0.2f of %0.2f.\n", pos, offset, total);
} else
Com_Printf("OGG_Seek: invalid offset.\n");
break;
case REL:
if (pos + offset >= 0 && pos + offset <= total) {
if (ov_time_seek(&ovFile, pos + offset) != 0)
Com_Printf("OGG_Seek: could not seek.\n");
else
Com_Printf("%0.2f -> %0.2f of %0.2f.\n", pos, pos + offset, total);
} else
Com_Printf("OGG_Seek: invalid offset.\n");
break;
}
}
/*
==========
OGG_LoadFileList
Load list of Ogg Vorbis files in "music".
==========
*/
void OGG_LoadFileList(void)
{
char **list; /* List of .ogg files. */
int i; /* Loop counter. */
int j; /* Real position in list. */
* Load list of Ogg Vorbis files in "music".
*/
void OGG_LoadFileList(void) {
char **list; /* List of .ogg files. */
int i; /* Loop counter. */
int j; /* Real position in list. */
/* Get file list. */
list = FS_ListFiles2(va("%s/*.ogg", OGG_DIR), &ogg_numfiles, 0,
SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM);
SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM);
ogg_numfiles--;
/* Check if there are posible Ogg files. */
@ -274,6 +262,7 @@ void OGG_LoadFileList(void)
free(list[i]);
continue;
}
ogg_filelist[j++] = list[i];
}
@ -286,32 +275,28 @@ void OGG_LoadFileList(void)
}
/*
==========
OGG_LoadPlaylist
Load playlist.
==========
*/
void OGG_LoadPlaylist(char *playlist)
{
byte *buffer; /* Buffer to read the file. */
char *ptr; /* Pointer for parsing the file. */
int i; /* Loop counter. */
int size; /* Length of buffer and strings. */
* Load playlist.
*/
void OGG_LoadPlaylist(char *playlist) {
byte *buffer; /* Buffer to read the file. */
char *ptr; /* Pointer for parsing the file. */
int i; /* Loop counter. */
int size; /* Length of buffer and strings. */
/* Open playlist. */
if ((size = FS_LoadFile(va("%s/%s.lst", OGG_DIR, ogg_playlist->string),
(void **)&buffer)) < 0) {
(void **)&buffer)) < 0) {
Com_Printf("OGG_LoadPlaylist: could not open playlist: %s.\n", strerror(errno));
return;
}
/* Count the files in playlist. */
for (ptr = strsep((char **) &buffer, "\n");
ptr != NULL;
ptr = strsep(NULL, "\n")) {
ptr != NULL;
ptr = strsep(NULL, "\n")) {
if ((byte *)ptr != buffer)
ptr[-1] = '\n';
if (OGG_Check(va("%s/%s", OGG_DIR, ptr)))
ogg_numfiles++;
}
@ -320,9 +305,10 @@ void OGG_LoadPlaylist(char *playlist)
ogg_filelist = malloc(sizeof(char *) * ogg_numfiles);
i = 0;
for (ptr = strsep((char **) &buffer, "\n");
ptr != NULL;
ptr = strsep(NULL, "\n"))
ptr != NULL;
ptr = strsep(NULL, "\n"))
if (OGG_Check(va("%s/%s", OGG_DIR, ptr)))
ogg_filelist[i++] = strdup(va("%s/%s", OGG_DIR, ptr));
@ -331,45 +317,48 @@ void OGG_LoadPlaylist(char *playlist)
}
/*
==========
OGG_Open
Play Ogg Vorbis file (with absolute or relative index).
==========
*/
qboolean OGG_Open(ogg_seek_t type, int offset)
{
int size; /* File size. */
int pos; /* Absolute position. */
int res; /* Error indicator. */
* Play Ogg Vorbis file (with absolute or relative index).
*/
qboolean OGG_Open(ogg_seek_t type, int offset) {
int size; /* File size. */
int pos; /* Absolute position. */
int res; /* Error indicator. */
pos = -1;
switch (type) {
case ABS:
/* Absolute index. */
if (offset < 0 || offset >= ogg_numfiles) {
Com_Printf("OGG_Open: %d out of range.\n", offset+1);
return (false);
} else
pos = offset;
break;
case REL:
/* Simulate a loopback. */
if (ogg_curfile == -1 && offset < 0)
offset++;
while (ogg_curfile + offset < 0)
offset += ogg_numfiles;
while (ogg_curfile + offset >= ogg_numfiles)
offset -= ogg_numfiles;
pos = ogg_curfile + offset;
break;
case ABS:
/* Absolute index. */
if (offset < 0 || offset >= ogg_numfiles) {
Com_Printf("OGG_Open: %d out of range.\n", offset+1);
return (false);
} else
pos = offset;
break;
case REL:
/* Simulate a loopback. */
if (ogg_curfile == -1 && offset < 0)
offset++;
while (ogg_curfile + offset < 0)
offset += ogg_numfiles;
while (ogg_curfile + offset >= ogg_numfiles)
offset -= ogg_numfiles;
pos = ogg_curfile + offset;
break;
}
/* Check running music. */
if (ogg_status == PLAY) {
if (ogg_curfile == pos)
return (true);
else
OGG_Stop();
}
@ -396,14 +385,9 @@ qboolean OGG_Open(ogg_seek_t type, int offset)
}
/*
==========
OGG_OpenName
Play Ogg Vorbis file (with name only).
==========
*/
qboolean OGG_OpenName(char *filename)
{
* Play Ogg Vorbis file (with name only).
*/
qboolean OGG_OpenName(char *filename) {
char *name; /* File name. */
int i; /* Loop counter. */
@ -415,6 +399,7 @@ qboolean OGG_OpenName(char *filename)
if (i < ogg_numfiles)
return (OGG_Open(ABS, i));
else {
Com_Printf("OGG_OpenName: '%s' not in the list.\n", filename);
return (false);
@ -422,14 +407,9 @@ qboolean OGG_OpenName(char *filename)
}
/*
==========
OGG_Read
Play a portion of the currently opened file.
==========
*/
int OGG_Read(void)
{
* Play a portion of the currently opened file.
*/
int OGG_Read(void) {
int res; /* Number of bytes read. */
/* Read and resample. */
@ -446,23 +426,22 @@ int OGG_Read(void)
}
/*
==========
OGG_Sequence
Play files in sequence.
==========
*/
void OGG_Sequence(void)
{
* Play files in sequence.
*/
void OGG_Sequence(void) {
if (strcmp(ogg_sequence->string, "next") == 0)
OGG_Open(REL, 1);
else if (strcmp(ogg_sequence->string, "prev") == 0)
OGG_Open(REL, -1);
else if (strcmp(ogg_sequence->string, "random") == 0)
OGG_Open(ABS, rand() % ogg_numfiles);
else if (strcmp(ogg_sequence->string, "loop") == 0)
OGG_Open(REL, 0);
else if (strcmp(ogg_sequence->string, "none") != 0) {
Com_Printf("Invalid value of ogg_sequence: %s\n", ogg_sequence->string);
Cvar_Set("ogg_sequence", "none");
@ -470,14 +449,9 @@ void OGG_Sequence(void)
}
/*
==========
OGG_Stop
Stop playing the current file.
==========
*/
void OGG_Stop(void)
{
* Stop playing the current file.
*/
void OGG_Stop(void) {
if (ogg_status == STOP)
return;
@ -492,15 +466,9 @@ void OGG_Stop(void)
}
/*
==========
OGG_Stream
Stream music.
==========
*/
void OGG_Stream(void)
{
* Stream music.
*/
void OGG_Stream(void) {
if (!ogg_started)
return;
@ -509,14 +477,9 @@ void OGG_Stream(void)
}
/*
============
S_RawSamplesVol
Cinematic streaming and voice over network (with volume)
============
*/
void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data, float volume)
{
* Cinematic streaming
*/
void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data, float volume) {
int i;
int src, dst;
float scale;
@ -529,13 +492,10 @@ void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data
scale = (float)rate / dma.speed;
//Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
if (channels == 2 && width == 2)
{
if (scale == 1.0)
{ // optimized case
for (i=0 ; i<samples ; i++)
{
if (channels == 2 && width == 2) {
if (scale == 1.0) {
/* optimized case */
for (i=0 ; i<samples ; i++) {
dst = s_rawend&(MAX_RAW_SAMPLES-1);
s_rawend++;
s_rawsamples[dst].left =
@ -543,14 +503,14 @@ void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data
s_rawsamples[dst].right =
(int)(volume * LittleShort(((short *)data)[i*2+1])) << 8;
}
}
else
{
for (i=0 ; ; i++)
{
} else {
for (i=0 ; ; i++) {
src = i*scale;
if (src >= samples)
break;
dst = s_rawend&(MAX_RAW_SAMPLES-1);
s_rawend++;
s_rawsamples[dst].left =
@ -559,14 +519,14 @@ void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data
(int)(volume * LittleShort(((short *)data)[src*2+1])) << 8;
}
}
}
else if (channels == 1 && width == 2)
{
for (i=0 ; ; i++)
{
} 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 =
@ -574,14 +534,14 @@ void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data
s_rawsamples[dst].right =
(int)(volume * LittleShort(((short *)data)[src])) << 8;
}
}
else if (channels == 2 && width == 1)
{
for (i=0 ; ; i++)
{
} else if (channels == 2 && width == 1) {
for (i=0 ; ; i++) {
src = i*scale;
if (src >= samples)
break;
dst = s_rawend&(MAX_RAW_SAMPLES-1);
s_rawend++;
s_rawsamples[dst].left =
@ -589,35 +549,28 @@ void S_RawSamplesVol (int samples, int rate, int width, int channels, byte *data
s_rawsamples[dst].right =
(int)(volume * ((char *)data)[src*2+1]) << 16;
}
}
else if (channels == 1 && width == 1)
{
for (i=0 ; ; i++)
{
} else if (channels == 1 && width == 1) {
for (i=0 ; ; i++) {
src = i*scale;
if (src >= samples)
break;
dst = s_rawend&(MAX_RAW_SAMPLES-1);
s_rawend++;
s_rawsamples[dst].left =
(int)(volume * (((byte *)data)[src]-128)) << 16;
s_rawsamples[dst].right =
(int)(volume * (((byte *)data)[src]-128)) << 16;
s_rawsamples[dst].right =
(int)(volume * (((byte *)data)[src]-128)) << 16;
}
}
}
/* Console commands. */
/*
==========
OGG_ListCmd
List Ogg Vorbis files.
==========
*/
void OGG_ListCmd(void)
{
* List Ogg Vorbis files.
*/
void OGG_ListCmd(void) {
int i;
for (i = 0; i < ogg_numfiles; i++)
@ -627,68 +580,61 @@ void OGG_ListCmd(void)
}
/*
==========
OGG_ParseCmd
Parse play controls.
==========
*/
void OGG_ParseCmd(char *arg)
{
int n;
* Parse play controls.
*/
void OGG_ParseCmd(char *arg) {
int n;
cvar_t *ogg_enable;
ogg_enable = Cvar_Get ("ogg_enable", "0", CVAR_ARCHIVE);
ogg_enable = Cvar_Get ("ogg_enable", "0", CVAR_ARCHIVE);
switch (arg[0]) {
case '#':
n = atoi(arg+1) - 1;
OGG_Open(ABS, n);
break;
case '?':
OGG_Open(ABS, rand() % ogg_numfiles);
break;
case '>':
if (strlen(arg) > 1)
OGG_Open(REL, atoi(arg+1));
else
OGG_Open(REL, 1);
break;
case '<':
if (strlen(arg) > 1)
OGG_Open(REL, -atoi(arg+1));
else
OGG_Open(REL, -1);
break;
default:
if (ogg_enable->value != 0)
OGG_OpenName(arg);
break;
case '#':
n = atoi(arg+1) - 1;
OGG_Open(ABS, n);
break;
case '?':
OGG_Open(ABS, rand() % ogg_numfiles);
break;
case '>':
if (strlen(arg) > 1)
OGG_Open(REL, atoi(arg+1));
else
OGG_Open(REL, 1);
break;
case '<':
if (strlen(arg) > 1)
OGG_Open(REL, -atoi(arg+1));
else
OGG_Open(REL, -1);
break;
default:
if (ogg_enable->value != 0)
OGG_OpenName(arg);
break;
}
}
/*
==========
OGG_PauseCmd
Pause current song.
==========
*/
void OGG_PauseCmd(void)
{
* Pause current song.
*/
void OGG_PauseCmd(void) {
if (ogg_status == PLAY)
ogg_status = PAUSE;
}
/*
==========
OGG_PlayCmd
Play control.
==========
*/
void OGG_PlayCmd( void )
{
* Play control.
*/
void OGG_PlayCmd( void ) {
if (Cmd_Argc() < 2) {
Com_Printf("Usage: ogg_play {filename | #n | ? | >n | <n}\n");
@ -699,28 +645,18 @@ void OGG_PlayCmd( void )
}
/*
==========
OGG_ResumeCmd
Resume current song.
==========
*/
void OGG_ResumeCmd(void)
{
* Resume current song.
*/
void OGG_ResumeCmd(void) {
if (ogg_status == PAUSE)
ogg_status = PLAY;
}
/*
==========
OGG_SeekCmd
Change position in the file being played.
==========
*/
void OGG_SeekCmd(void)
{
* Change position in the file being played.
*/
void OGG_SeekCmd(void) {
if (ogg_status != STOP)
return;
@ -744,30 +680,28 @@ void OGG_SeekCmd(void)
}
/*
==========
OGG_StatusCmd
Display status.
==========
*/
void OGG_StatusCmd(void)
{
* Display status.
*/
void OGG_StatusCmd(void) {
switch (ogg_status) {
case PLAY:
Com_Printf("Playing file %d (%s) at %0.2f seconds.\n",
ogg_curfile+1, ogg_filelist[ogg_curfile], ov_time_tell(&ovFile));
break;
case PAUSE:
Com_Printf("Paused file %d (%s) at %0.2f seconds.\n",
ogg_curfile+1, ogg_filelist[ogg_curfile], ov_time_tell(&ovFile));
break;
case STOP:
if (ogg_curfile == -1)
Com_Printf("Stopped.\n");
else
Com_Printf("Stopped file %d (%s).\n",
ogg_curfile+1, ogg_filelist[ogg_curfile]);
break;
case PLAY:
Com_Printf("Playing file %d (%s) at %0.2f seconds.\n",
ogg_curfile+1, ogg_filelist[ogg_curfile], ov_time_tell(&ovFile));
break;
case PAUSE:
Com_Printf("Paused file %d (%s) at %0.2f seconds.\n",
ogg_curfile+1, ogg_filelist[ogg_curfile], ov_time_tell(&ovFile));
break;
case STOP:
if (ogg_curfile == -1)
Com_Printf("Stopped.\n");
else
Com_Printf("Stopped file %d (%s).\n",
ogg_curfile+1, ogg_filelist[ogg_curfile]);
break;
}
}

View file

@ -1,32 +1,31 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or(at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* ==========================================================
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* OGG Vorbis decoding
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* ==========================================================
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* The header file for the OGG/Vorbis playback
*
* =======================================================================
*/
#ifndef _SND_OGG_H_
#define _SND_OGG_H_
#define OGG_DIR "music"
#define OGG_DIR "music"
typedef enum {
PLAY,
@ -48,14 +47,13 @@ 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);
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);