Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
Dave Chapman | 198845f | 2007-05-10 21:56:34 +0000 | [diff] [blame] | 8 | * $Id$ |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 9 | * |
| 10 | * Copyright (C) 2007 Dave Chapman |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame] | 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. |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 16 | * |
| 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 Martitz | cae4ae2 | 2010-08-24 14:30:46 +0000 | [diff] [blame] | 23 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 24 | |
Jens Arnold | 29361ab | 2008-03-22 10:24:28 +0000 | [diff] [blame] | 25 | /* All swcodec targets have BUTTON_SELECT apart from the H10 and M3 */ |
Dave Chapman | 621725a | 2007-05-23 20:51:47 +0000 | [diff] [blame] | 26 | |
| 27 | #if CONFIG_KEYPAD == IRIVER_H10_PAD |
| 28 | #define TESTCODEC_EXITBUTTON BUTTON_RIGHT |
Jens Arnold | 29361ab | 2008-03-22 10:24:28 +0000 | [diff] [blame] | 29 | #elif CONFIG_KEYPAD == IAUDIO_M3_PAD |
| 30 | #define TESTCODEC_EXITBUTTON BUTTON_RC_PLAY |
Michael Giacomelli | 594b6e2 | 2009-08-04 03:08:32 +0000 | [diff] [blame] | 31 | #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD |
| 32 | #define TESTCODEC_EXITBUTTON BUTTON_PLAY |
Szymon Dziok | 290e27b | 2010-12-02 20:25:04 +0000 | [diff] [blame] | 33 | #elif CONFIG_KEYPAD == COWON_D2_PAD || CONFIG_KEYPAD == ONDAVX747_PAD \ |
| 34 | || CONFIG_KEYPAD == PHILIPS_HDD6330_PAD |
Rob Purchase | 1bcd53d | 2008-06-23 17:47:09 +0000 | [diff] [blame] | 35 | #define TESTCODEC_EXITBUTTON BUTTON_POWER |
Szymon Dziok | 7074a64 | 2010-02-14 21:56:53 +0000 | [diff] [blame] | 36 | #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD |
| 37 | #define TESTCODEC_EXITBUTTON BUTTON_REC |
Marcin Bukat | dd61702 | 2010-11-30 10:52:14 +0000 | [diff] [blame] | 38 | #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 Kurbjun | 26348fb | 2009-11-07 22:56:00 +0000 | [diff] [blame] | 42 | #elif defined(HAVE_TOUCHSCREEN) |
| 43 | #define TESTCODEC_EXITBUTTON BUTTON_TOPLEFT |
Dave Chapman | 621725a | 2007-05-23 20:51:47 +0000 | [diff] [blame] | 44 | #else |
| 45 | #define TESTCODEC_EXITBUTTON BUTTON_SELECT |
| 46 | #endif |
| 47 | |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 48 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 49 | static unsigned int boost =1; |
| 50 | |
| 51 | static const struct opt_items boost_settings[2] = { |
| 52 | { "No", -1 }, |
| 53 | { "Yes", -1 }, |
| 54 | }; |
| 55 | |
| 56 | #endif |
| 57 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 58 | /* Log functions copied from test_disk.c */ |
| 59 | static int line = 0; |
| 60 | static int max_line = 0; |
| 61 | static int log_fd = -1; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 62 | |
Rob Purchase | 550ca64 | 2010-05-31 21:07:25 +0000 | [diff] [blame] | 63 | static void log_close(void) |
| 64 | { |
| 65 | if (log_fd >= 0) |
| 66 | rb->close(log_fd); |
| 67 | } |
| 68 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 69 | static bool log_init(bool use_logfile) |
| 70 | { |
| 71 | int h; |
Rafaël Carré | 7aee791 | 2010-06-22 10:43:45 +0000 | [diff] [blame] | 72 | char logfilename[MAX_PATH]; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 73 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 74 | 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 Purchase | 550ca64 | 2010-05-31 21:07:25 +0000 | [diff] [blame] | 81 | log_close(); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 82 | rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt", |
| 83 | 2 IF_CNFN_NUM_(, NULL)); |
Thomas Martitz | 0a1d7c2 | 2010-05-06 17:35:13 +0000 | [diff] [blame] | 84 | log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 85 | return log_fd >= 0; |
| 86 | } |
| 87 | |
| 88 | return true; |
| 89 | } |
| 90 | |
| 91 | static 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 Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 104 | struct wavinfo_t |
| 105 | { |
| 106 | int fd; |
| 107 | int samplerate; |
| 108 | int channels; |
| 109 | int sampledepth; |
| 110 | int stereomode; |
| 111 | int totalsamples; |
| 112 | }; |
| 113 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 114 | static void* audiobuf; |
| 115 | static void* codec_mallocbuf; |
| 116 | static size_t audiosize; |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 117 | static size_t audiobufsize; |
| 118 | static int offset; |
| 119 | static int fd; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 120 | |
| 121 | /* Our local implementation of the codec API */ |
| 122 | static struct codec_api ci; |
| 123 | |
Dave Chapman | a0f3443 | 2007-11-12 22:10:36 +0000 | [diff] [blame] | 124 | struct test_track_info { |
| 125 | struct mp3entry id3; /* TAG metadata */ |
| 126 | size_t filesize; /* File total length */ |
| 127 | }; |
| 128 | |
Steve Bavin | 4d34457 | 2007-10-02 07:47:43 +0000 | [diff] [blame] | 129 | static struct test_track_info track; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 130 | |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 131 | static bool use_dsp; |
| 132 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 133 | static bool checksum; |
| 134 | static uint32_t crc32; |
| 135 | |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 136 | static volatile unsigned int elapsed; |
| 137 | static volatile bool codec_playing; |
Jens Arnold | 4c3a19f | 2008-11-23 23:54:27 +0000 | [diff] [blame] | 138 | static volatile long endtick; |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 139 | static volatile long rebuffertick; |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 140 | struct wavinfo_t wavinfo; |
| 141 | |
| 142 | static 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 | |
| 159 | static 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 | |
| 167 | static 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 | |
| 174 | static 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é | 5c50021 | 2010-06-22 10:43:50 +0000 | [diff] [blame] | 180 | static unsigned char *wavbuffer; |
| 181 | static unsigned char *dspbuffer; |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 182 | |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 183 | void init_wav(char* filename) |
| 184 | { |
| 185 | wavinfo.totalsamples = 0; |
| 186 | |
Thomas Martitz | c61e89c | 2010-05-06 17:35:04 +0000 | [diff] [blame] | 187 | wavinfo.fd = rb->creat(filename, 0666); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 188 | |
| 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énius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 197 | void 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 Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 202 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 203 | /* We assume 16-bit, Stereo */ |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 204 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 205 | rb->lseek(wavinfo.fd,0,SEEK_SET); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 206 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 207 | int2le32(wav_header+4, filesize-8); /* ChunkSize */ |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 208 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 209 | int2le16(wav_header+22, channels); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 210 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 211 | int2le32(wav_header+24, wavinfo.samplerate); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 212 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 213 | int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */ |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 214 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 215 | int2le16(wav_header+32, channels * (bps / 8)); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 216 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 217 | int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */ |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 218 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 219 | rb->write(wavinfo.fd, wav_header, sizeof(wav_header)); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 220 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 221 | rb->close(wavinfo.fd); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 222 | } |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 223 | |
| 224 | /* Returns buffer to malloc array. Only codeclib should need this. */ |
Nils Wallménius | 4e14f2d | 2008-10-22 18:42:55 +0000 | [diff] [blame] | 225 | static void* codec_get_buffer(size_t *size) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 226 | { |
Rafaël Carré | 34aac0e | 2010-06-22 06:58:17 +0000 | [diff] [blame] | 227 | DEBUGF("codec_get_buffer(%"PRIuPTR")\n",(uintptr_t)size); |
Nils Wallménius | 4e14f2d | 2008-10-22 18:42:55 +0000 | [diff] [blame] | 228 | *size = CODEC_SIZE; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 229 | return codec_mallocbuf; |
| 230 | } |
| 231 | |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 232 | static 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 Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 264 | static 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énius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 272 | /* Null output */ |
| 273 | static 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 Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 282 | /* |
| 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 | */ |
| 287 | static 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énius | d0a170c | 2010-03-08 12:08:29 +0000 | [diff] [blame] | 320 | /* WAV output or calculate crc32 of output*/ |
| 321 | static void pcmbuf_insert_wav_checksum(const void *ch1, const void *ch2, int count) |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 322 | { |
| 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 Johansen | c668de3 | 2007-08-29 14:32:52 +0000 | [diff] [blame] | 328 | const int scale = wavinfo.sampledepth - 15; |
| 329 | const int dc_bias = 1 << (scale - 1); |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 330 | int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2; |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 331 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 332 | /* Prevent idle poweroff */ |
| 333 | rb->reset_poweroff_timer(); |
| 334 | |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 335 | 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énius | d0a170c | 2010-03-08 12:08:29 +0000 | [diff] [blame] | 350 | if (checksum) |
| 351 | crc32 = rb->crc_32(dspbuffer, count * 2 * channels, crc32); |
| 352 | else |
| 353 | rb->write(wavinfo.fd, dspbuffer, count * 2 * channels); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 354 | } |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 355 | else |
| 356 | { |
| 357 | if (wavinfo.sampledepth <= 16) { |
| 358 | data1_16 = ch1; |
| 359 | data2_16 = ch2; |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 360 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 361 | 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énius | d0a170c | 2010-03-08 12:08:29 +0000 | [diff] [blame] | 424 | if (checksum) |
| 425 | crc32 = rb->crc_32(wavbuffer, p - wavbuffer, crc32); |
| 426 | else |
| 427 | rb->write(wavinfo.fd, wavbuffer, p - wavbuffer); |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 428 | } /* else */ |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 429 | } |
| 430 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 431 | /* Set song position in WPS (value in ms). */ |
Jeffrey Goode | 013fe35 | 2009-11-05 17:32:32 +0000 | [diff] [blame] | 432 | static void set_elapsed(unsigned long value) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 433 | { |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 434 | elapsed = value; |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 435 | ci.id3->elapsed = value; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 436 | } |
| 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 Bavin | 135cc75 | 2008-03-28 12:51:33 +0000 | [diff] [blame] | 441 | static size_t read_filebuf(void *ptr, size_t size) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 442 | { |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 443 | if (ci.curpos > (off_t)track.filesize) |
| 444 | { |
| 445 | return 0; |
| 446 | } else { |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 447 | 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 Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 459 | } |
| 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 Bavin | 135cc75 | 2008-03-28 12:51:33 +0000 | [diff] [blame] | 467 | static void* request_buffer(size_t *realsize, size_t reqsize) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 468 | { |
| 469 | *realsize = MIN(track.filesize-ci.curpos,reqsize); |
| 470 | |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 471 | /*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 Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 479 | } |
| 480 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 481 | /* Advance file buffer position by <amount> amount of bytes. */ |
Steve Bavin | 135cc75 | 2008-03-28 12:51:33 +0000 | [diff] [blame] | 482 | static void advance_buffer(size_t amount) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 483 | { |
| 484 | ci.curpos += amount; |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 485 | ci.id3->offset = ci.curpos; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 486 | } |
| 487 | |
| 488 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 489 | /* Seek file buffer to position <newpos> beginning of file. */ |
Steve Bavin | 135cc75 | 2008-03-28 12:51:33 +0000 | [diff] [blame] | 490 | static bool seek_buffer(size_t newpos) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 491 | { |
| 492 | ci.curpos = newpos; |
| 493 | return true; |
| 494 | } |
| 495 | |
| 496 | |
| 497 | /* Codec should call this function when it has done the seeking. */ |
| 498 | static void seek_complete(void) |
| 499 | { |
| 500 | /* Do nothing */ |
| 501 | } |
| 502 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 503 | /* Codec calls this to know what it should do next. */ |
| 504 | static enum codec_command_action get_command(intptr_t *param) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 505 | { |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 506 | rb->yield(); |
| 507 | return CODEC_ACTION_NULL; /* just continue processing */ |
| 508 | (void)param; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 509 | } |
| 510 | |
Steve Bavin | 135cc75 | 2008-03-28 12:51:33 +0000 | [diff] [blame] | 511 | static void set_offset(size_t value) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 512 | { |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 513 | ci.id3->offset = value; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 514 | } |
| 515 | |
| 516 | |
| 517 | /* Configure different codec buffer parameters. */ |
| 518 | static void configure(int setting, intptr_t value) |
| 519 | { |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 520 | if (use_dsp) |
| 521 | rb->dsp_configure(ci.dsp, setting, value); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 522 | 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 Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 541 | } |
| 542 | |
| 543 | static void init_ci(void) |
| 544 | { |
| 545 | /* --- Our "fake" implementations of the codec API functions. --- */ |
| 546 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 547 | ci.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP, |
| 548 | CODEC_IDX_AUDIO); |
| 549 | |
Nils Wallménius | 4e14f2d | 2008-10-22 18:42:55 +0000 | [diff] [blame] | 550 | ci.codec_get_buffer = codec_get_buffer; |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 551 | |
Nils Wallménius | d0a170c | 2010-03-08 12:08:29 +0000 | [diff] [blame] | 552 | if (wavinfo.fd >= 0 || checksum) { |
| 553 | ci.pcmbuf_insert = pcmbuf_insert_wav_checksum; |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 554 | } else { |
| 555 | ci.pcmbuf_insert = pcmbuf_insert_null; |
| 556 | } |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 557 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 558 | ci.set_elapsed = set_elapsed; |
| 559 | ci.read_filebuf = read_filebuf; |
| 560 | ci.request_buffer = request_buffer; |
| 561 | ci.advance_buffer = advance_buffer; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 562 | ci.seek_buffer = seek_buffer; |
| 563 | ci.seek_complete = seek_complete; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 564 | ci.set_offset = set_offset; |
| 565 | ci.configure = configure; |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 566 | ci.get_command = get_command; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 567 | |
| 568 | /* --- "Core" functions --- */ |
| 569 | |
| 570 | /* kernel/ system */ |
Jens Arnold | 759bede | 2009-01-08 22:37:51 +0000 | [diff] [blame] | 571 | ci.sleep = rb->sleep; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 572 | ci.yield = rb->yield; |
| 573 | |
| 574 | /* strings and memory */ |
| 575 | ci.strcpy = rb->strcpy; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 576 | 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 Wenger | 25bb37b | 2008-07-26 15:16:10 +0000 | [diff] [blame] | 584 | ci.strcasestr = rb->strcasestr; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 585 | #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 Sevakis | d712e25 | 2007-10-08 18:17:46 +0000 | [diff] [blame] | 601 | |
Michael Sevakis | 21f0c9a | 2009-02-11 12:55:51 +0000 | [diff] [blame] | 602 | ci.cpucache_invalidate = rb->cpucache_invalidate; |
| 603 | ci.cpucache_flush = rb->cpucache_flush; |
Michael Giacomelli | ccd56bf | 2008-09-20 22:13:39 +0000 | [diff] [blame] | 604 | |
| 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 Giacomelli | ccd56bf | 2008-09-20 22:13:39 +0000 | [diff] [blame] | 612 | #endif |
| 613 | |
Thomas Martitz | bf301fd | 2010-10-10 14:43:40 +0000 | [diff] [blame] | 614 | #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE) |
Michael Sevakis | b0befad | 2009-01-24 03:47:09 +0000 | [diff] [blame] | 615 | ci.__div0 = rb->__div0; |
| 616 | #endif |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 617 | } |
| 618 | |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 619 | static void codec_thread(void) |
| 620 | { |
| 621 | const char* codecname; |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 622 | int res; |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 623 | |
| 624 | codecname = rb->get_codec_filename(track.id3.codectype); |
| 625 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 626 | /* Load the codec */ |
| 627 | res = rb->codec_load_file(codecname, &ci); |
Michael Sevakis | 6510973 | 2011-02-23 14:31:13 +0000 | [diff] [blame] | 628 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 629 | if (res >= 0) |
Michael Sevakis | 6510973 | 2011-02-23 14:31:13 +0000 | [diff] [blame] | 630 | { |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 631 | /* Decode the file */ |
| 632 | res = rb->codec_run_proc(); |
Michael Sevakis | 6510973 | 2011-02-23 14:31:13 +0000 | [diff] [blame] | 633 | } |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 634 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 635 | /* Clean up */ |
| 636 | rb->codec_close(); |
| 637 | |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 638 | /* Signal to the main thread that we are done */ |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 639 | endtick = *rb->current_tick - rebuffertick; |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 640 | codec_playing = false; |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 641 | } |
| 642 | |
Steve Bavin | fa0eabd | 2008-05-13 12:03:07 +0000 | [diff] [blame] | 643 | static enum plugin_status test_track(const char* filename) |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 644 | { |
| 645 | size_t n; |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 646 | enum plugin_status res = PLUGIN_ERROR; |
Jens Arnold | 4c3a19f | 2008-11-23 23:54:27 +0000 | [diff] [blame] | 647 | long starttick; |
| 648 | long ticks; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 649 | unsigned long speed; |
| 650 | unsigned long duration; |
Steve Bavin | fa0eabd | 2008-05-13 12:03:07 +0000 | [diff] [blame] | 651 | const char* ch; |
Rafaël Carré | 7aee791 | 2010-06-22 10:43:45 +0000 | [diff] [blame] | 652 | char str[MAX_PATH]; |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 653 | offset=0; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 654 | |
| 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 Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 671 | goto exit; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 672 | } |
| 673 | |
| 674 | track.filesize = rb->filesize(fd); |
| 675 | |
| 676 | /* Clear the id3 struct */ |
| 677 | rb->memset(&track.id3, 0, sizeof(struct mp3entry)); |
| 678 | |
Thom Johansen | 294ec1d | 2007-09-19 10:40:55 +0000 | [diff] [blame] | 679 | if (!rb->get_metadata(&(track.id3), fd, filename)) |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 680 | { |
| 681 | log_text("Cannot read metadata",true); |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 682 | goto exit; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 683 | } |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 684 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 685 | if (track.filesize > audiosize) |
| 686 | { |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 687 | audiobufsize=audiosize; |
| 688 | |
| 689 | } else |
| 690 | { |
| 691 | audiobufsize=track.filesize; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 692 | } |
| 693 | |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 694 | n = rb->read(fd, audiobuf, audiobufsize); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 695 | |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 696 | if (n != audiobufsize) |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 697 | { |
| 698 | log_text("Read failed.",true); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 699 | goto exit; |
| 700 | } |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 701 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 702 | |
| 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 Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 709 | ci.curpos = 0; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 710 | |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 711 | if (use_dsp) |
| 712 | rb->dsp_configure(ci.dsp, DSP_RESET, 0); |
| 713 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 714 | if (checksum) |
| 715 | crc32 = 0xffffffff; |
| 716 | |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 717 | rebuffertick=0; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 718 | starttick = *rb->current_tick; |
| 719 | |
| 720 | codec_playing = true; |
| 721 | |
Michael Sevakis | 2054627 | 2009-01-05 10:31:19 +0000 | [diff] [blame] | 722 | rb->codec_thread_do_callback(codec_thread, NULL); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 723 | |
| 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 Arnold | 4c3a19f | 2008-11-23 23:54:27 +0000 | [diff] [blame] | 731 | ticks = endtick - starttick; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 732 | |
Michael Sevakis | 7e12bba | 2007-10-22 05:57:38 +0000 | [diff] [blame] | 733 | /* Be sure it is done */ |
Michael Sevakis | 2054627 | 2009-01-05 10:31:19 +0000 | [diff] [blame] | 734 | rb->codec_thread_do_callback(NULL, NULL); |
Michael Giacomelli | 35717ec | 2010-07-06 00:11:30 +0000 | [diff] [blame] | 735 | rb->backlight_on(); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 736 | log_text(str,true); |
| 737 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 738 | if (checksum) |
| 739 | { |
Nils Wallménius | 10719ef | 2010-06-17 15:27:42 +0000 | [diff] [blame] | 740 | rb->snprintf(str, sizeof(str), "CRC32 - %08x", (unsigned)crc32); |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 741 | log_text(str,true); |
| 742 | } |
| 743 | else if (wavinfo.fd < 0) |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 744 | { |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 745 | /* 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 Buschmann | ea840e2 | 2008-06-04 06:07:43 +0000 | [diff] [blame] | 760 | |
Thomas Martitz | 35e8b14 | 2010-06-21 16:53:00 +0000 | [diff] [blame] | 761 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
Andree Buschmann | ea840e2 | 2008-06-04 06:07:43 +0000 | [diff] [blame] | 762 | /* show effective clockrate in MHz needed for realtime decoding */ |
| 763 | if (speed > 0) |
| 764 | { |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 765 | 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 Buschmann | ea840e2 | 2008-06-04 06:07:43 +0000 | [diff] [blame] | 773 | 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 Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 778 | } |
| 779 | |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 780 | res = PLUGIN_OK; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 781 | |
| 782 | exit: |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 783 | rb->backlight_on(); |
| 784 | |
| 785 | if (fd >= 0) |
| 786 | { |
| 787 | rb->close(fd); |
| 788 | } |
| 789 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 790 | return res; |
| 791 | } |
| 792 | |
| 793 | /* plugin entry point */ |
Andrew Mahone | 23d9812 | 2009-01-16 10:34:40 +0000 | [diff] [blame] | 794 | enum plugin_status plugin_start(const void* parameter) |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 795 | { |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 796 | int result, selection = 0; |
| 797 | enum plugin_status res = PLUGIN_OK; |
| 798 | int scandir; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 799 | struct dirent *entry; |
| 800 | DIR* dir; |
| 801 | char* ch; |
| 802 | char dirpath[MAX_PATH]; |
| 803 | char filename[MAX_PATH]; |
Rafaël Carré | 5c50021 | 2010-06-22 10:43:50 +0000 | [diff] [blame] | 804 | size_t buffer_size; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 805 | |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 806 | if (parameter == NULL) |
| 807 | { |
| 808 | rb->splash(HZ*2, "No File"); |
| 809 | return PLUGIN_ERROR; |
| 810 | } |
| 811 | |
Rafaël Carré | 5c50021 | 2010-06-22 10:43:50 +0000 | [diff] [blame] | 812 | wavbuffer = rb->plugin_get_buffer(&buffer_size); |
| 813 | dspbuffer = wavbuffer + buffer_size / 2; |
| 814 | |
Michael Sevakis | 9ec00d7 | 2007-10-19 09:11:23 +0000 | [diff] [blame] | 815 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); |
Nils Wallménius | 60c640b | 2010-10-27 15:07:05 +0000 | [diff] [blame] | 816 | /* 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 Sevakis | 2054627 | 2009-01-05 10:31:19 +0000 | [diff] [blame] | 819 | audiobuf = SKIPBYTES(codec_mallocbuf, CODEC_SIZE); |
| 820 | audiosize -= CODEC_SIZE; |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 821 | |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 822 | rb->lcd_clear_display(); |
| 823 | rb->lcd_update(); |
| 824 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 825 | enum |
| 826 | { |
| 827 | SPEED_TEST = 0, |
| 828 | SPEED_TEST_DIR, |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 829 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 830 | BOOST, |
| 831 | #endif |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 832 | 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 Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 841 | MENUITEM_STRINGLIST( |
| 842 | menu, "test_codec", NULL, |
| 843 | "Speed test", |
| 844 | "Speed test folder", |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 845 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 846 | "Boosting", |
| 847 | #endif |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 848 | "Write WAV", |
Jeffrey Goode | b60ddb8 | 2009-09-23 14:56:32 +0000 | [diff] [blame] | 849 | "Speed test with DSP", |
| 850 | "Speed test folder with DSP", |
| 851 | "Write WAV with DSP", |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 852 | "Checksum", |
| 853 | "Checksum folder", |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 854 | "Quit", |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 855 | ); |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 856 | |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 857 | |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 858 | show_menu: |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 859 | rb->lcd_clear_display(); |
| 860 | |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 861 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 862 | menu: |
Michael Giacomelli | 3f93231 | 2010-11-22 02:28:12 +0000 | [diff] [blame] | 863 | #endif |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 864 | |
Michael Giacomelli | 3f93231 | 2010-11-22 02:28:12 +0000 | [diff] [blame] | 865 | result = rb->do_menu(&menu, &selection, NULL, false); |
| 866 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 867 | |
| 868 | if (result == BOOST) |
| 869 | { |
| 870 | rb->set_option("Boosting", &boost, INT, |
| 871 | boost_settings, 2, NULL); |
| 872 | goto menu; |
| 873 | } |
Andree Buschmann | e3abdb1 | 2011-02-15 20:10:50 +0000 | [diff] [blame] | 874 | if(boost) |
| 875 | rb->cpu_boost(true); |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 876 | #endif |
| 877 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 878 | if (result == QUIT) |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 879 | { |
| 880 | res = PLUGIN_OK; |
| 881 | goto exit; |
| 882 | } |
| 883 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 884 | scandir = 0; |
| 885 | |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 886 | if ((checksum = (result == CHECKSUM || result == CHECKSUM_DIR))) |
Nils Wallménius | 05434eb | 2010-11-24 16:42:40 +0000 | [diff] [blame] | 887 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 888 | result -= 7; |
| 889 | #else |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 890 | result -= 6; |
Nils Wallménius | 05434eb | 2010-11-24 16:42:40 +0000 | [diff] [blame] | 891 | #endif |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 892 | |
| 893 | if ((use_dsp = ((result >= SPEED_TEST_WITH_DSP) |
| 894 | && (result <= WRITE_WAV_WITH_DSP)))) { |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 895 | result -= 3; |
| 896 | } |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 897 | if (result == SPEED_TEST) { |
Dave Chapman | 98b7229 | 2007-05-13 00:32:56 +0000 | [diff] [blame] | 898 | wavinfo.fd = -1; |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 899 | log_init(false); |
Nils Wallménius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 900 | } else if (result == SPEED_TEST_DIR) { |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 901 | 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énius | 4279c9f | 2009-11-22 18:48:07 +0000 | [diff] [blame] | 910 | } else if (result == WRITE_WAV) { |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 911 | log_init(false); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 912 | 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 Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 926 | if (scandir) { |
| 927 | /* Test all files in the same directory as the file selected by the |
| 928 | user */ |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 929 | |
Nils Wallménius | 3d4701a | 2009-07-14 13:57:45 +0000 | [diff] [blame] | 930 | rb->strlcpy(dirpath,parameter,sizeof(dirpath)); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 931 | ch = rb->strrchr(dirpath,'/'); |
| 932 | ch[1]=0; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 933 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 934 | 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é | a92d316 | 2010-09-02 12:10:37 +0000 | [diff] [blame] | 939 | struct dirinfo info = rb->dir_get_info(dir, entry); |
| 940 | if (!(info.attribute & ATTR_DIRECTORY)) { |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 941 | rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name); |
| 942 | test_track(filename); |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 943 | log_text("", true); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 944 | } |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 945 | |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 946 | /* Read next entry */ |
| 947 | entry = rb->readdir(dir); |
| 948 | } |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 949 | |
| 950 | rb->closedir(dir); |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 951 | } |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 952 | } else { |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 953 | /* Just test the file */ |
| 954 | res = test_track(parameter); |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 955 | |
Magnus Holmgren | c21f590 | 2007-12-15 13:54:58 +0000 | [diff] [blame] | 956 | /* Close WAV file (if there was one) */ |
| 957 | if (wavinfo.fd >= 0) { |
| 958 | close_wav(); |
| 959 | log_text("Wrote /test.wav",true); |
| 960 | } |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 961 | while (rb->button_get(true) != TESTCODEC_EXITBUTTON); |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 962 | } |
Michael Giacomelli | 7094181 | 2010-11-22 02:22:56 +0000 | [diff] [blame] | 963 | |
| 964 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 965 | if(boost) |
| 966 | rb->cpu_boost(false); |
| 967 | #endif |
| 968 | |
Rob Purchase | 550ca64 | 2010-05-31 21:07:25 +0000 | [diff] [blame] | 969 | rb->button_clear_queue(); |
Jeffrey Goode | 0dc2fb5 | 2009-08-12 18:12:25 +0000 | [diff] [blame] | 970 | goto show_menu; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 971 | |
Dave Chapman | f4a9dab | 2007-05-07 22:30:23 +0000 | [diff] [blame] | 972 | exit: |
Dave Chapman | f01b661 | 2007-06-19 00:25:36 +0000 | [diff] [blame] | 973 | log_close(); |
| 974 | |
Dave Chapman | 3463e87 | 2007-05-13 00:11:25 +0000 | [diff] [blame] | 975 | return res; |
Dave Chapman | 7cdd0fe | 2007-05-07 17:23:31 +0000 | [diff] [blame] | 976 | } |