From 2bb2d14b8961e65f2307fdcf53387f1b8839fd80 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Aug 2010 23:43:35 +0000 Subject: [PATCH] make "sample counts" frame based rather than mono sample based that was always horribly confusing --- include/QF/sound.h | 4 ++- include/snd_render.h | 5 ++-- libs/audio/renderer/snd_dma.c | 50 +++++++++++++++++------------------ libs/audio/targets/snd_alsa.c | 20 +++++++------- libs/audio/targets/snd_disk.c | 4 +-- libs/audio/targets/snd_oss.c | 47 +++++++++++++++++--------------- libs/audio/targets/snd_sdl.c | 36 ++++++++++++------------- 7 files changed, 86 insertions(+), 80 deletions(-) diff --git a/include/QF/sound.h b/include/QF/sound.h index 37a6401a9..c0b54c12a 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -55,11 +55,13 @@ struct sfx_s struct sfxbuffer_s *(*touch) (sfx_t *sfx); struct sfxbuffer_s *(*retain) (sfx_t *sfx); + void (*release) (sfx_t *sfx); + struct sfxbuffer_s *(*getbuffer) (sfx_t *sfx); struct wavinfo_s *(*wavinfo) (sfx_t *sfx); + sfx_t *(*open) (sfx_t *sfx); void (*close) (sfx_t *sfx); - void (*release) (sfx_t *sfx); }; //@} diff --git a/include/snd_render.h b/include/snd_render.h index b0a90877a..29e6df3d7 100644 --- a/include/snd_render.h +++ b/include/snd_render.h @@ -64,9 +64,10 @@ struct dma_s { int speed; //!< sample rate int samplebits; //!< bits per sample int channels; //!< number of output channels - int samples; //!< mono samples in buffer + int frames; //!< frames in buffer + //!< 1 frame = channels samples int submission_chunk; //!< don't mix less than this # - int samplepos; //!< in mono samples + int framepos; //!< ?? unsigned char *buffer; //!< destination for mixed sound /** Transfer mixed samples to the output. \param endtime sample end time (count = endtime - snd_paintedtime) diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index ca65bb31b..5976861d6 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -80,7 +80,7 @@ SND_WriteLinearBlastStereo16 (void) { int val, i; - for (i = 0; i < snd_linear_count; i += 2) { + for (i = 0; i < snd_linear_count * 2; i += 2) { val = (snd_p[i] * snd_vol) >> 8; if (val > 0x7fff) snd_out[i] = 0x7fff; @@ -103,7 +103,7 @@ static void s_xfer_stereo_16 (int endtime) { int lpaintedtime, lpos; - unsigned int *pbuf; + short *pbuf; snd_vol = snd_volume->value * 256; @@ -111,25 +111,23 @@ s_xfer_stereo_16 (int endtime) lpaintedtime = snd_paintedtime; - pbuf = (unsigned int *) snd_shm->buffer; + pbuf = (short *) snd_shm->buffer; while (lpaintedtime < endtime) { // handle recirculating buffer issues - lpos = lpaintedtime & ((snd_shm->samples >> 1) - 1); + lpos = lpaintedtime & (snd_shm->frames - 1); - snd_out = (short *) pbuf + (lpos << 1); + snd_out = pbuf + (lpos << 1); - snd_linear_count = (snd_shm->samples >> 1) - lpos; + snd_linear_count = snd_shm->frames - lpos; if (lpaintedtime + snd_linear_count > endtime) snd_linear_count = endtime - lpaintedtime; - snd_linear_count <<= 1; - // write a linear blast of samples SND_WriteLinearBlastStereo16 (); - snd_p += snd_linear_count; - lpaintedtime += (snd_linear_count >> 1); + snd_p += snd_linear_count << 1; + lpaintedtime += snd_linear_count; } } @@ -147,7 +145,7 @@ s_xfer_paint_buffer (int endtime) p = (int *) snd_paintbuffer; count = (endtime - snd_paintedtime) * snd_shm->channels; - out_mask = snd_shm->samples - 1; + out_mask = snd_shm->frames - 1; out_idx = snd_paintedtime * snd_shm->channels & out_mask; step = 3 - snd_shm->channels; snd_vol = snd_volume->value * 256; @@ -187,6 +185,7 @@ static void s_clear_buffer (void) { int clear, i; + int count; if (!sound_started || !snd_shm || !snd_shm->buffer) return; @@ -196,7 +195,8 @@ s_clear_buffer (void) else clear = 0; - for (i = 0; i < snd_shm->samples * snd_shm->samplebits / 8; i++) + count = snd_shm->frames * snd_shm->channels * snd_shm->samplebits / 8; + for (i = 0; i < count; i++) snd_shm->buffer[i] = clear; } @@ -213,29 +213,29 @@ s_stop_all_sounds (void) static void s_get_soundtime (void) { - int fullsamples, samplepos; - static int buffers, oldsamplepos; + int frames, framepos; + static int buffers, oldframepos; - fullsamples = snd_shm->samples / snd_shm->channels; + frames = snd_shm->frames; // it is possible to miscount buffers if it has wrapped twice between // calls to s_update. Oh well. - if ((samplepos = snd_output_funcs->pS_O_GetDMAPos ()) == -1) + if ((framepos = snd_output_funcs->pS_O_GetDMAPos ()) == -1) return; - if (samplepos < oldsamplepos) { + if (framepos < oldframepos) { buffers++; // buffer wrapped if (snd_paintedtime > 0x40000000) { // time to chop things off to avoid // 32 bit limits buffers = 0; - snd_paintedtime = fullsamples; + snd_paintedtime = frames; s_stop_all_sounds (); } } - oldsamplepos = samplepos; + oldframepos = framepos; - soundtime = buffers * fullsamples + samplepos / snd_shm->channels; + soundtime = buffers * frames + framepos; } static void @@ -256,7 +256,7 @@ s_update_ (void) } // mix ahead of current position endtime = soundtime + snd_mixahead->value * snd_shm->speed; - samps = snd_shm->samples >> (snd_shm->channels - 1); + samps = snd_shm->frames; if (endtime - soundtime > samps) endtime = soundtime + samps; @@ -322,13 +322,13 @@ s_soundinfo_f (void) return; } - Sys_Printf ("%5d stereo\n", snd_shm->channels - 1); - Sys_Printf ("%5d samples\n", snd_shm->samples); - Sys_Printf ("%5d samplepos\n", snd_shm->samplepos); + 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%p dma buffer\n", snd_shm->buffer); + Sys_Printf ("0x%lx dma buffer\n", (long) snd_shm->buffer); Sys_Printf ("%5d total_channels\n", snd_total_channels); } diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index f315e78e0..a4e0f9362 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -321,7 +321,7 @@ SNDDMA_Init (void) memset ((dma_t *) &sn, 0, sizeof (sn)); sn.channels = stereo + 1; - // don't mix less than this in mono samples: + // 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); @@ -331,7 +331,7 @@ SNDDMA_Init (void) goto error; } - sn.samplepos = 0; + sn.framepos = 0; sn.samplebits = bps; err = qfsnd_pcm_hw_params_get_buffer_size (hw, &buffer_size); @@ -346,12 +346,12 @@ SNDDMA_Init (void) Sys_Printf ("to have a power of 2 buffer size\n"); } - sn.samples = buffer_size * sn.channels; + sn.frames = buffer_size; sn.speed = rate; SNDDMA_GetDMAPos (); //XXX sets sn.buffer - Sys_Printf ("%5d stereo\n", sn.channels - 1); - Sys_Printf ("%5d samples\n", sn.samples); - Sys_Printf ("%5d samplepos\n", sn.samplepos); + Sys_Printf ("%5d channels\n", sn.channels); + Sys_Printf ("%5d samples\n", sn.frames); + Sys_Printf ("%5d samplepos\n", sn.framepos); Sys_Printf ("%5d samplebits\n", sn.samplebits); Sys_Printf ("%5d submission_chunk\n", sn.submission_chunk); Sys_Printf ("%5d speed\n", sn.speed); @@ -369,15 +369,13 @@ SNDDMA_GetDMAPos (void) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset; - snd_pcm_uframes_t nframes = sn.samples/sn.channels; + snd_pcm_uframes_t nframes = sn.frames; qfsnd_pcm_avail_update (pcm); qfsnd_pcm_mmap_begin (pcm, &areas, &offset, &nframes); - offset *= sn.channels; - nframes *= sn.channels; - sn.samplepos = offset; + sn.framepos = offset; sn.buffer = areas->addr; //XXX FIXME there's an area per channel - return sn.samplepos; + return sn.framepos; } static void diff --git a/libs/audio/targets/snd_disk.c b/libs/audio/targets/snd_disk.c index 04084d048..27b178f71 100644 --- a/libs/audio/targets/snd_disk.c +++ b/libs/audio/targets/snd_disk.c @@ -104,8 +104,8 @@ SNDDMA_Init (void) static int SNDDMA_GetDMAPos (void) { - sn.samplepos = 0; - return sn.samplepos; + sn.framepos = 0; + return sn.framepos; } static void diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c index 6fa5c08b6..6f21b03e8 100644 --- a/libs/audio/targets/snd_oss.c +++ b/libs/audio/targets/snd_oss.c @@ -250,7 +250,7 @@ try_open (int rw) return 0; } - sn.samples = info.fragstotal * info.fragsize / (sn.samplebits / 8); + sn.frames = info.fragstotal; sn.submission_chunk = 1; if (mmaped_io) { // memory map the dma buffer @@ -265,7 +265,7 @@ try_open (int rw) return 0; } } else { - sn.buffer = malloc (sn.samples * (sn.samplebits / 8) * 2); + sn.buffer = malloc (sn.frames * sn.channels * (sn.samplebits / 8)); if (!sn.buffer) { Sys_Printf ("SNDDMA_Init: memory allocation failure\n"); close (audio_fd); @@ -279,7 +279,7 @@ try_open (int rw) if (rc < 0) { Sys_Printf ("Could not toggle.: %s\n", strerror (errno)); if (mmaped_io) - munmap (sn.buffer, sn.samples * sn.samplebits / 8); + munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); close (audio_fd); return 0; } @@ -288,12 +288,12 @@ try_open (int rw) if (rc < 0) { Sys_Printf ("Could not toggle.: %s\n", strerror (errno)); if (mmaped_io) - munmap (sn.buffer, sn.samples * sn.samplebits / 8); + munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); close (audio_fd); return 0; } - sn.samplepos = 0; + sn.framepos = 0; snd_inited = 1; return &sn; @@ -319,16 +319,16 @@ 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.samples * sn.samplebits / 8); + munmap (sn.buffer, sn.frames * sn.channels * sn.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.samplepos = count.ptr / (sn.samplebits / 8); + sn.framepos = count.ptr / (sn.samplebits / 8) / sn.channels; //XXX??? - return sn.samplepos; + return sn.framepos; } @@ -337,14 +337,17 @@ SNDDMA_Shutdown (void) { if (snd_inited) { if (mmaped_io) - munmap (sn.buffer, sn.samples * sn.samplebits / 8); + munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); close (audio_fd); snd_inited = 0; } } -#define BITSIZE (sn.samplebits / 8) -#define BYTES (samples / BITSIZE) +static int +sample_bytes (int frames) +{ + return frames * sn.channels * sn.samplebits / 8; +} /* SNDDMA_Submit @@ -354,25 +357,27 @@ SNDDMA_Shutdown (void) static void SNDDMA_Submit (void) { - int samples; + int frames; + int len; + int offset; if (snd_inited && !mmaped_io) { - samples = *plugin_info_snd_output_data.paintedtime + frames = *plugin_info_snd_output_data.paintedtime - *plugin_info_snd_output_data.soundtime; + offset = frames * sn.channels * sn.samplebits / 8; - if (sn.samplepos + BYTES <= sn.samples) { - if (write (audio_fd, sn.buffer + BYTES, samples) != samples) + if (sn.framepos + frames <= sn.frames) { + len = sample_bytes (frames); + if (write (audio_fd, sn.buffer + offset, len) != len) Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno)); } else { - if (write (audio_fd, sn.buffer + BYTES, sn.samples - - sn.samplepos) != sn.samples - sn.samplepos) + int len = sample_bytes (sn.frames - sn.framepos); + if (write (audio_fd, sn.buffer + offset, len) != len) Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno)); - if (write (audio_fd, sn.buffer, BYTES - (sn.samples - - sn.samplepos)) != - BYTES - (sn.samples - sn.samplepos)) + if (write (audio_fd, sn.buffer, offset - len) != offset - len) Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno)); } - *plugin_info_snd_output_data.soundtime += samples; + *plugin_info_snd_output_data.soundtime += frames; } } diff --git a/libs/audio/targets/snd_sdl.c b/libs/audio/targets/snd_sdl.c index 59d5a185b..3c7c703f2 100644 --- a/libs/audio/targets/snd_sdl.c +++ b/libs/audio/targets/snd_sdl.c @@ -69,25 +69,25 @@ static snd_output_funcs_t plugin_info_snd_output_funcs; static void paint_audio (void *unused, Uint8 * stream, int len) { - int sampleposbytes, samplesbytes, streamsamples; + int frameposbytes, framesbytes, frames; - streamsamples = len / (sn.samplebits / 8); - sampleposbytes = sn.samplepos * (sn.samplebits / 8); - samplesbytes = sn.samples * (sn.samplebits / 8); + frames = len / (sn.channels * (sn.samplebits / 8)); + frameposbytes = sn.framepos * sn.channels * (sn.samplebits / 8); + framesbytes = sn.frames * sn.channels * (sn.samplebits / 8); - sn.samplepos += streamsamples; - while (sn.samplepos >= sn.samples) - sn.samplepos -= sn.samples; + sn.framepos += frames; + while (sn.framepos >= sn.frames) + sn.framepos -= sn.frames; - if (sn.samplepos + streamsamples <= sn.samples) - memcpy (stream, sn.buffer + sampleposbytes, len); + if (sn.framepos + frames <= sn.frames) + memcpy (stream, sn.buffer + frameposbytes, len); else { - memcpy (stream, sn.buffer + sampleposbytes, samplesbytes - - sampleposbytes); - memcpy (stream + samplesbytes - sampleposbytes, sn.buffer, len - - (samplesbytes - sampleposbytes)); + memcpy (stream, sn.buffer + frameposbytes, framesbytes - + frameposbytes); + memcpy (stream + framesbytes - frameposbytes, sn.buffer, len - + (framesbytes - frameposbytes)); } - *plugin_info_snd_output_data.soundtime += streamsamples; + *plugin_info_snd_output_data.soundtime += frames; } static void @@ -165,10 +165,10 @@ SNDDMA_Init (void) sn.samplebits = (obtained.format & 0xFF); sn.speed = obtained.freq; sn.channels = obtained.channels; - sn.samples = obtained.samples * 16; - sn.samplepos = 0; + sn.frames = obtained.samples * 8; // 8 chunks in the buffer + sn.framepos = 0; sn.submission_chunk = 1; - sn.buffer = calloc(sn.samples * (sn.samplebits / 8), 1); + sn.buffer = calloc(sn.frames * sn.channels * (sn.samplebits / 8), 1); if (!sn.buffer) { Sys_Error ("Failed to allocate buffer for sound!"); @@ -181,7 +181,7 @@ SNDDMA_Init (void) static int SNDDMA_GetDMAPos (void) { - return sn.samplepos; + return sn.framepos; } static void