summaryrefslogtreecommitdiff
path: root/firmware/pcm.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2012-05-02 20:53:07 -0400
committerMichael Sevakis <jethead71@rockbox.org>2012-05-02 20:53:07 -0400
commite189b33ff4cc530cb6e59a17b260675d7341e551 (patch)
tree948b635696cbea2eac432303fa2821cfbff13670 /firmware/pcm.c
parentc0208f0f64c68a97c67e42efc1b39df7c75bf7da (diff)
Clean up peak calculating code.
Mixer needn't keep peak data around that will never be used. Just pass pcm_peaks structure to it instead of allocating for every channel. Plugin API becomes incompatible. vu_meter digital mode was still using global peak calculation; switch it to playback channel like the rest. Remove some accumulated soil peaks inside pcm.c and make it more generic. Change-Id: Ib4d268d80b6a9d09915eea1c91eab483c1a2c009
Diffstat (limited to 'firmware/pcm.c')
-rw-r--r--firmware/pcm.c92
1 files changed, 44 insertions, 48 deletions
diff --git a/firmware/pcm.c b/firmware/pcm.c
index 621ed56e0d..94b0d6eefb 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -102,9 +102,6 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
/* samplerate frequency selection index */
int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
-/* peak data for the global peak values - i.e. what the final output is */
-static struct pcm_peaks global_peaks;
-
/* Called internally by functions to reset the state */
static void pcm_play_stopped(void)
{
@@ -125,42 +122,38 @@ static void pcm_wait_for_init(void)
*
* Used for recording and playback.
*/
-static void pcm_peak_peeker(const int32_t *addr, int count, uint16_t peaks[2])
+static void pcm_peak_peeker(const int16_t *p, int count,
+ struct pcm_peaks *peaks)
{
- int peak_l = 0, peak_r = 0;
- const int32_t * const end = addr + count;
+ uint32_t peak_l = 0, peak_r = 0;
+ const int16_t *pend = p + 2 * count;
do
{
- int32_t value = *addr;
- int ch;
-
-#ifdef ROCKBOX_BIG_ENDIAN
- ch = value >> 16;
-#else
- ch = (int16_t)value;
-#endif
- if (ch < 0)
- ch = -ch;
- if (ch > peak_l)
- peak_l = ch;
-
-#ifdef ROCKBOX_BIG_ENDIAN
- ch = (int16_t)value;
-#else
- ch = value >> 16;
-#endif
- if (ch < 0)
- ch = -ch;
- if (ch > peak_r)
- peak_r = ch;
-
- addr += 4;
+ int32_t s;
+
+ s = p[0];
+
+ if (s < 0)
+ s = -s;
+
+ if ((uint32_t)s > peak_l)
+ peak_l = s;
+
+ s = p[1];
+
+ if (s < 0)
+ s = -s;
+
+ if ((uint32_t)s > peak_r)
+ peak_r = s;
+
+ p += 4 * 2; /* Every 4th sample, interleaved */
}
- while (addr < end);
+ while (p < pend);
- peaks[0] = peak_l;
- peaks[1] = peak_r;
+ peaks->left = peak_l;
+ peaks->right = peak_r;
}
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
@@ -177,7 +170,7 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
else if (period > HZ/5)
period = HZ/5;
- peaks->period = (3*peaks->period + period) >> 2;
+ peaks->period = (3*peaks->period + period) / 4;
peaks->tick = tick;
if (active)
@@ -186,29 +179,32 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
count = MIN(framecount, count);
if (count > 0)
- pcm_peak_peeker((int32_t *)addr, count, peaks->val);
+ pcm_peak_peeker(addr, count, peaks);
/* else keep previous peak values */
}
else
{
/* peaks are zero */
- peaks->val[0] = peaks->val[1] = 0;
+ peaks->left = peaks->right = 0;
}
}
void pcm_calculate_peaks(int *left, int *right)
{
+ /* peak data for the global peak values - i.e. what the final output is */
+ static struct pcm_peaks peaks;
+
int count;
const void *addr = pcm_play_dma_get_peak_buffer(&count);
- pcm_do_peak_calculation(&global_peaks, pcm_playing && !pcm_paused,
+ pcm_do_peak_calculation(&peaks, pcm_playing && !pcm_paused,
addr, count);
if (left)
- *left = global_peaks.val[0];
+ *left = peaks.left;
if (right)
- *right = global_peaks.val[1];
+ *right = peaks.right;
}
const void* pcm_get_peak_buffer(int * count)
@@ -471,20 +467,20 @@ static void pcm_recording_stopped(void)
*/
void pcm_calculate_rec_peaks(int *left, int *right)
{
- static uint16_t peaks[2];
+ static struct pcm_peaks peaks;
if (pcm_recording)
{
- const void *peak_addr = pcm_rec_peak_addr;
- const void *addr = pcm_rec_dma_get_peak_buffer();
+ const int16_t *peak_addr = pcm_rec_peak_addr;
+ const int16_t *addr = pcm_rec_dma_get_peak_buffer();
if (addr != NULL)
{
- int count = (int)(((intptr_t)addr - (intptr_t)peak_addr) >> 2);
+ int count = (addr - peak_addr) / 2; /* Interleaved L+R */
if (count > 0)
{
- pcm_peak_peeker((int32_t *)peak_addr, count, peaks);
+ pcm_peak_peeker(peak_addr, count, &peaks);
if (peak_addr == pcm_rec_peak_addr)
pcm_rec_peak_addr = addr;
@@ -494,15 +490,15 @@ void pcm_calculate_rec_peaks(int *left, int *right)
}
else
{
- peaks[0] = peaks[1] = 0;
+ peaks.left = peaks.right = 0;
}
if (left)
- *left = peaks[0];
+ *left = peaks.left;
if (right)
- *right = peaks[1];
-} /* pcm_calculate_rec_peaks */
+ *right = peaks.right;
+}
bool pcm_is_recording(void)
{