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:
parent
bdcdf8b5e4
commit
93572e2a9e
12 changed files with 52 additions and 63 deletions
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue