New makefile solution: A single invocation of 'make' to build the entire tree. Fully...
[kugel-rb.git] / apps / plugins / test_sampr.c
blob01f24b5987f9b60b4e24d90267dc74228f1da6c0
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
22 #include "lib/oldmenuapi.h"
24 PLUGIN_HEADER
26 const struct plugin_api *rb;
28 enum
30 TONE_SINE = 0,
31 TONE_TRIANGLE,
32 TONE_SAWTOOTH,
33 TONE_SQUARE,
34 NUM_WAVEFORMS
37 static int freq = HW_FREQ_DEFAULT;
38 static int waveform = TONE_SINE;
40 /* A441 at 44100Hz. Pitch will change with changing samplerate.
41 Test different waveforms to detect any aliasing in signal which
42 indicates duplicated/dropped samples */
43 static const int16_t A441[NUM_WAVEFORMS][100] =
45 [TONE_SINE] =
47 0, 2057, 4106, 6139, 8148,
48 10125, 12062, 13951, 15785, 17557,
49 19259, 20886, 22430, 23886, 25247,
50 26509, 27666, 28713, 29648, 30465,
51 31163, 31737, 32186, 32508, 32702,
52 32767, 32702, 32508, 32186, 31737,
53 31163, 30465, 29648, 28713, 27666,
54 26509, 25247, 23886, 22430, 20886,
55 19259, 17557, 15785, 13951, 12062,
56 10125, 8148, 6139, 4106, 2057,
57 0, -2057, -4106, -6139, -8148,
58 -10125, -12062, -13951, -15785, -17557,
59 -19259, -20886, -22430, -23886, -25247,
60 -26509, -27666, -28713, -29648, -30465,
61 -31163, -31737, -32186, -32508, -32702,
62 -32767, -32702, -32508, -32186, -31737,
63 -31163, -30465, -29648, -28713, -27666,
64 -26509, -25247, -23886, -22430, -20886,
65 -19259, -17557, -15785, -13951, -12062,
66 -10125, -8148, -6139, -4106, -2057,
68 [TONE_TRIANGLE] =
70 0, 1310, 2621, 3932, 5242,
71 6553, 7864, 9174, 10485, 11796,
72 13106, 14417, 15728, 17038, 18349,
73 19660, 20970, 22281, 23592, 24902,
74 26213, 27524, 28834, 30145, 31456,
75 32767, 31456, 30145, 28834, 27524,
76 26213, 24902, 23592, 22281, 20970,
77 19660, 18349, 17038, 15728, 14417,
78 13106, 11796, 10485, 9174, 7864,
79 6553, 5242, 3932, 2621, 1310,
80 0, -1310, -2621, -3932, -5242,
81 -6553, -7864, -9174, -10485, -11796,
82 -13106, -14417, -15728, -17038, -18349,
83 -19660, -20970, -22281, -23592, -24902,
84 -26213, -27524, -28834, -30145, -31456,
85 -32767, -31456, -30145, -28834, -27524,
86 -26213, -24902, -23592, -22281, -20970,
87 -19660, -18349, -17038, -15728, -14417,
88 -13106, -11796, -10485, -9174, -7864,
89 -6553, -5242, -3932, -2621, -1310,
91 [TONE_SAWTOOTH] =
93 -32767, -32111, -31456, -30800, -30145,
94 -29490, -28834, -28179, -27524, -26868,
95 -26213, -25558, -24902, -24247, -23592,
96 -22936, -22281, -21626, -20970, -20315,
97 -19660, -19004, -18349, -17694, -17038,
98 -16383, -15728, -15072, -14417, -13762,
99 -13106, -12451, -11796, -11140, -10485,
100 -9830, -9174, -8519, -7864, -7208,
101 -6553, -5898, -5242, -4587, -3932,
102 -3276, -2621, -1966, -1310, -655,
103 0, 655, 1310, 1966, 2621,
104 3276, 3932, 4587, 5242, 5898,
105 6553, 7208, 7864, 8519, 9174,
106 9830, 10485, 11140, 11796, 12451,
107 13106, 13762, 14417, 15072, 15728,
108 16383, 17038, 17694, 18349, 19004,
109 19660, 20315, 20970, 21626, 22281,
110 22936, 23592, 24247, 24902, 25558,
111 26213, 26868, 27524, 28179, 28834,
112 29490, 30145, 30800, 31456, 32111,
114 [TONE_SQUARE] =
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 -32767, -32767, -32767, -32767, -32767,
134 -32767, -32767, -32767, -32767, -32767,
135 -32767, -32767, -32767, -32767, -32767,
139 void play_waveform(void)
141 static struct opt_items names[HW_NUM_FREQ] =
143 HW_HAVE_96_([HW_FREQ_96] = { "96kHz", -1 },)
144 HW_HAVE_88_([HW_FREQ_88] = { "88.2kHz", -1 },)
145 HW_HAVE_64_([HW_FREQ_64] = { "64kHz", -1 },)
146 HW_HAVE_48_([HW_FREQ_48] = { "48kHz", -1 },)
147 HW_HAVE_44_([HW_FREQ_44] = { "44.1kHz", -1 },)
148 HW_HAVE_32_([HW_FREQ_32] = { "32kHz", -1 },)
149 HW_HAVE_24_([HW_FREQ_24] = { "24kHz", -1 },)
150 HW_HAVE_22_([HW_FREQ_22] = { "22.05kHz", -1 },)
151 HW_HAVE_16_([HW_FREQ_16] = { "16kHz", -1 },)
152 HW_HAVE_12_([HW_FREQ_12] = { "12kHz", -1 },)
153 HW_HAVE_11_([HW_FREQ_11] = { "11.025kHz", -1 },)
154 HW_HAVE_8_( [HW_FREQ_8 ] = { "8kHz", -1 },)
157 /* 50 cycles of wavform */
158 static int32_t audio[5000];
160 void init_audio(int type)
162 int i;
163 /* Signal amplitudes to adjust for somewhat equal percieved
164 volume */
165 int amps[NUM_WAVEFORMS] =
167 [TONE_SINE] = 8191,
168 [TONE_TRIANGLE] = 5119,
169 [TONE_SAWTOOTH] = 2047,
170 [TONE_SQUARE] = 1535
173 /* Initialize one cycle of the waveform */
174 for (i = 0; i < 100; i++)
176 uint16_t val = amps[type]*A441[type][i]/32767;
177 audio[i] = (val << 16) | val;
180 /* Duplicate it 49 more times */
181 for (i = 1; i < 50; i++)
183 rb->memcpy(audio + i*100, audio, 100*sizeof(int32_t));
187 /* ISR handler to get next block of data */
188 void get_more(unsigned char **start, size_t *size)
190 *start = (unsigned char *)audio;
191 *size = sizeof (audio);
194 /* Called to switch samplerate on the fly */
195 void set_frequency(int index)
197 rb->pcm_set_frequency(rb->hw_freq_sampr[index]);
198 rb->pcm_apply_settings();
201 rb->audio_stop();
202 rb->sound_set(SOUND_VOLUME, rb->sound_default(SOUND_VOLUME));
204 #if INPUT_SRC_CAPS != 0
205 /* Select playback */
206 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
207 #endif
209 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
210 rb->cpu_boost(true);
211 #endif
213 rb->pcm_set_frequency(rb->hw_freq_sampr[freq]);
215 #if INPUT_SRC_CAPS != 0
216 /* Recordable targets can play back from other sources */
217 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
218 #endif
220 rb->pcm_apply_settings();
222 init_audio(waveform);
223 rb->pcm_play_data(get_more, NULL, 0);
225 rb->set_option("Sample Rate", &freq, INT, names,
226 HW_NUM_FREQ, set_frequency);
228 rb->pcm_play_stop();
230 while (rb->pcm_is_playing())
231 rb->yield();
233 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
234 rb->cpu_boost(false);
235 #endif
237 /* restore default - user of apis is responsible for restoring
238 default state - normally playback at 44100Hz */
239 rb->pcm_set_frequency(HW_FREQ_DEFAULT);
242 void set_waveform(void)
244 static struct opt_items names[NUM_WAVEFORMS] =
246 [TONE_SINE] = { "Sine", -1 },
247 [TONE_TRIANGLE] = { "Triangle", -1 },
248 [TONE_SAWTOOTH] = { "Sawtooth", -1 },
249 [TONE_SQUARE] = { "Square", -1 },
252 rb->set_option("Waveform", &waveform, INT, names,
253 NUM_WAVEFORMS, NULL);
256 /* Tests hardware sample rate switching */
257 /* TODO: needs a volume control */
258 enum plugin_status plugin_start(const struct plugin_api *api, const void *parameter)
260 static const struct menu_item items[] =
262 { "Set Waveform", NULL },
263 { "Play Waveform", NULL },
264 { "Quit", NULL },
267 bool exit = false;
268 int m;
269 bool talk_menu;
271 rb = api;
273 /* Have to shut up voice menus or it will mess up our waveform playback */
274 talk_menu = rb->global_settings->talk_menu;
275 rb->global_settings->talk_menu = false;
277 m = menu_init(rb, items, ARRAYLEN(items),
278 NULL, NULL, NULL, NULL);
280 while (!exit)
282 int result = menu_show(m);
284 switch (result)
286 case 0:
287 set_waveform();
288 break;
289 case 1:
290 play_waveform();
291 break;
292 case 2:
293 exit = true;
294 break;
298 menu_exit(m);
300 rb->global_settings->talk_menu = talk_menu;
302 return PLUGIN_OK;
303 (void)parameter;