diff options
-rw-r--r-- | apps/SOURCES | 1 | ||||
-rw-r--r-- | apps/codecs/libwavpack/metadata.c | 3 | ||||
-rw-r--r-- | apps/codecs/libwavpack/unpack.c | 16 | ||||
-rw-r--r-- | apps/codecs/libwavpack/wavpack.h | 2 | ||||
-rw-r--r-- | apps/codecs/wavpack.c | 5 | ||||
-rw-r--r-- | apps/metadata.c | 59 | ||||
-rw-r--r-- | apps/metadata/metadata_parsers.h | 1 | ||||
-rw-r--r-- | apps/metadata/wavpack.c | 122 |
8 files changed, 148 insertions, 61 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index bfa4490153..a8a4d0c91e 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -121,6 +121,7 @@ metadata/sid.c | |||
121 | metadata/spc.c | 121 | metadata/spc.c |
122 | metadata/vorbis.c | 122 | metadata/vorbis.c |
123 | metadata/wave.c | 123 | metadata/wave.c |
124 | metadata/wavpack.c | ||
124 | #endif | 125 | #endif |
125 | #ifdef HAVE_TAGCACHE | 126 | #ifdef HAVE_TAGCACHE |
126 | tagcache.c | 127 | tagcache.c |
diff --git a/apps/codecs/libwavpack/metadata.c b/apps/codecs/libwavpack/metadata.c index c7f2d61841..c944093b19 100644 --- a/apps/codecs/libwavpack/metadata.c +++ b/apps/codecs/libwavpack/metadata.c | |||
@@ -102,6 +102,9 @@ int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd) | |||
102 | case ID_CHANNEL_INFO: | 102 | case ID_CHANNEL_INFO: |
103 | return read_channel_info (wpc, wpmd); | 103 | return read_channel_info (wpc, wpmd); |
104 | 104 | ||
105 | case ID_SAMPLE_RATE: | ||
106 | return read_sample_rate (wpc, wpmd); | ||
107 | |||
105 | case ID_CONFIG_BLOCK: | 108 | case ID_CONFIG_BLOCK: |
106 | return read_config_info (wpc, wpmd); | 109 | return read_config_info (wpc, wpmd); |
107 | 110 | ||
diff --git a/apps/codecs/libwavpack/unpack.c b/apps/codecs/libwavpack/unpack.c index f2eca7619f..69252f24ad 100644 --- a/apps/codecs/libwavpack/unpack.c +++ b/apps/codecs/libwavpack/unpack.c | |||
@@ -270,6 +270,22 @@ int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd) | |||
270 | return TRUE; | 270 | return TRUE; |
271 | } | 271 | } |
272 | 272 | ||
273 | // Read non-standard sampling rate from metadata. | ||
274 | |||
275 | int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd) | ||
276 | { | ||
277 | int bytecnt = wpmd->byte_length; | ||
278 | uchar *byteptr = wpmd->data; | ||
279 | |||
280 | if (bytecnt == 3) { | ||
281 | wpc->config.sample_rate = (int32_t) *byteptr++; | ||
282 | wpc->config.sample_rate |= (int32_t) *byteptr++ << 8; | ||
283 | wpc->config.sample_rate |= (int32_t) *byteptr++ << 16; | ||
284 | } | ||
285 | |||
286 | return TRUE; | ||
287 | } | ||
288 | |||
273 | // This monster actually unpacks the WavPack bitstream(s) into the specified | 289 | // This monster actually unpacks the WavPack bitstream(s) into the specified |
274 | // buffer as 32-bit integers or floats (depending on orignal data). Lossy | 290 | // buffer as 32-bit integers or floats (depending on orignal data). Lossy |
275 | // samples will be clipped to their original limits (i.e. 8-bit samples are | 291 | // samples will be clipped to their original limits (i.e. 8-bit samples are |
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h index a000438081..e2952115e1 100644 --- a/apps/codecs/libwavpack/wavpack.h +++ b/apps/codecs/libwavpack/wavpack.h | |||
@@ -114,6 +114,7 @@ typedef struct { | |||
114 | #define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) | 114 | #define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) |
115 | #define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5) | 115 | #define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5) |
116 | #define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6) | 116 | #define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6) |
117 | #define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7) | ||
117 | 118 | ||
118 | ///////////////////////// WavPack Configuration /////////////////////////////// | 119 | ///////////////////////// WavPack Configuration /////////////////////////////// |
119 | 120 | ||
@@ -364,6 +365,7 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd); | |||
364 | int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd); | 365 | int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd); |
365 | int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd); | 366 | int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd); |
366 | int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd); | 367 | int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd); |
368 | int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd); | ||
367 | int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); | 369 | int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); |
368 | int check_crc_error (WavpackContext *wpc); | 370 | int check_crc_error (WavpackContext *wpc); |
369 | 371 | ||
diff --git a/apps/codecs/wavpack.c b/apps/codecs/wavpack.c index 680673fec7..1485eedf8b 100644 --- a/apps/codecs/wavpack.c +++ b/apps/codecs/wavpack.c | |||
@@ -57,9 +57,6 @@ enum codec_status codec_main(void) | |||
57 | while (!*ci->taginfo_ready && !ci->stop_codec) | 57 | while (!*ci->taginfo_ready && !ci->stop_codec) |
58 | ci->sleep(1); | 58 | ci->sleep(1); |
59 | 59 | ||
60 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | ||
61 | codec_set_replaygain(ci->id3); | ||
62 | |||
63 | /* Create a decoder instance */ | 60 | /* Create a decoder instance */ |
64 | wpc = WavpackOpenFileInput (read_callback, error); | 61 | wpc = WavpackOpenFileInput (read_callback, error); |
65 | 62 | ||
@@ -68,6 +65,8 @@ enum codec_status codec_main(void) | |||
68 | goto done; | 65 | goto done; |
69 | } | 66 | } |
70 | 67 | ||
68 | ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc)); | ||
69 | codec_set_replaygain(ci->id3); | ||
71 | bps = WavpackGetBytesPerSample (wpc); | 70 | bps = WavpackGetBytesPerSample (wpc); |
72 | nchans = WavpackGetReducedChannels (wpc); | 71 | nchans = WavpackGetReducedChannels (wpc); |
73 | ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO); | 72 | ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO); |
diff --git a/apps/metadata.c b/apps/metadata.c index 15813c679d..5796a5669f 100644 --- a/apps/metadata.c +++ b/apps/metadata.c | |||
@@ -51,12 +51,6 @@ static const unsigned short a52_441framesizes[] = | |||
51 | 1254 * 2, 1393 * 2, 1394 * 2 | 51 | 1254 * 2, 1393 * 2, 1394 * 2 |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static const long wavpack_sample_rates [] = | ||
55 | { | ||
56 | 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, | ||
57 | 32000, 44100, 48000, 64000, 88200, 96000, 192000 | ||
58 | }; | ||
59 | |||
60 | #endif /* CONFIG_CODEC == SWCODEC */ | 54 | #endif /* CONFIG_CODEC == SWCODEC */ |
61 | 55 | ||
62 | 56 | ||
@@ -179,59 +173,8 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname, | |||
179 | break; | 173 | break; |
180 | 174 | ||
181 | case AFMT_WAVPACK: | 175 | case AFMT_WAVPACK: |
182 | /* A simple parser to read basic information from a WavPack file. This | 176 | if (!get_wavpack_metadata(fd, &(track->id3))) |
183 | * now works with self-extrating WavPack files. This no longer fails on | ||
184 | * WavPack files containing floating-point audio data because these are | ||
185 | * now converted to standard Rockbox format in the decoder. | ||
186 | */ | ||
187 | |||
188 | /* Use the trackname part of the id3 structure as a temporary buffer */ | ||
189 | buf = (unsigned char *)track->id3.path; | ||
190 | |||
191 | for (i = 0; i < 256; ++i) { | ||
192 | |||
193 | /* at every 256 bytes into file, try to read a WavPack header */ | ||
194 | |||
195 | if ((lseek(fd, i * 256, SEEK_SET) < 0) || (read(fd, buf, 32) < 32)) | ||
196 | { | ||
197 | return false; | ||
198 | } | ||
199 | |||
200 | /* if valid WavPack 4 header version & not floating data, break */ | ||
201 | |||
202 | if (memcmp (buf, "wvpk", 4) == 0 && buf [9] == 4 && | ||
203 | (buf [8] >= 2 && buf [8] <= 0x10)) | ||
204 | { | ||
205 | break; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | if (i == 256) { | ||
210 | logf ("%s is not a WavPack file\n", trackname); | ||
211 | return false; | 177 | return false; |
212 | } | ||
213 | |||
214 | track->id3.vbr = true; /* All WavPack files are VBR */ | ||
215 | track->id3.filesize = filesize (fd); | ||
216 | |||
217 | if ((buf [20] | buf [21] | buf [22] | buf [23]) && | ||
218 | (buf [12] & buf [13] & buf [14] & buf [15]) != 0xff) | ||
219 | { | ||
220 | int srindx = ((buf [26] >> 7) & 1) + ((buf [27] << 1) & 14); | ||
221 | |||
222 | if (srindx == 15) | ||
223 | { | ||
224 | track->id3.frequency = 44100; | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | track->id3.frequency = wavpack_sample_rates[srindx]; | ||
229 | } | ||
230 | |||
231 | totalsamples = get_long_le(&buf[12]); | ||
232 | track->id3.length = totalsamples / (track->id3.frequency / 100) * 10; | ||
233 | track->id3.bitrate = filesize (fd) / (track->id3.length / 8); | ||
234 | } | ||
235 | 178 | ||
236 | read_ape_tags(fd, &track->id3); /* use any apetag info we find */ | 179 | read_ape_tags(fd, &track->id3); /* use any apetag info we find */ |
237 | break; | 180 | break; |
diff --git a/apps/metadata/metadata_parsers.h b/apps/metadata/metadata_parsers.h index 5fc674d31b..315305b0df 100644 --- a/apps/metadata/metadata_parsers.h +++ b/apps/metadata/metadata_parsers.h | |||
@@ -29,4 +29,5 @@ bool get_spc_metadata(int fd, struct mp3entry* id3); | |||
29 | bool get_speex_metadata(int fd, struct mp3entry* id3); | 29 | bool get_speex_metadata(int fd, struct mp3entry* id3); |
30 | bool get_vorbis_metadata(int fd, struct mp3entry* id3); | 30 | bool get_vorbis_metadata(int fd, struct mp3entry* id3); |
31 | bool get_wave_metadata(int fd, struct mp3entry* id3); | 31 | bool get_wave_metadata(int fd, struct mp3entry* id3); |
32 | bool get_wavpack_metadata(int fd, struct mp3entry* id3); | ||
32 | bool get_asf_metadata(int fd, struct mp3entry* id3); | 33 | bool get_asf_metadata(int fd, struct mp3entry* id3); |
diff --git a/apps/metadata/wavpack.c b/apps/metadata/wavpack.c new file mode 100644 index 0000000000..5d33c0dffd --- /dev/null +++ b/apps/metadata/wavpack.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id:$ | ||
9 | * | ||
10 | * Copyright (C) 2007 David Bryant | ||
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 | #include <stdio.h> | ||
20 | #include <string.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <ctype.h> | ||
23 | #include <inttypes.h> | ||
24 | |||
25 | #include "system.h" | ||
26 | #include "id3.h" | ||
27 | #include "metadata_common.h" | ||
28 | #include "logf.h" | ||
29 | |||
30 | #define ID_UNIQUE 0x3f | ||
31 | #define ID_LARGE 0x80 | ||
32 | #define ID_SAMPLE_RATE 0x27 | ||
33 | |||
34 | static const long wavpack_sample_rates [] = | ||
35 | { | ||
36 | 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, | ||
37 | 32000, 44100, 48000, 64000, 88200, 96000, 192000 | ||
38 | }; | ||
39 | |||
40 | /* A simple parser to read basic information from a WavPack file. This | ||
41 | * now works with self-extrating WavPack files and also will scan the | ||
42 | * metadata for non-standard sampling rates. This no longer fails on | ||
43 | * WavPack files containing floating-point audio data because these are | ||
44 | * now converted to standard Rockbox format in the decoder. | ||
45 | */ | ||
46 | |||
47 | bool get_wavpack_metadata(int fd, struct mp3entry* id3) | ||
48 | { | ||
49 | /* Use the trackname part of the id3 structure as a temporary buffer */ | ||
50 | unsigned char* buf = (unsigned char *)id3->path; | ||
51 | uint32_t totalsamples, blocksamples; | ||
52 | int i; | ||
53 | |||
54 | for (i = 0; i < 256; ++i) { | ||
55 | |||
56 | /* at every 256 bytes into file, try to read a WavPack header */ | ||
57 | |||
58 | if ((lseek(fd, i * 256, SEEK_SET) < 0) || (read(fd, buf, 32) < 32)) | ||
59 | return false; | ||
60 | |||
61 | /* if valid WavPack 4 header version, break */ | ||
62 | |||
63 | if (memcmp (buf, "wvpk", 4) == 0 && buf [9] == 4 && | ||
64 | (buf [8] >= 2 && buf [8] <= 0x10)) | ||
65 | break; | ||
66 | } | ||
67 | |||
68 | if (i == 256) { | ||
69 | logf ("Not a WavPack file"); | ||
70 | return false; | ||
71 | } | ||
72 | |||
73 | id3->vbr = true; /* All WavPack files are VBR */ | ||
74 | id3->filesize = filesize (fd); | ||
75 | totalsamples = get_long_le(&buf[12]); | ||
76 | blocksamples = get_long_le(&buf[20]); | ||
77 | |||
78 | if (blocksamples && totalsamples != (uint32_t) -1) { | ||
79 | int srindx = ((buf [26] >> 7) & 1) + ((buf [27] << 1) & 14); | ||
80 | |||
81 | if (srindx == 15) { | ||
82 | uint32_t meta_bytes = buf [4] + (buf [5] << 8) + (buf [6] << 16) - 24; | ||
83 | uint32_t meta_size; | ||
84 | |||
85 | id3->frequency = 44100; | ||
86 | |||
87 | while (meta_bytes >= 6) { | ||
88 | if (read(fd, buf, 2) < 2) | ||
89 | break; | ||
90 | |||
91 | if (buf [0] & ID_LARGE) { | ||
92 | if (read(fd, buf + 2, 2) < 2) | ||
93 | break; | ||
94 | |||
95 | meta_size = (buf [1] << 1) + (buf [2] << 9) + (buf [3] << 17); | ||
96 | meta_bytes -= meta_size + 4; | ||
97 | } | ||
98 | else { | ||
99 | meta_size = buf [1] << 1; | ||
100 | meta_bytes -= meta_size + 2; | ||
101 | |||
102 | if ((buf [0] & ID_UNIQUE) == ID_SAMPLE_RATE) { | ||
103 | if (meta_size == 4 && read(fd, buf + 2, 4) == 4) | ||
104 | id3->frequency = buf [2] + (buf [3] << 8) + (buf [4] << 16); | ||
105 | |||
106 | break; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | if (meta_size > 0 && lseek(fd, meta_size, SEEK_CUR) < 0) | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | else | ||
115 | id3->frequency = wavpack_sample_rates[srindx]; | ||
116 | |||
117 | id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; | ||
118 | id3->bitrate = filesize (fd) / (id3->length / 8); | ||
119 | } | ||
120 | |||
121 | return true; | ||
122 | } | ||