summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2005-06-10 18:08:08 +0000
committerDave Chapman <dave@dchapman.com>2005-06-10 18:08:08 +0000
commit3c2c2f59f4578c41d591f0e8e88a07103cee499b (patch)
tree9c05d5eaf112b5852b39532c420195df913a8637
parentd30f1100ec8d74f3c187271590b03d589ad4b7dc (diff)
downloadrockbox-3c2c2f59f4578c41d591f0e8e88a07103cee499b.tar.gz
rockbox-3c2c2f59f4578c41d591f0e8e88a07103cee499b.zip
Add first version of WAV playback to iRiver - only 16-bit Stereo 44.1KHz files supported.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6654 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/playback.c53
-rw-r--r--apps/plugins/codecwav.c131
2 files changed, 183 insertions, 1 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 71cb479059..4cefed20c2 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -598,7 +598,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
598 int rc, i; 598 int rc, i;
599 int copy_n; 599 int copy_n;
600 /* Used by the FLAC metadata parser */ 600 /* Used by the FLAC metadata parser */
601 unsigned long totalsamples; 601 unsigned long totalsamples,bytespersample,channels,bitspersample,numbytes;
602 unsigned char* buf; 602 unsigned char* buf;
603 603
604 if (track_count >= MAX_TRACK) 604 if (track_count >= MAX_TRACK)
@@ -677,6 +677,57 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
677 tracks[track_widx].taginfo_ready = true; 677 tracks[track_widx].taginfo_ready = true;
678 break ; 678 break ;
679 679
680 case AFMT_PCM_WAV:
681 /* Use the trackname part of the id3 structure as a temporary buffer */
682 buf=tracks[track_widx].id3.path;
683
684 lseek(fd, 0, SEEK_SET);
685
686 rc = read(fd, buf, 44);
687 if (rc < 44) {
688 close(fd);
689 return false;
690 }
691
692 if ((memcmp(buf,"RIFF",4)!=0) ||
693 (memcmp(&buf[8],"WAVEfmt",7)!=0)) {
694 logf("%s is not a WAV file\n",trackname);
695 close(fd);
696 return(false);
697 }
698
699 /* FIX: Correctly parse WAV header - we assume canonical
700 44-byte header */
701
702 bitspersample=buf[34];
703 channels=buf[22];
704
705 if ((bitspersample!=16) || (channels != 2)) {
706 logf("Unsupported WAV file - %d bitspersample, %d channels\n",
707 bitspersample,channels);
708 close(fd);
709 return(false);
710 }
711
712 bytespersample=((bitspersample/8)*channels);
713 numbytes=(buf[40]|(buf[41]<<8)|(buf[42]<<16)|(buf[43]<<24));
714 totalsamples=numbytes/bytespersample;
715
716 tracks[track_widx].id3.vbr=false; /* All WAV files are CBR */
717 tracks[track_widx].id3.filesize=filesize(fd);
718 tracks[track_widx].id3.frequency=buf[24]|(buf[25]<<8)|(buf[26]<<16)|(buf[27]<<24);
719
720 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
721 tracks[track_widx].id3.length=(totalsamples/tracks[track_widx].id3.frequency)*1000;
722 tracks[track_widx].id3.bitrate=(tracks[track_widx].id3.frequency*bytespersample)/1024;
723
724 lseek(fd, 0, SEEK_SET);
725 strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path));
726 tracks[track_widx].taginfo_ready = true;
727
728 break;
729
730
680 case AFMT_FLAC: 731 case AFMT_FLAC:
681 /* A simple parser to read vital metadata from a FLAC file - length, frequency, bitrate etc. */ 732 /* A simple parser to read vital metadata from a FLAC file - length, frequency, bitrate etc. */
682 /* This code should either be moved to a seperate file, or discarded in favour of the libFLAC code */ 733 /* This code should either be moved to a seperate file, or discarded in favour of the libFLAC code */
diff --git a/apps/plugins/codecwav.c b/apps/plugins/codecwav.c
new file mode 100644
index 0000000000..a02f2cdbff
--- /dev/null
+++ b/apps/plugins/codecwav.c
@@ -0,0 +1,131 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "plugin.h"
21#include "playback.h"
22#include "lib/codeclib.h"
23
24#ifndef SIMULATOR
25extern char iramcopy[];
26extern char iramstart[];
27extern char iramend[];
28#endif
29
30/* This is probably a waste of IRAM, but why not? */
31static unsigned char wavbuf[16384] IDATA_ATTR;
32
33/* this is the plugin entry point */
34enum plugin_status plugin_start(struct plugin_api* api, void* parm)
35{
36 struct plugin_api* rb = (struct plugin_api*)api;
37 struct codec_api* ci = (struct codec_api*)parm;
38 unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples;
39 int channels,bytespersample,bitspersample;
40 unsigned int i,j,n;
41 int endofstream;
42
43 /* Generic plugin initialisation */
44 TEST_PLUGIN_API(api);
45
46 /* if you are using a global api pointer, don't forget to copy it!
47 otherwise you will get lovely "I04: IllInstr" errors... :-) */
48 rb = api;
49
50#ifndef SIMULATOR
51 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
52#endif
53
54 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
55 ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
56
57 next_track:
58
59 if (codec_init(api, ci)) {
60 return PLUGIN_ERROR;
61 }
62
63 /* FIX: Correctly parse WAV header - we assume canonical 44-byte header */
64
65 n=(unsigned)(ci->read_filebuf(wavbuf,44));
66 if (n!=44) {
67 return PLUGIN_ERROR;
68 }
69 if ((memcmp(wavbuf,"RIFF",4)!=0) || (memcmp(&wavbuf[8],"WAVEfmt",7)!=0)) {
70 return PLUGIN_ERROR;
71 }
72
73 samplerate=wavbuf[24]|(wavbuf[25]<<8)|(wavbuf[26]<<16)|(wavbuf[27]<<24);
74 bitspersample=wavbuf[34];
75 channels=wavbuf[22];
76 bytespersample=((bitspersample/8)*channels);
77 numbytes=(wavbuf[40]|(wavbuf[41]<<8)|(wavbuf[42]<<16)|(wavbuf[43]<<24));
78 totalsamples=numbytes/bytespersample;
79
80 if ((bitspersample!=16) || (channels != 2)) {
81 return PLUGIN_ERROR;
82 }
83
84 /* The main decoder loop */
85
86 samplesdone=0;
87 ci->set_elapsed(0);
88 endofstream=0;
89 while (!endofstream) {
90 rb->yield();
91 if (ci->stop_codec || ci->reload_codec) {
92 break;
93 }
94
95 n=(unsigned)(ci->read_filebuf(wavbuf,sizeof(wavbuf)));
96
97 rb->yield();
98
99 if (n==0) break; /* End of stream */
100
101 nsamples=(n/bytespersample);
102
103 /* WAV files can contain extra data at the end - so we can't just
104 process until the end of the file */
105
106 if (samplesdone+nsamples > totalsamples) {
107 nsamples=(totalsamples-samplesdone);
108 n=nsamples*bytespersample;
109 endofstream=1;
110 }
111
112 /* Byte-swap data */
113 for (i=0;i<n;i+=2) {
114 j=wavbuf[i];
115 wavbuf[i]=wavbuf[i+1];
116 wavbuf[i+1]=j;
117 }
118
119 samplesdone+=nsamples;
120 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
121
122 rb->yield();
123 while (!ci->audiobuffer_insert(wavbuf, n))
124 rb->yield();
125 }
126
127 if (ci->request_next_track())
128 goto next_track;
129
130 return PLUGIN_OK;
131}