summaryrefslogtreecommitdiff
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
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
-rw-r--r--apps/plugin.h6
-rw-r--r--apps/plugins/oscilloscope.c4
-rw-r--r--apps/plugins/starfield.c6
-rw-r--r--apps/plugins/vu_meter.c13
-rw-r--r--apps/recorder/peakmeter.c7
-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
10 files changed, 84 insertions, 81 deletions
diff --git a/apps/plugin.h b/apps/plugin.h
index 588a01262e..4091cecc16 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -154,12 +154,12 @@ void* plugin_get_buffer(size_t *buffer_size);
154#define PLUGIN_MAGIC 0x526F634B /* RocK */ 154#define PLUGIN_MAGIC 0x526F634B /* RocK */
155 155
156/* increase this every time the api struct changes */ 156/* increase this every time the api struct changes */
157#define PLUGIN_API_VERSION 219 157#define PLUGIN_API_VERSION 220
158 158
159/* update this to latest version if a change to the api struct breaks 159/* update this to latest version if a change to the api struct breaks
160 backwards compatibility (and please take the opportunity to sort in any 160 backwards compatibility (and please take the opportunity to sort in any
161 new function which are "waiting" at the end of the function table) */ 161 new function which are "waiting" at the end of the function table) */
162#define PLUGIN_MIN_API_VERSION 219 162#define PLUGIN_MIN_API_VERSION 220
163 163
164/* plugin return codes */ 164/* plugin return codes */
165/* internal returns start at 0x100 to make exit(1..255) work */ 165/* internal returns start at 0x100 to make exit(1..255) work */
@@ -697,7 +697,7 @@ struct plugin_api {
697 const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel, 697 const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel,
698 int *count); 698 int *count);
699 void (*mixer_channel_calculate_peaks)(enum pcm_mixer_channel channel, 699 void (*mixer_channel_calculate_peaks)(enum pcm_mixer_channel channel,
700 int *left, int *right); 700 struct pcm_peaks *peaks);
701 void (*mixer_channel_play_data)(enum pcm_mixer_channel channel, 701 void (*mixer_channel_play_data)(enum pcm_mixer_channel channel,
702 pcm_play_callback_type get_more, 702 pcm_play_callback_type get_more,
703 const void *start, size_t size); 703 const void *start, size_t size);
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index a4be0fbd8e..0bf951f069 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -881,8 +881,10 @@ enum plugin_status plugin_start(const void* parameter)
881 left = rb->mas_codec_readreg(0xC); 881 left = rb->mas_codec_readreg(0xC);
882 right = rb->mas_codec_readreg(0xD); 882 right = rb->mas_codec_readreg(0xD);
883#elif (CONFIG_CODEC == SWCODEC) 883#elif (CONFIG_CODEC == SWCODEC)
884 static struct pcm_peaks peaks;
884 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK, 885 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
885 &left, &right); 886 &peaks);
887 left = peaks.left; right = peaks.right;
886#endif 888#endif
887 if (osc.orientation == OSC_HORIZ) 889 if (osc.orientation == OSC_HORIZ)
888 anim_horizontal(left, right); 890 anim_horizontal(left, right);
diff --git a/apps/plugins/starfield.c b/apps/plugins/starfield.c
index 811e9c61ae..30b01b2645 100644
--- a/apps/plugins/starfield.c
+++ b/apps/plugins/starfield.c
@@ -228,9 +228,11 @@ static int plugin_main(void)
228 228
229 /* Get the peaks. ( Borrowed from vu_meter ) */ 229 /* Get the peaks. ( Borrowed from vu_meter ) */
230#if (CONFIG_CODEC == SWCODEC) 230#if (CONFIG_CODEC == SWCODEC)
231 int left_peak, right_peak; 231 static struct pcm_peaks peaks;
232 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK, 232 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
233 &left_peak, &right_peak); 233 &peaks);
234 #define left_peak peaks.left
235 #define right_peak peaks.right
234#else 236#else
235 int left_peak = rb->mas_codec_readreg(0xC); 237 int left_peak = rb->mas_codec_readreg(0xC);
236 int right_peak = rb->mas_codec_readreg(0xD); 238 int right_peak = rb->mas_codec_readreg(0xD);
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index 51f2d19f40..ec884442d4 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -704,9 +704,11 @@ static void analog_meter(void) {
704 int left_peak = rb->mas_codec_readreg(0xC); 704 int left_peak = rb->mas_codec_readreg(0xC);
705 int right_peak = rb->mas_codec_readreg(0xD); 705 int right_peak = rb->mas_codec_readreg(0xD);
706#elif (CONFIG_CODEC == SWCODEC) 706#elif (CONFIG_CODEC == SWCODEC)
707 int left_peak, right_peak; 707 static struct pcm_peaks peaks;
708 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK, 708 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
709 &left_peak, &right_peak); 709 &peaks);
710 #define left_peak peaks.left
711 #define right_peak peaks.right
710#endif 712#endif
711 713
712 if(vumeter_settings.analog_use_db_scale) { 714 if(vumeter_settings.analog_use_db_scale) {
@@ -762,8 +764,11 @@ static void digital_meter(void) {
762 int left_peak = rb->mas_codec_readreg(0xC); 764 int left_peak = rb->mas_codec_readreg(0xC);
763 int right_peak = rb->mas_codec_readreg(0xD); 765 int right_peak = rb->mas_codec_readreg(0xD);
764#elif (CONFIG_CODEC == SWCODEC) 766#elif (CONFIG_CODEC == SWCODEC)
765 int left_peak, right_peak; 767 static struct pcm_peaks peaks;
766 rb->pcm_calculate_peaks(&left_peak, &right_peak); 768 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
769 &peaks);
770 #define left_peak peaks.left
771 #define right_peak peaks.right
767#endif 772#endif
768 773
769 if(vumeter_settings.digital_use_db_scale) { 774 if(vumeter_settings.digital_use_db_scale) {
diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c
index 9f0db3330a..48a695b933 100644
--- a/apps/recorder/peakmeter.c
+++ b/apps/recorder/peakmeter.c
@@ -619,8 +619,13 @@ void peak_meter_peek(void)
619 /* read current values */ 619 /* read current values */
620#if CONFIG_CODEC == SWCODEC 620#if CONFIG_CODEC == SWCODEC
621 if (pm_playback) 621 if (pm_playback)
622 {
623 static struct pcm_peaks chan_peaks; /* *MUST* be static */
622 mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK, 624 mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
623 &pm_cur_left, &pm_cur_right); 625 &chan_peaks);
626 pm_cur_left = chan_peaks.left;
627 pm_cur_right = chan_peaks.right;
628 }
624#ifdef HAVE_RECORDING 629#ifdef HAVE_RECORDING
625 else 630 else
626 pcm_calculate_rec_peaks(&pm_cur_left, &pm_cur_right); 631 pcm_calculate_rec_peaks(&pm_cur_left, &pm_cur_right);
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 */