diff options
author | Nils Wallménius <nils@rockbox.org> | 2009-11-22 18:48:07 +0000 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2009-11-22 18:48:07 +0000 |
commit | 4279c9f4aa871fc2bed08c66d1ad0580068d5140 (patch) | |
tree | b2977d0bce92742bc7266e0d4a32364a3cb15af1 /apps/plugins | |
parent | 1832def9b0b52b2a3385f9672aacc35dde9c389a (diff) | |
download | rockbox-4279c9f4aa871fc2bed08c66d1ad0580068d5140.tar.gz rockbox-4279c9f4aa871fc2bed08c66d1ad0580068d5140.zip |
Give test_codec the ability to checksum files or folders of files, usefull to verify output integrity.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23711 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/test_codec.c | 314 |
1 files changed, 222 insertions, 92 deletions
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index 156852a7b0..74d2e40fd2 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -111,6 +111,9 @@ static bool taginfo_ready = true; | |||
111 | 111 | ||
112 | static bool use_dsp; | 112 | static bool use_dsp; |
113 | 113 | ||
114 | static bool checksum; | ||
115 | static uint32_t crc32; | ||
116 | |||
114 | static volatile unsigned int elapsed; | 117 | static volatile unsigned int elapsed; |
115 | static volatile bool codec_playing; | 118 | static volatile bool codec_playing; |
116 | static volatile long endtick; | 119 | static volatile long endtick; |
@@ -172,30 +175,31 @@ void init_wav(char* filename) | |||
172 | } | 175 | } |
173 | 176 | ||
174 | 177 | ||
175 | void close_wav(void) { | 178 | void close_wav(void) |
176 | int filesize = rb->filesize(wavinfo.fd); | 179 | { |
177 | int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2; | 180 | int filesize = rb->filesize(wavinfo.fd); |
178 | int bps = 16; /* TODO */ | 181 | int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2; |
182 | int bps = 16; /* TODO */ | ||
179 | 183 | ||
180 | /* We assume 16-bit, Stereo */ | 184 | /* We assume 16-bit, Stereo */ |
181 | 185 | ||
182 | rb->lseek(wavinfo.fd,0,SEEK_SET); | 186 | rb->lseek(wavinfo.fd,0,SEEK_SET); |
183 | 187 | ||
184 | int2le32(wav_header+4, filesize-8); /* ChunkSize */ | 188 | int2le32(wav_header+4, filesize-8); /* ChunkSize */ |
185 | 189 | ||
186 | int2le16(wav_header+22, channels); | 190 | int2le16(wav_header+22, channels); |
187 | 191 | ||
188 | int2le32(wav_header+24, wavinfo.samplerate); | 192 | int2le32(wav_header+24, wavinfo.samplerate); |
189 | 193 | ||
190 | int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */ | 194 | int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */ |
191 | 195 | ||
192 | int2le16(wav_header+32, channels * (bps / 8)); | 196 | int2le16(wav_header+32, channels * (bps / 8)); |
193 | 197 | ||
194 | int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */ | 198 | int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */ |
195 | 199 | ||
196 | rb->write(wavinfo.fd, wav_header, sizeof(wav_header)); | 200 | rb->write(wavinfo.fd, wav_header, sizeof(wav_header)); |
197 | 201 | ||
198 | rb->close(wavinfo.fd); | 202 | rb->close(wavinfo.fd); |
199 | } | 203 | } |
200 | 204 | ||
201 | /* Returns buffer to malloc array. Only codeclib should need this. */ | 205 | /* Returns buffer to malloc array. Only codeclib should need this. */ |
@@ -238,23 +242,119 @@ static int process_dsp(const void *ch1, const void *ch2, int count) | |||
238 | return written_count; | 242 | return written_count; |
239 | } | 243 | } |
240 | 244 | ||
245 | static inline int32_t clip_sample(int32_t sample) | ||
246 | { | ||
247 | if ((int16_t)sample != sample) | ||
248 | sample = 0x7fff ^ (sample >> 31); | ||
249 | |||
250 | return sample; | ||
251 | } | ||
252 | |||
241 | /* Null output */ | 253 | /* Null output */ |
242 | static void pcmbuf_insert_null(const void *ch1, const void *ch2, int count) | 254 | static void pcmbuf_insert_null(const void *ch1, const void *ch2, int count) |
243 | { | 255 | { |
244 | if (use_dsp) process_dsp(ch1, ch2, count); | 256 | if (use_dsp) |
257 | process_dsp(ch1, ch2, count); | ||
245 | 258 | ||
246 | /* Prevent idle poweroff */ | 259 | /* Prevent idle poweroff */ |
247 | rb->reset_poweroff_timer(); | 260 | rb->reset_poweroff_timer(); |
248 | } | 261 | } |
249 | 262 | ||
250 | static inline int32_t clip_sample(int32_t sample) | 263 | static void pcmbuf_insert_checksum(const void *ch1, const void *ch2, int count) |
251 | { | 264 | { |
252 | if ((int16_t)sample != sample) | 265 | const int16_t* data1_16; |
253 | sample = 0x7fff ^ (sample >> 31); | 266 | const int16_t* data2_16; |
267 | const int32_t* data1_32; | ||
268 | const int32_t* data2_32; | ||
269 | const int scale = wavinfo.sampledepth - 15; | ||
270 | const int dc_bias = 1 << (scale - 1); | ||
271 | int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2; | ||
254 | 272 | ||
255 | return sample; | 273 | /* Prevent idle poweroff */ |
256 | } | 274 | rb->reset_poweroff_timer(); |
275 | |||
276 | if (use_dsp) { | ||
277 | count = process_dsp(ch1, ch2, count); | ||
278 | wavinfo.totalsamples += count; | ||
279 | if (channels == 1) | ||
280 | { | ||
281 | unsigned char *s = dspbuffer, *d = dspbuffer; | ||
282 | int c = count; | ||
283 | while (c-- > 0) | ||
284 | { | ||
285 | *d++ = *s++; | ||
286 | *d++ = *s++; | ||
287 | s++; | ||
288 | s++; | ||
289 | } | ||
290 | } | ||
291 | crc32 = rb->crc_32(dspbuffer, count * 2 * channels, crc32); | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | if (wavinfo.sampledepth <= 16) { | ||
296 | data1_16 = ch1; | ||
297 | data2_16 = ch2; | ||
298 | |||
299 | switch(wavinfo.stereomode) | ||
300 | { | ||
301 | case STEREO_INTERLEAVED: | ||
302 | while (count--) { | ||
303 | crc32 = rb->crc_32(data1_16, 4, crc32); | ||
304 | data1_16 += 2; | ||
305 | } | ||
306 | break; | ||
307 | |||
308 | case STEREO_NONINTERLEAVED: | ||
309 | while (count--) { | ||
310 | crc32 = rb->crc_32(data1_16++, 2, crc32); | ||
311 | crc32 = rb->crc_32(data2_16++, 2, crc32); | ||
312 | } | ||
313 | break; | ||
314 | |||
315 | case STEREO_MONO: | ||
316 | while (count--) { | ||
317 | crc32 = rb->crc_32(data1_16++, 2, crc32); | ||
318 | } | ||
319 | break; | ||
320 | } | ||
321 | } | ||
322 | else | ||
323 | { | ||
324 | data1_32 = ch1; | ||
325 | data2_32 = ch2; | ||
257 | 326 | ||
327 | switch(wavinfo.stereomode) | ||
328 | { | ||
329 | case STEREO_INTERLEAVED: | ||
330 | while (count--) { | ||
331 | int16_t s = clip_sample((*data1_32++ + dc_bias) >> scale); | ||
332 | crc32 = rb->crc_32(&s, 2, crc32); | ||
333 | s = clip_sample((*data1_32++ + dc_bias) >> scale); | ||
334 | crc32 = rb->crc_32(&s, 2, crc32); | ||
335 | } | ||
336 | break; | ||
337 | |||
338 | case STEREO_NONINTERLEAVED: | ||
339 | while (count--) { | ||
340 | int16_t s = clip_sample((*data1_32++ + dc_bias) >> scale); | ||
341 | crc32 = rb->crc_32(&s, 2, crc32); | ||
342 | s = clip_sample((*data2_32++ + dc_bias) >> scale); | ||
343 | crc32 = rb->crc_32(&s, 2, crc32); | ||
344 | } | ||
345 | |||
346 | break; | ||
347 | |||
348 | case STEREO_MONO: | ||
349 | while (count--) { | ||
350 | int16_t s = clip_sample((*data1_32++ + dc_bias) >> scale); | ||
351 | crc32 = rb->crc_32(&s, 2, crc32); | ||
352 | } | ||
353 | break; | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | } | ||
258 | 358 | ||
259 | /* WAV output */ | 359 | /* WAV output */ |
260 | static void pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | 360 | static void pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) |
@@ -287,76 +387,77 @@ static void pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
287 | } | 387 | } |
288 | } | 388 | } |
289 | rb->write(wavinfo.fd, dspbuffer, count * 2 * channels); | 389 | rb->write(wavinfo.fd, dspbuffer, count * 2 * channels); |
290 | } else { | 390 | } |
291 | 391 | else | |
292 | if (wavinfo.sampledepth <= 16) { | 392 | { |
293 | data1_16 = ch1; | 393 | if (wavinfo.sampledepth <= 16) { |
294 | data2_16 = ch2; | 394 | data1_16 = ch1; |
395 | data2_16 = ch2; | ||
295 | 396 | ||
296 | switch(wavinfo.stereomode) | 397 | switch(wavinfo.stereomode) |
297 | { | 398 | { |
298 | case STEREO_INTERLEAVED: | 399 | case STEREO_INTERLEAVED: |
299 | while (count--) { | 400 | while (count--) { |
300 | int2le16(p,*data1_16++); | 401 | int2le16(p,*data1_16++); |
301 | p += 2; | 402 | p += 2; |
302 | int2le16(p,*data1_16++); | 403 | int2le16(p,*data1_16++); |
303 | p += 2; | 404 | p += 2; |
304 | } | 405 | } |
305 | break; | 406 | break; |
306 | 407 | ||
307 | case STEREO_NONINTERLEAVED: | 408 | case STEREO_NONINTERLEAVED: |
308 | while (count--) { | 409 | while (count--) { |
309 | int2le16(p,*data1_16++); | 410 | int2le16(p,*data1_16++); |
310 | p += 2; | 411 | p += 2; |
311 | int2le16(p,*data2_16++); | 412 | int2le16(p,*data2_16++); |
312 | p += 2; | 413 | p += 2; |
313 | } | 414 | } |
314 | 415 | ||
315 | break; | 416 | break; |
316 | 417 | ||
317 | case STEREO_MONO: | 418 | case STEREO_MONO: |
318 | while (count--) { | 419 | while (count--) { |
319 | int2le16(p,*data1_16++); | 420 | int2le16(p,*data1_16++); |
320 | p += 2; | 421 | p += 2; |
321 | } | 422 | } |
322 | break; | 423 | break; |
323 | } | 424 | } |
324 | } else { | 425 | } else { |
325 | data1_32 = ch1; | 426 | data1_32 = ch1; |
326 | data2_32 = ch2; | 427 | data2_32 = ch2; |
327 | 428 | ||
328 | switch(wavinfo.stereomode) | 429 | switch(wavinfo.stereomode) |
329 | { | 430 | { |
330 | case STEREO_INTERLEAVED: | 431 | case STEREO_INTERLEAVED: |
331 | while (count--) { | 432 | while (count--) { |
332 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); | 433 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
333 | p += 2; | 434 | p += 2; |
334 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); | 435 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
335 | p += 2; | 436 | p += 2; |
336 | } | 437 | } |
337 | break; | 438 | break; |
338 | 439 | ||
339 | case STEREO_NONINTERLEAVED: | 440 | case STEREO_NONINTERLEAVED: |
340 | while (count--) { | 441 | while (count--) { |
341 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); | 442 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
342 | p += 2; | 443 | p += 2; |
343 | int2le16(p, clip_sample((*data2_32++ + dc_bias) >> scale)); | 444 | int2le16(p, clip_sample((*data2_32++ + dc_bias) >> scale)); |
344 | p += 2; | 445 | p += 2; |
345 | } | 446 | } |
346 | 447 | ||
347 | break; | 448 | break; |
348 | 449 | ||
349 | case STEREO_MONO: | 450 | case STEREO_MONO: |
350 | while (count--) { | 451 | while (count--) { |
351 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); | 452 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
352 | p += 2; | 453 | p += 2; |
353 | } | 454 | } |
354 | break; | 455 | break; |
456 | } | ||
355 | } | 457 | } |
356 | } | ||
357 | 458 | ||
358 | wavinfo.totalsamples += count; | 459 | wavinfo.totalsamples += count; |
359 | rb->write(wavinfo.fd, wavbuffer, p - wavbuffer); | 460 | rb->write(wavinfo.fd, wavbuffer, p - wavbuffer); |
360 | } /* else */ | 461 | } /* else */ |
361 | } | 462 | } |
362 | 463 | ||
@@ -481,9 +582,12 @@ static void init_ci(void) | |||
481 | 582 | ||
482 | if (wavinfo.fd >= 0) { | 583 | if (wavinfo.fd >= 0) { |
483 | ci.pcmbuf_insert = pcmbuf_insert_wav; | 584 | ci.pcmbuf_insert = pcmbuf_insert_wav; |
585 | } else if (checksum){ | ||
586 | ci.pcmbuf_insert = pcmbuf_insert_checksum; | ||
484 | } else { | 587 | } else { |
485 | ci.pcmbuf_insert = pcmbuf_insert_null; | 588 | ci.pcmbuf_insert = pcmbuf_insert_null; |
486 | } | 589 | } |
590 | |||
487 | ci.set_elapsed = set_elapsed; | 591 | ci.set_elapsed = set_elapsed; |
488 | ci.read_filebuf = read_filebuf; | 592 | ci.read_filebuf = read_filebuf; |
489 | ci.request_buffer = request_buffer; | 593 | ci.request_buffer = request_buffer; |
@@ -636,6 +740,9 @@ static enum plugin_status test_track(const char* filename) | |||
636 | if (use_dsp) | 740 | if (use_dsp) |
637 | rb->dsp_configure(ci.dsp, DSP_RESET, 0); | 741 | rb->dsp_configure(ci.dsp, DSP_RESET, 0); |
638 | 742 | ||
743 | if (checksum) | ||
744 | crc32 = 0xffffffff; | ||
745 | |||
639 | starttick = *rb->current_tick; | 746 | starttick = *rb->current_tick; |
640 | 747 | ||
641 | codec_playing = true; | 748 | codec_playing = true; |
@@ -656,7 +763,12 @@ static enum plugin_status test_track(const char* filename) | |||
656 | 763 | ||
657 | log_text(str,true); | 764 | log_text(str,true); |
658 | 765 | ||
659 | if (wavinfo.fd < 0) | 766 | if (checksum) |
767 | { | ||
768 | rb->snprintf(str, sizeof(str), "CRC32 - %x", (unsigned)crc32); | ||
769 | log_text(str,true); | ||
770 | } | ||
771 | else if (wavinfo.fd < 0) | ||
660 | { | 772 | { |
661 | /* Display benchmark information */ | 773 | /* Display benchmark information */ |
662 | rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); | 774 | rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); |
@@ -727,6 +839,19 @@ enum plugin_status plugin_start(const void* parameter) | |||
727 | rb->lcd_clear_display(); | 839 | rb->lcd_clear_display(); |
728 | rb->lcd_update(); | 840 | rb->lcd_update(); |
729 | 841 | ||
842 | enum | ||
843 | { | ||
844 | SPEED_TEST = 0, | ||
845 | SPEED_TEST_DIR, | ||
846 | WRITE_WAV, | ||
847 | SPEED_TEST_WITH_DSP, | ||
848 | SPEED_TEST_DIR_WITH_DSP, | ||
849 | WRITE_WAV_WITH_DSP, | ||
850 | CHECKSUM, | ||
851 | CHECKSUM_DIR, | ||
852 | QUIT, | ||
853 | }; | ||
854 | |||
730 | MENUITEM_STRINGLIST( | 855 | MENUITEM_STRINGLIST( |
731 | menu, "test_codec", NULL, | 856 | menu, "test_codec", NULL, |
732 | "Speed test", | 857 | "Speed test", |
@@ -735,15 +860,17 @@ enum plugin_status plugin_start(const void* parameter) | |||
735 | "Speed test with DSP", | 860 | "Speed test with DSP", |
736 | "Speed test folder with DSP", | 861 | "Speed test folder with DSP", |
737 | "Write WAV with DSP", | 862 | "Write WAV with DSP", |
863 | "Checksum", | ||
864 | "Checksum folder", | ||
738 | "Quit", | 865 | "Quit", |
739 | ); | 866 | ); |
740 | 867 | ||
741 | show_menu: | 868 | show_menu: |
742 | rb->lcd_clear_display(); | 869 | rb->lcd_clear_display(); |
743 | 870 | ||
744 | result=rb->do_menu(&menu,&selection, NULL, false); | 871 | result = rb->do_menu(&menu, &selection, NULL, false); |
745 | 872 | ||
746 | if (result == 6) | 873 | if (result == QUIT) |
747 | { | 874 | { |
748 | res = PLUGIN_OK; | 875 | res = PLUGIN_OK; |
749 | goto exit; | 876 | goto exit; |
@@ -751,13 +878,17 @@ show_menu: | |||
751 | 878 | ||
752 | scandir = 0; | 879 | scandir = 0; |
753 | 880 | ||
754 | if ((use_dsp = ((result >= 3) && (result <=5)))) { | 881 | if ((checksum = (result == CHECKSUM || result == CHECKSUM_DIR))) |
882 | result -= 6; | ||
883 | |||
884 | if ((use_dsp = ((result >= SPEED_TEST_WITH_DSP) | ||
885 | && (result <= WRITE_WAV_WITH_DSP)))) { | ||
755 | result -= 3; | 886 | result -= 3; |
756 | } | 887 | } |
757 | if (result==0) { | 888 | if (result == SPEED_TEST) { |
758 | wavinfo.fd = -1; | 889 | wavinfo.fd = -1; |
759 | log_init(false); | 890 | log_init(false); |
760 | } else if (result==1) { | 891 | } else if (result == SPEED_TEST_DIR) { |
761 | wavinfo.fd = -1; | 892 | wavinfo.fd = -1; |
762 | scandir = 1; | 893 | scandir = 1; |
763 | 894 | ||
@@ -767,7 +898,7 @@ show_menu: | |||
767 | res = PLUGIN_ERROR; | 898 | res = PLUGIN_ERROR; |
768 | goto exit; | 899 | goto exit; |
769 | } | 900 | } |
770 | } else if (result==2) { | 901 | } else if (result == WRITE_WAV) { |
771 | log_init(false); | 902 | log_init(false); |
772 | init_wav("/test.wav"); | 903 | init_wav("/test.wav"); |
773 | if (wavinfo.fd < 0) { | 904 | if (wavinfo.fd < 0) { |
@@ -817,7 +948,6 @@ show_menu: | |||
817 | close_wav(); | 948 | close_wav(); |
818 | log_text("Wrote /test.wav",true); | 949 | log_text("Wrote /test.wav",true); |
819 | } | 950 | } |
820 | |||
821 | while (rb->button_get(true) != TESTCODEC_EXITBUTTON); | 951 | while (rb->button_get(true) != TESTCODEC_EXITBUTTON); |
822 | } | 952 | } |
823 | goto show_menu; | 953 | goto show_menu; |