mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 05:00:35 +00:00
[audio] Rework alsa to use a pull model
This brings the alsa driver in line with the jack render (progress towards #16), but breaks most of the other drivers (for now: one step at a time). The idea is that once the pull model is working for at least one other target, the jack renderer can become just another target like it should have been in the first place (but I needed to get the pull model working first, then forgot about it). Correct state checking is not done yet, but testsound does produce what seems to be fairly good sound when it starts up correctly (part of the state checking (or lack thereof), I imagine).
This commit is contained in:
parent
c9319966ce
commit
fc907e232f
13 changed files with 506 additions and 331 deletions
|
@ -30,23 +30,15 @@
|
|||
#include <QF/plugin.h>
|
||||
#include <QF/qtypes.h>
|
||||
|
||||
/*
|
||||
All sound plugins must export these functions
|
||||
*/
|
||||
typedef volatile struct dma_s *(*P_S_O_Init) (void);
|
||||
typedef void (*P_S_O_Shutdown) (void);
|
||||
typedef int (*P_S_O_GetDMAPos) (void);
|
||||
typedef void (*P_S_O_Submit) (void);
|
||||
typedef void (*P_S_O_BlockSound) (void);
|
||||
typedef void (*P_S_O_UnblockSound) (void);
|
||||
struct snd_s;
|
||||
|
||||
typedef struct snd_output_funcs_s {
|
||||
P_S_O_Init pS_O_Init;
|
||||
P_S_O_Shutdown pS_O_Shutdown;
|
||||
P_S_O_GetDMAPos pS_O_GetDMAPos;
|
||||
P_S_O_Submit pS_O_Submit;
|
||||
P_S_O_BlockSound pS_O_BlockSound;
|
||||
P_S_O_UnblockSound pS_O_UnblockSound;
|
||||
int (*init) (struct snd_s *snd);
|
||||
void (*shutdown) (struct snd_s *snd);
|
||||
int (*get_dma_pos) (struct snd_s *snd);
|
||||
void (*submit) (struct snd_s *snd);
|
||||
void (*block_sound) (struct snd_s *snd);
|
||||
void (*unblock_sound) (struct snd_s *snd);
|
||||
} snd_output_funcs_t;
|
||||
|
||||
typedef struct snd_output_data_s {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
typedef struct sfx_s sfx_t;
|
||||
struct sfx_s
|
||||
{
|
||||
struct snd_s *snd; //!< ownding snd_t instance
|
||||
const char *name;
|
||||
sfx_t *owner;
|
||||
|
||||
|
|
|
@ -67,6 +67,11 @@ QF_ALSA_NEED (int, snd_pcm_sw_params_set_stop_threshold, (snd_pcm_t *pcm, snd_pc
|
|||
QF_ALSA_NEED (size_t, snd_pcm_sw_params_sizeof, (void))
|
||||
QF_ALSA_NEED (const char *, snd_strerror, (int errnum))
|
||||
|
||||
QF_ALSA_NEED (int, snd_async_add_pcm_handler, (snd_async_handler_t **handler, snd_pcm_t *pcm, snd_async_callback_t callback, void *private_data))
|
||||
QF_ALSA_NEED (snd_pcm_t *, snd_async_handler_get_pcm, (snd_async_handler_t *handler))
|
||||
QF_ALSA_NEED (void *, snd_async_handler_get_callback_private, (snd_async_handler_t *handler))
|
||||
QF_ALSA_NEED (int, snd_async_del_handler, (snd_async_handler_t *handler))
|
||||
|
||||
#ifdef UNDEF_QF_ALSA_NEED
|
||||
#undef QF_ALSA_NEED
|
||||
#undef UNDEF_QF_ALSA_NEED
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "QF/zone.h"
|
||||
|
||||
typedef struct portable_samplepair_s portable_samplepair_t;
|
||||
typedef struct dma_s dma_t;
|
||||
typedef struct snd_s snd_t;
|
||||
typedef struct wavinfo_s wavinfo_t;
|
||||
typedef struct channel_s channel_t;
|
||||
typedef struct sfxbuffer_s sfxbuffer_t;
|
||||
|
@ -70,7 +70,7 @@ struct portable_samplepair_s {
|
|||
|
||||
/** communication structure between output drivers and renderer
|
||||
*/
|
||||
struct dma_s {
|
||||
struct snd_s {
|
||||
int speed; //!< sample rate
|
||||
int samplebits; //!< bits per sample
|
||||
int channels; //!< number of output channels
|
||||
|
@ -84,7 +84,8 @@ struct dma_s {
|
|||
\param count The number of sample to transfer.
|
||||
\param volume The gain for the samples.
|
||||
*/
|
||||
void (*xfer) (portable_samplepair_t *paintbuffer, int count,
|
||||
void (*xfer) (struct snd_s *snd,
|
||||
portable_samplepair_t *paintbuffer, int count,
|
||||
float volume);
|
||||
/** Optional data for the xfer function.
|
||||
*/
|
||||
|
@ -229,8 +230,6 @@ extern struct cvar_s *snd_volume;
|
|||
extern struct cvar_s *snd_interp;
|
||||
extern struct cvar_s *snd_stereo_phase_separation;
|
||||
|
||||
extern volatile dma_t *snd_shm;
|
||||
|
||||
extern snd_render_data_t snd_render_data;
|
||||
#define PAINTBUFFER_SIZE 512
|
||||
extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2];
|
||||
|
@ -279,16 +278,16 @@ void SND_SFX_StreamClose (sfx_t *sfx);
|
|||
/** Pre-load a sound into the cache.
|
||||
\param sample name of sound to precache
|
||||
*/
|
||||
sfx_t *SND_PrecacheSound (const char *sample);
|
||||
sfx_t *SND_PrecacheSound (snd_t *snd, const char *sample);
|
||||
|
||||
/** Pre-load a sound.
|
||||
\param name name of sound to load
|
||||
*/
|
||||
sfx_t *SND_LoadSound (const char *name);
|
||||
sfx_t *SND_LoadSound (snd_t *snd, const char *name);
|
||||
|
||||
/** Initialize the sfx sub-subsystem
|
||||
*/
|
||||
void SND_SFX_Init (void);
|
||||
void SND_SFX_Init (snd_t *snd);
|
||||
|
||||
///@}
|
||||
|
||||
|
@ -312,29 +311,29 @@ extern int snd_total_channels; //!< number of active channels
|
|||
|
||||
/** Allocate a sound channel that can be used for playing sounds.
|
||||
*/
|
||||
struct channel_s *SND_AllocChannel (void);
|
||||
struct channel_s *SND_AllocChannel (snd_t *snd);
|
||||
|
||||
/** Stop a channel from playing.
|
||||
\param chan the channel to stop
|
||||
*/
|
||||
void SND_ChannelStop (channel_t *chan);
|
||||
void SND_ChannelStop (snd_t *snd, channel_t *chan);
|
||||
|
||||
/** Scan channels looking for stopped channels.
|
||||
\param wait if true, wait for the channels to be done. if false, force the
|
||||
channels to be done. true is for threaded, false for
|
||||
non-threaded.
|
||||
*/
|
||||
void SND_ScanChannels (int wait);
|
||||
void SND_ScanChannels (snd_t *snd, int wait);
|
||||
|
||||
/** Disable ambient sounds.
|
||||
\todo not used, remove?
|
||||
*/
|
||||
void SND_AmbientOff (void);
|
||||
void SND_AmbientOff (snd_t *snd);
|
||||
|
||||
/** Enable ambient sounds.
|
||||
\todo not used, remove?
|
||||
*/
|
||||
void SND_AmbientOn (void);
|
||||
void SND_AmbientOn (snd_t *snd);
|
||||
|
||||
/** Update the sound engine with the client's position and orientation and
|
||||
render some sound.
|
||||
|
@ -345,17 +344,17 @@ void SND_AmbientOn (void);
|
|||
\param ambient_sound_level Pointer to 4 bytes indicating the levels at
|
||||
which to play the ambient sounds.
|
||||
*/
|
||||
void SND_SetListener (const vec3_t origin, const vec3_t v_forward,
|
||||
void SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t v_forward,
|
||||
const vec3_t v_right, const vec3_t v_up,
|
||||
const byte *ambient_sound_level);
|
||||
|
||||
/** Stop all sounds from playing.
|
||||
*/
|
||||
void SND_StopAllSounds(void);
|
||||
void SND_StopAllSounds (snd_t *snd);
|
||||
|
||||
/** Initialize the channels sub-subsystem
|
||||
*/
|
||||
void SND_Channels_Init (void);
|
||||
void SND_Channels_Init (snd_t *snd);
|
||||
|
||||
/** Start a sound playing.
|
||||
\param entnum index of entity the sound is associated with.
|
||||
|
@ -370,8 +369,8 @@ void SND_Channels_Init (void);
|
|||
\param fvol absolute volume of the sound
|
||||
\param attenuation rate of volume dropoff vs distance
|
||||
*/
|
||||
void SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||
float fvol, float attenuation);
|
||||
void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
||||
const vec3_t origin, float fvol, float attenuation);
|
||||
|
||||
/** Create a sound generated by the world.
|
||||
\param sfx sound to play
|
||||
|
@ -379,18 +378,18 @@ void SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin
|
|||
\param vol absolute volume of the sound
|
||||
\param attenuation rate of volume dropoff vs distance
|
||||
*/
|
||||
void SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||
float attenuation);
|
||||
void SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol,
|
||||
float attenuation);
|
||||
/** Stop an entity's sound.
|
||||
\param entnum index of entity the sound is associated with.
|
||||
\param entchannel channel to silence
|
||||
*/
|
||||
void SND_StopSound (int entnum, int entchannel);
|
||||
void SND_StopSound (snd_t *snd, int entnum, int entchannel);
|
||||
|
||||
/** Start a sound local to the client view.
|
||||
\param s name of sound to play
|
||||
*/
|
||||
void SND_LocalSound (const char *s);
|
||||
void SND_LocalSound (snd_t *snd, const char *s);
|
||||
///@}
|
||||
|
||||
|
||||
|
@ -405,11 +404,11 @@ extern unsigned snd_paintedtime;
|
|||
/** Mix all active channels into the output buffer.
|
||||
\param endtime sample time until when to mix
|
||||
*/
|
||||
void SND_PaintChannels(unsigned int endtime);
|
||||
void SND_PaintChannels(snd_t *snd, unsigned int endtime);
|
||||
|
||||
/** Initialize the scale table for painting of 8 bit samples.
|
||||
*/
|
||||
void SND_InitScaletable (void);
|
||||
void SND_InitScaletable (snd_t *snd);
|
||||
|
||||
/** Set the paint function of the sfxbuffer
|
||||
\param sc sfxbuffer to set.
|
||||
|
@ -447,8 +446,8 @@ void SND_Resample (sfxbuffer_t *sc, float *data, int length);
|
|||
\param channels number of channels per frame
|
||||
\param width bytes per channel
|
||||
*/
|
||||
void SND_Convert (byte *idata, float *fdata, int frames, int channels,
|
||||
int width);
|
||||
void SND_Convert (byte *idata, float *fdata, int frames,
|
||||
int channels, int width);
|
||||
///@}
|
||||
|
||||
|
||||
|
@ -492,7 +491,7 @@ int SND_LoadWav (QFile *file, sfx_t *sfx, char *realname);
|
|||
\param realname path of sound file should it need to be re-opened
|
||||
\return 0 if ok, -1 on error
|
||||
*/
|
||||
int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname);
|
||||
int SND_LoadMidi (snd_t *snd, QFile *file, sfx_t *sfx, char *realname);
|
||||
///@}
|
||||
|
||||
/** \defgroup sound_render_cache_stream Cache/Stream Functions.
|
||||
|
|
|
@ -85,7 +85,7 @@ unlink_channel (channel_t **_ch)
|
|||
}
|
||||
|
||||
channel_t *
|
||||
SND_AllocChannel (void)
|
||||
SND_AllocChannel (snd_t *snd)
|
||||
{
|
||||
channel_t **free = &free_channels;
|
||||
channel_t *chan;
|
||||
|
@ -124,7 +124,7 @@ SND_AllocChannel (void)
|
|||
}
|
||||
|
||||
void
|
||||
SND_ChannelStop (channel_t *chan)
|
||||
SND_ChannelStop (snd_t *snd, channel_t *chan)
|
||||
{
|
||||
/* if chan->next is set, then this channel may have already been freed.
|
||||
a rather serious bug as it will create a loop in the free list
|
||||
|
@ -137,13 +137,13 @@ SND_ChannelStop (channel_t *chan)
|
|||
}
|
||||
|
||||
void
|
||||
SND_ScanChannels (int wait)
|
||||
SND_ScanChannels (snd_t *snd, int wait)
|
||||
{
|
||||
int i;
|
||||
channel_t *ch;
|
||||
int count = 0;
|
||||
|
||||
if (!snd_shm || !snd_shm->speed)
|
||||
if (!snd || !snd->speed)
|
||||
return;
|
||||
|
||||
if (wait) {
|
||||
|
@ -184,23 +184,23 @@ SND_ScanChannels (int wait)
|
|||
}
|
||||
|
||||
void
|
||||
SND_StopAllSounds (void)
|
||||
SND_StopAllSounds (snd_t *snd)
|
||||
{
|
||||
int i;
|
||||
|
||||
snd_num_statics = 0;
|
||||
while (dynamic_channels)
|
||||
SND_ChannelStop (unlink_channel (&dynamic_channels));
|
||||
SND_ChannelStop (snd, unlink_channel (&dynamic_channels));
|
||||
while (looped_dynamic_channels)
|
||||
SND_ChannelStop (unlink_channel (&looped_dynamic_channels));
|
||||
SND_ChannelStop (snd, unlink_channel (&looped_dynamic_channels));
|
||||
for (i = 0; i < NUM_AMBIENTS; i++) {
|
||||
if (ambient_channels[i])
|
||||
SND_ChannelStop (ambient_channels[i]);
|
||||
SND_ChannelStop (snd, ambient_channels[i]);
|
||||
ambient_channels[i] = 0;
|
||||
}
|
||||
for (i = 0; i < MAX_STATIC_CHANNELS; i++) {
|
||||
if (static_channels[i])
|
||||
SND_ChannelStop (static_channels[i]);
|
||||
SND_ChannelStop (snd, static_channels[i]);
|
||||
static_channels[i] = 0;
|
||||
}
|
||||
if (0) {
|
||||
|
@ -217,8 +217,9 @@ SND_StopAllSounds (void)
|
|||
}
|
||||
|
||||
static void
|
||||
s_play_f (void)
|
||||
s_play_f (void *_snd)
|
||||
{
|
||||
snd_t *snd = _snd;
|
||||
dstring_t *name = dstring_new ();
|
||||
int i;
|
||||
static int hash = 345;
|
||||
|
@ -231,16 +232,17 @@ s_play_f (void)
|
|||
} else {
|
||||
dsprintf (name, "%s", Cmd_Argv (i));
|
||||
}
|
||||
sfx = SND_PrecacheSound (name->str);
|
||||
SND_StartSound (hash++, 0, sfx, listener_origin, 1.0, 1.0);
|
||||
sfx = SND_PrecacheSound (snd, name->str);
|
||||
SND_StartSound (snd, hash++, 0, sfx, listener_origin, 1.0, 1.0);
|
||||
i++;
|
||||
}
|
||||
dstring_delete (name);
|
||||
}
|
||||
|
||||
static void
|
||||
s_playcenter_f (void)
|
||||
s_playcenter_f (void *_snd)
|
||||
{
|
||||
snd_t *snd = _snd;
|
||||
dstring_t *name = dstring_new ();
|
||||
int i;
|
||||
sfx_t *sfx;
|
||||
|
@ -255,15 +257,16 @@ s_playcenter_f (void)
|
|||
} else {
|
||||
dsprintf (name, "%s", Cmd_Argv (i));
|
||||
}
|
||||
sfx = SND_PrecacheSound (name->str);
|
||||
SND_StartSound (viewent, 0, sfx, listener_origin, 1.0, 1.0);
|
||||
sfx = SND_PrecacheSound (snd, name->str);
|
||||
SND_StartSound (snd, viewent, 0, sfx, listener_origin, 1.0, 1.0);
|
||||
}
|
||||
dstring_delete (name);
|
||||
}
|
||||
|
||||
static void
|
||||
s_playvol_f (void)
|
||||
s_playvol_f (void *_snd)
|
||||
{
|
||||
snd_t *snd = _snd;
|
||||
dstring_t *name = dstring_new ();
|
||||
float vol;
|
||||
int i;
|
||||
|
@ -277,9 +280,9 @@ s_playvol_f (void)
|
|||
} else {
|
||||
dsprintf (name, "%s", Cmd_Argv (i));
|
||||
}
|
||||
sfx = SND_PrecacheSound (name->str);
|
||||
sfx = SND_PrecacheSound (snd, name->str);
|
||||
vol = atof (Cmd_Argv (i + 1));
|
||||
SND_StartSound (hash++, 0, sfx, listener_origin, vol, 1.0);
|
||||
SND_StartSound (snd, hash++, 0, sfx, listener_origin, vol, 1.0);
|
||||
i += 2;
|
||||
}
|
||||
dstring_delete (name);
|
||||
|
@ -291,14 +294,15 @@ s_channels_gamedir (int phase)
|
|||
//FIXME for some reason, a gamedir change causes semi-random
|
||||
//"already released" cache errors. fortunatly, servers don't change
|
||||
//gamedir often, so I'll put this in the too-hard basket for now.
|
||||
if (phase) {
|
||||
ambient_sfx[AMBIENT_WATER] = SND_PrecacheSound ("ambience/water1.wav");
|
||||
ambient_sfx[AMBIENT_SKY] = SND_PrecacheSound ("ambience/wind2.wav");
|
||||
}
|
||||
//XXX FIXME set ambient sounds
|
||||
//if (phase) {
|
||||
// ambient_sfx[AMBIENT_WATER] = SND_PrecacheSound (snd, "ambience/water1.wav");
|
||||
// ambient_sfx[AMBIENT_SKY] = SND_PrecacheSound (snd, "ambience/wind2.wav");
|
||||
//}
|
||||
}
|
||||
|
||||
void
|
||||
SND_Channels_Init (void)
|
||||
SND_Channels_Init (snd_t *snd)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -315,12 +319,14 @@ SND_Channels_Init (void)
|
|||
ambient_level = Cvar_Get ("ambient_level", "0.3", CVAR_NONE, NULL,
|
||||
"Ambient sounds' volume");
|
||||
|
||||
Cmd_AddCommand ("play", s_play_f,
|
||||
"Play selected sound effect (play pathto/sound.wav)");
|
||||
Cmd_AddCommand ("playcenter", s_playcenter_f,
|
||||
"Play selected sound effect without 3D spatialization.");
|
||||
Cmd_AddCommand ("playvol", s_playvol_f, "Play selected sound effect at "
|
||||
"selected volume (playvol pathto/sound.wav num");
|
||||
Cmd_AddDataCommand ("play", s_play_f, snd,
|
||||
"Play selected sound effect (play pathto/sound.wav)");
|
||||
Cmd_AddDataCommand ("playcenter", s_playcenter_f, snd,
|
||||
"Play selected sound effect without 3D "
|
||||
"spatialization.");
|
||||
Cmd_AddDataCommand ("playvol", s_playvol_f, snd,
|
||||
"Play selected sound effect at selected volume "
|
||||
"(playvol pathto/sound.wav num");
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS - 1; i++)
|
||||
snd_channels[i].next = &snd_channels[i + 1];
|
||||
|
@ -333,14 +339,14 @@ SND_Channels_Init (void)
|
|||
}
|
||||
|
||||
static channel_t *
|
||||
s_pick_channel (int entnum, int entchannel, int looped)
|
||||
s_pick_channel (snd_t *snd, int entnum, int entchannel, int looped)
|
||||
{
|
||||
channel_t *ch, **_ch;
|
||||
|
||||
// check for finished non-looped sounds
|
||||
for (_ch = &dynamic_channels; *_ch; ) {
|
||||
if (!(*_ch)->sfx || (*_ch)->done) {
|
||||
SND_ChannelStop (unlink_channel (_ch));
|
||||
SND_ChannelStop (snd, unlink_channel (_ch));
|
||||
continue;
|
||||
}
|
||||
_ch = &(*_ch)->next;
|
||||
|
@ -352,13 +358,13 @@ s_pick_channel (int entnum, int entchannel, int looped)
|
|||
if (!(*_ch)->sfx || (*_ch)->done
|
||||
|| ((*_ch)->entnum == entnum
|
||||
&& ((*_ch)->entchannel == entchannel || entchannel == -1))) {
|
||||
SND_ChannelStop (unlink_channel (_ch));
|
||||
SND_ChannelStop (snd, unlink_channel (_ch));
|
||||
continue;
|
||||
}
|
||||
_ch = &(*_ch)->next;
|
||||
}
|
||||
_ch = looped ? &looped_dynamic_channels : &dynamic_channels;
|
||||
if ((ch = SND_AllocChannel ())) {
|
||||
if ((ch = SND_AllocChannel (snd))) {
|
||||
ch->next = *_ch;
|
||||
*_ch = ch;
|
||||
}
|
||||
|
@ -366,19 +372,19 @@ s_pick_channel (int entnum, int entchannel, int looped)
|
|||
}
|
||||
|
||||
void
|
||||
SND_AmbientOff (void)
|
||||
SND_AmbientOff (snd_t *snd)
|
||||
{
|
||||
snd_ambient = false;
|
||||
}
|
||||
|
||||
void
|
||||
SND_AmbientOn (void)
|
||||
SND_AmbientOn (snd_t *snd)
|
||||
{
|
||||
snd_ambient = true;
|
||||
}
|
||||
|
||||
static void
|
||||
s_updateAmbientSounds (const byte *ambient_sound_level)
|
||||
s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
||||
{
|
||||
float vol;
|
||||
int ambient_channel;
|
||||
|
@ -410,7 +416,7 @@ s_updateAmbientSounds (const byte *ambient_sound_level)
|
|||
|
||||
chan = ambient_channels[ambient_channel];
|
||||
if (!chan) {
|
||||
chan = ambient_channels[ambient_channel] = SND_AllocChannel ();
|
||||
chan = ambient_channels[ambient_channel] = SND_AllocChannel (snd);
|
||||
if (!chan)
|
||||
continue;
|
||||
}
|
||||
|
@ -450,7 +456,7 @@ s_updateAmbientSounds (const byte *ambient_sound_level)
|
|||
}
|
||||
|
||||
static void
|
||||
s_spatialize (channel_t *ch)
|
||||
s_spatialize (snd_t *snd, channel_t *ch)
|
||||
{
|
||||
int phase; // in samples
|
||||
vec_t dist, dot, lscale, rscale, scale;
|
||||
|
@ -477,14 +483,14 @@ s_spatialize (channel_t *ch)
|
|||
if (snd_swapchannelside->int_val)
|
||||
dot = -dot;
|
||||
|
||||
if (snd_shm->channels == 1) {
|
||||
if (snd->channels == 1) {
|
||||
rscale = 1.0;
|
||||
lscale = 1.0;
|
||||
phase = 0;
|
||||
} else {
|
||||
rscale = 1.0 + dot * snd_volumesep->value;
|
||||
lscale = 1.0 - dot * snd_volumesep->value;
|
||||
phase = snd_phasesep->value * 0.001 * snd_shm->speed * dot;
|
||||
phase = snd_phasesep->value * 0.001 * snd->speed * dot;
|
||||
}
|
||||
|
||||
// add in distance effect
|
||||
|
@ -502,11 +508,11 @@ s_spatialize (channel_t *ch)
|
|||
}
|
||||
|
||||
static inline int
|
||||
s_update_channel (channel_t *ch)
|
||||
s_update_channel (snd_t *snd, channel_t *ch)
|
||||
{
|
||||
if (!ch->sfx)
|
||||
return 0;
|
||||
s_spatialize (ch); // respatialize channel
|
||||
s_spatialize (snd, ch);
|
||||
if (!ch->leftvol && !ch->rightvol)
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -521,8 +527,9 @@ s_combine_channel (channel_t *combine, channel_t *ch)
|
|||
}
|
||||
|
||||
void
|
||||
SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
||||
const vec3_t up, const byte *ambient_sound_level)
|
||||
SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t forward,
|
||||
const vec3_t right, const vec3_t up,
|
||||
const byte *ambient_sound_level)
|
||||
{
|
||||
int i, j;
|
||||
channel_t *combine, *ch;
|
||||
|
@ -533,19 +540,19 @@ SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
|||
VectorCopy (up, listener_up);
|
||||
|
||||
// update general area ambient sound sources
|
||||
s_updateAmbientSounds (ambient_sound_level);
|
||||
s_updateAmbientSounds (snd, ambient_sound_level);
|
||||
|
||||
// update spatialization for dynamic sounds
|
||||
for (ch = dynamic_channels; ch; ch = ch->next)
|
||||
s_update_channel (ch);
|
||||
s_update_channel (snd, ch);
|
||||
for (ch = looped_dynamic_channels; ch; ch = ch->next)
|
||||
s_update_channel (ch);
|
||||
s_update_channel (snd, ch);
|
||||
|
||||
// update spatialization for static sounds
|
||||
combine = 0;
|
||||
for (i = 0; i < snd_num_statics; i++) {
|
||||
ch = static_channels[i];
|
||||
if (!s_update_channel (ch))
|
||||
if (!s_update_channel (snd, ch))
|
||||
continue;
|
||||
|
||||
// try to combine static sounds with a previous channel of the same
|
||||
|
@ -573,13 +580,13 @@ SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
|||
}
|
||||
|
||||
static int
|
||||
snd_check_channels (channel_t *target_chan, const channel_t *check,
|
||||
snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check,
|
||||
const sfx_t *osfx)
|
||||
{
|
||||
if (!check || check == target_chan)
|
||||
return 0;
|
||||
if (check->sfx->owner == osfx->owner && !check->pos) {
|
||||
int skip = rand () % (int) (0.01 * snd_shm->speed);
|
||||
int skip = rand () % (int) (0.01 * snd->speed);
|
||||
target_chan->pos = -skip;
|
||||
return 1;
|
||||
}
|
||||
|
@ -587,19 +594,19 @@ snd_check_channels (channel_t *target_chan, const channel_t *check,
|
|||
}
|
||||
|
||||
void
|
||||
SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||
float fvol, float attenuation)
|
||||
SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
||||
const vec3_t origin, float fvol, float attenuation)
|
||||
{
|
||||
int vol;
|
||||
int looped;
|
||||
channel_t *target_chan, *check;
|
||||
sfx_t *osfx;
|
||||
|
||||
if (!sfx || !snd_shm->speed)
|
||||
if (!sfx || !snd->speed)
|
||||
return;
|
||||
// pick a channel to play on
|
||||
looped = sfx->loopstart != (unsigned) -1;
|
||||
target_chan = s_pick_channel (entnum, entchannel, looped);
|
||||
target_chan = s_pick_channel (snd, entnum, entchannel, looped);
|
||||
if (!target_chan)
|
||||
return;
|
||||
|
||||
|
@ -611,11 +618,11 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
|||
target_chan->master_vol = vol;
|
||||
target_chan->entnum = entnum;
|
||||
target_chan->entchannel = entchannel;
|
||||
s_spatialize (target_chan);
|
||||
s_spatialize (snd, target_chan);
|
||||
|
||||
// new channel
|
||||
if (!(osfx = sfx->open (sfx))) {
|
||||
SND_ChannelStop (unlink_channel (looped ? &looped_dynamic_channels
|
||||
SND_ChannelStop (snd, unlink_channel (looped ? &looped_dynamic_channels
|
||||
: &dynamic_channels));
|
||||
return;
|
||||
}
|
||||
|
@ -625,13 +632,13 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
|||
// if an identical sound has also been started this frame, offset the pos
|
||||
// a bit to keep it from just making the first one louder
|
||||
for (check = dynamic_channels; check; check = check->next)
|
||||
if (snd_check_channels (target_chan, check, osfx))
|
||||
if (snd_check_channels (snd, target_chan, check, osfx))
|
||||
break;
|
||||
for (check = looped_dynamic_channels; check; check = check->next)
|
||||
if (snd_check_channels (target_chan, check, osfx))
|
||||
if (snd_check_channels (snd, target_chan, check, osfx))
|
||||
break;
|
||||
if (!osfx->retain (osfx)) {
|
||||
SND_ChannelStop (unlink_channel (looped ? &looped_dynamic_channels
|
||||
SND_ChannelStop (snd, unlink_channel (looped ? &looped_dynamic_channels
|
||||
: &dynamic_channels));
|
||||
return; // couldn't load the sound's data
|
||||
}
|
||||
|
@ -639,30 +646,30 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
|||
}
|
||||
|
||||
static int
|
||||
s_check_stop (channel_t **_ch, int entnum, int entchannel)
|
||||
s_check_stop (snd_t *snd, channel_t **_ch, int entnum, int entchannel)
|
||||
{
|
||||
if ((*_ch)->entnum == entnum && (*_ch)->entchannel == entchannel) {
|
||||
SND_ChannelStop (unlink_channel (_ch));
|
||||
SND_ChannelStop (snd, unlink_channel (_ch));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SND_StopSound (int entnum, int entchannel)
|
||||
SND_StopSound (snd_t *snd, int entnum, int entchannel)
|
||||
{
|
||||
channel_t **_ch;
|
||||
|
||||
for (_ch = &dynamic_channels; *_ch; )
|
||||
if (!s_check_stop (_ch, entnum, entchannel))
|
||||
if (!s_check_stop (snd, _ch, entnum, entchannel))
|
||||
_ch = &(*_ch)->next;
|
||||
for (_ch = &looped_dynamic_channels; *_ch; )
|
||||
if (!s_check_stop (_ch, entnum, entchannel))
|
||||
if (!s_check_stop (snd, _ch, entnum, entchannel))
|
||||
_ch = &(*_ch)->next;
|
||||
}
|
||||
|
||||
void
|
||||
SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||
SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol,
|
||||
float attenuation)
|
||||
{
|
||||
channel_t *ss;
|
||||
|
@ -676,7 +683,7 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
|||
}
|
||||
|
||||
if (!static_channels[snd_num_statics]) {
|
||||
if (!(static_channels[snd_num_statics] = SND_AllocChannel ())) {
|
||||
if (!(static_channels[snd_num_statics] = SND_AllocChannel (snd))) {
|
||||
Sys_Printf ("ran out of channels\n");
|
||||
return;
|
||||
}
|
||||
|
@ -692,7 +699,7 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
|||
ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist;
|
||||
ss->end = 0;
|
||||
|
||||
s_spatialize (ss);
|
||||
s_spatialize (snd, ss);
|
||||
ss->oldphase = ss->phase;
|
||||
|
||||
if (!osfx->retain (osfx))
|
||||
|
@ -702,17 +709,17 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
|||
}
|
||||
|
||||
void
|
||||
SND_LocalSound (const char *sound)
|
||||
SND_LocalSound (snd_t *snd, const char *sound)
|
||||
{
|
||||
sfx_t *sfx;
|
||||
int viewent = 0;
|
||||
|
||||
sfx = SND_PrecacheSound (sound);
|
||||
sfx = SND_PrecacheSound (snd, sound);
|
||||
if (!sfx) {
|
||||
Sys_Printf ("S_LocalSound: can't cache %s\n", sound);
|
||||
return;
|
||||
}
|
||||
if (snd_render_data.viewentity)
|
||||
viewent = *snd_render_data.viewentity;
|
||||
SND_StartSound (viewent, -1, sfx, vec3_origin, 1, 1);
|
||||
SND_StartSound (snd, viewent, -1, sfx, vec3_origin, 1, 1);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
snd_dma.c
|
||||
snd_default.c
|
||||
|
||||
main control for any streaming sound output device
|
||||
|
||||
|
@ -69,23 +69,26 @@ static general_data_t plugin_info_general_data;
|
|||
|
||||
static snd_output_funcs_t *snd_output_funcs;
|
||||
|
||||
static snd_t snd;
|
||||
static int snd_shutdown = 0;
|
||||
|
||||
static void
|
||||
s_xfer_paint_buffer (portable_samplepair_t *paintbuffer, int count,
|
||||
s_xfer_paint_buffer (snd_t *snd, portable_samplepair_t *paintbuffer, int count,
|
||||
float volume)
|
||||
{
|
||||
int out_idx, out_max, step, val;
|
||||
float *p;
|
||||
|
||||
p = (float *) paintbuffer;
|
||||
count *= snd_shm->channels;
|
||||
out_max = (snd_shm->frames * snd_shm->channels) - 1;
|
||||
out_idx = snd_paintedtime * snd_shm->channels;
|
||||
count *= snd->channels;
|
||||
out_max = (snd->frames * snd->channels) - 1;
|
||||
out_idx = snd_paintedtime * snd->channels;
|
||||
while (out_idx > out_max)
|
||||
out_idx -= out_max + 1;
|
||||
step = 3 - snd_shm->channels;
|
||||
step = 3 - snd->channels;
|
||||
|
||||
if (snd_shm->samplebits == 16) {
|
||||
short *out = (short *) snd_shm->buffer;
|
||||
if (snd->samplebits == 16) {
|
||||
short *out = (short *) snd->buffer;
|
||||
|
||||
while (count--) {
|
||||
val = (*p * volume) * 0x8000;
|
||||
|
@ -98,8 +101,8 @@ s_xfer_paint_buffer (portable_samplepair_t *paintbuffer, int count,
|
|||
if (out_idx > out_max)
|
||||
out_idx = 0;
|
||||
}
|
||||
} else if (snd_shm->samplebits == 8) {
|
||||
unsigned char *out = (unsigned char *) snd_shm->buffer;
|
||||
} else if (snd->samplebits == 8) {
|
||||
unsigned char *out = (unsigned char *) snd->buffer;
|
||||
|
||||
while (count--) {
|
||||
val = (*p * volume) * 128;
|
||||
|
@ -116,35 +119,35 @@ s_xfer_paint_buffer (portable_samplepair_t *paintbuffer, int count,
|
|||
}
|
||||
|
||||
static void
|
||||
s_clear_buffer (void)
|
||||
s_clear_buffer (snd_t *snd)
|
||||
{
|
||||
int clear, i;
|
||||
int count;
|
||||
|
||||
if (!sound_started || !snd_shm || !snd_shm->buffer)
|
||||
if (!sound_started || !snd || !snd->buffer)
|
||||
return;
|
||||
|
||||
if (snd_shm->samplebits == 8)
|
||||
if (snd->samplebits == 8)
|
||||
clear = 0x80;
|
||||
else
|
||||
clear = 0;
|
||||
|
||||
count = snd_shm->frames * snd_shm->channels * snd_shm->samplebits / 8;
|
||||
count = snd->frames * snd->channels * snd->samplebits / 8;
|
||||
for (i = 0; i < count; i++)
|
||||
snd_shm->buffer[i] = clear;
|
||||
snd->buffer[i] = clear;
|
||||
}
|
||||
|
||||
static void
|
||||
s_stop_all_sounds (void)
|
||||
{
|
||||
SND_StopAllSounds ();
|
||||
SND_ScanChannels (0);
|
||||
s_clear_buffer ();
|
||||
SND_StopAllSounds (&snd);
|
||||
SND_ScanChannels (&snd, 0);
|
||||
s_clear_buffer (&snd);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
static void
|
||||
/*static void
|
||||
s_get_soundtime (void)
|
||||
{
|
||||
int frames, framepos;
|
||||
|
@ -196,7 +199,7 @@ s_update_ (void)
|
|||
|
||||
SND_PaintChannels (endtime);
|
||||
snd_output_funcs->pS_O_Submit ();
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
s_update
|
||||
|
@ -210,27 +213,27 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
|||
if (!sound_started || (snd_blocked > 0))
|
||||
return;
|
||||
|
||||
SND_SetListener (origin, forward, right, up, ambient_sound_level);
|
||||
SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level);
|
||||
|
||||
// mix some sound
|
||||
s_update_ ();
|
||||
SND_ScanChannels (0);
|
||||
//s_update_ ();
|
||||
//SND_ScanChannels (0);
|
||||
}
|
||||
|
||||
static void
|
||||
s_extra_update (void)
|
||||
{
|
||||
if (!sound_started || snd_noextraupdate->int_val)
|
||||
return; // don't pollute timings
|
||||
s_update_ ();
|
||||
}
|
||||
//static void
|
||||
//s_extra_update (void)
|
||||
//{
|
||||
// if (!sound_started || snd_noextraupdate->int_val)
|
||||
// return; // don't pollute timings
|
||||
// s_update_ ();
|
||||
//}
|
||||
|
||||
static void
|
||||
s_block_sound (void)
|
||||
{
|
||||
if (++snd_blocked == 1) {
|
||||
snd_output_funcs->pS_O_BlockSound ();
|
||||
s_clear_buffer ();
|
||||
snd_output_funcs->block_sound (&snd);
|
||||
s_clear_buffer (&snd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,8 +244,8 @@ s_unblock_sound (void)
|
|||
return;
|
||||
|
||||
if (!--snd_blocked) {
|
||||
s_clear_buffer ();
|
||||
snd_output_funcs->pS_O_UnblockSound ();
|
||||
s_clear_buffer (&snd);
|
||||
snd_output_funcs->unblock_sound (&snd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,18 +254,20 @@ s_unblock_sound (void)
|
|||
static void
|
||||
s_soundinfo_f (void)
|
||||
{
|
||||
if (!sound_started || !snd_shm) {
|
||||
if (!sound_started) {
|
||||
Sys_Printf ("sound system not started\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Sys_Printf ("%5d channels\n", snd_shm->channels);
|
||||
Sys_Printf ("%5d frames\n", snd_shm->frames);
|
||||
Sys_Printf ("%5d framepos\n", snd_shm->framepos);
|
||||
Sys_Printf ("%5d samplebits\n", snd_shm->samplebits);
|
||||
Sys_Printf ("%5d submission_chunk\n", snd_shm->submission_chunk);
|
||||
Sys_Printf ("%5d speed\n", snd_shm->speed);
|
||||
Sys_Printf ("0x%"PRIxPTR" dma buffer\n", (intptr_t) snd_shm->buffer);
|
||||
Sys_Printf ("%5d channels\n", snd.channels);
|
||||
Sys_Printf ("%5d frames (%.1fms)\n", snd.frames,
|
||||
1000.0 * snd.frames / snd.speed);
|
||||
Sys_Printf ("%5d framepos\n", snd.framepos);
|
||||
Sys_Printf ("%5d samplebits\n", snd.samplebits);
|
||||
Sys_Printf ("%5d submission_chunk (%.1fms)\n", snd.submission_chunk,
|
||||
1000.0 * snd.submission_chunk / snd.speed);
|
||||
Sys_Printf ("%5d speed\n", snd.speed);
|
||||
Sys_Printf ("0x%"PRIxPTR" dma buffer\n", (intptr_t) snd.buffer);
|
||||
Sys_Printf ("%5d total_channels\n", snd_total_channels);
|
||||
}
|
||||
|
||||
|
@ -278,15 +283,13 @@ s_startup (void)
|
|||
if (!snd_initialized)
|
||||
return;
|
||||
|
||||
snd_shm = snd_output_funcs->pS_O_Init ();
|
||||
|
||||
if (!snd_shm) {
|
||||
if (!snd_output_funcs->init (&snd)) {
|
||||
Sys_Printf ("S_Startup: S_O_Init failed.\n");
|
||||
sound_started = 0;
|
||||
return;
|
||||
}
|
||||
if (!snd_shm->xfer)
|
||||
snd_shm->xfer = s_xfer_paint_buffer;
|
||||
if (!snd.xfer)
|
||||
snd.xfer = s_xfer_paint_buffer;
|
||||
|
||||
sound_started = 1;
|
||||
}
|
||||
|
@ -337,8 +340,8 @@ s_init (void)
|
|||
if (sound_started == 0) // sound startup failed? Bail out.
|
||||
return;
|
||||
|
||||
SND_SFX_Init ();
|
||||
SND_Channels_Init ();
|
||||
SND_SFX_Init (&snd);
|
||||
SND_Channels_Init (&snd);
|
||||
|
||||
s_stop_all_sounds ();
|
||||
}
|
||||
|
@ -350,10 +353,96 @@ s_shutdown (void)
|
|||
return;
|
||||
|
||||
sound_started = 0;
|
||||
snd_shutdown = 1;
|
||||
|
||||
snd_output_funcs->pS_O_Shutdown ();
|
||||
snd_output_funcs->shutdown (&snd);
|
||||
}
|
||||
|
||||
snd_shm = 0;
|
||||
static void
|
||||
s_ambient_off (void)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_AmbientOff (&snd);
|
||||
}
|
||||
|
||||
static void
|
||||
s_ambient_on (void)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_AmbientOn (&snd);
|
||||
}
|
||||
|
||||
static void
|
||||
s_static_sound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||
float attenuation)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_StaticSound (&snd, sfx, origin, vol, attenuation);
|
||||
}
|
||||
|
||||
static void
|
||||
s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||
float fvol, float attenuation)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
if (!snd_shutdown)
|
||||
SND_StartSound (&snd, entnum, entchannel, sfx, origin, fvol,
|
||||
attenuation);
|
||||
}
|
||||
|
||||
static void
|
||||
s_stop_sound (int entnum, int entchannel)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_StopSound (&snd, entnum, entchannel);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
s_precache_sound (const char *name)
|
||||
{
|
||||
if (!sound_started)
|
||||
return 0;
|
||||
return SND_PrecacheSound (&snd, name);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
s_load_sound (const char *name)
|
||||
{
|
||||
if (!sound_started)
|
||||
return 0;
|
||||
return SND_LoadSound (&snd, name);
|
||||
}
|
||||
|
||||
static void
|
||||
s_channel_stop (channel_t *chan)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_ChannelStop (&snd, chan);
|
||||
}
|
||||
|
||||
static void
|
||||
s_local_sound (const char *sound)
|
||||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
if (!snd_shutdown)
|
||||
SND_LocalSound (&snd, sound);
|
||||
}
|
||||
|
||||
static channel_t *
|
||||
s_alloc_channel (void)
|
||||
{
|
||||
if (!sound_started)
|
||||
return 0;
|
||||
if (!snd_shutdown)
|
||||
return SND_AllocChannel (&snd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static general_funcs_t plugin_info_general_funcs = {
|
||||
|
@ -362,21 +451,24 @@ static general_funcs_t plugin_info_general_funcs = {
|
|||
};
|
||||
|
||||
static snd_render_funcs_t plugin_info_render_funcs = {
|
||||
.ambient_off = SND_AmbientOff,
|
||||
.ambient_on = SND_AmbientOn,
|
||||
.static_sound = SND_StaticSound,
|
||||
.start_sound = SND_StartSound,
|
||||
.stop_sound = SND_StopSound,
|
||||
.precache_sound = SND_PrecacheSound,
|
||||
.update = s_update,
|
||||
.ambient_off = s_ambient_off,
|
||||
.ambient_on = s_ambient_on,
|
||||
.static_sound = s_static_sound,
|
||||
.start_sound = s_start_sound,
|
||||
.local_sound = s_local_sound,
|
||||
.stop_sound = s_stop_sound,
|
||||
|
||||
.alloc_channel = s_alloc_channel,
|
||||
.channel_stop = s_channel_stop,
|
||||
|
||||
.precache_sound = s_precache_sound,
|
||||
.load_sound = s_load_sound,
|
||||
|
||||
.update = s_update,
|
||||
.stop_all_sounds = s_stop_all_sounds,
|
||||
.extra_update = s_extra_update,
|
||||
.local_sound = SND_LocalSound,
|
||||
.block_sound = s_block_sound,
|
||||
.unblock_sound = s_unblock_sound,
|
||||
.load_sound = SND_LoadSound,
|
||||
.alloc_channel = SND_AllocChannel,
|
||||
.channel_stop = SND_ChannelStop,
|
||||
//.extra_update = s_extra_update,
|
||||
.block_sound = s_block_sound,
|
||||
.unblock_sound = s_unblock_sound,
|
||||
};
|
||||
|
||||
static plugin_funcs_t plugin_info_funcs = {
|
||||
|
|
|
@ -54,7 +54,7 @@ static int snd_alive = 0;
|
|||
static double snd_alive_time = 0;
|
||||
static jack_client_t *jack_handle;
|
||||
static jack_port_t *jack_out[2];
|
||||
static dma_t _snd_shm;
|
||||
static snd_t snd;
|
||||
static float *output[2];
|
||||
static cvar_t *snd_jack_server;
|
||||
|
||||
|
@ -65,8 +65,8 @@ s_stop_all_sounds (void)
|
|||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_StopAllSounds ();
|
||||
SND_ScanChannels (1);
|
||||
SND_StopAllSounds (&snd);
|
||||
SND_ScanChannels (&snd, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -76,7 +76,8 @@ s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
|||
if (!sound_started)
|
||||
return;
|
||||
if (!snd_shutdown)
|
||||
SND_StartSound (entnum, entchannel, sfx, origin, fvol, attenuation);
|
||||
SND_StartSound (&snd, entnum, entchannel, sfx, origin, fvol,
|
||||
attenuation);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -120,7 +121,7 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
|||
if (snd_shutdown)
|
||||
return;
|
||||
}
|
||||
SND_SetListener (origin, forward, right, up, ambient_sound_level);
|
||||
SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -129,7 +130,7 @@ s_local_sound (const char *sound)
|
|||
if (!sound_started)
|
||||
return;
|
||||
if (!snd_shutdown)
|
||||
SND_LocalSound (sound);
|
||||
SND_LocalSound (&snd, sound);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -184,7 +185,7 @@ s_alloc_channel (void)
|
|||
if (!sound_started)
|
||||
return 0;
|
||||
if (!snd_shutdown)
|
||||
return SND_AllocChannel ();
|
||||
return SND_AllocChannel (&snd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -202,7 +203,7 @@ s_ambient_off (void)
|
|||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_AmbientOff ();
|
||||
SND_AmbientOff (&snd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -210,7 +211,7 @@ s_ambient_on (void)
|
|||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_AmbientOn ();
|
||||
SND_AmbientOn (&snd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -219,7 +220,7 @@ s_static_sound (sfx_t *sfx, const vec3_t origin, float vol,
|
|||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_StaticSound (sfx, origin, vol, attenuation);
|
||||
SND_StaticSound (&snd, sfx, origin, vol, attenuation);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -227,7 +228,7 @@ s_stop_sound (int entnum, int entchannel)
|
|||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_StopSound (entnum, entchannel);
|
||||
SND_StopSound (&snd, entnum, entchannel);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
|
@ -235,7 +236,7 @@ s_precache_sound (const char *name)
|
|||
{
|
||||
if (!sound_started)
|
||||
return 0;
|
||||
return SND_PrecacheSound (name);
|
||||
return SND_PrecacheSound (&snd, name);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
|
@ -243,7 +244,7 @@ s_load_sound (const char *name)
|
|||
{
|
||||
if (!sound_started)
|
||||
return 0;
|
||||
return SND_LoadSound (name);
|
||||
return SND_LoadSound (&snd, name);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -251,11 +252,12 @@ s_channel_stop (channel_t *chan)
|
|||
{
|
||||
if (!sound_started)
|
||||
return;
|
||||
SND_ChannelStop (chan);
|
||||
SND_ChannelStop (&snd, chan);
|
||||
}
|
||||
|
||||
static void
|
||||
snd_jack_xfer (portable_samplepair_t *paintbuffer, int count, float volume)
|
||||
snd_jack_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count,
|
||||
float volume)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -281,7 +283,7 @@ snd_jack_process (jack_nframes_t nframes, void *arg)
|
|||
snd_alive = 1;
|
||||
for (i = 0; i < 2; i++)
|
||||
output[i] = (float *) jack_port_get_buffer (jack_out[i], nframes);
|
||||
SND_PaintChannels (snd_paintedtime + nframes);
|
||||
SND_PaintChannels (&snd, snd_paintedtime + nframes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -327,17 +329,16 @@ s_jack_connect (void)
|
|||
jack_out[i] = jack_port_register (jack_handle, va (0, "out_%d", i + 1),
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
snd_shm->speed = jack_get_sample_rate (jack_handle);
|
||||
snd.speed = jack_get_sample_rate (jack_handle);
|
||||
s_jack_activate ();
|
||||
sound_started = 1;
|
||||
Sys_Printf ("Connected to JACK: %d Sps\n", snd_shm->speed);
|
||||
Sys_Printf ("Connected to JACK: %d Sps\n", snd.speed);
|
||||
}
|
||||
|
||||
static void
|
||||
s_init (void)
|
||||
{
|
||||
snd_shm = &_snd_shm;
|
||||
snd_shm->xfer = snd_jack_xfer;
|
||||
snd.xfer = snd_jack_xfer;
|
||||
|
||||
Cmd_AddCommand ("snd_force_unblock", s_snd_force_unblock,
|
||||
"fix permanently blocked sound");
|
||||
|
@ -347,8 +348,8 @@ s_init (void)
|
|||
snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL,
|
||||
"The name of the JACK server to connect to");
|
||||
|
||||
SND_SFX_Init ();
|
||||
SND_Channels_Init ();
|
||||
SND_SFX_Init (&snd);
|
||||
SND_Channels_Init (&snd);
|
||||
|
||||
s_jack_connect ();
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
|
||||
#define SAMPLE_GAP 4
|
||||
|
||||
volatile dma_t *snd_shm;
|
||||
snd_render_data_t snd_render_data = {
|
||||
0,
|
||||
0,
|
||||
|
@ -212,7 +211,7 @@ SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos)
|
|||
sfxstream_t *stream = sfx->data.stream;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
|
||||
stepscale = (float) info->rate / snd_shm->speed;
|
||||
stepscale = (float) info->rate / sfx->snd->speed;
|
||||
|
||||
buffer->head = buffer->tail = 0;
|
||||
buffer->pos = pos;
|
||||
|
@ -235,7 +234,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
if (!count)
|
||||
return 1;
|
||||
|
||||
stepscale = (float) info->rate / snd_shm->speed;
|
||||
stepscale = (float) info->rate / sfx->snd->speed;
|
||||
|
||||
// find out how many samples the buffer currently holds
|
||||
samples = buffer->head - buffer->tail;
|
||||
|
@ -360,8 +359,9 @@ SND_GetCache (long frames, int rate, int channels,
|
|||
float stepscale;
|
||||
sfxbuffer_t *sc;
|
||||
sfx_t *sfx = block->sfx;
|
||||
snd_t *snd = sfx->snd;
|
||||
|
||||
stepscale = (float) rate / snd_shm->speed;
|
||||
stepscale = (float) rate / snd->speed;
|
||||
len = size = frames / stepscale;
|
||||
size *= sizeof (float) * channels;
|
||||
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
|
||||
|
|
|
@ -104,7 +104,7 @@ snd_paint_channel (channel_t *ch, sfxbuffer_t *sc, int count)
|
|||
}
|
||||
|
||||
void
|
||||
SND_PaintChannels (unsigned endtime)
|
||||
SND_PaintChannels (snd_t *snd, unsigned endtime)
|
||||
{
|
||||
unsigned end, ltime;
|
||||
int i, count;
|
||||
|
@ -171,8 +171,8 @@ SND_PaintChannels (unsigned endtime)
|
|||
}
|
||||
|
||||
// transfer out according to DMA format
|
||||
snd_shm->xfer (snd_paintbuffer, end - snd_paintedtime,
|
||||
snd_volume->value);
|
||||
snd->xfer (snd, snd_paintbuffer, end - snd_paintedtime,
|
||||
snd_volume->value);
|
||||
|
||||
memmove (snd_paintbuffer, snd_paintbuffer + end - snd_paintedtime,
|
||||
max_overpaint * sizeof (snd_paintbuffer[0]));
|
||||
|
|
|
@ -68,11 +68,12 @@ SND_Resample (sfxbuffer_t *sc, float *data, int length)
|
|||
int outcount;
|
||||
double stepscale;
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
snd_t *snd = sc->sfx->snd;
|
||||
int inrate = info->rate;
|
||||
int outwidth;
|
||||
SRC_DATA src_data;
|
||||
|
||||
stepscale = (double) snd_shm->speed / inrate;
|
||||
stepscale = (double) snd->speed / inrate;
|
||||
outcount = length * stepscale;
|
||||
|
||||
src_data.data_in = data;
|
||||
|
@ -119,7 +120,7 @@ static int
|
|||
snd_resample_read (sfxstream_t *stream, float *data, int frames)
|
||||
{
|
||||
int inrate = stream->wavinfo.rate;
|
||||
double ratio = (double) snd_shm->speed / inrate;
|
||||
double ratio = (double) stream->sfx->snd->speed / inrate;
|
||||
|
||||
return src_callback_read (stream->state, ratio, frames, data);
|
||||
}
|
||||
|
@ -143,9 +144,10 @@ SND_SetupResampler (sfxbuffer_t *sc, int streamed)
|
|||
{
|
||||
double stepscale;
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
snd_t *snd = sc->sfx->snd;
|
||||
int inrate = info->rate;
|
||||
|
||||
stepscale = (double) snd_shm->speed / inrate;
|
||||
stepscale = (double) snd->speed / inrate;
|
||||
|
||||
sc->sfx->length = info->frames * stepscale;
|
||||
if (info->loopstart != (unsigned int)-1)
|
||||
|
@ -159,7 +161,7 @@ SND_SetupResampler (sfxbuffer_t *sc, int streamed)
|
|||
int err;
|
||||
sfxstream_t *stream = sc->sfx->data.stream;
|
||||
|
||||
if (snd_shm->speed == inrate) {
|
||||
if (snd->speed == inrate) {
|
||||
stream->state = calloc (sizeof (snd_null_state_t), 1);
|
||||
stream->read = snd_read;
|
||||
} else {
|
||||
|
|
|
@ -112,6 +112,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
int (*seek)(sfxstream_t *, int),
|
||||
void (*close) (sfx_t *))
|
||||
{
|
||||
snd_t *snd = sfx->snd;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
int frames;
|
||||
|
@ -119,11 +120,12 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
|
||||
// if the speed is 0, there is no sound driver (probably failed to connect
|
||||
// to jackd)
|
||||
if (!snd_shm->speed)
|
||||
if (!snd->speed)
|
||||
return 0;
|
||||
|
||||
sfx_t *new_sfx = calloc (1, sizeof (sfx_t));
|
||||
|
||||
new_sfx->snd = sfx->snd;
|
||||
new_sfx->name = sfx->name;
|
||||
new_sfx->owner = sfx;
|
||||
new_sfx->wavinfo = SND_CacheWavinfo;
|
||||
|
@ -132,7 +134,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
new_sfx->getbuffer = SND_StreamGetBuffer;
|
||||
new_sfx->close = close;
|
||||
|
||||
frames = snd_shm->speed * 0.3;
|
||||
frames = snd->speed * 0.3;
|
||||
frames = (frames + 255) & ~255;
|
||||
size = frames * info->channels * sizeof (float);
|
||||
|
||||
|
@ -168,7 +170,7 @@ SND_SFX_StreamClose (sfx_t *sfx)
|
|||
}
|
||||
|
||||
sfx_t *
|
||||
SND_LoadSound (const char *name)
|
||||
SND_LoadSound (snd_t *snd, const char *name)
|
||||
{
|
||||
sfx_t *sfx;
|
||||
|
||||
|
@ -181,6 +183,7 @@ SND_LoadSound (const char *name)
|
|||
Sys_Error ("s_load_sound: out of sfx_t");
|
||||
|
||||
sfx = &snd_sfx[snd_num_sfx++];
|
||||
sfx->snd = snd;
|
||||
sfx->name = strdup (name);
|
||||
sfx->owner = sfx;
|
||||
if (SND_Load (sfx) == -1) {
|
||||
|
@ -192,14 +195,14 @@ SND_LoadSound (const char *name)
|
|||
}
|
||||
|
||||
sfx_t *
|
||||
SND_PrecacheSound (const char *name)
|
||||
SND_PrecacheSound (snd_t *snd, const char *name)
|
||||
{
|
||||
sfx_t *sfx;
|
||||
|
||||
if (!name)
|
||||
Sys_Error ("SND_PrecacheSound: NULL");
|
||||
|
||||
sfx = SND_LoadSound (va (0, "sound/%s", name));
|
||||
sfx = SND_LoadSound (snd, va (0, "sound/%s", name));
|
||||
if (sfx && precache->int_val) {
|
||||
if (sfx->retain (sfx))
|
||||
sfx->release (sfx);
|
||||
|
@ -243,7 +246,7 @@ s_soundlist_f (void)
|
|||
}
|
||||
|
||||
void
|
||||
SND_SFX_Init (void)
|
||||
SND_SFX_Init (snd_t *snd)
|
||||
{
|
||||
snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0, 0);
|
||||
precache = Cvar_Get ("precache", "1", CVAR_NONE, NULL,
|
||||
|
|
|
@ -39,14 +39,20 @@
|
|||
|
||||
#include "snd_internal.h"
|
||||
|
||||
typedef struct {
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
snd_pcm_uframes_t offset;
|
||||
snd_pcm_uframes_t nframes;
|
||||
} alsa_pkt_t;
|
||||
|
||||
static int snd_inited;
|
||||
static int snd_blocked = 0;
|
||||
static volatile dma_t sn;
|
||||
static snd_pcm_uframes_t buffer_size;
|
||||
|
||||
static void *alsa_handle;
|
||||
static const char *pcmname = NULL;
|
||||
static snd_pcm_t *pcm;
|
||||
static snd_async_handler_t *async_haandler;
|
||||
|
||||
static plugin_t plugin_info;
|
||||
static plugin_data_t plugin_info_data;
|
||||
|
@ -101,7 +107,7 @@ SNDDMA_Init_Cvars (void)
|
|||
"sound sample depth. 0 is system default");
|
||||
}
|
||||
|
||||
static int SNDDMA_GetDMAPos (void);
|
||||
static int SNDDMA_GetDMAPos (snd_t *snd);
|
||||
|
||||
static __attribute__((const)) snd_pcm_uframes_t
|
||||
round_buffer_size (snd_pcm_uframes_t sz)
|
||||
|
@ -136,25 +142,26 @@ clamp_8 (int val)
|
|||
}
|
||||
|
||||
static void
|
||||
SNDDMA_ni_xfer (portable_samplepair_t *paintbuffer, int count, float volume)
|
||||
alsa_ni_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count,
|
||||
float volume)
|
||||
{
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
int out_idx, out_max;
|
||||
float *p;
|
||||
|
||||
areas = sn.xfer_data;
|
||||
areas = snd->xfer_data;
|
||||
|
||||
p = (float *) paintbuffer;
|
||||
out_max = sn.frames - 1;
|
||||
out_max = snd->frames - 1;
|
||||
out_idx = *plugin_info_snd_output_data.paintedtime;
|
||||
while (out_idx > out_max)
|
||||
out_idx -= out_max + 1;
|
||||
|
||||
if (sn.samplebits == 16) {
|
||||
if (snd->samplebits == 16) {
|
||||
short *out_0 = (short *) areas[0].addr;
|
||||
short *out_1 = (short *) areas[1].addr;
|
||||
|
||||
if (sn.channels == 2) {
|
||||
if (snd->channels == 2) {
|
||||
while (count--) {
|
||||
out_0[out_idx] = clamp_16 ((*p++ * volume) * 0x8000);
|
||||
out_1[out_idx] = clamp_16 ((*p++ * volume) * 0x8000);
|
||||
|
@ -169,11 +176,11 @@ SNDDMA_ni_xfer (portable_samplepair_t *paintbuffer, int count, float volume)
|
|||
out_idx = 0;
|
||||
}
|
||||
}
|
||||
} else if (sn.samplebits == 8) {
|
||||
} else if (snd->samplebits == 8) {
|
||||
byte *out_0 = (byte *) areas[0].addr;
|
||||
byte *out_1 = (byte *) areas[1].addr;
|
||||
|
||||
if (sn.channels == 2) {
|
||||
if (snd->channels == 2) {
|
||||
while (count--) {
|
||||
out_0[out_idx] = clamp_8 ((*p++ * volume) * 0x80);
|
||||
out_1[out_idx] = clamp_8 ((*p++ * volume) * 0x80);
|
||||
|
@ -191,8 +198,71 @@ SNDDMA_ni_xfer (portable_samplepair_t *paintbuffer, int count, float volume)
|
|||
}
|
||||
}
|
||||
|
||||
static volatile dma_t *
|
||||
SNDDMA_Init (void)
|
||||
static void
|
||||
alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count,
|
||||
float volume)
|
||||
{
|
||||
int out_idx, out_max, step, val;
|
||||
float *p;
|
||||
|
||||
p = (float *) paintbuffer;
|
||||
count *= snd->channels;
|
||||
out_max = (snd->frames * snd->channels) - 1;
|
||||
out_idx = snd_paintedtime * snd->channels;
|
||||
while (out_idx > out_max)
|
||||
out_idx -= out_max + 1;
|
||||
step = 3 - snd->channels;
|
||||
|
||||
if (snd->samplebits == 16) {
|
||||
short *out = (short *) snd->buffer;
|
||||
|
||||
while (count--) {
|
||||
val = (*p * volume) * 0x8000;
|
||||
p += step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < -0x8000)
|
||||
val = -0x8000;
|
||||
out[out_idx++] = val;
|
||||
if (out_idx > out_max)
|
||||
out_idx = 0;
|
||||
}
|
||||
} else if (snd->samplebits == 8) {
|
||||
unsigned char *out = (unsigned char *) snd->buffer;
|
||||
|
||||
while (count--) {
|
||||
val = (*p * volume) * 128;
|
||||
p += step;
|
||||
if (val > 0x7f)
|
||||
val = 0x7f;
|
||||
else if (val < -0x80)
|
||||
val = -0x80;
|
||||
out[out_idx++] = val + 0x80;
|
||||
if (out_idx > out_max)
|
||||
out_idx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
alsa_callback (snd_async_handler_t *handler)
|
||||
{
|
||||
snd_pcm_t *pcm = qfsnd_async_handler_get_pcm (handler);
|
||||
snd_t *snd = qfsnd_async_handler_get_callback_private (handler);
|
||||
alsa_pkt_t packet;
|
||||
|
||||
qfsnd_pcm_avail_update (pcm);
|
||||
qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, &packet.nframes);
|
||||
|
||||
snd->xfer_data = &packet;
|
||||
|
||||
SND_PaintChannels (snd, snd_paintedtime + packet.nframes);
|
||||
|
||||
qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes);
|
||||
}
|
||||
|
||||
static int
|
||||
SNDDMA_Init (snd_t *snd)
|
||||
{
|
||||
int err;
|
||||
int bps = -1, stereo = -1;
|
||||
|
@ -238,6 +308,7 @@ retry_open:
|
|||
goto error;
|
||||
}
|
||||
|
||||
snd->xfer = alsa_xfer;
|
||||
err = qfsnd_pcm_hw_params_set_access (pcm, hw,
|
||||
SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
if (0 > err) {
|
||||
|
@ -257,7 +328,7 @@ retry_open:
|
|||
Sys_Printf ("ALSA: could not set mmap access\n");
|
||||
goto error;
|
||||
}
|
||||
sn.xfer = SNDDMA_ni_xfer;
|
||||
snd->xfer = alsa_ni_xfer;
|
||||
}
|
||||
Sys_Printf ("Using PCM %s.\n", pcmname);
|
||||
|
||||
|
@ -371,8 +442,6 @@ retry_open:
|
|||
(int) period_size, qfsnd_strerror (err));
|
||||
goto error;
|
||||
}
|
||||
int dir;
|
||||
qfsnd_pcm_hw_params_get_period_size (hw, &period_size, &dir);
|
||||
err = qfsnd_pcm_hw_params (pcm, hw);
|
||||
if (0 > err) {
|
||||
Sys_Printf ("ALSA: unable to install hw params: %s\n",
|
||||
|
@ -404,21 +473,19 @@ retry_open:
|
|||
goto error;
|
||||
}
|
||||
|
||||
memset ((dma_t *) &sn, 0, sizeof (sn));
|
||||
sn.channels = stereo + 1;
|
||||
snd->channels = stereo + 1;
|
||||
|
||||
// don't mix less than this in frames:
|
||||
err = qfsnd_pcm_hw_params_get_period_size (hw, (snd_pcm_uframes_t *)
|
||||
(char *)
|
||||
&sn.submission_chunk, 0);
|
||||
err = qfsnd_pcm_hw_params_get_period_size (hw, &period_size, 0);
|
||||
if (0 > err) {
|
||||
Sys_Printf ("ALSA: unable to get period size. %s\n",
|
||||
qfsnd_strerror (err));
|
||||
goto error;
|
||||
}
|
||||
snd->submission_chunk = period_size;
|
||||
|
||||
sn.framepos = 0;
|
||||
sn.samplebits = bps;
|
||||
snd->framepos = 0;
|
||||
snd->samplebits = bps;
|
||||
|
||||
err = qfsnd_pcm_hw_params_get_buffer_size (hw, &buffer_size);
|
||||
if (0 > err) {
|
||||
|
@ -432,46 +499,58 @@ retry_open:
|
|||
Sys_Printf ("to have a power of 2 buffer size\n");
|
||||
}
|
||||
|
||||
sn.frames = buffer_size;
|
||||
sn.speed = rate;
|
||||
SNDDMA_GetDMAPos (); //XXX sets sn.buffer
|
||||
Sys_Printf ("%5d channels %sinterleaved\n", sn.channels,
|
||||
sn.xfer ? "non-" : "");
|
||||
Sys_Printf ("%5d samples (%.1fms)\n", sn.frames,
|
||||
1000.0 * sn.frames / sn.speed);
|
||||
Sys_Printf ("%5d samplepos\n", sn.framepos);
|
||||
Sys_Printf ("%5d samplebits\n", sn.samplebits);
|
||||
Sys_Printf ("%5d submission_chunk (%.1fms)\n", sn.submission_chunk,
|
||||
1000.0 * sn.submission_chunk / sn.speed);
|
||||
Sys_Printf ("%5d speed\n", sn.speed);
|
||||
Sys_Printf ("0x%lx dma buffer\n", (long) sn.buffer);
|
||||
qfsnd_async_add_pcm_handler (&async_haandler, pcm, alsa_callback, snd);
|
||||
|
||||
snd->frames = buffer_size;
|
||||
snd->speed = rate;
|
||||
SNDDMA_GetDMAPos (snd); //XXX sets snd->buffer
|
||||
Sys_Printf ("%5d channels %sinterleaved\n", snd->channels,
|
||||
snd->xfer ? "non-" : "");
|
||||
Sys_Printf ("%5d samples (%.1fms)\n", snd->frames,
|
||||
1000.0 * snd->frames / snd->speed);
|
||||
Sys_Printf ("%5d samplepos\n", snd->framepos);
|
||||
Sys_Printf ("%5d samplebits\n", snd->samplebits);
|
||||
Sys_Printf ("%5d submission_chunk (%.1fms)\n", snd->submission_chunk,
|
||||
1000.0 * snd->submission_chunk / snd->speed);
|
||||
Sys_Printf ("%5d speed\n", snd->speed);
|
||||
Sys_Printf ("0x%lx dma buffer\n", (long) snd->buffer);
|
||||
|
||||
snd_inited = 1;
|
||||
return &sn;
|
||||
|
||||
alsa_pkt_t packet;
|
||||
qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, &packet.nframes);
|
||||
snd->xfer_data = &packet;
|
||||
SND_PaintChannels (snd, snd_paintedtime + packet.nframes);
|
||||
qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes);
|
||||
qfsnd_pcm_start (pcm);
|
||||
|
||||
return 1;
|
||||
error:
|
||||
qfsnd_pcm_close (pcm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SNDDMA_GetDMAPos (void)
|
||||
SNDDMA_GetDMAPos (snd_t *snd)
|
||||
{
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
snd_pcm_uframes_t offset;
|
||||
snd_pcm_uframes_t nframes = sn.frames;
|
||||
snd_pcm_uframes_t nframes = snd->frames;
|
||||
|
||||
qfsnd_pcm_avail_update (pcm);
|
||||
qfsnd_pcm_mmap_begin (pcm, &areas, &offset, &nframes);
|
||||
sn.framepos = offset;
|
||||
sn.buffer = areas->addr;
|
||||
sn.xfer_data = (void *) areas;
|
||||
return sn.framepos;
|
||||
snd->framepos = offset;
|
||||
snd->buffer = areas->addr;
|
||||
snd->xfer_data = (void *) areas;
|
||||
return snd->framepos;
|
||||
}
|
||||
|
||||
static void
|
||||
SNDDMA_shutdown (void)
|
||||
SNDDMA_shutdown (snd_t *snd)
|
||||
{
|
||||
if (snd_inited) {
|
||||
qfsnd_async_del_handler (async_haandler);
|
||||
async_haandler = 0;
|
||||
qfsnd_pcm_close (pcm);
|
||||
snd_inited = 0;
|
||||
}
|
||||
|
@ -483,7 +562,7 @@ SNDDMA_shutdown (void)
|
|||
Send sound to device if buffer isn't really the dma buffer
|
||||
*/
|
||||
static void
|
||||
SNDDMA_Submit (void)
|
||||
SNDDMA_Submit (snd_t *snd)
|
||||
{
|
||||
int state;
|
||||
int count = (*plugin_info_snd_output_data.paintedtime -
|
||||
|
@ -516,14 +595,14 @@ SNDDMA_Submit (void)
|
|||
}
|
||||
|
||||
static void
|
||||
SNDDMA_BlockSound (void)
|
||||
SNDDMA_BlockSound (snd_t *snd)
|
||||
{
|
||||
if (snd_inited && ++snd_blocked == 1)
|
||||
qfsnd_pcm_pause (pcm, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
SNDDMA_UnblockSound (void)
|
||||
SNDDMA_UnblockSound (snd_t *snd)
|
||||
{
|
||||
if (!snd_inited || !snd_blocked)
|
||||
return;
|
||||
|
@ -554,12 +633,12 @@ PLUGIN_INFO(snd_output, alsa)
|
|||
|
||||
plugin_info_general_funcs.init = SNDDMA_Init_Cvars;
|
||||
plugin_info_general_funcs.shutdown = NULL;
|
||||
plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init;
|
||||
plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown;
|
||||
plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos;
|
||||
plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit;
|
||||
plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound;
|
||||
plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound;
|
||||
plugin_info_snd_output_funcs.init = SNDDMA_Init;
|
||||
plugin_info_snd_output_funcs.shutdown = SNDDMA_shutdown;
|
||||
plugin_info_snd_output_funcs.get_dma_pos = SNDDMA_GetDMAPos;
|
||||
plugin_info_snd_output_funcs.submit = SNDDMA_Submit;
|
||||
plugin_info_snd_output_funcs.block_sound = SNDDMA_BlockSound;
|
||||
plugin_info_snd_output_funcs.unblock_sound = SNDDMA_UnblockSound;
|
||||
|
||||
return &plugin_info;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ static int audio_fd;
|
|||
static int snd_inited;
|
||||
static int mmaped_io = 0;
|
||||
static const char *snd_dev = "/dev/dsp";
|
||||
static volatile dma_t sn;
|
||||
|
||||
static int tryrates[] = { 44100, 48000, 11025, 22050, 22051, 44100, 8000 };
|
||||
|
||||
|
@ -112,8 +111,8 @@ SNDDMA_Init_Cvars (void)
|
|||
"mmaped io");
|
||||
}
|
||||
|
||||
static volatile dma_t *
|
||||
try_open (int rw)
|
||||
static int
|
||||
try_open (snd_t *snd, int rw)
|
||||
{
|
||||
int caps, fmt, rc, tmp, i;
|
||||
int retries = 3;
|
||||
|
@ -169,21 +168,21 @@ try_open (int rw)
|
|||
}
|
||||
|
||||
// set sample bits & speed
|
||||
sn.samplebits = snd_bits->int_val;
|
||||
snd->samplebits = snd_bits->int_val;
|
||||
|
||||
if (sn.samplebits != 16 && sn.samplebits != 8) {
|
||||
if (snd->samplebits != 16 && snd->samplebits != 8) {
|
||||
ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
|
||||
|
||||
if (fmt & AFMT_S16_LE) { // little-endian 16-bit signed
|
||||
sn.samplebits = 16;
|
||||
snd->samplebits = 16;
|
||||
} else {
|
||||
if (fmt & AFMT_U8) { // unsigned 8-bit ulaw
|
||||
sn.samplebits = 8;
|
||||
snd->samplebits = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sn.samplebits == 16) {
|
||||
if (snd->samplebits == 16) {
|
||||
rc = AFMT_S16_LE;
|
||||
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
|
||||
if (rc < 0) {
|
||||
|
@ -192,7 +191,7 @@ try_open (int rw)
|
|||
close (audio_fd);
|
||||
return 0;
|
||||
}
|
||||
} else if (sn.samplebits == 8) {
|
||||
} else if (snd->samplebits == 8) {
|
||||
rc = AFMT_U8;
|
||||
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
|
||||
if (rc < 0) {
|
||||
|
@ -202,39 +201,39 @@ try_open (int rw)
|
|||
return 0;
|
||||
}
|
||||
} else {
|
||||
Sys_Printf ("%d-bit sound not supported. %s", sn.samplebits,
|
||||
Sys_Printf ("%d-bit sound not supported. %s", snd->samplebits,
|
||||
strerror (errno));
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = sn.channels;
|
||||
tmp = snd->channels;
|
||||
rc = ioctl (audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
|
||||
if (rc < 0) {
|
||||
Sys_Printf ("Could not set %s to stereo=%d: %s\n", snd_dev,
|
||||
sn.channels, strerror (errno));
|
||||
snd->channels, strerror (errno));
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snd_rate->int_val) {
|
||||
sn.speed = snd_rate->int_val;
|
||||
snd->speed = snd_rate->int_val;
|
||||
} else {
|
||||
for (i = 0; i < ((int) sizeof (tryrates) / 4); i++)
|
||||
if (!ioctl (audio_fd, SNDCTL_DSP_SPEED, &tryrates[i]))
|
||||
break;
|
||||
sn.speed = tryrates[i];
|
||||
snd->speed = tryrates[i];
|
||||
}
|
||||
|
||||
if (!snd_stereo->int_val) {
|
||||
sn.channels = 1;
|
||||
snd->channels = 1;
|
||||
} else {
|
||||
sn.channels = 2;
|
||||
snd->channels = 2;
|
||||
}
|
||||
|
||||
rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &sn.speed);
|
||||
rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &snd->speed);
|
||||
if (rc < 0) {
|
||||
Sys_Printf ("Could not set %s speed to %d: %s\n", snd_dev, sn.speed,
|
||||
Sys_Printf ("Could not set %s speed to %d: %s\n", snd_dev, snd->speed,
|
||||
strerror (errno));
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
|
@ -246,25 +245,25 @@ try_open (int rw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
sn.frames = info.fragstotal * info.fragsize;
|
||||
sn.frames /= sn.channels * sn.samplebits / 8;
|
||||
sn.submission_chunk = 1;
|
||||
snd->frames = info.fragstotal * info.fragsize;
|
||||
snd->frames /= snd->channels * snd->samplebits / 8;
|
||||
snd->submission_chunk = 1;
|
||||
|
||||
if (mmaped_io) { // memory map the dma buffer
|
||||
unsigned long sz = sysconf (_SC_PAGESIZE);
|
||||
unsigned long len = info.fragstotal * info.fragsize;
|
||||
|
||||
len = (len + sz - 1) & ~(sz - 1);
|
||||
sn.buffer = (byte *) mmap (NULL, len, mmmode, mmflags, audio_fd, 0);
|
||||
if (sn.buffer == MAP_FAILED) {
|
||||
snd->buffer = (byte *) mmap (NULL, len, mmmode, mmflags, audio_fd, 0);
|
||||
if (snd->buffer == MAP_FAILED) {
|
||||
Sys_MaskPrintf (SYS_snd, "Could not mmap %s: %s\n", snd_dev,
|
||||
strerror (errno));
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
sn.buffer = malloc (sn.frames * sn.channels * (sn.samplebits / 8));
|
||||
if (!sn.buffer) {
|
||||
snd->buffer = malloc (snd->frames * snd->channels * (snd->samplebits / 8));
|
||||
if (!snd->buffer) {
|
||||
Sys_Printf ("SNDDMA_Init: memory allocation failure\n");
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
|
@ -277,7 +276,7 @@ try_open (int rw)
|
|||
if (rc < 0) {
|
||||
Sys_Printf ("Could not toggle.: %s\n", strerror (errno));
|
||||
if (mmaped_io)
|
||||
munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8);
|
||||
munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8);
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -286,28 +285,25 @@ try_open (int rw)
|
|||
if (rc < 0) {
|
||||
Sys_Printf ("Could not toggle.: %s\n", strerror (errno));
|
||||
if (mmaped_io)
|
||||
munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8);
|
||||
munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8);
|
||||
close (audio_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sn.framepos = 0;
|
||||
snd->framepos = 0;
|
||||
|
||||
snd_inited = 1;
|
||||
return &sn;
|
||||
}
|
||||
|
||||
static volatile dma_t *
|
||||
SNDDMA_Init (void)
|
||||
{
|
||||
volatile dma_t *shm;
|
||||
if ((shm = try_open (0)))
|
||||
return shm;
|
||||
return try_open (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
SNDDMA_GetDMAPos (void)
|
||||
SNDDMA_Init (snd_t *snd)
|
||||
{
|
||||
return try_open (snd, 0) || try_open (snd, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
SNDDMA_GetDMAPos (snd_t *snd)
|
||||
{
|
||||
struct count_info count;
|
||||
|
||||
|
@ -317,34 +313,32 @@ SNDDMA_GetDMAPos (void)
|
|||
if (ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
|
||||
Sys_Printf ("Uh, %s dead: %s\n", snd_dev, strerror (errno));
|
||||
if (mmaped_io)
|
||||
munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8);
|
||||
munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8);
|
||||
close (audio_fd);
|
||||
snd_inited = 0;
|
||||
return 0;
|
||||
}
|
||||
// sn.samplepos = (count.bytes / (sn.samplebits / 8)) & (sn.samples-1);
|
||||
// fprintf(stderr, "%d \r", count.ptr);
|
||||
sn.framepos = count.ptr / (sn.channels * sn.samplebits / 8);
|
||||
snd->framepos = count.ptr / (snd->channels * snd->samplebits / 8);
|
||||
|
||||
return sn.framepos;
|
||||
return snd->framepos;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
SNDDMA_shutdown (void)
|
||||
SNDDMA_shutdown (snd_t *snd)
|
||||
{
|
||||
if (snd_inited) {
|
||||
if (mmaped_io)
|
||||
munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8);
|
||||
munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8);
|
||||
close (audio_fd);
|
||||
snd_inited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sample_bytes (int frames)
|
||||
sample_bytes (snd_t *snd, int frames)
|
||||
{
|
||||
return frames * sn.channels * sn.samplebits / 8;
|
||||
return frames * snd->channels * snd->samplebits / 8;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -353,7 +347,7 @@ sample_bytes (int frames)
|
|||
Send sound to device if buffer isn't really the dma buffer
|
||||
*/
|
||||
static void
|
||||
SNDDMA_Submit (void)
|
||||
SNDDMA_Submit (snd_t *snd)
|
||||
{
|
||||
int frames;
|
||||
int len;
|
||||
|
@ -362,17 +356,17 @@ SNDDMA_Submit (void)
|
|||
if (snd_inited && !mmaped_io) {
|
||||
frames = *plugin_info_snd_output_data.paintedtime
|
||||
- *plugin_info_snd_output_data.soundtime;
|
||||
offset = frames * sn.channels * sn.samplebits / 8;
|
||||
offset = frames * snd->channels * snd->samplebits / 8;
|
||||
|
||||
if (sn.framepos + frames <= sn.frames) {
|
||||
len = sample_bytes (frames);
|
||||
if (write (audio_fd, sn.buffer + offset, len) != len)
|
||||
if (snd->framepos + frames <= snd->frames) {
|
||||
len = sample_bytes (snd, frames);
|
||||
if (write (audio_fd, snd->buffer + offset, len) != len)
|
||||
Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno));
|
||||
} else {
|
||||
int len = sample_bytes (sn.frames - sn.framepos);
|
||||
if (write (audio_fd, sn.buffer + offset, len) != len)
|
||||
int len = sample_bytes (snd, snd->frames - snd->framepos);
|
||||
if (write (audio_fd, snd->buffer + offset, len) != len)
|
||||
Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno));
|
||||
if (write (audio_fd, sn.buffer, offset - len) != offset - len)
|
||||
if (write (audio_fd, snd->buffer, offset - len) != offset - len)
|
||||
Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno));
|
||||
}
|
||||
*plugin_info_snd_output_data.soundtime += frames;
|
||||
|
@ -380,12 +374,12 @@ SNDDMA_Submit (void)
|
|||
}
|
||||
|
||||
static void
|
||||
SNDDMA_BlockSound (void)
|
||||
SNDDMA_BlockSound (snd_t *snd)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
SNDDMA_UnblockSound (void)
|
||||
SNDDMA_UnblockSound (snd_t *snd)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -412,12 +406,12 @@ PLUGIN_INFO(snd_output, oss)
|
|||
|
||||
plugin_info_general_funcs.init = SNDDMA_Init_Cvars;
|
||||
plugin_info_general_funcs.shutdown = NULL;
|
||||
plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init;
|
||||
plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown;
|
||||
plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos;
|
||||
plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit;
|
||||
plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound;
|
||||
plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound;
|
||||
plugin_info_snd_output_funcs.init = SNDDMA_Init;
|
||||
plugin_info_snd_output_funcs.shutdown = SNDDMA_shutdown;
|
||||
plugin_info_snd_output_funcs.get_dma_pos = SNDDMA_GetDMAPos;
|
||||
plugin_info_snd_output_funcs.submit = SNDDMA_Submit;
|
||||
plugin_info_snd_output_funcs.block_sound = SNDDMA_BlockSound;
|
||||
plugin_info_snd_output_funcs.unblock_sound = SNDDMA_UnblockSound;
|
||||
|
||||
return &plugin_info;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue