summaryrefslogtreecommitdiff
path: root/firmware
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
parentc0208f0f64c68a97c67e42efc1b39df7c75bf7da (diff)
downloadrockbox-e189b33ff4cc530cb6e59a17b260675d7341e551.tar.gz
rockbox-e189b33ff4cc530cb6e59a17b260675d7341e551.zip
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')
-rw-r--r--firmware/export/pcm-internal.h7
-rw-r--r--firmware/export/pcm.h12
-rw-r--r--firmware/export/pcm_mixer.h2
-rw-r--r--firmware/pcm.c92
-rw-r--r--firmware/pcm_mixer.c16
5 files changed, 59 insertions, 70 deletions
diff --git a/firmware/export/pcm-internal.h b/firmware/export/pcm-internal.h
index abe3fe08dc..397cf6832f 100644
--- a/firmware/export/pcm-internal.h
+++ b/firmware/export/pcm-internal.h
@@ -29,13 +29,6 @@
29 ({ (start) = (void *)(((uintptr_t)(start) + 3) & ~3); \ 29 ({ (start) = (void *)(((uintptr_t)(start) + 3) & ~3); \
30 (size) &= ~3; }) 30 (size) &= ~3; })
31 31
32struct pcm_peaks
33{
34 long period;
35 long tick;
36 uint16_t val[2];
37};
38
39void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, 32void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
40 const void *addr, int count); 33 const void *addr, int count);
41 34
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h
index df82c6092d..608129c078 100644
--- a/firmware/export/pcm.h
+++ b/firmware/export/pcm.h
@@ -21,7 +21,7 @@
21#ifndef PCM_PLAYBACK_H 21#ifndef PCM_PLAYBACK_H
22#define PCM_PLAYBACK_H 22#define PCM_PLAYBACK_H
23 23
24#include <string.h> /* size_t */ 24#include <sys/types.h> /* size_t, uint32_t */
25#include "config.h" 25#include "config.h"
26 26
27enum pcm_dma_status 27enum pcm_dma_status
@@ -71,6 +71,16 @@ void pcm_play_data(pcm_play_callback_type get_more,
71 pcm_status_callback_type status_cb, 71 pcm_status_callback_type status_cb,
72 const void *start, size_t size); 72 const void *start, size_t size);
73 73
74/* Kept internally for global PCM and used by mixer's verion of peak
75 calculation */
76struct pcm_peaks
77{
78 uint32_t left; /* Left peak value */
79 uint32_t right; /* Right peak value */
80 long period; /* For tracking calling period */
81 long tick; /* Last tick called */
82};
83
74void pcm_calculate_peaks(int *left, int *right); 84void pcm_calculate_peaks(int *left, int *right);
75const void* pcm_get_peak_buffer(int* count); 85const void* pcm_get_peak_buffer(int* count);
76size_t pcm_get_bytes_waiting(void); 86size_t pcm_get_bytes_waiting(void);
diff --git a/firmware/export/pcm_mixer.h b/firmware/export/pcm_mixer.h
index 5d8deb2bbf..f6d212d8e0 100644
--- a/firmware/export/pcm_mixer.h
+++ b/firmware/export/pcm_mixer.h
@@ -111,7 +111,7 @@ const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count
111 111
112/* Calculate peak values for channel */ 112/* Calculate peak values for channel */
113void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel, 113void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
114 int *left, int *right); 114 struct pcm_peaks *peaks);
115 115
116/* Adjust channel pointer by a given offset to support movable buffers */ 116/* Adjust channel pointer by a given offset to support movable buffers */
117void mixer_adjust_channel_address(enum pcm_mixer_channel channel, 117void mixer_adjust_channel_address(enum pcm_mixer_channel channel,
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;
102/* samplerate frequency selection index */ 102/* samplerate frequency selection index */
103int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; 103int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
104 104
105/* peak data for the global peak values - i.e. what the final output is */
106static struct pcm_peaks global_peaks;
107
108/* Called internally by functions to reset the state */ 105/* Called internally by functions to reset the state */
109static void pcm_play_stopped(void) 106static void pcm_play_stopped(void)
110{ 107{
@@ -125,42 +122,38 @@ static void pcm_wait_for_init(void)
125 * 122 *
126 * Used for recording and playback. 123 * Used for recording and playback.
127 */ 124 */
128static void pcm_peak_peeker(const int32_t *addr, int count, uint16_t peaks[2]) 125static void pcm_peak_peeker(const int16_t *p, int count,
126 struct pcm_peaks *peaks)
129{ 127{
130 int peak_l = 0, peak_r = 0; 128 uint32_t peak_l = 0, peak_r = 0;
131 const int32_t * const end = addr + count; 129 const int16_t *pend = p + 2 * count;
132 130
133 do 131 do
134 { 132 {
135 int32_t value = *addr; 133 int32_t s;
136 int ch; 134
137 135 s = p[0];
138#ifdef ROCKBOX_BIG_ENDIAN 136
139 ch = value >> 16; 137 if (s < 0)
140#else 138 s = -s;
141 ch = (int16_t)value; 139
142#endif 140 if ((uint32_t)s > peak_l)
143 if (ch < 0) 141 peak_l = s;
144 ch = -ch; 142
145 if (ch > peak_l) 143 s = p[1];
146 peak_l = ch; 144
147 145 if (s < 0)
148#ifdef ROCKBOX_BIG_ENDIAN 146 s = -s;
149 ch = (int16_t)value; 147
150#else 148 if ((uint32_t)s > peak_r)
151 ch = value >> 16; 149 peak_r = s;
152#endif 150
153 if (ch < 0) 151 p += 4 * 2; /* Every 4th sample, interleaved */
154 ch = -ch;
155 if (ch > peak_r)
156 peak_r = ch;
157
158 addr += 4;
159 } 152 }
160 while (addr < end); 153 while (p < pend);
161 154
162 peaks[0] = peak_l; 155 peaks->left = peak_l;
163 peaks[1] = peak_r; 156 peaks->right = peak_r;
164} 157}
165 158
166void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, 159void 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,
177 else if (period > HZ/5) 170 else if (period > HZ/5)
178 period = HZ/5; 171 period = HZ/5;
179 172
180 peaks->period = (3*peaks->period + period) >> 2; 173 peaks->period = (3*peaks->period + period) / 4;
181 peaks->tick = tick; 174 peaks->tick = tick;
182 175
183 if (active) 176 if (active)
@@ -186,29 +179,32 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
186 count = MIN(framecount, count); 179 count = MIN(framecount, count);
187 180
188 if (count > 0) 181 if (count > 0)
189 pcm_peak_peeker((int32_t *)addr, count, peaks->val); 182 pcm_peak_peeker(addr, count, peaks);
190 /* else keep previous peak values */ 183 /* else keep previous peak values */
191 } 184 }
192 else 185 else
193 { 186 {
194 /* peaks are zero */ 187 /* peaks are zero */
195 peaks->val[0] = peaks->val[1] = 0; 188 peaks->left = peaks->right = 0;
196 } 189 }
197} 190}
198 191
199void pcm_calculate_peaks(int *left, int *right) 192void pcm_calculate_peaks(int *left, int *right)
200{ 193{
194 /* peak data for the global peak values - i.e. what the final output is */
195 static struct pcm_peaks peaks;
196
201 int count; 197 int count;
202 const void *addr = pcm_play_dma_get_peak_buffer(&count); 198 const void *addr = pcm_play_dma_get_peak_buffer(&count);
203 199
204 pcm_do_peak_calculation(&global_peaks, pcm_playing && !pcm_paused, 200 pcm_do_peak_calculation(&peaks, pcm_playing && !pcm_paused,
205 addr, count); 201 addr, count);
206 202
207 if (left) 203 if (left)
208 *left = global_peaks.val[0]; 204 *left = peaks.left;
209 205
210 if (right) 206 if (right)
211 *right = global_peaks.val[1]; 207 *right = peaks.right;
212} 208}
213 209
214const void* pcm_get_peak_buffer(int * count) 210const void* pcm_get_peak_buffer(int * count)
@@ -471,20 +467,20 @@ static void pcm_recording_stopped(void)
471 */ 467 */
472void pcm_calculate_rec_peaks(int *left, int *right) 468void pcm_calculate_rec_peaks(int *left, int *right)
473{ 469{
474 static uint16_t peaks[2]; 470 static struct pcm_peaks peaks;
475 471
476 if (pcm_recording) 472 if (pcm_recording)
477 { 473 {
478 const void *peak_addr = pcm_rec_peak_addr; 474 const int16_t *peak_addr = pcm_rec_peak_addr;
479 const void *addr = pcm_rec_dma_get_peak_buffer(); 475 const int16_t *addr = pcm_rec_dma_get_peak_buffer();
480 476
481 if (addr != NULL) 477 if (addr != NULL)
482 { 478 {
483 int count = (int)(((intptr_t)addr - (intptr_t)peak_addr) >> 2); 479 int count = (addr - peak_addr) / 2; /* Interleaved L+R */
484 480
485 if (count > 0) 481 if (count > 0)
486 { 482 {
487 pcm_peak_peeker((int32_t *)peak_addr, count, peaks); 483 pcm_peak_peeker(peak_addr, count, &peaks);
488 484
489 if (peak_addr == pcm_rec_peak_addr) 485 if (peak_addr == pcm_rec_peak_addr)
490 pcm_rec_peak_addr = addr; 486 pcm_rec_peak_addr = addr;
@@ -494,15 +490,15 @@ void pcm_calculate_rec_peaks(int *left, int *right)
494 } 490 }
495 else 491 else
496 { 492 {
497 peaks[0] = peaks[1] = 0; 493 peaks.left = peaks.right = 0;
498 } 494 }
499 495
500 if (left) 496 if (left)
501 *left = peaks[0]; 497 *left = peaks.left;
502 498
503 if (right) 499 if (right)
504 *right = peaks[1]; 500 *right = peaks.right;
505} /* pcm_calculate_rec_peaks */ 501}
506 502
507bool pcm_is_recording(void) 503bool pcm_is_recording(void)
508{ 504{
diff --git a/firmware/pcm_mixer.c b/firmware/pcm_mixer.c
index 85d31ade70..cddff431ec 100644
--- a/firmware/pcm_mixer.c
+++ b/firmware/pcm_mixer.c
@@ -60,9 +60,6 @@ static size_t next_size = 0; /* Size of buffer to play next time */
60/* Descriptors for all available channels */ 60/* Descriptors for all available channels */
61static struct mixer_channel channels[PCM_MIXER_NUM_CHANNELS] IBSS_ATTR; 61static struct mixer_channel channels[PCM_MIXER_NUM_CHANNELS] IBSS_ATTR;
62 62
63/* History for channel peaks */
64static struct pcm_peaks channel_peaks[PCM_MIXER_NUM_CHANNELS];
65
66/* Packed pointer array of all playing (active) channels in "channels" array */ 63/* Packed pointer array of all playing (active) channels in "channels" array */
67static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR; 64static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR;
68 65
@@ -389,21 +386,14 @@ const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count
389 386
390/* Calculate peak values for channel */ 387/* Calculate peak values for channel */
391void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel, 388void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
392 int *left, int *right) 389 struct pcm_peaks *peaks)
393{ 390{
394 struct mixer_channel *chan = &channels[channel];
395 struct pcm_peaks *peaks = &channel_peaks[channel];
396 int count; 391 int count;
397 const void *addr = mixer_channel_get_buffer(channel, &count); 392 const void *addr = mixer_channel_get_buffer(channel, &count);
398 393
399 pcm_do_peak_calculation(peaks, chan->status == CHANNEL_PLAYING, 394 pcm_do_peak_calculation(peaks,
395 channels[channel].status == CHANNEL_PLAYING,
400 addr, count); 396 addr, count);
401
402 if (left)
403 *left = peaks->val[0];
404
405 if (right)
406 *right = peaks->val[1];
407} 397}
408 398
409/* Adjust channel pointer by a given offset to support movable buffers */ 399/* Adjust channel pointer by a given offset to support movable buffers */