summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/pcm_playback.h2
-rw-r--r--firmware/pcm_playback.c83
2 files changed, 85 insertions, 0 deletions
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);
25/* This is for playing "raw" PCM data */ 25/* This is for playing "raw" PCM data */
26void pcm_play_data(void (*get_more)(unsigned char** start, long* size)); 26void pcm_play_data(void (*get_more)(unsigned char** start, long* size));
27 27
28void pcm_calculate_peaks(int *left, int *right);
29
28void pcm_play_stop(void); 30void pcm_play_stop(void);
29void pcm_play_pause(bool play); 31void pcm_play_pause(bool play);
30bool pcm_is_paused(void); 32bool 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)
89 pcm_paused = false; 89 pcm_paused = false;
90} 90}
91 91
92#define PEEK_SAMPLE_COUNT 64
93static long calculate_channel_peak_average(int channel, unsigned short *addr,
94 long size)
95{
96 int i;
97 long min, max;
98 int count, min_count, max_count;
99 unsigned long average, zero_point;
100
101 addr = &addr[channel];
102 average = 0;
103
104 if (pcm_playing && !pcm_paused && addr != NULL)
105 {
106 /* Calculate the zero point and remove DC offset (should be around 32768) */
107 zero_point = 0;
108 for (i = 0; i < size; i++)
109 zero_point += addr[i*2];
110 zero_point /= i;
111
112 /*for (i = 0; i < size; i++) {
113 long peak = addr[i*2] - 32768;
114 if (peak < 0)
115 peak = 0;
116 average += peak;
117 }
118 average /= i;*/
119
120 count = 0;
121
122 while (size > PEEK_SAMPLE_COUNT)
123 {
124 min = zero_point;
125 max = zero_point;
126 min_count = 1;
127 max_count = 1;
128
129 for (i = 0; i < PEEK_SAMPLE_COUNT; i++)
130 {
131 unsigned long value = *addr;
132 if (value < zero_point) {
133 min += value;
134 min_count++;
135 }
136 if (value > zero_point) {
137 max += value;
138 max_count++;
139 }
140 addr = &addr[2];
141 }
142
143 min /= min_count;
144 max /= max_count;
145
146 size -= PEEK_SAMPLE_COUNT;
147 average += (max - min) / 2;
148 //average += (max - zero_point) + (zero_point - min);
149 //average += zero_point - min;
150 count += 1;
151 }
152
153 if (count)
154 {
155 average /= count;
156 /* I don't know why this is needed. Should be fixed. */
157 average = zero_point - average;
158 }
159 }
160
161 return average;
162}
163
164void pcm_calculate_peaks(int *left, int *right)
165{
166 unsigned short *addr = (unsigned short *)SAR0;
167 long size = MIN(512, BCR0);
168
169 if (left != NULL)
170 *left = calculate_channel_peak_average(0, addr, size);
171 if (right != NULL)
172 *right = calculate_channel_peak_average(1, addr, size);;
173}
174
92/* sets frequency of input to DAC */ 175/* sets frequency of input to DAC */
93void pcm_set_frequency(unsigned int frequency) 176void pcm_set_frequency(unsigned int frequency)
94{ 177{