mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 13:10:34 +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 sfxbuffer_s sfxbuffer_t;
|
||||||
typedef struct sfxblock_s sfxblock_t;
|
typedef struct sfxblock_s sfxblock_t;
|
||||||
typedef struct sfxstream_s sfxstream_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.
|
/** Represent a sound sample in the mixer.
|
||||||
*/
|
*/
|
||||||
|
@ -99,15 +107,7 @@ struct sfxbuffer_s {
|
||||||
unsigned length; //!< length of buffer in frames
|
unsigned length; //!< length of buffer in frames
|
||||||
unsigned pos; //!< position of tail within full stream
|
unsigned pos; //!< position of tail within full stream
|
||||||
unsigned channels; //!< number of channels per frame
|
unsigned channels; //!< number of channels per frame
|
||||||
/** paint samples into the mix buffer
|
sfxpaint_t *paint; //!< channel count specific paint function
|
||||||
\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);
|
|
||||||
/** Advance the position with the stream, updating the ring buffer as
|
/** Advance the position with the stream, updating the ring buffer as
|
||||||
necessary. Null for chached sounds.
|
necessary. Null for chached sounds.
|
||||||
\param buffer "this"
|
\param buffer "this"
|
||||||
|
|
|
@ -453,7 +453,7 @@ SND_LoadFLAC (QFile *file, sfx_t *sfx, char *realname)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
info = flac_get_info (ff);
|
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");
|
Sys_Printf ("unsupported number of channels");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "snd_render.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
|
// note: must be >= 255 due to the channel
|
||||||
// volumes being 0-255.
|
// 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
|
static void
|
||||||
snd_paint_mono (int offs, channel_t *ch, float *sfx, unsigned count)
|
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
|
static void
|
||||||
snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count)
|
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;
|
pair = snd_paintbuffer + offs;
|
||||||
while (count-- > 0) {
|
while (count-- > 0) {
|
||||||
pair->left += *samp++ * leftvol;
|
snd_mix_pair (pair, &samp, leftvol, rightvol);
|
||||||
pair->right += *samp++ * 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++;
|
pair++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,9 +461,20 @@ snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count)
|
||||||
void
|
void
|
||||||
SND_SetPaint (sfxbuffer_t *sc)
|
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);
|
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||||
if (info->channels == 2)
|
if (info->channels < 0 || info->channels > 8)
|
||||||
sc->paint = snd_paint_stereo;
|
Sys_Error ("illegal channel count %d", info->channels);
|
||||||
else
|
sc->paint = painters[info->channels];
|
||||||
sc->paint = snd_paint_mono;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,7 +297,7 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
info = vorbis_get_info (&vf);
|
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");
|
Sys_Printf ("unsupported number of channels");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,7 @@ wav_get_info (QFile *file)
|
||||||
Sys_Printf ("not Microsfot PCM\n");
|
Sys_Printf ("not Microsfot PCM\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (dfmt->channels < 1 || dfmt->channels > 2) {
|
if (dfmt->channels < 1 || dfmt->channels > 8) {
|
||||||
Sys_Printf ("unsupported channel count\n");
|
Sys_Printf ("unsupported channel count\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue