blob: 4bde1ba39dbaa48d7e4bad53db6ad8b35af15b13 [file] [log] [blame]
Dave Chapman7cdd0fe2007-05-07 17:23:31 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
Dave Chapman198845f2007-05-10 21:56:34 +00008 * $Id$
Dave Chapman7cdd0fe2007-05-07 17:23:31 +00009 *
10 * Copyright (C) 2007 Dave Chapman
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Dave Chapman7cdd0fe2007-05-07 17:23:31 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "plugin.h"
22
Thomas Martitzcae4ae22010-08-24 14:30:46 +000023
Dave Chapman7cdd0fe2007-05-07 17:23:31 +000024
Jens Arnold29361ab2008-03-22 10:24:28 +000025/* All swcodec targets have BUTTON_SELECT apart from the H10 and M3 */
Dave Chapman621725a2007-05-23 20:51:47 +000026
27#if CONFIG_KEYPAD == IRIVER_H10_PAD
28#define TESTCODEC_EXITBUTTON BUTTON_RIGHT
Jens Arnold29361ab2008-03-22 10:24:28 +000029#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
30#define TESTCODEC_EXITBUTTON BUTTON_RC_PLAY
Michael Giacomelli594b6e22009-08-04 03:08:32 +000031#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
32#define TESTCODEC_EXITBUTTON BUTTON_PLAY
Szymon Dziok290e27b2010-12-02 20:25:04 +000033#elif CONFIG_KEYPAD == COWON_D2_PAD || CONFIG_KEYPAD == ONDAVX747_PAD \
34 || CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
Rob Purchase1bcd53d2008-06-23 17:47:09 +000035#define TESTCODEC_EXITBUTTON BUTTON_POWER
Szymon Dziok7074a642010-02-14 21:56:53 +000036#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
37#define TESTCODEC_EXITBUTTON BUTTON_REC
Marcin Bukatdd617022010-11-30 10:52:14 +000038#elif CONFIG_KEYPAD == MPIO_HD200_PAD
39#define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_PLAY)
40#elif CONFIG_KEYPAD == MPIO_HD300_PAD
41#define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_REPEAT)
Karl Kurbjun26348fb2009-11-07 22:56:00 +000042#elif defined(HAVE_TOUCHSCREEN)
43#define TESTCODEC_EXITBUTTON BUTTON_TOPLEFT
Dave Chapman621725a2007-05-23 20:51:47 +000044#else
45#define TESTCODEC_EXITBUTTON BUTTON_SELECT
46#endif
47
Michael Giacomelli70941812010-11-22 02:22:56 +000048#ifdef HAVE_ADJUSTABLE_CPU_FREQ
49static unsigned int boost =1;
50
51static const struct opt_items boost_settings[2] = {
52 { "No", -1 },
53 { "Yes", -1 },
54};
55
56#endif
57
Dave Chapmanf01b6612007-06-19 00:25:36 +000058/* Log functions copied from test_disk.c */
59static int line = 0;
60static int max_line = 0;
61static int log_fd = -1;
Dave Chapmanf01b6612007-06-19 00:25:36 +000062
Rob Purchase550ca642010-05-31 21:07:25 +000063static void log_close(void)
64{
65 if (log_fd >= 0)
66 rb->close(log_fd);
67}
68
Dave Chapmanf01b6612007-06-19 00:25:36 +000069static bool log_init(bool use_logfile)
70{
71 int h;
Rafaël Carré7aee7912010-06-22 10:43:45 +000072 char logfilename[MAX_PATH];
Dave Chapmanf01b6612007-06-19 00:25:36 +000073
Dave Chapmanf01b6612007-06-19 00:25:36 +000074 rb->lcd_getstringsize("A", NULL, &h);
75 max_line = LCD_HEIGHT / h;
76 line = 0;
77 rb->lcd_clear_display();
78 rb->lcd_update();
79
80 if (use_logfile) {
Rob Purchase550ca642010-05-31 21:07:25 +000081 log_close();
Dave Chapmanf01b6612007-06-19 00:25:36 +000082 rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt",
83 2 IF_CNFN_NUM_(, NULL));
Thomas Martitz0a1d7c22010-05-06 17:35:13 +000084 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666);
Dave Chapmanf01b6612007-06-19 00:25:36 +000085 return log_fd >= 0;
86 }
87
88 return true;
89}
90
91static void log_text(char *text, bool advance)
92{
93 rb->lcd_puts(0, line, text);
94 rb->lcd_update();
95 if (advance)
96 {
97 if (++line >= max_line)
98 line = 0;
99 if (log_fd >= 0)
100 rb->fdprintf(log_fd, "%s\n", text);
101 }
102}
103
Dave Chapman3463e872007-05-13 00:11:25 +0000104struct wavinfo_t
105{
106 int fd;
107 int samplerate;
108 int channels;
109 int sampledepth;
110 int stereomode;
111 int totalsamples;
112};
113
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000114static void* audiobuf;
115static void* codec_mallocbuf;
116static size_t audiosize;
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000117static size_t audiobufsize;
118static int offset;
119static int fd;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000120
121/* Our local implementation of the codec API */
122static struct codec_api ci;
123
Dave Chapmana0f34432007-11-12 22:10:36 +0000124struct test_track_info {
125 struct mp3entry id3; /* TAG metadata */
126 size_t filesize; /* File total length */
127};
128
Steve Bavin4d344572007-10-02 07:47:43 +0000129static struct test_track_info track;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000130
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000131static bool use_dsp;
132
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000133static bool checksum;
134static uint32_t crc32;
135
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000136static volatile unsigned int elapsed;
137static volatile bool codec_playing;
Jens Arnold4c3a19f2008-11-23 23:54:27 +0000138static volatile long endtick;
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000139static volatile long rebuffertick;
Dave Chapman3463e872007-05-13 00:11:25 +0000140struct wavinfo_t wavinfo;
141
142static unsigned char wav_header[44] =
143{
144 'R','I','F','F', // 0 - ChunkID
145 0,0,0,0, // 4 - ChunkSize (filesize-8)
146 'W','A','V','E', // 8 - Format
147 'f','m','t',' ', // 12 - SubChunkID
148 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
149 1,0, // 20 - AudioFormat (1=16-bit)
150 0,0, // 22 - NumChannels
151 0,0,0,0, // 24 - SampleRate in Hz
152 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
153 0,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
154 16,0, // 34 - BitsPerSample
155 'd','a','t','a', // 36 - Subchunk2ID
156 0,0,0,0 // 40 - Subchunk2Size
157};
158
159static inline void int2le32(unsigned char* buf, int32_t x)
160{
161 buf[0] = (x & 0xff);
162 buf[1] = (x & 0xff00) >> 8;
163 buf[2] = (x & 0xff0000) >> 16;
164 buf[3] = (x & 0xff000000) >>24;
165}
166
167static inline void int2le24(unsigned char* buf, int32_t x)
168{
169 buf[0] = (x & 0xff);
170 buf[1] = (x & 0xff00) >> 8;
171 buf[2] = (x & 0xff0000) >> 16;
172}
173
174static inline void int2le16(unsigned char* buf, int16_t x)
175{
176 buf[0] = (x & 0xff);
177 buf[1] = (x & 0xff00) >> 8;
178}
179
Rafaël Carré5c500212010-06-22 10:43:50 +0000180static unsigned char *wavbuffer;
181static unsigned char *dspbuffer;
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000182
Dave Chapman3463e872007-05-13 00:11:25 +0000183void init_wav(char* filename)
184{
185 wavinfo.totalsamples = 0;
186
Thomas Martitzc61e89c2010-05-06 17:35:04 +0000187 wavinfo.fd = rb->creat(filename, 0666);
Dave Chapman3463e872007-05-13 00:11:25 +0000188
189 if (wavinfo.fd >= 0)
190 {
191 /* Write WAV header - we go back and fill in the details at the end */
192 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
193 }
194}
195
196
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000197void close_wav(void)
198{
199 int filesize = rb->filesize(wavinfo.fd);
200 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
201 int bps = 16; /* TODO */
Dave Chapman3463e872007-05-13 00:11:25 +0000202
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000203 /* We assume 16-bit, Stereo */
Dave Chapman3463e872007-05-13 00:11:25 +0000204
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000205 rb->lseek(wavinfo.fd,0,SEEK_SET);
Dave Chapman3463e872007-05-13 00:11:25 +0000206
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000207 int2le32(wav_header+4, filesize-8); /* ChunkSize */
Dave Chapman3463e872007-05-13 00:11:25 +0000208
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000209 int2le16(wav_header+22, channels);
Dave Chapman3463e872007-05-13 00:11:25 +0000210
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000211 int2le32(wav_header+24, wavinfo.samplerate);
Dave Chapman3463e872007-05-13 00:11:25 +0000212
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000213 int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */
Dave Chapman3463e872007-05-13 00:11:25 +0000214
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000215 int2le16(wav_header+32, channels * (bps / 8));
Dave Chapman3463e872007-05-13 00:11:25 +0000216
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000217 int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */
Dave Chapman3463e872007-05-13 00:11:25 +0000218
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000219 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
Dave Chapman3463e872007-05-13 00:11:25 +0000220
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000221 rb->close(wavinfo.fd);
Dave Chapman3463e872007-05-13 00:11:25 +0000222}
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000223
224/* Returns buffer to malloc array. Only codeclib should need this. */
Nils Wallménius4e14f2d2008-10-22 18:42:55 +0000225static void* codec_get_buffer(size_t *size)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000226{
Rafaël Carré34aac0e2010-06-22 06:58:17 +0000227 DEBUGF("codec_get_buffer(%"PRIuPTR")\n",(uintptr_t)size);
Nils Wallménius4e14f2d2008-10-22 18:42:55 +0000228 *size = CODEC_SIZE;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000229 return codec_mallocbuf;
230}
231
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000232static int process_dsp(const void *ch1, const void *ch2, int count)
233{
234 const char *src[2] = { ch1, ch2 };
235 int written_count = 0;
236 char *dest = dspbuffer;
237
238 while (count > 0)
239 {
240 int out_count = rb->dsp_output_count(ci.dsp, count);
241
242 int inp_count = rb->dsp_input_count(ci.dsp, out_count);
243
244 if (inp_count <= 0)
245 break;
246
247 if (inp_count > count)
248 inp_count = count;
249
250 out_count = rb->dsp_process(ci.dsp, dest, src, inp_count);
251
252 if (out_count <= 0)
253 break;
254
255 written_count += out_count;
256 dest += out_count * 4;
257
258 count -= inp_count;
259 }
260
261 return written_count;
262}
263
Dave Chapman3463e872007-05-13 00:11:25 +0000264static inline int32_t clip_sample(int32_t sample)
265{
266 if ((int16_t)sample != sample)
267 sample = 0x7fff ^ (sample >> 31);
268
269 return sample;
270}
271
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000272/* Null output */
273static void pcmbuf_insert_null(const void *ch1, const void *ch2, int count)
274{
275 if (use_dsp)
276 process_dsp(ch1, ch2, count);
277
278 /* Prevent idle poweroff */
279 rb->reset_poweroff_timer();
280}
281
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000282/*
283 * Helper function used when the file is larger then the available memory.
284 * Rebuffers the file by setting the start of the audio buffer to be
285 * new_offset and filling from there.
286 */
287static int fill_buffer(int new_offset){
288 size_t n, bytestoread;
289 long temp = *rb->current_tick;
290 rb->lseek(fd,new_offset,SEEK_SET);
291
292 if(new_offset + audiobufsize <= track.filesize)
293 bytestoread = audiobufsize;
294 else
295 bytestoread = track.filesize-new_offset;
296
297 n = rb->read(fd, audiobuf,bytestoread);
298
299 if (n != bytestoread)
300 {
301 log_text("Read failed.",true);
302 DEBUGF("read fail: got %d bytes, expected %d\n", (int)n, (int)audiobufsize);
303 rb->backlight_on();
304
305 if (fd >= 0)
306 {
307 rb->close(fd);
308 }
309
310 return -1;
311 }
312 offset = new_offset;
313
314 /*keep track of how much time we spent buffering*/
315 rebuffertick += *rb->current_tick-temp;
316
317 return 0;
318}
319
Nils Wallméniusd0a170c2010-03-08 12:08:29 +0000320/* WAV output or calculate crc32 of output*/
321static void pcmbuf_insert_wav_checksum(const void *ch1, const void *ch2, int count)
Dave Chapman3463e872007-05-13 00:11:25 +0000322{
323 const int16_t* data1_16;
324 const int16_t* data2_16;
325 const int32_t* data1_32;
326 const int32_t* data2_32;
327 unsigned char* p = wavbuffer;
Thom Johansenc668de32007-08-29 14:32:52 +0000328 const int scale = wavinfo.sampledepth - 15;
329 const int dc_bias = 1 << (scale - 1);
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000330 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
Dave Chapman3463e872007-05-13 00:11:25 +0000331
Dave Chapmanf01b6612007-06-19 00:25:36 +0000332 /* Prevent idle poweroff */
333 rb->reset_poweroff_timer();
334
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000335 if (use_dsp) {
336 count = process_dsp(ch1, ch2, count);
337 wavinfo.totalsamples += count;
338 if (channels == 1)
339 {
340 unsigned char *s = dspbuffer, *d = dspbuffer;
341 int c = count;
342 while (c-- > 0)
343 {
344 *d++ = *s++;
345 *d++ = *s++;
346 s++;
347 s++;
348 }
349 }
Nils Wallméniusd0a170c2010-03-08 12:08:29 +0000350 if (checksum)
351 crc32 = rb->crc_32(dspbuffer, count * 2 * channels, crc32);
352 else
353 rb->write(wavinfo.fd, dspbuffer, count * 2 * channels);
Dave Chapman3463e872007-05-13 00:11:25 +0000354 }
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000355 else
356 {
357 if (wavinfo.sampledepth <= 16) {
358 data1_16 = ch1;
359 data2_16 = ch2;
Dave Chapman3463e872007-05-13 00:11:25 +0000360
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000361 switch(wavinfo.stereomode)
362 {
363 case STEREO_INTERLEAVED:
364 while (count--) {
365 int2le16(p,*data1_16++);
366 p += 2;
367 int2le16(p,*data1_16++);
368 p += 2;
369 }
370 break;
371
372 case STEREO_NONINTERLEAVED:
373 while (count--) {
374 int2le16(p,*data1_16++);
375 p += 2;
376 int2le16(p,*data2_16++);
377 p += 2;
378 }
379
380 break;
381
382 case STEREO_MONO:
383 while (count--) {
384 int2le16(p,*data1_16++);
385 p += 2;
386 }
387 break;
388 }
389 } else {
390 data1_32 = ch1;
391 data2_32 = ch2;
392
393 switch(wavinfo.stereomode)
394 {
395 case STEREO_INTERLEAVED:
396 while (count--) {
397 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
398 p += 2;
399 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
400 p += 2;
401 }
402 break;
403
404 case STEREO_NONINTERLEAVED:
405 while (count--) {
406 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
407 p += 2;
408 int2le16(p, clip_sample((*data2_32++ + dc_bias) >> scale));
409 p += 2;
410 }
411
412 break;
413
414 case STEREO_MONO:
415 while (count--) {
416 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
417 p += 2;
418 }
419 break;
420 }
421 }
422
423 wavinfo.totalsamples += count;
Nils Wallméniusd0a170c2010-03-08 12:08:29 +0000424 if (checksum)
425 crc32 = rb->crc_32(wavbuffer, p - wavbuffer, crc32);
426 else
427 rb->write(wavinfo.fd, wavbuffer, p - wavbuffer);
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000428 } /* else */
Dave Chapman3463e872007-05-13 00:11:25 +0000429}
430
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000431/* Set song position in WPS (value in ms). */
Jeffrey Goode013fe352009-11-05 17:32:32 +0000432static void set_elapsed(unsigned long value)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000433{
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000434 elapsed = value;
Michael Sevakisc537d592011-04-27 03:08:23 +0000435 ci.id3->elapsed = value;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000436}
437
438
439/* Read next <size> amount bytes from file buffer to <ptr>.
440 Will return number of bytes read or 0 if end of file. */
Steve Bavin135cc752008-03-28 12:51:33 +0000441static size_t read_filebuf(void *ptr, size_t size)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000442{
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000443 if (ci.curpos > (off_t)track.filesize)
444 {
445 return 0;
446 } else {
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000447 size_t realsize = MIN(track.filesize-ci.curpos,size);
448
449 /* check if we have enough bytes ready*/
450 if(realsize >(audiobufsize - (ci.curpos-offset)))
451 {
452 /*rebuffer so that we start at ci.curpos*/
453 fill_buffer(ci.curpos);
454 }
455
456 rb->memcpy(ptr, audiobuf + (ci.curpos-offset), realsize);
457 ci.curpos += realsize;
458 return realsize;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000459 }
460}
461
462
463/* Request pointer to file buffer which can be used to read
464 <realsize> amount of data. <reqsize> tells the buffer system
465 how much data it should try to allocate. If <realsize> is 0,
466 end of file is reached. */
Steve Bavin135cc752008-03-28 12:51:33 +0000467static void* request_buffer(size_t *realsize, size_t reqsize)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000468{
469 *realsize = MIN(track.filesize-ci.curpos,reqsize);
470
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000471 /*check if we have enough bytes ready - requested > bufsize-currentbufpos*/
472 if(*realsize>(audiobufsize - (ci.curpos-offset)))
473 {
474 /*rebuffer so that we start at ci.curpos*/
475 fill_buffer(ci.curpos);
476 }
477
478 return (audiobuf + (ci.curpos-offset));
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000479}
480
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000481/* Advance file buffer position by <amount> amount of bytes. */
Steve Bavin135cc752008-03-28 12:51:33 +0000482static void advance_buffer(size_t amount)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000483{
484 ci.curpos += amount;
Michael Sevakisc537d592011-04-27 03:08:23 +0000485 ci.id3->offset = ci.curpos;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000486}
487
488
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000489/* Seek file buffer to position <newpos> beginning of file. */
Steve Bavin135cc752008-03-28 12:51:33 +0000490static bool seek_buffer(size_t newpos)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000491{
492 ci.curpos = newpos;
493 return true;
494}
495
496
497/* Codec should call this function when it has done the seeking. */
498static void seek_complete(void)
499{
500 /* Do nothing */
501}
502
Michael Sevakisc537d592011-04-27 03:08:23 +0000503/* Codec calls this to know what it should do next. */
504static enum codec_command_action get_command(intptr_t *param)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000505{
Michael Sevakisc537d592011-04-27 03:08:23 +0000506 rb->yield();
507 return CODEC_ACTION_NULL; /* just continue processing */
508 (void)param;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000509}
510
Steve Bavin135cc752008-03-28 12:51:33 +0000511static void set_offset(size_t value)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000512{
Michael Sevakisc537d592011-04-27 03:08:23 +0000513 ci.id3->offset = value;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000514}
515
516
517/* Configure different codec buffer parameters. */
518static void configure(int setting, intptr_t value)
519{
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000520 if (use_dsp)
521 rb->dsp_configure(ci.dsp, setting, value);
Dave Chapman3463e872007-05-13 00:11:25 +0000522 switch(setting)
523 {
524 case DSP_SWITCH_FREQUENCY:
525 case DSP_SET_FREQUENCY:
526 DEBUGF("samplerate=%d\n",(int)value);
527 wavinfo.samplerate = (int)value;
528 break;
529
530 case DSP_SET_SAMPLE_DEPTH:
531 DEBUGF("sampledepth = %d\n",(int)value);
532 wavinfo.sampledepth=(int)value;
533 break;
534
535 case DSP_SET_STEREO_MODE:
536 DEBUGF("Stereo mode = %d\n",(int)value);
537 wavinfo.stereomode=(int)value;
538 break;
539 }
540
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000541}
542
543static void init_ci(void)
544{
545 /* --- Our "fake" implementations of the codec API functions. --- */
546
Michael Sevakisc537d592011-04-27 03:08:23 +0000547 ci.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP,
548 CODEC_IDX_AUDIO);
549
Nils Wallménius4e14f2d2008-10-22 18:42:55 +0000550 ci.codec_get_buffer = codec_get_buffer;
Dave Chapman3463e872007-05-13 00:11:25 +0000551
Nils Wallméniusd0a170c2010-03-08 12:08:29 +0000552 if (wavinfo.fd >= 0 || checksum) {
553 ci.pcmbuf_insert = pcmbuf_insert_wav_checksum;
Dave Chapman3463e872007-05-13 00:11:25 +0000554 } else {
555 ci.pcmbuf_insert = pcmbuf_insert_null;
556 }
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000557
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000558 ci.set_elapsed = set_elapsed;
559 ci.read_filebuf = read_filebuf;
560 ci.request_buffer = request_buffer;
561 ci.advance_buffer = advance_buffer;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000562 ci.seek_buffer = seek_buffer;
563 ci.seek_complete = seek_complete;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000564 ci.set_offset = set_offset;
565 ci.configure = configure;
Michael Sevakisc537d592011-04-27 03:08:23 +0000566 ci.get_command = get_command;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000567
568 /* --- "Core" functions --- */
569
570 /* kernel/ system */
Jens Arnold759bede2009-01-08 22:37:51 +0000571 ci.sleep = rb->sleep;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000572 ci.yield = rb->yield;
573
574 /* strings and memory */
575 ci.strcpy = rb->strcpy;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000576 ci.strlen = rb->strlen;
577 ci.strcmp = rb->strcmp;
578 ci.strcat = rb->strcat;
579 ci.memset = rb->memset;
580 ci.memcpy = rb->memcpy;
581 ci.memmove = rb->memmove;
582 ci.memcmp = rb->memcmp;
583 ci.memchr = rb->memchr;
Dominik Wenger25bb37b2008-07-26 15:16:10 +0000584 ci.strcasestr = rb->strcasestr;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000585#if defined(DEBUG) || defined(SIMULATOR)
586 ci.debugf = rb->debugf;
587#endif
588#ifdef ROCKBOX_HAS_LOGF
589 ci.logf = rb->logf;
590#endif
591
592 ci.qsort = rb->qsort;
593 ci.global_settings = rb->global_settings;
594
595#ifdef RB_PROFILE
596 ci.profile_thread = rb->profile_thread;
597 ci.profstop = rb->profstop;
598 ci.profile_func_enter = rb->profile_func_enter;
599 ci.profile_func_exit = rb->profile_func_exit;
600#endif
Michael Sevakisd712e252007-10-08 18:17:46 +0000601
Michael Sevakis21f0c9a2009-02-11 12:55:51 +0000602 ci.cpucache_invalidate = rb->cpucache_invalidate;
603 ci.cpucache_flush = rb->cpucache_flush;
Michael Giacomelliccd56bf2008-09-20 22:13:39 +0000604
605#if NUM_CORES > 1
606 ci.create_thread = rb->create_thread;
607 ci.thread_thaw = rb->thread_thaw;
608 ci.thread_wait = rb->thread_wait;
609 ci.semaphore_init = rb->semaphore_init;
610 ci.semaphore_wait = rb->semaphore_wait;
611 ci.semaphore_release = rb->semaphore_release;
Michael Giacomelliccd56bf2008-09-20 22:13:39 +0000612#endif
613
Thomas Martitzbf301fd2010-10-10 14:43:40 +0000614#if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
Michael Sevakisb0befad2009-01-24 03:47:09 +0000615 ci.__div0 = rb->__div0;
616#endif
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000617}
618
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000619static void codec_thread(void)
620{
621 const char* codecname;
Michael Sevakisc537d592011-04-27 03:08:23 +0000622 int res;
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000623
624 codecname = rb->get_codec_filename(track.id3.codectype);
625
Michael Sevakisc537d592011-04-27 03:08:23 +0000626 /* Load the codec */
627 res = rb->codec_load_file(codecname, &ci);
Michael Sevakis65109732011-02-23 14:31:13 +0000628
Michael Sevakisc537d592011-04-27 03:08:23 +0000629 if (res >= 0)
Michael Sevakis65109732011-02-23 14:31:13 +0000630 {
Michael Sevakisc537d592011-04-27 03:08:23 +0000631 /* Decode the file */
632 res = rb->codec_run_proc();
Michael Sevakis65109732011-02-23 14:31:13 +0000633 }
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000634
Michael Sevakisc537d592011-04-27 03:08:23 +0000635 /* Clean up */
636 rb->codec_close();
637
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000638 /* Signal to the main thread that we are done */
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000639 endtick = *rb->current_tick - rebuffertick;
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000640 codec_playing = false;
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000641}
642
Steve Bavinfa0eabd2008-05-13 12:03:07 +0000643static enum plugin_status test_track(const char* filename)
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000644{
645 size_t n;
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000646 enum plugin_status res = PLUGIN_ERROR;
Jens Arnold4c3a19f2008-11-23 23:54:27 +0000647 long starttick;
648 long ticks;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000649 unsigned long speed;
650 unsigned long duration;
Steve Bavinfa0eabd2008-05-13 12:03:07 +0000651 const char* ch;
Rafaël Carré7aee7912010-06-22 10:43:45 +0000652 char str[MAX_PATH];
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000653 offset=0;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000654
655 /* Display filename (excluding any path)*/
656 ch = rb->strrchr(filename, '/');
657 if (ch==NULL)
658 ch = filename;
659 else
660 ch++;
661
662 rb->snprintf(str,sizeof(str),"%s",ch);
663 log_text(str,true);
664
665 log_text("Loading...",false);
666
667 fd = rb->open(filename,O_RDONLY);
668 if (fd < 0)
669 {
670 log_text("Cannot open file",true);
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000671 goto exit;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000672 }
673
674 track.filesize = rb->filesize(fd);
675
676 /* Clear the id3 struct */
677 rb->memset(&track.id3, 0, sizeof(struct mp3entry));
678
Thom Johansen294ec1d2007-09-19 10:40:55 +0000679 if (!rb->get_metadata(&(track.id3), fd, filename))
Dave Chapmanf01b6612007-06-19 00:25:36 +0000680 {
681 log_text("Cannot read metadata",true);
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000682 goto exit;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000683 }
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000684
Dave Chapmanf01b6612007-06-19 00:25:36 +0000685 if (track.filesize > audiosize)
686 {
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000687 audiobufsize=audiosize;
688
689 } else
690 {
691 audiobufsize=track.filesize;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000692 }
693
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000694 n = rb->read(fd, audiobuf, audiobufsize);
Dave Chapmanf01b6612007-06-19 00:25:36 +0000695
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000696 if (n != audiobufsize)
Dave Chapmanf01b6612007-06-19 00:25:36 +0000697 {
698 log_text("Read failed.",true);
Dave Chapmanf01b6612007-06-19 00:25:36 +0000699 goto exit;
700 }
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000701
Dave Chapmanf01b6612007-06-19 00:25:36 +0000702
703 /* Initialise the function pointers in the codec API */
704 init_ci();
705
706 /* Prepare the codec struct for playing the whole file */
707 ci.filesize = track.filesize;
708 ci.id3 = &track.id3;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000709 ci.curpos = 0;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000710
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000711 if (use_dsp)
712 rb->dsp_configure(ci.dsp, DSP_RESET, 0);
713
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000714 if (checksum)
715 crc32 = 0xffffffff;
716
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000717 rebuffertick=0;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000718 starttick = *rb->current_tick;
719
720 codec_playing = true;
721
Michael Sevakis20546272009-01-05 10:31:19 +0000722 rb->codec_thread_do_callback(codec_thread, NULL);
Dave Chapmanf01b6612007-06-19 00:25:36 +0000723
724 /* Wait for codec thread to die */
725 while (codec_playing)
726 {
727 rb->sleep(HZ);
728 rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
729 log_text(str,false);
730 }
Jens Arnold4c3a19f2008-11-23 23:54:27 +0000731 ticks = endtick - starttick;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000732
Michael Sevakis7e12bba2007-10-22 05:57:38 +0000733 /* Be sure it is done */
Michael Sevakis20546272009-01-05 10:31:19 +0000734 rb->codec_thread_do_callback(NULL, NULL);
Michael Giacomelli35717ec2010-07-06 00:11:30 +0000735 rb->backlight_on();
Dave Chapmanf01b6612007-06-19 00:25:36 +0000736 log_text(str,true);
737
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000738 if (checksum)
739 {
Nils Wallménius10719ef2010-06-17 15:27:42 +0000740 rb->snprintf(str, sizeof(str), "CRC32 - %08x", (unsigned)crc32);
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000741 log_text(str,true);
742 }
743 else if (wavinfo.fd < 0)
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000744 {
Dave Chapmanf01b6612007-06-19 00:25:36 +0000745 /* Display benchmark information */
746 rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
747 log_text(str,true);
748
749 duration = track.id3.length / 10;
750 rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
751 log_text(str,true);
752
753 if (ticks > 0)
754 speed = duration * 10000 / ticks;
755 else
756 speed = 0;
757
758 rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
759 log_text(str,true);
Andree Buschmannea840e22008-06-04 06:07:43 +0000760
Thomas Martitz35e8b142010-06-21 16:53:00 +0000761#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
Andree Buschmannea840e22008-06-04 06:07:43 +0000762 /* show effective clockrate in MHz needed for realtime decoding */
763 if (speed > 0)
764 {
Michael Giacomelli70941812010-11-22 02:22:56 +0000765 int freq = CPUFREQ_MAX;
766
767#ifdef HAVE_ADJUSTABLE_CPU_FREQ
768 if(!boost)
769 freq = CPUFREQ_NORMAL;
770#endif
771
772 speed = freq / speed;
Andree Buschmannea840e22008-06-04 06:07:43 +0000773 rb->snprintf(str,sizeof(str),"%d.%02dMHz needed for realtime",
774 (int)speed/100,(int)speed%100);
775 log_text(str,true);
776 }
777#endif
Dave Chapmanf01b6612007-06-19 00:25:36 +0000778 }
779
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000780 res = PLUGIN_OK;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000781
782exit:
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000783 rb->backlight_on();
784
785 if (fd >= 0)
786 {
787 rb->close(fd);
788 }
789
Dave Chapmanf01b6612007-06-19 00:25:36 +0000790 return res;
791}
792
793/* plugin entry point */
Andrew Mahone23d98122009-01-16 10:34:40 +0000794enum plugin_status plugin_start(const void* parameter)
Dave Chapmanf01b6612007-06-19 00:25:36 +0000795{
Dave Chapmanf01b6612007-06-19 00:25:36 +0000796 int result, selection = 0;
797 enum plugin_status res = PLUGIN_OK;
798 int scandir;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000799 struct dirent *entry;
800 DIR* dir;
801 char* ch;
802 char dirpath[MAX_PATH];
803 char filename[MAX_PATH];
Rafaël Carré5c500212010-06-22 10:43:50 +0000804 size_t buffer_size;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000805
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000806 if (parameter == NULL)
807 {
808 rb->splash(HZ*2, "No File");
809 return PLUGIN_ERROR;
810 }
811
Rafaël Carré5c500212010-06-22 10:43:50 +0000812 wavbuffer = rb->plugin_get_buffer(&buffer_size);
813 dspbuffer = wavbuffer + buffer_size / 2;
814
Michael Sevakis9ec00d72007-10-19 09:11:23 +0000815 codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize);
Nils Wallménius60c640b2010-10-27 15:07:05 +0000816 /* Align codec_mallocbuf to pointer size, tlsf wants that */
817 codec_mallocbuf = (void*)(((intptr_t)codec_mallocbuf +
818 sizeof(intptr_t)-1) & ~(sizeof(intptr_t)-1));
Michael Sevakis20546272009-01-05 10:31:19 +0000819 audiobuf = SKIPBYTES(codec_mallocbuf, CODEC_SIZE);
820 audiosize -= CODEC_SIZE;
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000821
Dave Chapman3463e872007-05-13 00:11:25 +0000822 rb->lcd_clear_display();
823 rb->lcd_update();
824
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000825 enum
826 {
827 SPEED_TEST = 0,
828 SPEED_TEST_DIR,
Michael Giacomelli70941812010-11-22 02:22:56 +0000829#ifdef HAVE_ADJUSTABLE_CPU_FREQ
830 BOOST,
831#endif
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000832 WRITE_WAV,
833 SPEED_TEST_WITH_DSP,
834 SPEED_TEST_DIR_WITH_DSP,
835 WRITE_WAV_WITH_DSP,
836 CHECKSUM,
837 CHECKSUM_DIR,
838 QUIT,
839 };
840
Dave Chapmanf01b6612007-06-19 00:25:36 +0000841 MENUITEM_STRINGLIST(
842 menu, "test_codec", NULL,
843 "Speed test",
844 "Speed test folder",
Michael Giacomelli70941812010-11-22 02:22:56 +0000845#ifdef HAVE_ADJUSTABLE_CPU_FREQ
846 "Boosting",
847#endif
Dave Chapmanf01b6612007-06-19 00:25:36 +0000848 "Write WAV",
Jeffrey Goodeb60ddb82009-09-23 14:56:32 +0000849 "Speed test with DSP",
850 "Speed test folder with DSP",
851 "Write WAV with DSP",
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000852 "Checksum",
853 "Checksum folder",
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000854 "Quit",
Dave Chapmanf01b6612007-06-19 00:25:36 +0000855 );
Michael Giacomelli70941812010-11-22 02:22:56 +0000856
Dave Chapman3463e872007-05-13 00:11:25 +0000857
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000858show_menu:
Dave Chapman3463e872007-05-13 00:11:25 +0000859 rb->lcd_clear_display();
860
Michael Giacomelli70941812010-11-22 02:22:56 +0000861#ifdef HAVE_ADJUSTABLE_CPU_FREQ
862menu:
Michael Giacomelli3f932312010-11-22 02:28:12 +0000863#endif
Dave Chapman3463e872007-05-13 00:11:25 +0000864
Michael Giacomelli3f932312010-11-22 02:28:12 +0000865 result = rb->do_menu(&menu, &selection, NULL, false);
866#ifdef HAVE_ADJUSTABLE_CPU_FREQ
Michael Giacomelli70941812010-11-22 02:22:56 +0000867
868 if (result == BOOST)
869 {
870 rb->set_option("Boosting", &boost, INT,
871 boost_settings, 2, NULL);
872 goto menu;
873 }
Andree Buschmanne3abdb12011-02-15 20:10:50 +0000874 if(boost)
875 rb->cpu_boost(true);
Michael Giacomelli70941812010-11-22 02:22:56 +0000876#endif
877
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000878 if (result == QUIT)
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000879 {
880 res = PLUGIN_OK;
881 goto exit;
882 }
883
Dave Chapmanf01b6612007-06-19 00:25:36 +0000884 scandir = 0;
885
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000886 if ((checksum = (result == CHECKSUM || result == CHECKSUM_DIR)))
Nils Wallménius05434eb2010-11-24 16:42:40 +0000887#ifdef HAVE_ADJUSTABLE_CPU_FREQ
888 result -= 7;
889#else
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000890 result -= 6;
Nils Wallménius05434eb2010-11-24 16:42:40 +0000891#endif
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000892
893 if ((use_dsp = ((result >= SPEED_TEST_WITH_DSP)
894 && (result <= WRITE_WAV_WITH_DSP)))) {
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000895 result -= 3;
896 }
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000897 if (result == SPEED_TEST) {
Dave Chapman98b72292007-05-13 00:32:56 +0000898 wavinfo.fd = -1;
Dave Chapmanf01b6612007-06-19 00:25:36 +0000899 log_init(false);
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000900 } else if (result == SPEED_TEST_DIR) {
Dave Chapmanf01b6612007-06-19 00:25:36 +0000901 wavinfo.fd = -1;
902 scandir = 1;
903
904 /* Only create a log file when we are testing a folder */
905 if (!log_init(true)) {
906 rb->splash(HZ*2, "Cannot create logfile");
907 res = PLUGIN_ERROR;
908 goto exit;
909 }
Nils Wallménius4279c9f2009-11-22 18:48:07 +0000910 } else if (result == WRITE_WAV) {
Dave Chapmanf01b6612007-06-19 00:25:36 +0000911 log_init(false);
Dave Chapman3463e872007-05-13 00:11:25 +0000912 init_wav("/test.wav");
913 if (wavinfo.fd < 0) {
914 rb->splash(HZ*2, "Cannot create /test.wav");
915 res = PLUGIN_ERROR;
916 goto exit;
917 }
918 } else if (result == MENU_ATTACHED_USB) {
919 res = PLUGIN_USB_CONNECTED;
920 goto exit;
921 } else if (result < 0) {
922 res = PLUGIN_OK;
923 goto exit;
924 }
925
Dave Chapmanf01b6612007-06-19 00:25:36 +0000926 if (scandir) {
927 /* Test all files in the same directory as the file selected by the
928 user */
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000929
Nils Wallménius3d4701a2009-07-14 13:57:45 +0000930 rb->strlcpy(dirpath,parameter,sizeof(dirpath));
Dave Chapmanf01b6612007-06-19 00:25:36 +0000931 ch = rb->strrchr(dirpath,'/');
932 ch[1]=0;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000933
Dave Chapmanf01b6612007-06-19 00:25:36 +0000934 DEBUGF("Scanning directory \"%s\"\n",dirpath);
935 dir = rb->opendir(dirpath);
936 if (dir) {
937 entry = rb->readdir(dir);
938 while (entry) {
Rafaël Carréa92d3162010-09-02 12:10:37 +0000939 struct dirinfo info = rb->dir_get_info(dir, entry);
940 if (!(info.attribute & ATTR_DIRECTORY)) {
Dave Chapmanf01b6612007-06-19 00:25:36 +0000941 rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name);
942 test_track(filename);
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000943 log_text("", true);
Dave Chapmanf01b6612007-06-19 00:25:36 +0000944 }
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000945
Dave Chapmanf01b6612007-06-19 00:25:36 +0000946 /* Read next entry */
947 entry = rb->readdir(dir);
948 }
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000949
950 rb->closedir(dir);
Dave Chapmanf01b6612007-06-19 00:25:36 +0000951 }
Dave Chapman3463e872007-05-13 00:11:25 +0000952 } else {
Dave Chapmanf01b6612007-06-19 00:25:36 +0000953 /* Just test the file */
954 res = test_track(parameter);
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000955
Magnus Holmgrenc21f5902007-12-15 13:54:58 +0000956 /* Close WAV file (if there was one) */
957 if (wavinfo.fd >= 0) {
958 close_wav();
959 log_text("Wrote /test.wav",true);
960 }
Dave Chapmanf01b6612007-06-19 00:25:36 +0000961 while (rb->button_get(true) != TESTCODEC_EXITBUTTON);
Dave Chapman3463e872007-05-13 00:11:25 +0000962 }
Michael Giacomelli70941812010-11-22 02:22:56 +0000963
964 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
965 if(boost)
966 rb->cpu_boost(false);
967 #endif
968
Rob Purchase550ca642010-05-31 21:07:25 +0000969 rb->button_clear_queue();
Jeffrey Goode0dc2fb52009-08-12 18:12:25 +0000970 goto show_menu;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000971
Dave Chapmanf4a9dab2007-05-07 22:30:23 +0000972exit:
Dave Chapmanf01b6612007-06-19 00:25:36 +0000973 log_close();
974
Dave Chapman3463e872007-05-13 00:11:25 +0000975 return res;
Dave Chapman7cdd0fe2007-05-07 17:23:31 +0000976}