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
This commit is contained in:
Michael Sevakis 2008-12-13 06:01:08 +00:00
parent bdcdf8b5e4
commit 93572e2a9e
12 changed files with 52 additions and 63 deletions

View file

@ -130,7 +130,7 @@ static int get_action_worker(int context, int timeout,
/* Produce keyclick */ /* Produce keyclick */
if (global_settings.keyclick && !(button & BUTTON_REL)) if (global_settings.keyclick && !(button & BUTTON_REL))
if (!(button & BUTTON_REPEAT) || global_settings.keyclick_repeats) 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 #endif
if ((context != last_context) && ((last_button & BUTTON_REL) == 0)) if ((context != last_context) && ((last_button & BUTTON_REL) == 0))

View file

@ -509,9 +509,6 @@ int ft_enter(struct tree_context* c)
MAX_FILENAME); MAX_FILENAME);
talk_init(); /* use voice of same language */ talk_init(); /* use voice of same language */
splash(HZ, ID2P(LANG_LANGUAGE_LOADED)); splash(HZ, ID2P(LANG_LANGUAGE_LOADED));
#if CONFIG_CODEC == SWCODEC && !defined(HAVE_HARDWARE_BEEP)
audio_buffer_reset();
#endif
} }
break; break;

View file

@ -955,25 +955,22 @@ bool pcmbuf_insert_buffer(char *buf, int count)
#endif #endif
#ifndef HAVE_HARDWARE_BEEP #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 /* Generates a constant square wave sound with a given frequency
in Hertz for a duration in milliseconds. */ in Hertz for a duration in milliseconds. */
void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
{ {
unsigned int step; unsigned int step = 0xffffffffu / NATIVE_FREQUENCY * frequency;
int32_t phase; int32_t phase = 0;
int16_t *bufptr, *bufstart, *bufend; int16_t *bufptr, *bufstart, *bufend;
int32_t sample; int32_t sample;
int nsamples; int nsamples = NATIVE_FREQUENCY / 1000 * duration;
bool mix; bool mix = pcmbuf_read != NULL && pcmbuf_read->link != NULL;
int i; int i;
if (audio_buffer_state() == AUDIOBUF_STATE_TRASHED) bufend = SKIPBYTES((int16_t *)audiobuffer, pcmbuf_size);
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;
/* Find the insertion point and set bufstart to the start of it */ /* Find the insertion point and set bufstart to the start of it */
if (mix) if (mix)
@ -987,21 +984,31 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
/* Give 5ms clearance. */ /* Give 5ms clearance. */
bufstart += NATIVE_FREQUENCY * 4 / 200; bufstart += NATIVE_FREQUENCY * 4 / 200;
/* Wrapped above? */
if (bufstart >= bufend)
bufstart -= pcmbuf_size;
/* NOTE: On some targets using hardware DMA, cache range flushing may /* NOTE: On some targets using hardware DMA, cache range flushing may
* be required or the writes may not be picked up by the controller. * be required or the writes may not be picked up by the controller.
* An incremental flush should be done periodically during the mixdown. */ * 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 */ /* Use audiobuffer */
bufstart = (int16_t *)audiobuffer; bufstart = (int16_t *)audiobuffer;
} }
else
bufend = (int16_t *)SKIPBYTES(audiobuffer, pcmbuf_size); {
/* No place */
/* Wrapped above? */ return;
if (bufstart >= bufend) }
bufstart -= pcmbuf_size;
bufptr = bufstart; bufptr = bufstart;
@ -1022,14 +1029,24 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
} }
pcm_play_lock(); pcm_play_lock();
#ifdef HAVE_RECORDING
pcm_rec_lock();
#endif
/* Kick off playback if required */ /* Kick off playback if required and it won't interfere */
if (!pcm_is_playing()) if (!pcm_is_playing()
#ifdef HAVE_RECORDING
&& !pcm_is_recording()
#endif
)
{ {
pcm_play_data(NULL, (unsigned char *)bufstart, nsamples * 4); pcm_play_data(NULL, (unsigned char *)bufstart, nsamples * 4);
} }
pcm_play_unlock(); pcm_play_unlock();
#ifdef HAVE_RECORDING
pcm_rec_unlock();
#endif
} }
#endif /* HAVE_HARDWARE_BEEP */ #endif /* HAVE_HARDWARE_BEEP */

View file

@ -136,7 +136,6 @@ enum {
Q_AUDIO_POSTINIT, Q_AUDIO_POSTINIT,
Q_AUDIO_FILL_BUFFER, Q_AUDIO_FILL_BUFFER,
Q_AUDIO_FINISH_LOAD, Q_AUDIO_FINISH_LOAD,
Q_AUDIO_RESTORE_BUFFER,
Q_CODEC_REQUEST_COMPLETE, Q_CODEC_REQUEST_COMPLETE,
Q_CODEC_REQUEST_FAILED, Q_CODEC_REQUEST_FAILED,
@ -491,12 +490,6 @@ int audio_buffer_state(void)
return buffer_state; 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 #ifdef HAVE_RECORDING
unsigned char *audio_get_recording_buffer(size_t *buffer_size) unsigned char *audio_get_recording_buffer(size_t *buffer_size)
{ {
@ -2396,12 +2389,6 @@ static void audio_thread(void)
audio_finish_load_track(); audio_finish_load_track();
break; 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: case Q_AUDIO_PLAY:
LOGFQUEUE("audio < Q_AUDIO_PLAY"); LOGFQUEUE("audio < Q_AUDIO_PLAY");
if (playing && ev.data <= 0) if (playing && ev.data <= 0)

View file

@ -785,12 +785,6 @@ int plugin_load(const char* plugin, const void* parameter)
break; 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; return PLUGIN_OK;
} }

View file

@ -1167,10 +1167,6 @@ static void pcmrec_close(void)
pcm_close_recording(); pcm_close_recording();
reset_hardware(); reset_hardware();
audio_remove_encoder(); audio_remove_encoder();
#ifndef HAVE_HARDWARE_BEEP
/* Restore keyclicks */
audio_buffer_reset();
#endif
} /* pcmrec_close */ } /* pcmrec_close */
/* PCMREC_OPTIONS */ /* PCMREC_OPTIONS */

View file

@ -885,9 +885,6 @@ void settings_apply(bool read_disk)
global_settings.lang_file); global_settings.lang_file);
lang_load(buf); lang_load(buf);
talk_init(); /* use voice of same language */ talk_init(); /* use voice of same language */
#if CONFIG_CODEC == SWCODEC && !defined(HAVE_HARDWARE_BEEP)
audio_buffer_reset();
#endif
} }
/* load the icon set */ /* load the icon set */
icons_init(); icons_init();

View file

@ -177,6 +177,12 @@ enum { ALARM_START_WPS = 0,
#endif #endif
#endif /* HAVE_RTC_ALARM */ #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? **/ /** virtual pointer stuff.. move to another .h maybe? **/
/* These define "virtual pointers", which could either be a literal string, /* 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. or a mean a string ID if the pointer is in a certain range.

View file

@ -112,7 +112,6 @@ enum audio_buffer_state
AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */ AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
}; };
int audio_buffer_state(void); int audio_buffer_state(void);
void audio_buffer_reset(void);
#endif #endif
/* channel modes */ /* channel modes */

View file

@ -126,6 +126,9 @@ void pcm_record_data(pcm_more_callback_type2 more_ready,
/* Stop tranferring data into supplied buffer */ /* Stop tranferring data into supplied buffer */
void pcm_stop_recording(void); void pcm_stop_recording(void);
/* Is pcm currently recording? */
bool pcm_is_recording(void);
/* Continue transferring data in - call during interrupt handler */ /* Continue transferring data in - call during interrupt handler */
void pcm_record_more(void *start, size_t size); void pcm_record_more(void *start, size_t size);

View file

@ -478,6 +478,11 @@ void pcm_stop_recording(void)
pcm_rec_unlock(); pcm_rec_unlock();
} /* pcm_stop_recording */ } /* pcm_stop_recording */
bool pcm_is_recording(void)
{
return pcm_recording;
}
void pcm_rec_dma_stopped_callback(void) void pcm_rec_dma_stopped_callback(void)
{ {
pcm_recording = false; pcm_recording = false;

View file

@ -124,18 +124,6 @@ static void usb_slave_mode(bool on)
rc = disk_mount_all(); rc = disk_mount_all();
if (rc <= 0) /* no partition */ if (rc <= 0) /* no partition */
panicf("mount: %d",rc); 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 #endif