diff options
-rw-r--r-- | apps/recorder/peakmeter.c | 16 | ||||
-rw-r--r-- | firmware/export/pcm_playback.h | 2 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 83 |
3 files changed, 94 insertions, 7 deletions
diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c index 7746fb9f9f..002a3c48d5 100644 --- a/apps/recorder/peakmeter.c +++ b/apps/recorder/peakmeter.c @@ -32,6 +32,10 @@ #include "lang.h" #include "peakmeter.h" +#if CONFIG_HWCODEC == MASNONE +#include "pcm_playback.h" +#endif + /* no inline in simulator mode */ #ifdef SIMULATOR #define inline @@ -552,9 +556,9 @@ inline void peak_meter_peek(void) int left = 8000; int right = 9000; #elif CONFIG_HWCODEC == MASNONE - /* FIX */ - int left = 9000; - int right = 8000; + int left; + int right; + pcm_calculate_peaks(&left, &right); #else /* read the peak values */ int left = mas_codec_readreg(peak_meter_src_l); @@ -729,8 +733,7 @@ static int peak_meter_read_l (void) #ifdef SIMULATOR peak_meter_l = 8000; #elif CONFIG_HWCODEC == MASNONE - /* FIX */ - peak_meter_l = 8000; + pcm_calculate_peaks(&peak_meter_l, NULL); #else /* reset peak_meter_l so that subsequent calls of peak_meter_peek doesn't get fooled by an old @@ -758,8 +761,7 @@ static int peak_meter_read_r (void) { #ifdef SIMULATOR peak_meter_l = 8000; #elif CONFIG_HWCODEC == MASNONE - /* FIX */ - peak_meter_r = 8000; + pcm_calculate_peaks(NULL, &peak_meter_r); #else /* reset peak_meter_r so that subsequent calls of peak_meter_peek doesn't get fooled by an old diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h index 3f0b5eee86..6222574ed8 100644 --- a/firmware/export/pcm_playback.h +++ b/firmware/export/pcm_playback.h @@ -25,6 +25,8 @@ void pcm_set_frequency(unsigned int frequency); /* This is for playing "raw" PCM data */ void pcm_play_data(void (*get_more)(unsigned char** start, long* size)); +void pcm_calculate_peaks(int *left, int *right); + void pcm_play_stop(void); void pcm_play_pause(bool play); bool pcm_is_paused(void); diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index 7682ce03c8..fc7239bf86 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c @@ -89,6 +89,89 @@ static void dma_stop(void) pcm_paused = false; } +#define PEEK_SAMPLE_COUNT 64 +static long calculate_channel_peak_average(int channel, unsigned short *addr, + long size) +{ + int i; + long min, max; + int count, min_count, max_count; + unsigned long average, zero_point; + + addr = &addr[channel]; + average = 0; + + if (pcm_playing && !pcm_paused && addr != NULL) + { + /* Calculate the zero point and remove DC offset (should be around 32768) */ + zero_point = 0; + for (i = 0; i < size; i++) + zero_point += addr[i*2]; + zero_point /= i; + + /*for (i = 0; i < size; i++) { + long peak = addr[i*2] - 32768; + if (peak < 0) + peak = 0; + average += peak; + } + average /= i;*/ + + count = 0; + + while (size > PEEK_SAMPLE_COUNT) + { + min = zero_point; + max = zero_point; + min_count = 1; + max_count = 1; + + for (i = 0; i < PEEK_SAMPLE_COUNT; i++) + { + unsigned long value = *addr; + if (value < zero_point) { + min += value; + min_count++; + } + if (value > zero_point) { + max += value; + max_count++; + } + addr = &addr[2]; + } + + min /= min_count; + max /= max_count; + + size -= PEEK_SAMPLE_COUNT; + average += (max - min) / 2; + //average += (max - zero_point) + (zero_point - min); + //average += zero_point - min; + count += 1; + } + + if (count) + { + average /= count; + /* I don't know why this is needed. Should be fixed. */ + average = zero_point - average; + } + } + + return average; +} + +void pcm_calculate_peaks(int *left, int *right) +{ + unsigned short *addr = (unsigned short *)SAR0; + long size = MIN(512, BCR0); + + if (left != NULL) + *left = calculate_channel_peak_average(0, addr, size); + if (right != NULL) + *right = calculate_channel_peak_average(1, addr, size);; +} + /* sets frequency of input to DAC */ void pcm_set_frequency(unsigned int frequency) { |