mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-19 07:20:50 +00:00
add support for up to 8 channels in sound effect files
The sounds are down-mixed to 2 channels (qf does not (yet) support more than 2 channel output), but this allows pretty much anything to be used for a source of music. Only 5.1 (6 channel), stereo and mono have been tested, but the others should work (any issues would be mis-interpretation/implementation of the channel layout).
This commit is contained in:
parent
96f1573136
commit
ce5658416d
5 changed files with 200 additions and 19 deletions
|
@ -50,6 +50,14 @@ typedef struct channel_s channel_t;
|
|||
typedef struct sfxbuffer_s sfxbuffer_t;
|
||||
typedef struct sfxblock_s sfxblock_t;
|
||||
typedef struct sfxstream_s sfxstream_t;
|
||||
/** paint samples into the mix buffer
|
||||
\param offset offset into the mix buffer at which to start mixing
|
||||
the channel
|
||||
\param ch sound channel
|
||||
\param buffer sound data
|
||||
\param count number of frames to paint
|
||||
*/
|
||||
typedef void sfxpaint_t (int, channel_t *, float *, unsigned);
|
||||
|
||||
/** Represent a sound sample in the mixer.
|
||||
*/
|
||||
|
@ -99,15 +107,7 @@ struct sfxbuffer_s {
|
|||
unsigned length; //!< length of buffer in frames
|
||||
unsigned pos; //!< position of tail within full stream
|
||||
unsigned channels; //!< number of channels per frame
|
||||
/** paint samples into the mix buffer
|
||||
\param offset offset into the mix buffer at which to start mixing
|
||||
the channel
|
||||
\param ch sound channel
|
||||
\param buffer sound data
|
||||
\param count number of frames to paint
|
||||
*/
|
||||
void (*paint) (int offset, channel_t *ch, float *buffer,
|
||||
unsigned count);
|
||||
sfxpaint_t *paint; //!< channel count specific paint function
|
||||
/** Advance the position with the stream, updating the ring buffer as
|
||||
necessary. Null for chached sounds.
|
||||
\param buffer "this"
|
||||
|
|
|
@ -453,7 +453,7 @@ SND_LoadFLAC (QFile *file, sfx_t *sfx, char *realname)
|
|||
return -1;
|
||||
}
|
||||
info = flac_get_info (ff);
|
||||
if (info.channels < 1 || info.channels > 2) {
|
||||
if (info.channels < 1 || info.channels > 8) {
|
||||
Sys_Printf ("unsupported number of channels");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "compat.h"
|
||||
#include "snd_render.h"
|
||||
|
||||
#define VOLSCALE 1024.0 // so mixing is less likely to overflow
|
||||
#define VOLSCALE 512.0 // so mixing is less likely to overflow
|
||||
// note: must be >= 255 due to the channel
|
||||
// volumes being 0-255.
|
||||
|
||||
|
@ -179,6 +179,45 @@ SND_PaintChannels (unsigned endtime)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
snd_mix_single (portable_samplepair_t *pair, float **samp,
|
||||
float lvol, float rvol)
|
||||
{
|
||||
float single = *(*samp)++;
|
||||
|
||||
pair->left += single * lvol;
|
||||
pair->right += single * rvol;
|
||||
}
|
||||
|
||||
static inline void
|
||||
snd_mix_pair (portable_samplepair_t *pair, float **samp,
|
||||
float lvol, float rvol)
|
||||
{
|
||||
float left = *(*samp)++;
|
||||
float right = *(*samp)++;
|
||||
|
||||
pair->left += left * lvol;
|
||||
pair->right += right * rvol;
|
||||
}
|
||||
|
||||
static inline void
|
||||
snd_mix_tripple (portable_samplepair_t *pair, float **samp,
|
||||
float lvol, float rvol)
|
||||
{
|
||||
float left = *(*samp)++;
|
||||
float center = *(*samp)++;
|
||||
float right = *(*samp)++;
|
||||
|
||||
pair->left += left * lvol;
|
||||
pair->left += center * lvol;
|
||||
pair->right += center * rvol;
|
||||
pair->right += right * rvol;
|
||||
}
|
||||
|
||||
/* mono
|
||||
center
|
||||
Spacializes the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_mono (int offs, channel_t *ch, float *sfx, unsigned count)
|
||||
{
|
||||
|
@ -273,6 +312,10 @@ snd_paint_mono (int offs, channel_t *ch, float *sfx, unsigned count)
|
|||
}
|
||||
}
|
||||
|
||||
/* stereo
|
||||
left, right
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
|
@ -282,8 +325,135 @@ snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count)
|
|||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
pair->left += *samp++ * leftvol;
|
||||
pair->right += *samp++ * rightvol;
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 1d surround
|
||||
left, center, right
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_3 (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
portable_samplepair_t *pair;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
snd_mix_tripple (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
/* quadraphonic surround
|
||||
front (left, right),
|
||||
rear (left, right)
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_4 (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
portable_samplepair_t *pair;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
/* five-channel surround
|
||||
front (left, center, right),
|
||||
rear (left, right)
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_5 (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
portable_samplepair_t *pair;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
snd_mix_tripple (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 5.1 surround
|
||||
front (left, center, right),
|
||||
rear (left, right),
|
||||
lfe
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_6 (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
portable_samplepair_t *pair;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
snd_mix_tripple (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_single (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 6.1 surround
|
||||
front (left, center, right),
|
||||
side (left, right),
|
||||
rear (center),
|
||||
lfe
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_7 (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
portable_samplepair_t *pair;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
snd_mix_tripple (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_single (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_single (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 7.1 surround
|
||||
front (left, center, right),
|
||||
side (left, right),
|
||||
rear (left, right),
|
||||
lfe
|
||||
Does not spacialize the sound.
|
||||
*/
|
||||
static void
|
||||
snd_paint_8 (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
portable_samplepair_t *pair;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
snd_mix_tripple (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||
snd_mix_single (pair, &samp, leftvol, rightvol);
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
@ -291,9 +461,20 @@ snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count)
|
|||
void
|
||||
SND_SetPaint (sfxbuffer_t *sc)
|
||||
{
|
||||
static sfxpaint_t *painters[] = {
|
||||
0,
|
||||
snd_paint_mono,
|
||||
snd_paint_stereo,
|
||||
snd_paint_3,
|
||||
snd_paint_4,
|
||||
snd_paint_5,
|
||||
snd_paint_6,
|
||||
snd_paint_7,
|
||||
snd_paint_8,
|
||||
};
|
||||
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
if (info->channels == 2)
|
||||
sc->paint = snd_paint_stereo;
|
||||
else
|
||||
sc->paint = snd_paint_mono;
|
||||
if (info->channels < 0 || info->channels > 8)
|
||||
Sys_Error ("illegal channel count %d", info->channels);
|
||||
sc->paint = painters[info->channels];
|
||||
}
|
||||
|
|
|
@ -297,7 +297,7 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname)
|
|||
return -1;
|
||||
}
|
||||
info = vorbis_get_info (&vf);
|
||||
if (info.channels < 1 || info.channels > 2) {
|
||||
if (info.channels < 1 || info.channels > 8) {
|
||||
Sys_Printf ("unsupported number of channels");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ wav_get_info (QFile *file)
|
|||
Sys_Printf ("not Microsfot PCM\n");
|
||||
goto bail;
|
||||
}
|
||||
if (dfmt->channels < 1 || dfmt->channels > 2) {
|
||||
if (dfmt->channels < 1 || dfmt->channels > 8) {
|
||||
Sys_Printf ("unsupported channel count\n");
|
||||
goto bail;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue