From 93572e2a9e651b7d0bffae491da3d2ece2f0c2d2 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sat, 13 Dec 2008 06:01:08 +0000 Subject: [PATCH] Keyclick fixup take two. It is only 88 samples (2msec) long so keep a small static buffer around for beeps less than or equal to keyclick duration. This way it operates no matter the buffer state and still won't interfere with alternate PCM operations like recording or plugin playback. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19415 a1c6a512-1295-4272-9138-f99709370657 --- apps/action.c | 2 +- apps/filetree.c | 3 -- apps/pcmbuf.c | 57 +++++++++++++++++++++++++------------- apps/playback.c | 13 --------- apps/plugin.c | 6 ---- apps/recorder/pcm_record.c | 4 --- apps/settings.c | 3 -- apps/settings.h | 6 ++++ firmware/export/audio.h | 1 - firmware/export/pcm.h | 3 ++ firmware/pcm.c | 5 ++++ firmware/usb.c | 12 -------- 12 files changed, 52 insertions(+), 63 deletions(-) diff --git a/apps/action.c b/apps/action.c index 5f845ab272..aad5348e48 100644 --- a/apps/action.c +++ b/apps/action.c @@ -130,7 +130,7 @@ static int get_action_worker(int context, int timeout, /* Produce keyclick */ if (global_settings.keyclick && !(button & BUTTON_REL)) if (!(button & BUTTON_REPEAT) || global_settings.keyclick_repeats) - pcmbuf_beep(4000, 2, 2500*global_settings.keyclick); + pcmbuf_beep(4000, KEYCLICK_DURATION, 2500*global_settings.keyclick); #endif if ((context != last_context) && ((last_button & BUTTON_REL) == 0)) diff --git a/apps/filetree.c b/apps/filetree.c index 03a4d7ca36..fc5e4d3934 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -509,9 +509,6 @@ int ft_enter(struct tree_context* c) MAX_FILENAME); talk_init(); /* use voice of same language */ splash(HZ, ID2P(LANG_LANGUAGE_LOADED)); -#if CONFIG_CODEC == SWCODEC && !defined(HAVE_HARDWARE_BEEP) - audio_buffer_reset(); -#endif } break; diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 5b9e7270cc..b22fd789a6 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -955,25 +955,22 @@ bool pcmbuf_insert_buffer(char *buf, int count) #endif #ifndef HAVE_HARDWARE_BEEP +#define MINIBUF_SAMPLES (NATIVE_FREQUENCY / 1000 * KEYCLICK_DURATION) +#define MINIBUF_SIZE (MINIBUF_SAMPLES*4) + /* Generates a constant square wave sound with a given frequency in Hertz for a duration in milliseconds. */ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) { - unsigned int step; - int32_t phase; + unsigned int step = 0xffffffffu / NATIVE_FREQUENCY * frequency; + int32_t phase = 0; int16_t *bufptr, *bufstart, *bufend; int32_t sample; - int nsamples; - bool mix; + int nsamples = NATIVE_FREQUENCY / 1000 * duration; + bool mix = pcmbuf_read != NULL && pcmbuf_read->link != NULL; 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; + bufend = SKIPBYTES((int16_t *)audiobuffer, pcmbuf_size); /* Find the insertion point and set bufstart to the start of it */ if (mix) @@ -987,21 +984,31 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) /* Give 5ms clearance. */ bufstart += NATIVE_FREQUENCY * 4 / 200; + /* Wrapped above? */ + if (bufstart >= bufend) + bufstart -= pcmbuf_size; + /* 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 + else if (nsamples <= MINIBUF_SAMPLES) + { + static int16_t minibuf[MINIBUF_SAMPLES*2]; + /* Use mini buffer */ + bufstart = minibuf; + bufend = SKIPBYTES(bufstart, MINIBUF_SIZE); + } + else if (audio_buffer_state() != AUDIOBUF_STATE_TRASHED) { /* Use audiobuffer */ bufstart = (int16_t *)audiobuffer; } - - bufend = (int16_t *)SKIPBYTES(audiobuffer, pcmbuf_size); - - /* Wrapped above? */ - if (bufstart >= bufend) - bufstart -= pcmbuf_size; + else + { + /* No place */ + return; + } bufptr = bufstart; @@ -1022,14 +1029,24 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) } pcm_play_lock(); +#ifdef HAVE_RECORDING + pcm_rec_lock(); +#endif - /* Kick off playback if required */ - if (!pcm_is_playing()) + /* Kick off playback if required and it won't interfere */ + if (!pcm_is_playing() +#ifdef HAVE_RECORDING + && !pcm_is_recording() +#endif + ) { pcm_play_data(NULL, (unsigned char *)bufstart, nsamples * 4); } pcm_play_unlock(); +#ifdef HAVE_RECORDING + pcm_rec_unlock(); +#endif } #endif /* HAVE_HARDWARE_BEEP */ diff --git a/apps/playback.c b/apps/playback.c index 1a638eb7c8..d2d9bb6a34 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -136,7 +136,6 @@ enum { Q_AUDIO_POSTINIT, Q_AUDIO_FILL_BUFFER, Q_AUDIO_FINISH_LOAD, - Q_AUDIO_RESTORE_BUFFER, Q_CODEC_REQUEST_COMPLETE, Q_CODEC_REQUEST_FAILED, @@ -491,12 +490,6 @@ int audio_buffer_state(void) return buffer_state; } -void audio_buffer_reset(void) -{ - LOGFQUEUE("audio_queue >| Q_AUDIO_RESTORE_BUFFER"); - queue_send(&audio_queue, Q_AUDIO_RESTORE_BUFFER, 0); -} - #ifdef HAVE_RECORDING unsigned char *audio_get_recording_buffer(size_t *buffer_size) { @@ -2396,12 +2389,6 @@ static void audio_thread(void) audio_finish_load_track(); break; - case Q_AUDIO_RESTORE_BUFFER: - LOGFQUEUE("audio < Q_AUDIO_RESTORE_BUFFER"); - if (buffer_state != AUDIOBUF_STATE_INITIALIZED) - audio_reset_buffer(); - break; - case Q_AUDIO_PLAY: LOGFQUEUE("audio < Q_AUDIO_PLAY"); if (playing && ev.data <= 0) diff --git a/apps/plugin.c b/apps/plugin.c index cf015e2503..f78b6bf4e1 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -785,12 +785,6 @@ int plugin_load(const char* plugin, const void* parameter) break; } -#if CONFIG_CODEC == SWCODEC && !defined (HAVE_HARDWARE_BEEP) - /* Did the plugin trash the buffer? Restore it. */ - if (audio_buffer_state() == AUDIOBUF_STATE_TRASHED) - audio_buffer_reset(); -#endif - return PLUGIN_OK; } diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c index bc6a532f2f..8642150b18 100644 --- a/apps/recorder/pcm_record.c +++ b/apps/recorder/pcm_record.c @@ -1167,10 +1167,6 @@ static void pcmrec_close(void) pcm_close_recording(); reset_hardware(); audio_remove_encoder(); -#ifndef HAVE_HARDWARE_BEEP - /* Restore keyclicks */ - audio_buffer_reset(); -#endif } /* pcmrec_close */ /* PCMREC_OPTIONS */ diff --git a/apps/settings.c b/apps/settings.c index cc50b93869..4babe33cdb 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -885,9 +885,6 @@ void settings_apply(bool read_disk) global_settings.lang_file); lang_load(buf); talk_init(); /* use voice of same language */ -#if CONFIG_CODEC == SWCODEC && !defined(HAVE_HARDWARE_BEEP) - audio_buffer_reset(); -#endif } /* load the icon set */ icons_init(); diff --git a/apps/settings.h b/apps/settings.h index 60d5245f1b..b0117874cc 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -177,6 +177,12 @@ enum { ALARM_START_WPS = 0, #endif #endif /* HAVE_RTC_ALARM */ + +/* Keyclick stuff */ + + /* Not really a setting but several files should stay synced */ +#define KEYCLICK_DURATION 2 + /** virtual pointer stuff.. move to another .h maybe? **/ /* These define "virtual pointers", which could either be a literal string, or a mean a string ID if the pointer is in a certain range. diff --git a/firmware/export/audio.h b/firmware/export/audio.h index 8320642947..b4a2c82200 100644 --- a/firmware/export/audio.h +++ b/firmware/export/audio.h @@ -112,7 +112,6 @@ enum audio_buffer_state AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */ }; int audio_buffer_state(void); -void audio_buffer_reset(void); #endif /* channel modes */ diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h index ac8ddb1b3c..053f954767 100644 --- a/firmware/export/pcm.h +++ b/firmware/export/pcm.h @@ -126,6 +126,9 @@ void pcm_record_data(pcm_more_callback_type2 more_ready, /* Stop tranferring data into supplied buffer */ void pcm_stop_recording(void); +/* Is pcm currently recording? */ +bool pcm_is_recording(void); + /* Continue transferring data in - call during interrupt handler */ void pcm_record_more(void *start, size_t size); diff --git a/firmware/pcm.c b/firmware/pcm.c index 0b5b49ebab..19bba4143e 100644 --- a/firmware/pcm.c +++ b/firmware/pcm.c @@ -478,6 +478,11 @@ void pcm_stop_recording(void) pcm_rec_unlock(); } /* pcm_stop_recording */ +bool pcm_is_recording(void) +{ + return pcm_recording; +} + void pcm_rec_dma_stopped_callback(void) { pcm_recording = false; diff --git a/firmware/usb.c b/firmware/usb.c index eb040a60a0..ec47e0653c 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -124,18 +124,6 @@ static void usb_slave_mode(bool on) rc = disk_mount_all(); if (rc <= 0) /* no partition */ panicf("mount: %d",rc); - -#ifndef BOOTLOADER -#if CONFIG_CPU == IMX31L || CONFIG_USBOTG == USBOTG_ISP1583 || \ - defined(CPU_TCC77X) || defined(CPU_TCC780X) - /* These use a static transfer buffer */ -#elif defined(USB_STORAGE) && !defined (HAVE_HARDWARE_BEEP) - /* Storage can use the audio buffer, restore it if it did to get - * keyclicks back. */ - if (audio_buffer_state() == BUFFER_STATE_TRASHED) - audio_buffer_reset(); -#endif /* USB_STORAGE */ -#endif /* BOOTLOADER */ } } #endif