From 159c52dd36e5c008612458192904f57ea6dfdfad Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Sat, 20 Aug 2005 11:13:19 +0000 Subject: Initial voice ui support for software codec platforms. Added also a beep when changing tracks. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7360 a1c6a512-1295-4272-9138-f99709370657 --- apps/pcmbuf.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) (limited to 'apps/pcmbuf.c') diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 691f8d5a19..5f78901a56 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -34,6 +34,7 @@ #include "buffer.h" #include "settings.h" #include "audio.h" +#include "dsp.h" #define CHUNK_SIZE PCMBUF_GUARD /* Must be a power of 2 */ @@ -86,9 +87,11 @@ struct pcmbufdesc volatile int pcmbuf_read_index; volatile int pcmbuf_write_index; int pcmbuf_unplayed_bytes; +int pcmbuf_mix_used_bytes; int pcmbuf_watermark; void (*pcmbuf_watermark_event)(int bytes_left); static int last_chunksize; +static long mixpos = 0; static void pcmbuf_boost(bool state) { @@ -173,6 +176,7 @@ bool pcmbuf_add_chunk(void *addr, int size, void (*callback)(void)) pcmbuffers[pcmbuf_write_index].callback = callback; pcmbuf_write_index = (pcmbuf_write_index+1) & NUM_PCM_BUFFERS_MASK; pcmbuf_unplayed_bytes += size; + pcmbuf_mix_used_bytes = MAX(0, pcmbuf_mix_used_bytes - size); return true; } else @@ -254,6 +258,7 @@ void pcmbuf_play_stop(void) pcm_play_stop(); last_chunksize = 0; pcmbuf_unplayed_bytes = 0; + pcmbuf_mix_used_bytes = 0; pcmbuf_read_index = 0; pcmbuf_write_index = 0; audiobuffer_pos = 0; @@ -297,6 +302,13 @@ void pcmbuf_flush_audio(void) crossfade_init = true; } +/* Force playback. */ +void pcmbuf_play_start(void) +{ + if (!pcm_is_playing() && pcmbuf_unplayed_bytes) + pcm_play_data(pcmbuf_callback); +} + void pcmbuf_flush_fillpos(void) { int copy_n; @@ -562,6 +574,98 @@ bool pcmbuf_insert_buffer(char *buf, long length) return true; } +/* 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) +{ + int state = 0, count = 0; + int interval = NATIVE_FREQUENCY / frequency; + int pos; + short *buf = (short *)audiobuffer; + int bufsize = pcmbuf_size / 2; + + /* FIXME: Should start playback. */ + //if (pcmbuf_unplayed_bytes * 1000 < 4 * NATIVE_FREQUENCY * duration) + // return ; + + pos = (audiobuffer_pos - pcmbuf_unplayed_bytes) / 2; + if (pos < 0) + pos += bufsize; + + duration = NATIVE_FREQUENCY / 1000 * duration; + while (duration-- > 0) + { + 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); + } else { + buf[pos] = MIN(MAX(buf[pos] - amplitude, -32768), 32767); + if (++pos >= bufsize) + pos = 0; + buf[pos] = MIN(MAX(buf[pos] - amplitude, -32768), 32767); + } + + if (++count >= interval) + { + count = 0; + if (state) + state = 0; + else + state = 1; + } + pos++; + if (pos >= bufsize) + pos = 0; + } +} + +/* Returns pcm buffer usage in percents (0 to 100). */ +int pcmbuf_usage(void) +{ + return pcmbuf_unplayed_bytes * 100 / pcmbuf_size; +} + +int pcmbuf_mix_usage(void) +{ + return pcmbuf_mix_used_bytes * 100 / pcmbuf_unplayed_bytes; +} + +void pcmbuf_reset_mixpos(void) +{ + int bufsize = pcmbuf_size / 2; + + pcmbuf_mix_used_bytes = 0; + mixpos = (audiobuffer_pos - pcmbuf_unplayed_bytes) / 2; + if (mixpos < 0) + mixpos += bufsize; + if (mixpos >= bufsize) + mixpos -= bufsize; +} + +void pcmbuf_mix(char *buf, long length) +{ + short *ibuf = (short *)buf; + short *obuf = (short *)audiobuffer; + int bufsize = pcmbuf_size / 2; + + if (pcmbuf_mix_used_bytes == 0) + pcmbuf_reset_mixpos(); + + pcmbuf_mix_used_bytes += length; + length /= 2; + + while (length-- > 0) { + obuf[mixpos] = MIN(MAX(obuf[mixpos] + *ibuf*4, -32768), 32767); + + ibuf++; + mixpos++; + if (mixpos >= bufsize) + mixpos = 0; + } +} + void pcmbuf_crossfade_enable(bool on_off) { crossfade_enabled = on_off; -- cgit v1.2.3