diff --git a/include/snd_internal.h b/include/snd_internal.h index 91e0a53c7..5690b98fb 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -77,6 +77,7 @@ struct snd_s { int frames; //!< frames in buffer //!< 1 frame = channels samples int submission_chunk; //!< don't mix less than this # + unsigned paintedtime; //!< sound clock in samples int framepos; //!< position of dma cursor unsigned char *buffer; //!< destination for mixed sound /** Transfer mixed samples to the output. @@ -90,6 +91,9 @@ struct snd_s { /** Optional data for the xfer function. */ void *xfer_data; + + void (*finish_channels) (void); + void (*paint_channels) (struct snd_s *snd, unsigned endtime); }; /** Describes the sound data. @@ -318,6 +322,12 @@ struct channel_s *SND_AllocChannel (snd_t *snd); */ void SND_ChannelStop (snd_t *snd, channel_t *chan); +/** Mark all channels as no longer in use. + + For use by asynchronous output drivers. +*/ +void SND_FinishChannels (void); + /** 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 @@ -397,9 +407,6 @@ void SND_LocalSound (snd_t *snd, const char *s); \ingroup sound_render */ ///@{ -/** sound clock in samples -*/ -extern unsigned snd_paintedtime; /** Mix all active channels into the output buffer. \param endtime sample time until when to mix diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 7c0d27efc..d08706d65 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -183,6 +183,18 @@ SND_ScanChannels (snd_t *snd, int wait) } } +void +SND_FinishChannels (void) +{ + int i; + channel_t *ch; + + for (i = 0; i < MAX_CHANNELS; i++) { + ch = &snd_channels[i]; + ch->done = ch->stop = 1; + } +} + void SND_StopAllSounds (snd_t *snd) { diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 35df3fc69..489f3b620 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -70,7 +70,10 @@ static general_data_t plugin_info_general_data; static snd_output_funcs_t *snd_output_funcs; static snd_output_data_t *snd_output_data; -static snd_t snd; +static snd_t snd = { + .finish_channels = SND_FinishChannels, + .paint_channels = SND_PaintChannels, +}; static int snd_shutdown = 0; static void @@ -83,7 +86,7 @@ s_xfer_paint_buffer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, p = (float *) paintbuffer; count *= snd->channels; out_max = (snd->frames * snd->channels) - 1; - out_idx = snd_paintedtime * snd->channels; + out_idx = snd->paintedtime * snd->channels; while (out_idx > out_max) out_idx -= out_max + 1; step = 3 - snd->channels; @@ -164,10 +167,10 @@ s_get_soundtime (void) if (framepos < oldframepos) { buffers++; // buffer wrapped - if (snd_paintedtime > 0x40000000) { // time to chop things off to avoid + if (snd.paintedtime > 0x40000000) { // time to chop things off to avoid // 32 bit limits buffers = 0; - snd_paintedtime = frames; + snd.paintedtime = frames; s_stop_all_sounds (); } } @@ -188,9 +191,9 @@ s_update_ (void) s_get_soundtime (); // check to make sure that we haven't overshot - if (snd_paintedtime < soundtime) { + if (snd.paintedtime < soundtime) { // Sys_Printf ("S_Update_ : overflow\n"); - snd_paintedtime = soundtime; + snd.paintedtime = soundtime; } // mix ahead of current position endtime = soundtime + snd_mixahead->value * snd.speed; @@ -492,6 +495,10 @@ static plugin_funcs_t plugin_info_funcs = { .snd_render = &plugin_info_render_funcs, }; +snd_render_data_t snd_render_data = { + .paintedtime = &snd.paintedtime, +}; + static plugin_data_t plugin_info_data = { .general = &plugin_info_general_data, .snd_render = &snd_render_data, diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 6f21a1f6f..c76d3e923 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -51,14 +51,6 @@ #define SAMPLE_GAP 4 -snd_render_data_t snd_render_data = { - 0, - 0, - 0, - &snd_paintedtime, - 0, -}; - static sfxbuffer_t * snd_fail (sfx_t *sfx) { diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index f993852a9..d26b4e430 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -50,8 +50,6 @@ cvar_t *snd_volume; -unsigned snd_paintedtime; // sample PAIRS - portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; static int max_overpaint; // number of extra samples painted // due to phase shift @@ -118,11 +116,11 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) snd_paintbuffer[i].right = 0; } - while (snd_paintedtime < endtime) { + while (snd->paintedtime < endtime) { // if snd_paintbuffer is smaller than DMA buffer end = endtime; - if (end - snd_paintedtime > PAINTBUFFER_SIZE) - end = snd_paintedtime + PAINTBUFFER_SIZE; + if (end - snd->paintedtime > PAINTBUFFER_SIZE) + end = snd->paintedtime + PAINTBUFFER_SIZE; max_overpaint = 0; @@ -144,9 +142,9 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) } if (!ch->end) - ch->end = snd_paintedtime + sfx->length - ch->pos; + ch->end = snd->paintedtime + sfx->length - ch->pos; - ltime = snd_paintedtime; + ltime = snd->paintedtime; while (ltime < end) { // paint up to end count = ((ch->end < end) ? ch->end : end) - ltime; @@ -171,15 +169,15 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) } // transfer out according to DMA format - snd->xfer (snd, snd_paintbuffer, end - snd_paintedtime, + snd->xfer (snd, snd_paintbuffer, end - snd->paintedtime, snd_volume->value); - memmove (snd_paintbuffer, snd_paintbuffer + end - snd_paintedtime, + memmove (snd_paintbuffer, snd_paintbuffer + end - snd->paintedtime, max_overpaint * sizeof (snd_paintbuffer[0])); memset (snd_paintbuffer + max_overpaint, 0, sizeof (snd_paintbuffer) - max_overpaint * sizeof (snd_paintbuffer[0])); - snd_paintedtime = end; + snd->paintedtime = end; } } diff --git a/libs/audio/targets/Makemodule.am b/libs/audio/targets/Makemodule.am index 9b05e055b..8997eb847 100644 --- a/libs/audio/targets/Makemodule.am +++ b/libs/audio/targets/Makemodule.am @@ -21,14 +21,15 @@ libs_audio_targets_snd_output_sdl_la_SOURCES= libs/audio/targets/snd_sdl.c libs_audio_targets_snd_output_alsa_la_LDFLAGS= $(plugin_ldflags) libs_audio_targets_snd_output_alsa_la_LIBADD= $(snd_deps) -libs_audio_targets_snd_output_alsa_la_DEPENDENCIES=$(snd_deps) +libs_audio_targets_snd_output_alsa_la_DEPENDENCIES= $(snd_deps) libs_audio_targets_snd_output_alsa_la_CFLAGS= $(ALSA_CFLAGS) libs_audio_targets_snd_output_alsa_la_SOURCES= libs/audio/targets/snd_alsa.c -libs_audio_targets_snd_output_jack_la_LDFLAGS= $(plugin_ldflags) -libs_audio_targets_snd_output_jack_la_SOURCES= libs/audio/targets/snd_jack.c $(snd_common) $(format_src) -libs_audio_targets_snd_output_jack_la_LIBADD= $(snd_libs) $(format_libs) $(JACK_LIBS) +libs_audio_targets_snd_output_jack_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_jack_la_LIBADD= $(snd_deps) $(JACK_LIBS) libs_audio_targets_snd_output_jack_la_DEPENDENCIES= $(snd_libs) +libs_audio_targets_snd_output_jack_la_CFLAGS= $(JACK_CFLAGS) +libs_audio_targets_snd_output_jack_la_SOURCES= libs/audio/targets/snd_jack.c libs_audio_targets_snd_output_oss_la_LDFLAGS= $(plugin_ldflags) libs_audio_targets_snd_output_oss_la_LIBADD= $(snd_deps) $(OSS_LIBS) diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index f0e1c52a8..fdee222b1 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -202,7 +202,7 @@ alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, p = (float *) paintbuffer; count *= snd->channels; out_max = (snd->frames * snd->channels) - 1; - out_idx = snd_paintedtime * snd->channels; + out_idx = snd->paintedtime * snd->channels; while (out_idx > out_max) out_idx -= out_max + 1; step = 3 - snd->channels; @@ -288,7 +288,7 @@ alsa_process (snd_pcm_t *pcm, snd_t *snd) ret = 0; } snd->buffer = packet.areas[0].addr; - SND_PaintChannels (snd, snd_paintedtime + packet.nframes); + snd->paint_channels (snd, snd->paintedtime + packet.nframes); if ((res = qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes)) < 0 || (snd_pcm_uframes_t) res != packet.nframes) { diff --git a/libs/audio/targets/snd_jack.c b/libs/audio/targets/snd_jack.c index 0d9f282c9..d2c299410 100644 --- a/libs/audio/targets/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -59,18 +59,6 @@ static cvar_t *snd_jack_server; static int s_jack_connect (snd_t *snd); -static void -s_finish_channels (void) -{ - int i; - channel_t *ch; - - for (i = 0; i < MAX_CHANNELS; i++) { - ch = &snd_channels[i]; - ch->done = ch->stop = 1; - } -} - static void s_update (snd_t *snd) { @@ -85,7 +73,7 @@ s_update (snd_t *snd) if (!snd_shutdown) { if (now - snd_alive_time > 1.0) { Sys_Printf ("jackd client thread seems to have died\n"); - s_finish_channels (); + snd->finish_channels (); snd_shutdown = 1; } } @@ -162,8 +150,8 @@ snd_jack_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, } for (i = 0; i < count; i++) { /* max is +/- 1.0. need to implement clamping. */ - *output[0]++ = volume * snd_paintbuffer[i].left; - *output[1]++ = volume * snd_paintbuffer[i].right; + *output[0]++ = volume * paintbuffer[i].left; + *output[1]++ = volume * paintbuffer[i].right; } } @@ -176,15 +164,17 @@ 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, snd_paintedtime + nframes); + snd->paint_channels (snd, snd->paintedtime + nframes); return 0; } static void snd_jack_shutdown (void *arg) { + snd_t *snd = arg; + snd_shutdown = 1; - s_finish_channels (); + snd->finish_channels (); } static void @@ -217,12 +207,13 @@ s_jack_connect (snd_t *snd) if (jack_set_xrun_callback (jack_handle, snd_jack_xrun, 0)) Sys_Printf ("Could not set xrun callback\n"); jack_set_process_callback (jack_handle, snd_jack_process, snd); - jack_on_shutdown (jack_handle, snd_jack_shutdown, 0); + jack_on_shutdown (jack_handle, snd_jack_shutdown, snd); for (i = 0; i < 2; i++) jack_out[i] = jack_port_register (jack_handle, va (0, "out_%d", i + 1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); snd->speed = jack_get_sample_rate (jack_handle); + snd->channels = 2; s_jack_activate (); sound_started = 1; Sys_Printf ("Connected to JACK: %d Sps\n", snd->speed);