From 9535a9a6390ca51b11d13a8dd338432c466f4477 Mon Sep 17 00:00:00 2001 From: Brandon Low Date: Wed, 22 Feb 2006 01:56:44 +0000 Subject: Fix some of the voice and beep bugs that people have noticed since my new pcmbuf code went in, reduce code duplication, and improve performance while I'm at it git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8775 a1c6a512-1295-4272-9138-f99709370657 --- apps/pcmbuf.c | 105 +++++++++++++++++++++++++++++----------------------------- apps/pcmbuf.h | 3 +- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index c79b0d5fd9..31b59f88f6 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -97,7 +97,7 @@ static size_t last_chunksize IDATA_ATTR; static size_t pcmbuf_unplayed_bytes IDATA_ATTR; static size_t pcmbuf_mix_used_bytes IDATA_ATTR; static size_t pcmbuf_watermark IDATA_ATTR; -static size_t mixpos IDATA_ATTR = 0; +static short *mixpos IDATA_ATTR; static bool low_latency_mode = false; /* Helpful macros for use in conditionals this assumes some of the above @@ -805,13 +805,6 @@ void pcmbuf_write_complete(size_t length) } } -void pcmbuf_write_voice(size_t length) -{ - while (pcm_is_playing()) - sleep(1); - pcm_play_data(NULL, &guardbuf[0], length); -} - bool pcmbuf_insert_buffer(const char *buf, size_t length) { if (!prepare_insert(length)) @@ -827,52 +820,63 @@ bool pcmbuf_insert_buffer(const char *buf, size_t length) return true; } +/* Get a pointer to where to mix immediate audio */ +static inline short* get_mix_insert_pos(void) { + /* Give at least 1/8s clearance here */ + size_t pcmbuf_mix_back_pos = + pcmbuf_unplayed_bytes - NATIVE_FREQUENCY * 4 / 8; + + if (audiobuffer_pos < pcmbuf_mix_back_pos) + return (short *)&audiobuffer[pcmbuf_size + + audiobuffer_pos - pcmbuf_mix_back_pos]; + else + return (short *)&audiobuffer[audiobuffer_pos - pcmbuf_mix_back_pos]; +} + /* Generates a constant square wave sound with a given frequency in Hertz for a duration in milliseconds. */ -void pcmbuf_beep(int frequency, int duration, int amplitude) +void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) { - unsigned int state = 0, count = 0; + unsigned int count = 0, i = 0; + bool state = false; unsigned int interval = NATIVE_FREQUENCY / frequency; - size_t pos; - short *buf = (short *)audiobuffer; - size_t bufsize = pcmbuf_size / 2; + short *buf; + short *pcmbuf_end = (short *)guardbuf; + bool playing = pcm_is_playing(); + size_t samples = NATIVE_FREQUENCY / 1000 * duration; - /* FIXME: Should start playback. */ - //if (pcmbuf_unplayed_bytes * 1000 < 4 * NATIVE_FREQUENCY * duration) - // return ; - - if (audiobuffer_pos < pcmbuf_unplayed_bytes) - pos = pcmbuf_size + audiobuffer_pos - pcmbuf_unplayed_bytes; - else - pos = audiobuffer_pos - pcmbuf_unplayed_bytes; - pos /= 2; - - duration = NATIVE_FREQUENCY / 1000 * duration; - while (duration-- > 0) + if (playing) { + buf = get_mix_insert_pos(); + } else { + buf = (short *)audiobuffer; + } + while (i++ < samples) { + long sample = *buf; if (state) { - buf[pos] = MIN(MAX(buf[pos] + amplitude, -32768), 32767); - if (++pos >= bufsize) - pos = 0; - buf[pos] = MIN(MAX(buf[pos] + amplitude, -32768), 32767); + *buf++ = MIN(MAX(sample + amplitude, -32768), 32767); + if (buf > pcmbuf_end) + buf = (short *)audiobuffer; + sample = *buf; + *buf++ = MIN(MAX(sample + amplitude, -32768), 32767); } else { - buf[pos] = MIN(MAX(buf[pos] - amplitude, -32768), 32767); - if (++pos >= bufsize) - pos = 0; - buf[pos] = MIN(MAX(buf[pos] - amplitude, -32768), 32767); + *buf++ = MIN(MAX(sample - amplitude, -32768), 32767); + if (buf > pcmbuf_end) + buf = (short *)audiobuffer; + sample = *buf; + *buf++ = MIN(MAX(sample - amplitude, -32768), 32767); } if (++count >= interval) { count = 0; - if (state) - state = 0; - else - state = 1; + state = !state; } - pos++; - if (pos >= bufsize) - pos = 0; + if (buf > pcmbuf_end) + buf = (short *)audiobuffer; + } + if (!playing) { + pcm_play_data(NULL, (unsigned char *)audiobuffer, samples * 4); } } @@ -889,19 +893,14 @@ int pcmbuf_mix_usage(void) void pcmbuf_reset_mixpos(void) { + mixpos = get_mix_insert_pos(); pcmbuf_mix_used_bytes = 0; - if (audiobuffer_pos < pcmbuf_unplayed_bytes) - mixpos = pcmbuf_size + audiobuffer_pos - pcmbuf_unplayed_bytes; - else - mixpos = audiobuffer_pos - pcmbuf_unplayed_bytes; - mixpos /= 2; } void pcmbuf_mix(char *buf, size_t length) { short *ibuf = (short *)buf; - short *obuf = (short *)audiobuffer; - size_t bufsize = pcmbuf_size / 2; + short *pcmbuf_end = (short *)guardbuf; if (pcmbuf_mix_used_bytes == 0) pcmbuf_reset_mixpos(); @@ -910,12 +909,12 @@ void pcmbuf_mix(char *buf, size_t length) length /= 2; while (length-- > 0) { - obuf[mixpos] = MIN(MAX(obuf[mixpos]/4 + *ibuf, -32768), 32767); - - ibuf++; - mixpos++; - if (mixpos >= bufsize) - mixpos = 0; + long sample = *ibuf++; + sample += *mixpos >> 2; + *mixpos++ = MIN(MAX(sample, -32768), 32767); + + if (mixpos >= pcmbuf_end) + mixpos = (short *)audiobuffer; } } diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h index 555c1bcb33..b659e8fa4e 100644 --- a/apps/pcmbuf.h +++ b/apps/pcmbuf.h @@ -58,7 +58,6 @@ unsigned int pcmbuf_get_latency(void); void pcmbuf_set_low_latency(bool state); bool pcmbuf_insert_buffer(const char *buf, size_t length); void pcmbuf_write_complete(size_t length); -void pcmbuf_write_voice(size_t length); void* pcmbuf_request_buffer(size_t length, size_t *realsize); void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix); bool pcmbuf_is_crossfade_enabled(void); @@ -66,7 +65,7 @@ void pcmbuf_crossfade_enable(bool on_off); int pcmbuf_usage(void); int pcmbuf_mix_usage(void); -void pcmbuf_beep(int frequency, int duration, int amplitude); +void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude); void pcmbuf_reset_mixpos(void); void pcmbuf_mix(char *buf, size_t length); -- cgit v1.2.3