From fdd0efa9909f96c4cad118c82a20d679d20f75f1 Mon Sep 17 00:00:00 2001 From: funman Date: Fri, 14 May 2010 12:59:54 +0000 Subject: [PATCH] as3525v1: duplicate the right channel into the left channel when recording microphone git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26023 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/as3525/audio-as3525.c | 5 +++ firmware/target/arm/as3525/pcm-as3525.c | 72 +++++++++++++++++++++++++------ 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/firmware/target/arm/as3525/audio-as3525.c b/firmware/target/arm/as3525/audio-as3525.c index c56024f2b..570ff1491 100644 --- a/firmware/target/arm/as3525/audio-as3525.c +++ b/firmware/target/arm/as3525/audio-as3525.c @@ -25,6 +25,8 @@ #include "audiohw.h" #include "sound.h" +int audio_channels = 2; + void audio_set_output_source(int source) { (void)source; @@ -47,6 +49,7 @@ void audio_input_mux(int source, unsigned flags) case AUDIO_SRC_PLAYBACK: if (source != last_source) { + audio_channels = 2; #if defined(HAVE_RECORDING) || defined(HAVE_FMRADIO_IN) audiohw_set_monitor(false); #endif @@ -60,6 +63,7 @@ void audio_input_mux(int source, unsigned flags) case AUDIO_SRC_MIC: /* recording only */ if (source != last_source) { + audio_channels = 1; audiohw_set_monitor(false); audiohw_enable_recording(true); /* source mic */ } @@ -76,6 +80,7 @@ void audio_input_mux(int source, unsigned flags) ) break; + audio_channels = 2; #ifdef HAVE_RECORDING last_recording = recording; diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c index c649acee7..10877ecf4 100644 --- a/firmware/target/arm/as3525/pcm-as3525.c +++ b/firmware/target/arm/as3525/pcm-as3525.c @@ -193,8 +193,12 @@ void * pcm_dma_addr(void *addr) static int rec_locked = 0; static unsigned char *rec_dma_start_addr; -static size_t rec_dma_size; +static size_t rec_dma_size, rec_dma_transfer_size; static void rec_dma_callback(void); +#if CONFIG_CPU == AS3525 +/* points to the samples which need to be duplicated into the right channel */ +static int16_t *mono_samples; +#endif void pcm_rec_lock(void) @@ -213,25 +217,58 @@ void pcm_rec_unlock(void) static void rec_dma_start(void) { - void* addr = rec_dma_start_addr; - size_t size = rec_dma_size; + rec_dma_transfer_size = rec_dma_size; /* We are limited to 8188 DMA transfers, and the recording core asks for * 8192 bytes. Avoid splitting 8192 bytes transfers in 8188 + 4 */ - if(size > 4096) - size = 4096; - - rec_dma_size -= size; - rec_dma_start_addr += size; + if(rec_dma_transfer_size > 4096) + rec_dma_transfer_size = 4096; - dma_enable_channel(1, (void*)I2SIN_DATA, addr, DMA_PERI_I2SIN, - DMAC_FLOWCTRL_DMAC_PERI_TO_MEM, false, true, size >> 2, DMA_S4, - rec_dma_callback); + dma_enable_channel(1, (void*)I2SIN_DATA, rec_dma_start_addr, DMA_PERI_I2SIN, + DMAC_FLOWCTRL_DMAC_PERI_TO_MEM, false, true, + rec_dma_transfer_size >> 2, DMA_S4, rec_dma_callback); } +/* if needed, duplicate samples of the working channel until the given bound */ +static inline void mono2stereo(int16_t *end) +{ +#if CONFIG_CPU == AS3525 + if(audio_channels != 1) /* only for microphone */ + return; +#if 0 + do { + int16_t left = *mono_samples++; + *mono_samples++ = left; + } while(mono_samples != end); +#else + /* gcc doesn't use pre indexing and load/store mono_samples at each loop + * let's save some cycles with a smaller loop */ + int16_t tmp; + asm ( + "1: ldrh %0, [%1], #2 \n" + " strh %0, [%1], #2 \n" + " cmp %1, %2 \n" + " bne 1b \n" + : "=r"(tmp), "+r"(mono_samples) + : "r"(end) + : "memory" + ); +#endif /* C / ASM */ +#else + /* microphone recording is stereo on as3525v2 */ + (void)end; +#endif +} + static void rec_dma_callback(void) { + rec_dma_size -= rec_dma_transfer_size; + rec_dma_start_addr += rec_dma_transfer_size; + + /* the 2nd channel is silent when recording microphone on as3525v1 */ + mono2stereo(UNCACHED_ADDR((int16_t*)rec_dma_start_addr)); + if(!rec_dma_size) { register pcm_more_callback_type2 more_ready = pcm_callback_more_ready; @@ -252,6 +289,9 @@ void pcm_rec_dma_record_more(void *start, size_t size) { dump_dcache_range(start, size); rec_dma_start_addr = start; +#if CONFIG_CPU == AS3525 + mono_samples = UNCACHED_ADDR(start); +#endif rec_dma_size = size; } @@ -274,6 +314,9 @@ void pcm_rec_dma_start(void *addr, size_t size) { dump_dcache_range(addr, size); rec_dma_start_addr = addr; +#if CONFIG_CPU == AS3525 + mono_samples = UNCACHED_ADDR(addr); +#endif rec_dma_size = size; dma_retain(); @@ -311,7 +354,12 @@ void pcm_rec_dma_init(void) const void * pcm_rec_dma_get_peak_buffer(void) { - return UNCACHED_ADDR((void*)DMAC_CH_DST_ADDR(1)); + pcm_rec_lock(); + int16_t *addr = UNCACHED_ADDR((int16_t *)DMAC_CH_DST_ADDR(1)); + mono2stereo(addr); + pcm_rec_unlock(); + + return addr; } #endif /* HAVE_RECORDING */ -- 2.11.4.GIT