summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/test_sampr.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/apps/plugins/test_sampr.c b/apps/plugins/test_sampr.c
new file mode 100644
index 0000000000..cab81d2a80
--- /dev/null
+++ b/apps/plugins/test_sampr.c
@@ -0,0 +1,296 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21PLUGIN_HEADER
22
23struct plugin_api *rb;
24
25enum
26{
27 TONE_SINE = 0,
28 TONE_TRIANGLE,
29 TONE_SAWTOOTH,
30 TONE_SQUARE,
31 NUM_WAVEFORMS
32};
33
34static int freq = HW_FREQ_DEFAULT;
35static int waveform = TONE_SINE;
36
37/* A441 at 44100Hz. Pitch will change with changing samplerate.
38 Test different waveforms to detect any aliasing in signal which
39 indicates duplicated/dropped samples */
40static const int16_t A441[NUM_WAVEFORMS][100] =
41{
42 [TONE_SINE] =
43 {
44 0, 2057, 4106, 6139, 8148,
45 10125, 12062, 13951, 15785, 17557,
46 19259, 20886, 22430, 23886, 25247,
47 26509, 27666, 28713, 29648, 30465,
48 31163, 31737, 32186, 32508, 32702,
49 32767, 32702, 32508, 32186, 31737,
50 31163, 30465, 29648, 28713, 27666,
51 26509, 25247, 23886, 22430, 20886,
52 19259, 17557, 15785, 13951, 12062,
53 10125, 8148, 6139, 4106, 2057,
54 0, -2057, -4106, -6139, -8148,
55 -10125, -12062, -13951, -15785, -17557,
56 -19259, -20886, -22430, -23886, -25247,
57 -26509, -27666, -28713, -29648, -30465,
58 -31163, -31737, -32186, -32508, -32702,
59 -32767, -32702, -32508, -32186, -31737,
60 -31163, -30465, -29648, -28713, -27666,
61 -26509, -25247, -23886, -22430, -20886,
62 -19259, -17557, -15785, -13951, -12062,
63 -10125, -8148, -6139, -4106, -2057,
64 },
65 [TONE_TRIANGLE] =
66 {
67 0, 1310, 2621, 3932, 5242,
68 6553, 7864, 9174, 10485, 11796,
69 13106, 14417, 15728, 17038, 18349,
70 19660, 20970, 22281, 23592, 24902,
71 26213, 27524, 28834, 30145, 31456,
72 32767, 31456, 30145, 28834, 27524,
73 26213, 24902, 23592, 22281, 20970,
74 19660, 18349, 17038, 15728, 14417,
75 13106, 11796, 10485, 9174, 7864,
76 6553, 5242, 3932, 2621, 1310,
77 0, -1310, -2621, -3932, -5242,
78 -6553, -7864, -9174, -10485, -11796,
79 -13106, -14417, -15728, -17038, -18349,
80 -19660, -20970, -22281, -23592, -24902,
81 -26213, -27524, -28834, -30145, -31456,
82 -32767, -31456, -30145, -28834, -27524,
83 -26213, -24902, -23592, -22281, -20970,
84 -19660, -18349, -17038, -15728, -14417,
85 -13106, -11796, -10485, -9174, -7864,
86 -6553, -5242, -3932, -2621, -1310,
87 },
88 [TONE_SAWTOOTH] =
89 {
90 -32767, -32111, -31456, -30800, -30145,
91 -29490, -28834, -28179, -27524, -26868,
92 -26213, -25558, -24902, -24247, -23592,
93 -22936, -22281, -21626, -20970, -20315,
94 -19660, -19004, -18349, -17694, -17038,
95 -16383, -15728, -15072, -14417, -13762,
96 -13106, -12451, -11796, -11140, -10485,
97 -9830, -9174, -8519, -7864, -7208,
98 -6553, -5898, -5242, -4587, -3932,
99 -3276, -2621, -1966, -1310, -655,
100 0, 655, 1310, 1966, 2621,
101 3276, 3932, 4587, 5242, 5898,
102 6553, 7208, 7864, 8519, 9174,
103 9830, 10485, 11140, 11796, 12451,
104 13106, 13762, 14417, 15072, 15728,
105 16383, 17038, 17694, 18349, 19004,
106 19660, 20315, 20970, 21626, 22281,
107 22936, 23592, 24247, 24902, 25558,
108 26213, 26868, 27524, 28179, 28834,
109 29490, 30145, 30800, 31456, 32111,
110 },
111 [TONE_SQUARE] =
112 {
113 32767, 32767, 32767, 32767, 32767,
114 32767, 32767, 32767, 32767, 32767,
115 32767, 32767, 32767, 32767, 32767,
116 32767, 32767, 32767, 32767, 32767,
117 32767, 32767, 32767, 32767, 32767,
118 32767, 32767, 32767, 32767, 32767,
119 32767, 32767, 32767, 32767, 32767,
120 32767, 32767, 32767, 32767, 32767,
121 32767, 32767, 32767, 32767, 32767,
122 32767, 32767, 32767, 32767, 32767,
123 -32767, -32767, -32767, -32767, -32767,
124 -32767, -32767, -32767, -32767, -32767,
125 -32767, -32767, -32767, -32767, -32767,
126 -32767, -32767, -32767, -32767, -32767,
127 -32767, -32767, -32767, -32767, -32767,
128 -32767, -32767, -32767, -32767, -32767,
129 -32767, -32767, -32767, -32767, -32767,
130 -32767, -32767, -32767, -32767, -32767,
131 -32767, -32767, -32767, -32767, -32767,
132 -32767, -32767, -32767, -32767, -32767,
133 }
134};
135
136void play_waveform(void)
137{
138 static struct opt_items names[HW_NUM_FREQ] =
139 {
140 HW_HAVE_96_([HW_FREQ_96] = { "96kHz", NULL },)
141 HW_HAVE_88_([HW_FREQ_88] = { "88.2kHz", NULL },)
142 HW_HAVE_64_([HW_FREQ_64] = { "64kHz", NULL },)
143 HW_HAVE_48_([HW_FREQ_48] = { "48kHz", NULL },)
144 HW_HAVE_44_([HW_FREQ_44] = { "44.1kHz", NULL },)
145 HW_HAVE_32_([HW_FREQ_32] = { "32kHz", NULL },)
146 HW_HAVE_24_([HW_FREQ_24] = { "24kHz", NULL },)
147 HW_HAVE_22_([HW_FREQ_22] = { "22.05kHz", NULL },)
148 HW_HAVE_16_([HW_FREQ_16] = { "16kHz", NULL },)
149 HW_HAVE_12_([HW_FREQ_12] = { "12kHz", NULL },)
150 HW_HAVE_11_([HW_FREQ_11] = { "11.025kHz", NULL },)
151 HW_HAVE_8_( [HW_FREQ_8 ] = { "8kHz", NULL },)
152 };
153
154 /* 50 cycles of wavform */
155 static int32_t audio[5000];
156
157 void init_audio(int type)
158 {
159 int i;
160 /* Signal amplitudes to adjust for somewhat equal percieved
161 volume */
162 int amps[NUM_WAVEFORMS] =
163 {
164 [TONE_SINE] = 8191,
165 [TONE_TRIANGLE] = 5119,
166 [TONE_SAWTOOTH] = 2047,
167 [TONE_SQUARE] = 1535
168 };
169
170 /* Initialize one cycle of the waveform */
171 for (i = 0; i < 100; i++)
172 {
173 uint16_t val = amps[type]*A441[type][i]/32767;
174 audio[i] = (val << 16) | val;
175 }
176
177 /* Duplicate it 49 more times */
178 for (i = 1; i < 50; i++)
179 {
180 rb->memcpy(audio + i*100, audio, 100*sizeof(int32_t));
181 }
182 }
183
184 /* ISR handler to get next block of data */
185 void get_more(unsigned char **start, size_t *size)
186 {
187 *start = (unsigned char *)audio;
188 *size = sizeof (audio);
189 }
190
191 /* Called to switch samplerate on the fly */
192 void set_frequency(int index)
193 {
194 rb->pcm_set_frequency(rb->hw_freq_sampr[index]);
195 rb->pcm_apply_settings(false);
196 }
197
198 rb->audio_stop();
199 rb->sound_set(SOUND_VOLUME, rb->sound_default(SOUND_VOLUME));
200
201 /* Select playback */
202 rb->rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
203
204 rb->cpu_boost(true);
205
206 rb->pcm_set_frequency(rb->hw_freq_sampr[freq]);
207
208#ifdef HAVE_RECORDING
209 /* Recordable targets can play back from other sources */
210 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
211#endif
212 /* This reset parameter will likely be deleted soon and resetting be
213 automatic - ignore if the implementation doesn't need it */
214 rb->pcm_apply_settings(true);
215
216 init_audio(waveform);
217 rb->pcm_play_data(get_more, NULL, 0);
218
219 rb->set_option("Sample Rate", &freq, INT, names,
220 HW_NUM_FREQ, set_frequency);
221
222 rb->pcm_play_stop();
223
224 while (rb->pcm_is_playing())
225 rb->yield();
226
227 rb->cpu_boost(false);
228
229 /* restore default - user of apis is responsible for restoring
230 default state - normally playback at 44100Hz */
231 rb->pcm_set_frequency(HW_FREQ_DEFAULT);
232}
233
234void set_waveform(void)
235{
236 static struct opt_items names[NUM_WAVEFORMS] =
237 {
238 [TONE_SINE] = { "Sine", NULL },
239 [TONE_TRIANGLE] = { "Triangle", NULL },
240 [TONE_SAWTOOTH] = { "Sawtooth", NULL },
241 [TONE_SQUARE] = { "Square", NULL },
242 };
243
244 rb->set_option("Waveform", &waveform, INT, names,
245 NUM_WAVEFORMS, NULL);
246}
247
248/* Tests hardware sample rate switching */
249/* TODO: needs a volume control */
250enum plugin_status plugin_start(struct plugin_api *api, void *parameter)
251{
252 static const struct menu_item items[] =
253 {
254 { "Set Waveform", NULL },
255 { "Play Waveform", NULL },
256 { "Quit", NULL },
257 };
258
259 bool exit = false;
260 int m;
261 bool talk_menu;
262
263 rb = api;
264
265 /* Have to shut up voice menus or it will mess up our waveform playback */
266 talk_menu = rb->global_settings->talk_menu;
267 rb->global_settings->talk_menu = false;
268
269 m = rb->menu_init(items, ARRAYLEN(items),
270 NULL, NULL, NULL, NULL);
271
272 while (!exit)
273 {
274 int result = rb->menu_show(m);
275
276 switch (result)
277 {
278 case 0:
279 set_waveform();
280 break;
281 case 1:
282 play_waveform();
283 break;
284 case 2:
285 exit = true;
286 break;
287 }
288 }
289
290 rb->menu_exit(m);
291
292 rb->global_settings->talk_menu = talk_menu;
293
294 return PLUGIN_OK;
295 (void)parameter;
296}