summaryrefslogtreecommitdiffstats
path: root/apps/pcmbuf.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-12-13 01:32:39 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-12-13 01:32:39 +0000
commit5e73f9ff2087cc82705b49fc813a6b60633ac756 (patch)
treef0eb330476561208ca0a8f7f91bb879c96d85234 /apps/pcmbuf.c
parentbdf3004f966b7095b2b404bea9f15f18c9de8918 (diff)
downloadrockbox-5e73f9ff2087cc82705b49fc813a6b60633ac756.tar.gz
rockbox-5e73f9ff2087cc82705b49fc813a6b60633ac756.zip
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
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r--apps/pcmbuf.c59
1 files changed, 42 insertions, 17 deletions
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 */