From 5e73f9ff2087cc82705b49fc813a6b60633ac756 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sat, 13 Dec 2008 01:32:39 +0000 Subject: Fix FS#8660-Recording hardlocks with keyclick enabled and FS#9388-keyclicks too late. Introduce audio_buffer_state to check whether PCM buffer is useable or disabled (trashed). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19411 a1c6a512-1295-4272-9138-f99709370657 --- apps/pcmbuf.c | 59 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'apps/pcmbuf.c') diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 695dfc55dc..5b9e7270cc 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -959,23 +959,37 @@ bool pcmbuf_insert_buffer(char *buf, int count) in Hertz for a duration in milliseconds. */ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) { - int i; - unsigned int step = 0xffffffffu / NATIVE_FREQUENCY * frequency; - int32_t phase = 0; - int samples = NATIVE_FREQUENCY / 1000 * duration; + unsigned int step; + int32_t phase; + int16_t *bufptr, *bufstart, *bufend; int32_t sample; - int16_t *bufstart; - int16_t *bufptr; - int16_t *pcmbuf_end = (int16_t *)fadebuf; - bool mix = pcmbuf_read != NULL && pcmbuf_read->link != NULL; + int nsamples; + bool mix; + int i; + + if (audio_buffer_state() == AUDIOBUF_STATE_TRASHED) + return; /* No voice or playback = no beeping. */ + + phase = 0; + step = 0xffffffffu / NATIVE_FREQUENCY * frequency; + nsamples = NATIVE_FREQUENCY / 1000 * duration; + mix = pcmbuf_read != NULL && pcmbuf_read->link != NULL; /* Find the insertion point and set bufstart to the start of it */ if (mix) { - /* Get the next chunk */ - char *pcmbuf_mix_buf = pcmbuf_read->link->addr; - /* Give 1/8s clearance. */ - bufstart = (int16_t *)&pcmbuf_mix_buf[NATIVE_FREQUENCY * 4 / 8]; + /* Get the currently playing chunk at the current position. */ + bufstart = (int16_t *)pcm_play_dma_get_peak_buffer(&i); + + if (!bufstart) + return; /* If above isn't implemented, no beepeth */ + + /* Give 5ms clearance. */ + bufstart += NATIVE_FREQUENCY * 4 / 200; + + /* NOTE: On some targets using hardware DMA, cache range flushing may + * be required or the writes may not be picked up by the controller. + * An incremental flush should be done periodically during the mixdown. */ } else { @@ -983,28 +997,39 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) bufstart = (int16_t *)audiobuffer; } - /* Mix square wave into buffer */ + bufend = (int16_t *)SKIPBYTES(audiobuffer, pcmbuf_size); + + /* Wrapped above? */ + if (bufstart >= bufend) + bufstart -= pcmbuf_size; + bufptr = bufstart; - for (i = 0; i < samples; ++i) + + /* Mix square wave into buffer */ + for (i = 0; i < nsamples; ++i) { int32_t amp = (phase >> 31) ^ (int32_t)amplitude; sample = mix ? *bufptr : 0; *bufptr++ = clip_sample_16(sample + amp); - if (bufptr >= pcmbuf_end) + if (bufptr >= bufend) bufptr = (int16_t *)audiobuffer; sample = mix ? *bufptr : 0; *bufptr++ = clip_sample_16(sample + amp); - if (bufptr >= pcmbuf_end) + if (bufptr >= bufend) bufptr = (int16_t *)audiobuffer; phase += step; } + pcm_play_lock(); + /* Kick off playback if required */ if (!pcm_is_playing()) { - pcm_play_data(NULL, (unsigned char *)bufstart, samples * 4); + pcm_play_data(NULL, (unsigned char *)bufstart, nsamples * 4); } + + pcm_play_unlock(); } #endif /* HAVE_HARDWARE_BEEP */ -- cgit