summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrandon Low <lostlogic@rockbox.org>2006-02-22 01:56:44 +0000
committerBrandon Low <lostlogic@rockbox.org>2006-02-22 01:56:44 +0000
commit9535a9a6390ca51b11d13a8dd338432c466f4477 (patch)
treef42602ea43e1c2d0e196fd293ac7561bcccfe6d8
parenta13f8471863e868a2d744baac4a5f5b20b3fa842 (diff)
downloadrockbox-9535a9a6390ca51b11d13a8dd338432c466f4477.tar.gz
rockbox-9535a9a6390ca51b11d13a8dd338432c466f4477.tar.bz2
rockbox-9535a9a6390ca51b11d13a8dd338432c466f4477.zip
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
-rw-r--r--apps/pcmbuf.c105
-rw-r--r--apps/pcmbuf.h3
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);