mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-06-04 10:30:52 +00:00
cached wav files almost work (seems cached ogg are borked now :/)
This commit is contained in:
parent
5be73df678
commit
948c97a6a4
4 changed files with 183 additions and 44 deletions
|
@ -115,7 +115,8 @@ void SND_LocalSound (const char *s);
|
||||||
void SND_BlockSound (void);
|
void SND_BlockSound (void);
|
||||||
void SND_UnblockSound (void);
|
void SND_UnblockSound (void);
|
||||||
|
|
||||||
void SND_ResampleSfx (sfx_t *sfx, sfxbuffer_t *sc, byte *data);
|
void SND_ResampleMono (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length);
|
||||||
|
void SND_ResampleStereo (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length);
|
||||||
sfxbuffer_t *SND_GetCache (long samples, int rate, int inwidth, int channels,
|
sfxbuffer_t *SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||||
sfxblock_t *block, cache_allocator_t allocator);
|
sfxblock_t *block, cache_allocator_t allocator);
|
||||||
|
|
||||||
|
@ -130,6 +131,7 @@ void SND_CallbackLoad (void *object, cache_allocator_t allocator);
|
||||||
void SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname);
|
void SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname);
|
||||||
void SND_LoadWav (QFile *file, sfx_t *sfx, char *realname);
|
void SND_LoadWav (QFile *file, sfx_t *sfx, char *realname);
|
||||||
|
|
||||||
|
sfxbuffer_t *SND_CacheTouch (sfx_t *sfx);
|
||||||
sfxbuffer_t *SND_CacheRetain (sfx_t *sfx);
|
sfxbuffer_t *SND_CacheRetain (sfx_t *sfx);
|
||||||
void SND_CacheRelease (sfx_t *sfx);
|
void SND_CacheRelease (sfx_t *sfx);
|
||||||
sfxbuffer_t *SND_StreamRetain (sfx_t *sfx);
|
sfxbuffer_t *SND_StreamRetain (sfx_t *sfx);
|
||||||
|
|
|
@ -48,6 +48,16 @@ static __attribute__ ((unused)) const char rcsid[] =
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "snd_render.h"
|
#include "snd_render.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte left;
|
||||||
|
byte right;
|
||||||
|
} stereo8_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short left;
|
||||||
|
short right;
|
||||||
|
} stereo16_t;
|
||||||
|
|
||||||
static sfxbuffer_t *
|
static sfxbuffer_t *
|
||||||
snd_fail (sfx_t *sfx)
|
snd_fail (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
|
@ -59,6 +69,12 @@ snd_noop (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sfxbuffer_t *
|
||||||
|
SND_CacheTouch (sfx_t *sfx)
|
||||||
|
{
|
||||||
|
return Cache_Check (&((sfxblock_t *) sfx->data)->cache);
|
||||||
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t *
|
||||||
SND_CacheRetain (sfx_t *sfx)
|
SND_CacheRetain (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
|
@ -145,16 +161,12 @@ SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||||
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
|
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
|
||||||
if (!sc)
|
if (!sc)
|
||||||
return 0;
|
return 0;
|
||||||
sfx->length = samples;
|
|
||||||
sfx->speed = rate;
|
|
||||||
sfx->width = inwidth;
|
|
||||||
sfx->channels = channels;
|
|
||||||
block->bytes = size;
|
block->bytes = size;
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_ResampleSfx (sfx_t *sfx, sfxbuffer_t *sc, byte *data)
|
SND_ResampleMono (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
||||||
{
|
{
|
||||||
unsigned char *ib, *ob;
|
unsigned char *ib, *ob;
|
||||||
int fracstep, outcount, sample, samplefrac, srcsample, i;
|
int fracstep, outcount, sample, samplefrac, srcsample, i;
|
||||||
|
@ -162,6 +174,7 @@ SND_ResampleSfx (sfx_t *sfx, sfxbuffer_t *sc, byte *data)
|
||||||
short *is, *os;
|
short *is, *os;
|
||||||
int inwidth = sfx->width;
|
int inwidth = sfx->width;
|
||||||
int inrate = sfx->speed;
|
int inrate = sfx->speed;
|
||||||
|
int outwidth;
|
||||||
|
|
||||||
is = (short *) data;
|
is = (short *) data;
|
||||||
os = (short *) sc->data;
|
os = (short *) sc->data;
|
||||||
|
@ -170,30 +183,31 @@ SND_ResampleSfx (sfx_t *sfx, sfxbuffer_t *sc, byte *data)
|
||||||
|
|
||||||
stepscale = (float) inrate / shm->speed; // usually 0.5, 1, or 2
|
stepscale = (float) inrate / shm->speed; // usually 0.5, 1, or 2
|
||||||
|
|
||||||
outcount = sfx->length / stepscale;
|
outcount = length / stepscale;
|
||||||
|
|
||||||
sfx->speed = shm->speed;
|
if (snd_loadas8bit->int_val) {
|
||||||
if (snd_loadas8bit->int_val)
|
outwidth = 1;
|
||||||
sfx->width = 1;
|
sc->paint = SND_PaintChannelFrom8;
|
||||||
else
|
} else {
|
||||||
sfx->width = 2;
|
outwidth = 2;
|
||||||
sfx->channels = 1;
|
sc->paint = SND_PaintChannelFrom16;
|
||||||
|
}
|
||||||
|
|
||||||
// resample / decimate to the current source rate
|
// resample / decimate to the current source rate
|
||||||
if (stepscale == 1) {
|
if (stepscale == 1) {
|
||||||
if (inwidth == 1 && sfx->width == 1) {
|
if (inwidth == 1 && outwidth == 1) {
|
||||||
for (i = 0; i < outcount; i++) {
|
for (i = 0; i < outcount; i++) {
|
||||||
*ob++ = *ib++ - 128;
|
*ob++ = *ib++ - 128;
|
||||||
}
|
}
|
||||||
} else if (inwidth == 1 && sfx->width == 2) {
|
} else if (inwidth == 1 && outwidth == 2) {
|
||||||
for (i = 0; i < outcount; i++) {
|
for (i = 0; i < outcount; i++) {
|
||||||
*os++ = (*ib++ - 128) << 8;
|
*os++ = (*ib++ - 128) << 8;
|
||||||
}
|
}
|
||||||
} else if (inwidth == 2 && sfx->width == 1) {
|
} else if (inwidth == 2 && outwidth == 1) {
|
||||||
for (i = 0; i < outcount; i++) {
|
for (i = 0; i < outcount; i++) {
|
||||||
*ob++ = LittleShort (*is++) >> 8;
|
*ob++ = LittleShort (*is++) >> 8;
|
||||||
}
|
}
|
||||||
} else if (inwidth == 2 && sfx->width == 2) {
|
} else if (inwidth == 2 && outwidth == 2) {
|
||||||
for (i = 0; i < outcount; i++) {
|
for (i = 0; i < outcount; i++) {
|
||||||
*os++ = LittleShort (*is++);
|
*os++ = LittleShort (*is++);
|
||||||
}
|
}
|
||||||
|
@ -204,29 +218,29 @@ SND_ResampleSfx (sfx_t *sfx, sfxbuffer_t *sc, byte *data)
|
||||||
int j;
|
int j;
|
||||||
int points = 1 / stepscale;
|
int points = 1 / stepscale;
|
||||||
|
|
||||||
for (i = 0; i < sfx->length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
int s1, s2;
|
int s1, s2;
|
||||||
|
|
||||||
if (inwidth == 2) {
|
if (inwidth == 2) {
|
||||||
s2 = s1 = LittleShort (is[0]);
|
s2 = s1 = LittleShort (is[0]);
|
||||||
if (i < sfx->length - 1)
|
if (i < length - 1)
|
||||||
s2 = LittleShort (is[1]);
|
s2 = LittleShort (is[1]);
|
||||||
is++;
|
is++;
|
||||||
} else {
|
} else {
|
||||||
s2 = s1 = (ib[0] - 128) << 8;
|
s2 = s1 = (ib[0] - 128) << 8;
|
||||||
if (i < sfx->length - 1)
|
if (i < length - 1)
|
||||||
s2 = (ib[1] - 128) << 8;
|
s2 = (ib[1] - 128) << 8;
|
||||||
ib++;
|
ib++;
|
||||||
}
|
}
|
||||||
for (j = 0; j < points; j++) {
|
for (j = 0; j < points; j++) {
|
||||||
sample = s1 + (s2 - s1) * ((float) j) / points;
|
sample = s1 + (s2 - s1) * ((float) j) / points;
|
||||||
if (sfx->width == 2) {
|
if (outwidth == 2) {
|
||||||
os[j] = sample;
|
os[j] = sample;
|
||||||
} else {
|
} else {
|
||||||
ob[j] = sample >> 8;
|
ob[j] = sample >> 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sfx->width == 2) {
|
if (outwidth == 2) {
|
||||||
os += points;
|
os += points;
|
||||||
} else {
|
} else {
|
||||||
ob += points;
|
ob += points;
|
||||||
|
@ -239,19 +253,134 @@ SND_ResampleSfx (sfx_t *sfx, sfxbuffer_t *sc, byte *data)
|
||||||
srcsample = samplefrac >> 8;
|
srcsample = samplefrac >> 8;
|
||||||
samplefrac += fracstep;
|
samplefrac += fracstep;
|
||||||
if (inwidth == 2)
|
if (inwidth == 2)
|
||||||
sample = LittleShort (((short *) data)[srcsample]);
|
sample = LittleShort (is[srcsample]);
|
||||||
else
|
else
|
||||||
sample =
|
sample = (ib[srcsample] - 128) << 8;
|
||||||
(int) ((unsigned char) (data[srcsample]) - 128) << 8;
|
if (outwidth == 2)
|
||||||
if (sfx->width == 2)
|
os[i] = sample;
|
||||||
((short *) sc->data)[i] = sample;
|
|
||||||
else
|
else
|
||||||
((signed char *) sc->data)[i] = sample >> 8;
|
ob[i] = sample >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SND_ResampleStereo (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
||||||
|
{
|
||||||
|
int fracstep, outcount, sl, sr, samplefrac, srcsample, i;
|
||||||
|
float stepscale;
|
||||||
|
stereo8_t *ib, *ob;
|
||||||
|
stereo16_t *is, *os;
|
||||||
|
int inwidth = sfx->width;
|
||||||
|
int inrate = sfx->speed;
|
||||||
|
int outwidth;
|
||||||
|
|
||||||
|
is = (stereo16_t *) data;
|
||||||
|
os = (stereo16_t *) sc->data;
|
||||||
|
ib = (stereo8_t *) data;
|
||||||
|
ob = (stereo8_t *) sc->data;
|
||||||
|
|
||||||
|
stepscale = (float) inrate / shm->speed; // usually 0.5, 1, or 2
|
||||||
|
|
||||||
|
outcount = length / stepscale;
|
||||||
|
|
||||||
|
if (snd_loadas8bit->int_val) {
|
||||||
|
outwidth = 1;
|
||||||
|
sc->paint = SND_PaintChannelStereo8;
|
||||||
|
} else {
|
||||||
|
outwidth = 2;
|
||||||
|
sc->paint = SND_PaintChannelStereo16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resample / decimate to the current source rate
|
||||||
|
if (stepscale == 1) {
|
||||||
|
if (inwidth == 1 && outwidth == 1) {
|
||||||
|
for (i = 0; i < outcount; i++, ob++, ib++) {
|
||||||
|
ob->left = ib->left - 128;
|
||||||
|
ob->right = ib->right - 128;
|
||||||
|
}
|
||||||
|
} else if (inwidth == 1 && outwidth == 2) {
|
||||||
|
for (i = 0; i < outcount; i++, os++, ib++) {
|
||||||
|
os->left = (ib->left - 128) << 8;
|
||||||
|
os->right = (ib->right - 128) << 8;
|
||||||
|
}
|
||||||
|
} else if (inwidth == 2 && outwidth == 1) {
|
||||||
|
for (i = 0; i < outcount; i++, ob++, ib++) {
|
||||||
|
ob->left = LittleShort (is->left) >> 8;
|
||||||
|
ob->right = LittleShort (is->right) >> 8;
|
||||||
|
}
|
||||||
|
} else if (inwidth == 2 && outwidth == 2) {
|
||||||
|
for (i = 0; i < outcount; i++, os++, is++) {
|
||||||
|
os->left = LittleShort (is->left);
|
||||||
|
os->right = LittleShort (is->right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// general case
|
||||||
|
if (snd_interp->int_val && stepscale < 1) {
|
||||||
|
int j;
|
||||||
|
int points = 1 / stepscale;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
int sl1, sl2;
|
||||||
|
int sr1, sr2;
|
||||||
|
|
||||||
|
if (inwidth == 2) {
|
||||||
|
sl2 = sl1 = LittleShort (is[0].left);
|
||||||
|
sr2 = sr1 = LittleShort (is[0].right);
|
||||||
|
if (i < length - 1) {
|
||||||
|
sl2 = LittleShort (is[1].left);
|
||||||
|
sr2 = LittleShort (is[1].right);
|
||||||
|
}
|
||||||
|
is++;
|
||||||
|
} else {
|
||||||
|
sl2 = sl1 = (ib[0].left - 128) << 8;
|
||||||
|
sr2 = sr1 = (ib[0].right - 128) << 8;
|
||||||
|
if (i < length - 1) {
|
||||||
|
sl2 = (ib[1].left - 128) << 8;
|
||||||
|
sr2 = (ib[1].right - 128) << 8;
|
||||||
|
}
|
||||||
|
ib++;
|
||||||
|
}
|
||||||
|
for (j = 0; j < points; j++) {
|
||||||
|
sl = sl1 + (sl2 - sl1) * ((float) j) / points;
|
||||||
|
sr = sr1 + (sr2 - sr1) * ((float) j) / points;
|
||||||
|
if (outwidth == 2) {
|
||||||
|
os[j].left = sl;
|
||||||
|
os[j].right = sr;
|
||||||
|
} else {
|
||||||
|
ob[j].left = sl >> 8;
|
||||||
|
ob[j].right = sr >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outwidth == 2) {
|
||||||
|
os += points;
|
||||||
|
} else {
|
||||||
|
ob += points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
samplefrac = 0;
|
||||||
|
fracstep = stepscale * 256;
|
||||||
|
for (i = 0; i < outcount; i++) {
|
||||||
|
srcsample = samplefrac >> 8;
|
||||||
|
samplefrac += fracstep;
|
||||||
|
if (inwidth == 2) {
|
||||||
|
sl = LittleShort (is[srcsample].left);
|
||||||
|
sr = LittleShort (is[srcsample].right);
|
||||||
|
} else {
|
||||||
|
sl = (ib[srcsample].left - 128) << 8;
|
||||||
|
sr = (ib[srcsample].right - 128) << 8;
|
||||||
|
}
|
||||||
|
if (outwidth == 2) {
|
||||||
|
os[i].left = sl;
|
||||||
|
os[i].right = sr;
|
||||||
|
} else {
|
||||||
|
ob[i].left = sl >> 8;
|
||||||
|
ob[i].right = sr >> 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sfx->length = outcount;
|
|
||||||
if (sfx->loopstart != -1)
|
|
||||||
sfx->loopstart = sfx->loopstart / stepscale;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,16 +149,16 @@ load_ogg (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
|
||||||
sfxbuffer_t *sc = 0;
|
sfxbuffer_t *sc = 0;
|
||||||
sfx_t *sfx = block->sfx;
|
sfx_t *sfx = block->sfx;
|
||||||
int channels;
|
int channels;
|
||||||
void (*paint) (channel_t *ch, sfxbuffer_t *buffer, int count);
|
void (*resample)(sfx_t *, sfxbuffer_t *, byte *, int);
|
||||||
|
|
||||||
get_info (vf, sfx);
|
get_info (vf, sfx);
|
||||||
|
|
||||||
switch (sfx->channels) {
|
switch (sfx->channels) {
|
||||||
case 1:
|
case 1:
|
||||||
paint = SND_PaintChannelFrom16;
|
resample = SND_ResampleMono;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
paint = SND_PaintChannelStereo16;
|
resample = SND_ResampleStereo;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Sys_Printf ("%s: unsupported channel count: %d\n",
|
Sys_Printf ("%s: unsupported channel count: %d\n",
|
||||||
|
@ -178,8 +178,7 @@ load_ogg (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
|
||||||
goto bail;
|
goto bail;
|
||||||
if (read_ogg (vf, data, size) < 0)
|
if (read_ogg (vf, data, size) < 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
SND_ResampleSfx (sfx, sc, data);
|
resample (sfx, sc, data, sfx->length);
|
||||||
sc->paint = paint;
|
|
||||||
sc->length = sc->head = sfx->length;
|
sc->length = sc->head = sfx->length;
|
||||||
bail:
|
bail:
|
||||||
if (data)
|
if (data)
|
||||||
|
@ -266,13 +265,14 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname)
|
||||||
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
||||||
ov_clear (&vf);
|
ov_clear (&vf);
|
||||||
sfx->data = block;
|
sfx->data = block;
|
||||||
|
sfx->touch = SND_CacheTouch;
|
||||||
sfx->retain = SND_CacheRetain;
|
sfx->retain = SND_CacheRetain;
|
||||||
sfx->release = SND_CacheRelease;
|
sfx->release = SND_CacheRelease;
|
||||||
block->sfx = sfx;
|
block->sfx = sfx;
|
||||||
block->file = realname;
|
block->file = realname;
|
||||||
Cache_Add (&block->cache, block, ogg_callback_load);
|
Cache_Add (&block->cache, block, ogg_callback_load);
|
||||||
} else {
|
} else {
|
||||||
sfx->retain = SND_StreamRetain;
|
sfx->touch = sfx->retain = SND_StreamRetain;
|
||||||
sfx->release = SND_StreamRelease;
|
sfx->release = SND_StreamRelease;
|
||||||
free (realname);
|
free (realname);
|
||||||
stream_ogg (sfx, &vf);
|
stream_ogg (sfx, &vf);
|
||||||
|
|
|
@ -52,6 +52,7 @@ typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
int data_start;
|
int data_start;
|
||||||
int data_length;
|
int data_length;
|
||||||
|
int length;
|
||||||
} wavfile_t;
|
} wavfile_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -64,7 +65,7 @@ wav_callback_load (void *object, cache_allocator_t allocator)
|
||||||
byte *data;
|
byte *data;
|
||||||
sfxbuffer_t *buffer;
|
sfxbuffer_t *buffer;
|
||||||
|
|
||||||
QFS_FOpenFile (block->file, &file);
|
QFS_FOpenFile (wavfile->name, &file);
|
||||||
if (!file)
|
if (!file)
|
||||||
return; //FIXME Sys_Error?
|
return; //FIXME Sys_Error?
|
||||||
|
|
||||||
|
@ -73,9 +74,13 @@ wav_callback_load (void *object, cache_allocator_t allocator)
|
||||||
Qread (file, data, wavfile->data_length);
|
Qread (file, data, wavfile->data_length);
|
||||||
Qclose (file);
|
Qclose (file);
|
||||||
|
|
||||||
buffer = SND_GetCache (sfx->length, sfx->speed, sfx->width, sfx->channels,
|
buffer = SND_GetCache (wavfile->length, sfx->speed, sfx->width,
|
||||||
block, allocator);
|
sfx->channels, block, allocator);
|
||||||
SND_ResampleSfx (sfx, buffer, data);
|
if (sfx->channels == 2)
|
||||||
|
SND_ResampleStereo (sfx, buffer, data, wavfile->length);
|
||||||
|
else
|
||||||
|
SND_ResampleMono (sfx, buffer, data, wavfile->length);
|
||||||
|
buffer->length = buffer->head = sfx->length;
|
||||||
free (data);
|
free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,17 +176,20 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
||||||
wavfile->name = realname;
|
wavfile->name = realname;
|
||||||
wavfile->data_start = *(int *)data->data;
|
wavfile->data_start = *(int *)data->data;
|
||||||
wavfile->data_length = data->ck.len;
|
wavfile->data_length = data->ck.len;
|
||||||
|
wavfile->length = sfx->length;
|
||||||
|
|
||||||
if (sfx->length < 3 * shm->speed) {
|
if (sfx->length < 8 * shm->speed) {
|
||||||
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
||||||
sfx->data = block;
|
sfx->data = block;
|
||||||
|
sfx->touch = SND_CacheTouch;
|
||||||
sfx->retain = SND_CacheRetain;
|
sfx->retain = SND_CacheRetain;
|
||||||
sfx->release = SND_CacheRelease;
|
sfx->release = SND_CacheRelease;
|
||||||
|
sfx->data = block;
|
||||||
block->sfx = sfx;
|
block->sfx = sfx;
|
||||||
block->file = wavfile;
|
block->file = wavfile;
|
||||||
Cache_Add (&block->cache, block, wav_callback_load);
|
Cache_Add (&block->cache, block, wav_callback_load);
|
||||||
} else {
|
} else {
|
||||||
sfx->retain = SND_StreamRetain;
|
sfx->touch = sfx->retain = SND_StreamRetain;
|
||||||
sfx->release = SND_StreamRelease;
|
sfx->release = SND_StreamRelease;
|
||||||
free (realname);
|
free (realname);
|
||||||
stream_wav (sfx, wavfile);
|
stream_wav (sfx, wavfile);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue