summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/recorder/peakmeter.c16
-rw-r--r--firmware/export/pcm_playback.h2
-rw-r--r--firmware/pcm_playback.c83
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)
{