1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Brandon Low 2006-02-22 01:56:44 +00:00
parent a13f847186
commit 9535a9a639
2 changed files with 53 additions and 55 deletions

View file

@ -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;
}
}

View file

@ -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);