diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/aiff.c | 58 | ||||
-rw-r--r-- | apps/codecs/libpcm/SOURCES | 7 | ||||
-rw-r--r-- | apps/codecs/libpcm/adpcm_seek.c | 101 | ||||
-rw-r--r-- | apps/codecs/libpcm/adpcm_seek.h | 39 | ||||
-rw-r--r-- | apps/codecs/libpcm/dialogic_oki_adpcm.c | 183 | ||||
-rw-r--r-- | apps/codecs/libpcm/dvi_adpcm.c | 444 | ||||
-rw-r--r-- | apps/codecs/libpcm/ieee_float.c | 29 | ||||
-rw-r--r-- | apps/codecs/libpcm/ima_adpcm_common.c | 171 | ||||
-rw-r--r-- | apps/codecs/libpcm/ima_adpcm_common.h | 32 | ||||
-rw-r--r-- | apps/codecs/libpcm/itut_g711.c | 44 | ||||
-rw-r--r-- | apps/codecs/libpcm/linear_pcm.c | 39 | ||||
-rw-r--r-- | apps/codecs/libpcm/ms_adpcm.c | 166 | ||||
-rw-r--r-- | apps/codecs/libpcm/pcm_common.h | 77 | ||||
-rw-r--r-- | apps/codecs/libpcm/qt_ima_adpcm.c | 136 | ||||
-rw-r--r-- | apps/codecs/libpcm/support_formats.h | 21 | ||||
-rw-r--r-- | apps/codecs/libpcm/swf_adpcm.c | 233 | ||||
-rw-r--r-- | apps/codecs/libpcm/yamaha_adpcm.c | 245 | ||||
-rw-r--r-- | apps/codecs/wav.c | 122 | ||||
-rw-r--r-- | apps/metadata/aiff.c | 23 | ||||
-rw-r--r-- | apps/metadata/wave.c | 138 |
20 files changed, 1968 insertions, 340 deletions
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index 2e10d1e416..4b870386c1 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c | |||
@@ -36,6 +36,7 @@ enum { | |||
36 | AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */ | 36 | AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */ |
37 | AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */ | 37 | AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */ |
38 | AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */ | 38 | AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */ |
39 | AIFC_FORMAT_QT_IMA_ADPCM = FOURCC('i', 'm', 'a', '4'), /* AIFC QuickTime IMA ADPCM */ | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static const struct pcm_entry pcm_codecs[] = { | 42 | static const struct pcm_entry pcm_codecs[] = { |
@@ -44,9 +45,10 @@ static const struct pcm_entry pcm_codecs[] = { | |||
44 | { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec }, | 45 | { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
45 | { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec }, | 46 | { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec }, |
46 | { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec }, | 47 | { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec }, |
48 | { AIFC_FORMAT_QT_IMA_ADPCM, get_qt_ima_adpcm_codec }, | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | #define NUM_FORMATS 5 | 51 | #define NUM_FORMATS 6 |
50 | 52 | ||
51 | static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; | 53 | static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; |
52 | 54 | ||
@@ -70,7 +72,7 @@ enum codec_status codec_main(void) | |||
70 | { | 72 | { |
71 | int status = CODEC_OK; | 73 | int status = CODEC_OK; |
72 | struct pcm_format format; | 74 | struct pcm_format format; |
73 | uint32_t bytesdone, decodedbytes; | 75 | uint32_t bytesdone, decodedsamples; |
74 | uint32_t num_sample_frames = 0; | 76 | uint32_t num_sample_frames = 0; |
75 | uint32_t i = CODEC_OK; | 77 | uint32_t i = CODEC_OK; |
76 | size_t n; | 78 | size_t n; |
@@ -128,7 +130,7 @@ next_track: | |||
128 | format.is_signed = true; | 130 | format.is_signed = true; |
129 | format.is_little_endian = false; | 131 | format.is_little_endian = false; |
130 | 132 | ||
131 | decodedbytes = 0; | 133 | decodedsamples = 0; |
132 | codec = 0; | 134 | codec = 0; |
133 | 135 | ||
134 | /* read until 'SSND' chunk, which typically is last */ | 136 | /* read until 'SSND' chunk, which typically is last */ |
@@ -168,8 +170,11 @@ next_track: | |||
168 | * aiff's sample_size is uncompressed sound data size. | 170 | * aiff's sample_size is uncompressed sound data size. |
169 | * But format.bitspersample is compressed sound data size. | 171 | * But format.bitspersample is compressed sound data size. |
170 | */ | 172 | */ |
171 | if (format.formattag == AIFC_FORMAT_ALAW || format.formattag == AIFC_FORMAT_MULAW) | 173 | if (format.formattag == AIFC_FORMAT_ALAW || |
174 | format.formattag == AIFC_FORMAT_MULAW) | ||
172 | format.bitspersample = 8; | 175 | format.bitspersample = 8; |
176 | else if (format.formattag == AIFC_FORMAT_QT_IMA_ADPCM) | ||
177 | format.bitspersample = 4; | ||
173 | } | 178 | } |
174 | else | 179 | else |
175 | format.formattag = AIFC_FORMAT_PCM; | 180 | format.formattag = AIFC_FORMAT_PCM; |
@@ -184,9 +189,9 @@ next_track: | |||
184 | /* offset2snd */ | 189 | /* offset2snd */ |
185 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; | 190 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; |
186 | /* block_size */ | 191 | /* block_size */ |
187 | format.blockalign = (buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]; | 192 | format.blockalign = ((buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]) >> 3; |
188 | if (format.blockalign == 0) | 193 | if (format.blockalign == 0) |
189 | format.blockalign = format.channels*format.bitspersample; | 194 | format.blockalign = format.channels * format.bitspersample >> 3; |
190 | format.numbytes = i - 8 - offset2snd; | 195 | format.numbytes = i - 8 - offset2snd; |
191 | i = 8 + offset2snd; /* advance to the beginning of data */ | 196 | i = 8 + offset2snd; /* advance to the beginning of data */ |
192 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { | 197 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { |
@@ -228,7 +233,7 @@ next_track: | |||
228 | goto done; | 233 | goto done; |
229 | } | 234 | } |
230 | 235 | ||
231 | if (!codec->set_format(&format, 0)) | 236 | if (!codec->set_format(&format)) |
232 | { | 237 | { |
233 | i = CODEC_ERROR; | 238 | i = CODEC_ERROR; |
234 | goto done; | 239 | goto done; |
@@ -246,6 +251,30 @@ next_track: | |||
246 | goto done; | 251 | goto done; |
247 | } | 252 | } |
248 | 253 | ||
254 | if (format.samplesperblock == 0) | ||
255 | { | ||
256 | DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); | ||
257 | i = CODEC_ERROR; | ||
258 | goto done; | ||
259 | } | ||
260 | if (format.blockalign == 0) | ||
261 | { | ||
262 | DEBUGF("CODEC_ERROR: blockalign is 0\n"); | ||
263 | i = CODEC_ERROR; | ||
264 | goto done; | ||
265 | } | ||
266 | |||
267 | /* check chunksize */ | ||
268 | if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels | ||
269 | > PCM_CHUNK_SIZE) | ||
270 | format.chunksize = (PCM_CHUNK_SIZE / format.blockalign) * format.blockalign; | ||
271 | if (format.chunksize == 0) | ||
272 | { | ||
273 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | ||
274 | i = CODEC_ERROR; | ||
275 | goto done; | ||
276 | } | ||
277 | |||
249 | firstblockposn = 1024 - n; | 278 | firstblockposn = 1024 - n; |
250 | ci->advance_buffer(firstblockposn); | 279 | ci->advance_buffer(firstblockposn); |
251 | 280 | ||
@@ -260,11 +289,14 @@ next_track: | |||
260 | break; | 289 | break; |
261 | 290 | ||
262 | if (ci->seek_time) { | 291 | if (ci->seek_time) { |
263 | uint32_t newpos = codec->get_seek_pos(ci->seek_time); | 292 | /* 2nd args(read_buffer) is unnecessary in the format which AIFF supports. */ |
264 | if (newpos > format.numbytes) | 293 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, NULL); |
294 | |||
295 | decodedsamples = newpos->samples; | ||
296 | if (newpos->pos > format.numbytes) | ||
265 | break; | 297 | break; |
266 | if (ci->seek_buffer(firstblockposn + newpos)) | 298 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
267 | bytesdone = newpos; | 299 | bytesdone = newpos->pos; |
268 | ci->seek_complete(); | 300 | ci->seek_complete(); |
269 | } | 301 | } |
270 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); | 302 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); |
@@ -288,11 +320,11 @@ next_track: | |||
288 | 320 | ||
289 | ci->advance_buffer(n); | 321 | ci->advance_buffer(n); |
290 | bytesdone += n; | 322 | bytesdone += n; |
291 | decodedbytes += bufcount; | 323 | decodedsamples += bufcount; |
292 | if (bytesdone >= format.numbytes) | 324 | if (bytesdone >= format.numbytes) |
293 | endofstream = 1; | 325 | endofstream = 1; |
294 | 326 | ||
295 | ci->set_elapsed(decodedbytes*1000LL/ci->id3->frequency); | 327 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
296 | } | 328 | } |
297 | i = CODEC_OK; | 329 | i = CODEC_OK; |
298 | 330 | ||
diff --git a/apps/codecs/libpcm/SOURCES b/apps/codecs/libpcm/SOURCES index 89be3452b1..356c9cdbb7 100644 --- a/apps/codecs/libpcm/SOURCES +++ b/apps/codecs/libpcm/SOURCES | |||
@@ -2,3 +2,10 @@ linear_pcm.c | |||
2 | itut_g711.c | 2 | itut_g711.c |
3 | dvi_adpcm.c | 3 | dvi_adpcm.c |
4 | ieee_float.c | 4 | ieee_float.c |
5 | adpcm_seek.c | ||
6 | dialogic_oki_adpcm.c | ||
7 | ms_adpcm.c | ||
8 | yamaha_adpcm.c | ||
9 | ima_adpcm_common.c | ||
10 | qt_ima_adpcm.c | ||
11 | swf_adpcm.c | ||
diff --git a/apps/codecs/libpcm/adpcm_seek.c b/apps/codecs/libpcm/adpcm_seek.c new file mode 100644 index 0000000000..ce49d5fcd3 --- /dev/null +++ b/apps/codecs/libpcm/adpcm_seek.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "adpcm_seek.h" | ||
22 | #include "codeclib.h" | ||
23 | |||
24 | /* | ||
25 | * The helper functions in order to seek for the adpcm codec | ||
26 | * which does not include the header each the data block. | ||
27 | */ | ||
28 | |||
29 | #define MAX_STORE_COUNT 1000 | ||
30 | |||
31 | static struct adpcm_data seek_table[MAX_STORE_COUNT]; | ||
32 | static int seek_count; | ||
33 | static int cur_count; | ||
34 | static int max_ratio; | ||
35 | static int cur_ratio; | ||
36 | |||
37 | void init_seek_table(uint32_t max_count) | ||
38 | { | ||
39 | int i = 0; | ||
40 | |||
41 | for ( ; i < MAX_STORE_COUNT; i++) | ||
42 | { | ||
43 | seek_table[i].is_valid = false; | ||
44 | } | ||
45 | seek_count = max_count / MAX_STORE_COUNT + 1; | ||
46 | max_ratio = max_count / seek_count + 1; | ||
47 | cur_count = 0; | ||
48 | cur_ratio = -1; | ||
49 | } | ||
50 | |||
51 | void add_adpcm_data(struct adpcm_data *data) | ||
52 | { | ||
53 | if (--cur_count <= 0) | ||
54 | { | ||
55 | cur_count = seek_count; | ||
56 | if (++cur_ratio >= max_ratio) | ||
57 | cur_ratio = max_ratio - 1; | ||
58 | |||
59 | if (!seek_table[cur_ratio].is_valid) | ||
60 | { | ||
61 | seek_table[cur_ratio].pcmdata[0] = data->pcmdata[0]; | ||
62 | seek_table[cur_ratio].pcmdata[1] = data->pcmdata[1]; | ||
63 | seek_table[cur_ratio].step[0] = data->step[0]; | ||
64 | seek_table[cur_ratio].step[1] = data->step[1]; | ||
65 | seek_table[cur_ratio].is_valid = true; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | uint32_t seek(uint32_t count, struct adpcm_data *seek_data, | ||
71 | uint8_t *(*read_buffer)(size_t *realsize), | ||
72 | int (*decode)(const uint8_t *inbuf, size_t inbufsize)) | ||
73 | { | ||
74 | int new_ratio = count / seek_count; | ||
75 | |||
76 | if (new_ratio >= max_ratio) | ||
77 | new_ratio = max_ratio - 1; | ||
78 | |||
79 | if (!seek_table[new_ratio].is_valid) | ||
80 | { | ||
81 | uint8_t *buffer; | ||
82 | size_t n; | ||
83 | |||
84 | do | ||
85 | { | ||
86 | buffer = read_buffer(&n); | ||
87 | if (n == 0) | ||
88 | break; | ||
89 | decode(buffer, n); | ||
90 | } while (cur_ratio < new_ratio); | ||
91 | } | ||
92 | |||
93 | seek_data->pcmdata[0] = seek_table[new_ratio].pcmdata[0]; | ||
94 | seek_data->pcmdata[1] = seek_table[new_ratio].pcmdata[1]; | ||
95 | seek_data->step[0] = seek_table[new_ratio].step[0]; | ||
96 | seek_data->step[1] = seek_table[new_ratio].step[1]; | ||
97 | |||
98 | cur_ratio = new_ratio; | ||
99 | cur_count = seek_count; | ||
100 | return cur_ratio * seek_count; | ||
101 | } | ||
diff --git a/apps/codecs/libpcm/adpcm_seek.h b/apps/codecs/libpcm/adpcm_seek.h new file mode 100644 index 0000000000..66ec390097 --- /dev/null +++ b/apps/codecs/libpcm/adpcm_seek.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef CODEC_LIBPCM_ADPCM_SEEK_H | ||
22 | #define CODEC_LIBPCM_ADPCM_SEEK_H | ||
23 | |||
24 | #include <sys/types.h> | ||
25 | #include <stdbool.h> | ||
26 | #include <inttypes.h> | ||
27 | |||
28 | struct adpcm_data { | ||
29 | int16_t pcmdata[2]; | ||
30 | uint16_t step[2]; | ||
31 | bool is_valid; | ||
32 | }; | ||
33 | |||
34 | void init_seek_table(uint32_t max_count); | ||
35 | void add_adpcm_data(struct adpcm_data *data); | ||
36 | uint32_t seek(uint32_t seek_time, struct adpcm_data *seek_data, | ||
37 | uint8_t *(*read_buffer)(size_t *realsize), | ||
38 | int (*decode)(const uint8_t *inbuf, size_t inbufsize)); | ||
39 | #endif | ||
diff --git a/apps/codecs/libpcm/dialogic_oki_adpcm.c b/apps/codecs/libpcm/dialogic_oki_adpcm.c new file mode 100644 index 0000000000..e12930057b --- /dev/null +++ b/apps/codecs/libpcm/dialogic_oki_adpcm.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | #include "adpcm_seek.h" | ||
24 | |||
25 | /* | ||
26 | * Dialogic OKI ADPCM | ||
27 | * | ||
28 | * References | ||
29 | * [1] Dialogic Corporation, Dialogic ADPCM Algorithm, 1988 | ||
30 | * [2] MultimediaWiki, Dialogic IMA ADPCM, URL:http://wiki.multimedia.cx/index.php?title=Dialogic_IMA_ADPCM | ||
31 | * [3] sox source code, src/adpcms.c | ||
32 | * [4] Tetsuya Isaki, NetBSD:/sys/dev/audio.c, http://www.tri-tree.gr.jp/~isaki/NetBSD/src/sys/dev/ic/msm6258.c.html | ||
33 | */ | ||
34 | |||
35 | static const uint16_t step_table[] ICONST_ATTR = { | ||
36 | 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, | ||
37 | 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, | ||
38 | 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | ||
39 | 876, 963, 1060, 1166, 1282, 1411, 1552, | ||
40 | }; | ||
41 | |||
42 | static const int index_table[] ICONST_ATTR = { | ||
43 | -1, -1, -1, -1, 2, 4, 6, 8 | ||
44 | }; | ||
45 | |||
46 | static struct adpcm_data cur_data; | ||
47 | |||
48 | static struct pcm_format *fmt; | ||
49 | |||
50 | static bool set_format(struct pcm_format *format) | ||
51 | { | ||
52 | uint32_t max_chunk_count; | ||
53 | |||
54 | fmt = format; | ||
55 | |||
56 | if (fmt->bitspersample != 4) | ||
57 | { | ||
58 | DEBUGF("CODEC_ERROR: dialogic oki adpcm must be 4 bitspersample: %d\n", | ||
59 | fmt->bitspersample); | ||
60 | return false; | ||
61 | } | ||
62 | |||
63 | if (fmt->channels != 1) | ||
64 | { | ||
65 | DEBUGF("CODEC_ERROR: dialogic oki adpcm must be monaural\n"); | ||
66 | return false; | ||
67 | } | ||
68 | |||
69 | /* blockalign = 2 samples */ | ||
70 | fmt->blockalign = 1; | ||
71 | fmt->samplesperblock = 2; | ||
72 | |||
73 | /* chunksize = about 1/32[sec] data */ | ||
74 | fmt->chunksize = ci->id3->frequency >> 6; | ||
75 | |||
76 | max_chunk_count = (uint64_t)ci->id3->length * ci->id3->frequency | ||
77 | / (2000LL * fmt->chunksize); | ||
78 | |||
79 | /* initialize seek table */ | ||
80 | init_seek_table(max_chunk_count); | ||
81 | /* add first data */ | ||
82 | add_adpcm_data(&cur_data); | ||
83 | |||
84 | return true; | ||
85 | } | ||
86 | |||
87 | static int16_t create_pcmdata(uint8_t nibble) | ||
88 | { | ||
89 | int16_t delta; | ||
90 | int16_t index = cur_data.step[0]; | ||
91 | int16_t step = step_table[index]; | ||
92 | |||
93 | delta = (step >> 3); | ||
94 | if (nibble & 4) delta += step; | ||
95 | if (nibble & 2) delta += (step >> 1); | ||
96 | if (nibble & 1) delta += (step >> 2); | ||
97 | |||
98 | if (nibble & 0x08) | ||
99 | cur_data.pcmdata[0] -= delta; | ||
100 | else | ||
101 | cur_data.pcmdata[0] += delta; | ||
102 | |||
103 | CLIP(cur_data.pcmdata[0], -2048, 2047); | ||
104 | |||
105 | index += index_table[nibble & 0x07]; | ||
106 | CLIP(index, 0, 48); | ||
107 | cur_data.step[0] = index; | ||
108 | |||
109 | return cur_data.pcmdata[0]; | ||
110 | } | ||
111 | |||
112 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
113 | int32_t *outbuf, int *outbufcount) | ||
114 | { | ||
115 | size_t nsamples = 0; | ||
116 | |||
117 | while (inbufsize) | ||
118 | { | ||
119 | *outbuf++ = create_pcmdata(*inbuf >> 4) << 17; | ||
120 | *outbuf++ = create_pcmdata(*inbuf ) << 17; | ||
121 | nsamples += 2; | ||
122 | |||
123 | inbuf++; | ||
124 | inbufsize--; | ||
125 | } | ||
126 | |||
127 | *outbufcount = nsamples; | ||
128 | add_adpcm_data(&cur_data); | ||
129 | |||
130 | return CODEC_OK; | ||
131 | } | ||
132 | |||
133 | static int decode_for_seek(const uint8_t *inbuf, size_t inbufsize) | ||
134 | { | ||
135 | while (inbufsize) | ||
136 | { | ||
137 | create_pcmdata(*inbuf >> 4); | ||
138 | create_pcmdata(*inbuf ); | ||
139 | |||
140 | inbuf++; | ||
141 | inbufsize--; | ||
142 | } | ||
143 | |||
144 | add_adpcm_data(&cur_data); | ||
145 | |||
146 | return CODEC_OK; | ||
147 | } | ||
148 | |||
149 | static struct pcm_pos *get_seek_pos(long seek_time, | ||
150 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
151 | { | ||
152 | static struct pcm_pos newpos; | ||
153 | uint32_t seek_count = 0; | ||
154 | uint32_t new_count; | ||
155 | |||
156 | if (seek_time > 0) | ||
157 | seek_count = (uint64_t)seek_time * ci->id3->frequency | ||
158 | / (2000LL * fmt->chunksize); | ||
159 | |||
160 | new_count = seek(seek_count, &cur_data, read_buffer, &decode_for_seek); | ||
161 | newpos.pos = new_count * fmt->chunksize; | ||
162 | newpos.samples = (newpos.pos / fmt->blockalign) * fmt->samplesperblock; | ||
163 | return &newpos; | ||
164 | } | ||
165 | |||
166 | static const struct pcm_codec codec = { | ||
167 | set_format, | ||
168 | get_seek_pos, | ||
169 | decode, | ||
170 | }; | ||
171 | |||
172 | const struct pcm_codec *get_dialogic_oki_adpcm_codec(void) | ||
173 | { | ||
174 | /* | ||
175 | * initialize first pcm data, step index | ||
176 | * because the dialogic oki adpcm is always monaural, | ||
177 | * pcmdata[1], step[1] do not use. | ||
178 | */ | ||
179 | cur_data.pcmdata[0] = 0; | ||
180 | cur_data.step[0] = 0; | ||
181 | |||
182 | return &codec; | ||
183 | } | ||
diff --git a/apps/codecs/libpcm/dvi_adpcm.c b/apps/codecs/libpcm/dvi_adpcm.c index 3df5e901be..97ba017451 100644 --- a/apps/codecs/libpcm/dvi_adpcm.c +++ b/apps/codecs/libpcm/dvi_adpcm.c | |||
@@ -21,280 +21,282 @@ | |||
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | #include "codeclib.h" | 22 | #include "codeclib.h" |
23 | #include "pcm_common.h" | 23 | #include "pcm_common.h" |
24 | #include "support_formats.h" | 24 | #include "ima_adpcm_common.h" |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Intel DVI ADPCM | 27 | * Intel DVI ADPCM (IMA ADPCM) |
28 | * | ||
29 | * References | ||
30 | * [1] The IMA Digital Audio Focus and Technical Working Groups, | ||
31 | * Recommended Practices for Enhancing Digital Audio Compatibility | ||
32 | * in Multimedia Systems Revision 3.00, 1992 | ||
33 | * [2] Microsoft Corporation, New Multimedia Data Types and Data Techniques, | ||
34 | * Revision:3.0, 1994 | ||
35 | * [3] ffmpeg source code, libavcodec/adpcm.c | ||
28 | */ | 36 | */ |
29 | 37 | ||
30 | static const uint16_t dvi_adpcm_steptab[89] ICONST_ATTR = { | ||
31 | 7, 8, 9, 10, 11, 12, 13, 14, | ||
32 | 16, 17, 19, 21, 23, 25, 28, 31, | ||
33 | 34, 37, 41, 45, 50, 55, 60, 66, | ||
34 | 73, 80, 88, 97, 107, 118, 130, 143, | ||
35 | 157, 173, 190, 209, 230, 253, 279, 307, | ||
36 | 337, 371, 408, 449, 494, 544, 598, 658, | ||
37 | 724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||
38 | 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||
39 | 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||
40 | 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||
41 | 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||
42 | 32767 }; | ||
43 | |||
44 | static const int dvi_adpcm_indextab4[8] ICONST_ATTR = { | ||
45 | -1, -1, -1, -1, 2, 4, 6, 8 }; | ||
46 | |||
47 | static const int dvi_adpcm_indextab3[4] ICONST_ATTR = { -1, -1, 1, 2 }; | ||
48 | |||
49 | static struct pcm_format *fmt; | 38 | static struct pcm_format *fmt; |
50 | 39 | ||
51 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | 40 | static bool set_format(struct pcm_format *format) |
52 | { | 41 | { |
53 | fmt = format; | 42 | fmt = format; |
54 | 43 | ||
55 | (void)fmtpos; | 44 | if (fmt->bitspersample < 2 || fmt->bitspersample > 5) |
56 | |||
57 | if (fmt->bitspersample != 4 && fmt->bitspersample != 3) | ||
58 | { | 45 | { |
59 | DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n"); | 46 | DEBUGF("CODEC_ERROR: dvi adpcm must be 2, 3, 4 or 5 bitspersample: %d\n", |
47 | fmt->bitspersample); | ||
60 | return false; | 48 | return false; |
61 | } | 49 | } |
62 | 50 | ||
63 | if (fmt->size < 2) { | 51 | fmt->chunksize = fmt->blockalign; |
64 | DEBUGF("CODEC_ERROR: dvi_adpcm is missing SamplesPerBlock value\n"); | ||
65 | return false; | ||
66 | } | ||
67 | |||
68 | /* chunksize is computed so that one chunk is about 1/50s. | ||
69 | * this make 4096 for 44.1kHz 16bits stereo. | ||
70 | * It also has to be a multiple of blockalign */ | ||
71 | fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; | ||
72 | |||
73 | /* check that the output buffer is big enough (convert to samplespersec, | ||
74 | then round to the blockalign multiple below) */ | ||
75 | if ((((uint64_t)fmt->chunksize * ci->id3->frequency * fmt->channels * fmt->bitspersample)>>3) | ||
76 | /(uint64_t)fmt->avgbytespersec >= PCM_CHUNK_SIZE) | ||
77 | fmt->chunksize = ((uint64_t)PCM_CHUNK_SIZE * fmt->avgbytespersec | ||
78 | /((uint64_t)ci->id3->frequency * fmt->channels * 2 | ||
79 | * fmt->blockalign)) * fmt->blockalign; | ||
80 | 52 | ||
53 | init_ima_adpcm_decoder(fmt->bitspersample, NULL); | ||
81 | return true; | 54 | return true; |
82 | } | 55 | } |
83 | 56 | ||
84 | static uint32_t get_seek_pos(long seek_time) | 57 | static struct pcm_pos *get_seek_pos(long seek_time, |
58 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
85 | { | 59 | { |
86 | uint32_t newpos; | 60 | static struct pcm_pos newpos; |
61 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | ||
62 | / (1000LL * fmt->samplesperblock); | ||
87 | 63 | ||
88 | /* use avgbytespersec to round to the closest blockalign multiple, | 64 | (void)read_buffer; |
89 | add firstblockposn. 64-bit casts to avoid overflows. */ | 65 | newpos.pos = newblock * fmt->blockalign; |
90 | newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) | 66 | newpos.samples = newblock * fmt->samplesperblock; |
91 | / (1000LL*fmt->blockalign))*fmt->blockalign; | 67 | return &newpos; |
92 | return newpos; | ||
93 | } | 68 | } |
94 | 69 | ||
95 | static int decode_dvi_adpcm(const uint8_t *inbuf, size_t inbufsize, | 70 | static inline void decode_2bit(const uint8_t **inbuf, |
96 | int32_t *outbuf, size_t *outbufcount) | 71 | int32_t **outbuf, int *outbufcount) |
97 | { | 72 | { |
98 | size_t nsamples = 0; | 73 | int ch; |
99 | int sample[2]; | ||
100 | int samplecode[32][2]; | ||
101 | int i; | 74 | int i; |
102 | int stepindex[2]; | 75 | int32_t *pcmbuf; |
103 | int c; | 76 | int samples; |
104 | int diff; | ||
105 | int step; | ||
106 | int codem; | ||
107 | int code; | ||
108 | 77 | ||
109 | if (fmt->bitspersample != 4 && fmt->bitspersample != 3) { | 78 | samples = fmt->blockalign / (4 * fmt->channels) - 1; |
110 | DEBUGF("decode_dvi_adpcm: wrong bitspersample\n"); | 79 | *outbufcount += (samples << 4); |
111 | return CODEC_ERROR; | 80 | while (samples-- > 0) |
81 | { | ||
82 | for (ch = 0; ch < fmt->channels; ch++) | ||
83 | { | ||
84 | pcmbuf = *outbuf + ch; | ||
85 | for (i = 0; i < 4; i++) | ||
86 | { | ||
87 | *pcmbuf = create_pcmdata(ch, **inbuf ) << 13; | ||
88 | pcmbuf += fmt->channels; | ||
89 | *pcmbuf = create_pcmdata(ch, **inbuf >> 2) << 13; | ||
90 | pcmbuf += fmt->channels; | ||
91 | *pcmbuf = create_pcmdata(ch, **inbuf >> 4) << 13; | ||
92 | pcmbuf += fmt->channels; | ||
93 | *pcmbuf = create_pcmdata(ch, **inbuf >> 6) << 13; | ||
94 | pcmbuf += fmt->channels; | ||
95 | (*inbuf)++; | ||
96 | } | ||
97 | } | ||
98 | *outbuf += 16 * fmt->channels; | ||
112 | } | 99 | } |
100 | } | ||
113 | 101 | ||
114 | /* decode block header */ | 102 | static inline void decode_3bit(const uint8_t **inbuf, |
115 | for (c = 0; c < fmt->channels && inbufsize >= 4; c++) { | 103 | int32_t **outbuf, int *outbufcount) |
116 | /* decode + push first sample */ | 104 | { |
117 | sample[c] = (short)(inbuf[0]|(inbuf[1]<<8));/* need cast for sign-extend */ | 105 | const uint8_t *adpcmbuf; |
118 | outbuf[c] = sample[c] << 13; | 106 | uint32_t adpcms; |
119 | nsamples++; | 107 | int ch; |
120 | stepindex[c] = inbuf[2]; | 108 | int i; |
121 | /* check for step table index overflow */ | 109 | int32_t *pcmbuf; |
122 | if (stepindex[c] > 88) { | 110 | int samples; |
123 | DEBUGF("decode_dvi_adpcm: stepindex[%d]=%d>88\n",c,stepindex[c]); | ||
124 | return CODEC_ERROR; | ||
125 | } | ||
126 | 111 | ||
127 | inbuf += 4; | 112 | samples = (fmt->blockalign - 4 * fmt->channels) / (12 * fmt->channels); |
128 | inbufsize -= 4; | 113 | *outbufcount += (samples << 5); |
129 | } | 114 | while (samples--) |
130 | if (fmt->bitspersample == 4) { | 115 | { |
131 | while (inbufsize >= (size_t)(fmt->channels*4) && | 116 | for (ch = 0; ch < fmt->channels; ch++) |
132 | (nsamples + (fmt->channels*8) <= *outbufcount)) | ||
133 | { | 117 | { |
134 | for (c = 0; c < fmt->channels; c++) | 118 | adpcmbuf = *inbuf + ch * 4; |
119 | pcmbuf = *outbuf + ch; | ||
120 | adpcms = *adpcmbuf++; | ||
121 | adpcms |= (*adpcmbuf++) << 8; | ||
122 | adpcms |= (*adpcmbuf++) << 16; | ||
123 | for (i = 0; i < 8; i++) | ||
135 | { | 124 | { |
136 | samplecode[0][c] = inbuf[0]&0xf; | 125 | *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; |
137 | samplecode[1][c] = inbuf[0]>>4; | 126 | pcmbuf += fmt->channels; |
138 | samplecode[2][c] = inbuf[1]&0xf; | ||
139 | samplecode[3][c] = inbuf[1]>>4; | ||
140 | samplecode[4][c] = inbuf[2]&0xf; | ||
141 | samplecode[5][c] = inbuf[2]>>4; | ||
142 | samplecode[6][c] = inbuf[3]&0xf; | ||
143 | samplecode[7][c] = inbuf[3]>>4; | ||
144 | inbuf += 4; | ||
145 | inbufsize -= 4; | ||
146 | } | 127 | } |
128 | adpcms = *adpcmbuf++; | ||
129 | adpcmbuf += (fmt->channels - 1) * 4; | ||
130 | adpcms |= (*adpcmbuf++) << 8; | ||
131 | adpcms |= (*adpcmbuf++) << 16; | ||
147 | for (i = 0; i < 8; i++) | 132 | for (i = 0; i < 8; i++) |
148 | { | 133 | { |
149 | for (c = 0; c < fmt->channels; c++) | 134 | *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; |
150 | { | 135 | pcmbuf += fmt->channels; |
151 | step = dvi_adpcm_steptab[stepindex[c]]; | ||
152 | codem = samplecode[i][c]; | ||
153 | code = codem & 0x07; | ||
154 | |||
155 | /* adjust the step table index */ | ||
156 | stepindex[c] += dvi_adpcm_indextab4[code]; | ||
157 | /* check for step table index overflow and underflow */ | ||
158 | if (stepindex[c] > 88) | ||
159 | stepindex[c] = 88; | ||
160 | else if (stepindex[c] < 0) | ||
161 | stepindex[c] = 0; | ||
162 | /* calculate the difference */ | ||
163 | #ifdef STRICT_IMA | ||
164 | diff = 0; | ||
165 | if (code & 4) | ||
166 | diff += step; | ||
167 | step = step >> 1; | ||
168 | if (code & 2) | ||
169 | diff += step; | ||
170 | step = step >> 1; | ||
171 | if (code & 1) | ||
172 | diff += step; | ||
173 | step = step >> 1; | ||
174 | diff += step; | ||
175 | #else | ||
176 | diff = ((code + code + 1) * step) >> 3; /* faster */ | ||
177 | #endif | ||
178 | /* check the sign bit */ | ||
179 | /* check for overflow and underflow errors */ | ||
180 | if (code != codem) | ||
181 | { | ||
182 | sample[c] -= diff; | ||
183 | if (sample[c] < -32768) | ||
184 | sample[c] = -32768; | ||
185 | } | ||
186 | else | ||
187 | { | ||
188 | sample[c] += diff; | ||
189 | if (sample[c] > 32767) | ||
190 | sample[c] = 32767; | ||
191 | } | ||
192 | /* output the new sample */ | ||
193 | outbuf[nsamples] = sample[c] << 13; | ||
194 | nsamples++; | ||
195 | } | ||
196 | } | 136 | } |
197 | } | 137 | adpcms = *adpcmbuf++; |
198 | } else { /* bitspersample == 3 */ | 138 | adpcms |= (*adpcmbuf++) << 8; |
199 | while (inbufsize >= (uint32_t)(fmt->channels*12) && | 139 | adpcmbuf += (fmt->channels - 1) * 4; |
200 | (nsamples + 32*fmt->channels) <= *outbufcount) { | 140 | adpcms |= (*adpcmbuf++) << 16; |
201 | for (c = 0; c < fmt->channels; c++) { | 141 | for (i = 0; i < 8; i++) |
202 | uint16_t bitstream = 0; | 142 | { |
203 | int bitsread = 0; | 143 | *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; |
204 | for (i = 0; i < 32 && inbufsize > 0; i++) { | 144 | pcmbuf += fmt->channels; |
205 | if (bitsread < 3) { | ||
206 | /* read 8 more bits */ | ||
207 | bitstream |= inbuf[0]<<bitsread; | ||
208 | bitsread += 8; | ||
209 | inbufsize--; | ||
210 | inbuf++; | ||
211 | } | ||
212 | samplecode[i][c] = bitstream & 7; | ||
213 | bitstream = bitstream>>3; | ||
214 | bitsread -= 3; | ||
215 | } | ||
216 | if (bitsread != 0) { | ||
217 | /* 32*3 = 3 words, so we should end with bitsread==0 */ | ||
218 | DEBUGF("decode_dvi_adpcm: error in implementation\n"); | ||
219 | return CODEC_ERROR; | ||
220 | } | ||
221 | } | 145 | } |
222 | 146 | adpcms = *adpcmbuf++; | |
223 | for (i = 0; i < 32; i++) { | 147 | adpcms |= (*adpcmbuf++) << 8; |
224 | for (c = 0; c < fmt->channels; c++) { | 148 | adpcms |= (*adpcmbuf++) << 16; |
225 | step = dvi_adpcm_steptab[stepindex[c]]; | 149 | for (i = 0; i < 8; i++) |
226 | codem = samplecode[i][c]; | 150 | { |
227 | code = codem & 0x03; | 151 | *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; |
228 | 152 | pcmbuf += fmt->channels; | |
229 | /* adjust the step table index */ | ||
230 | stepindex[c] += dvi_adpcm_indextab3[code]; | ||
231 | /* check for step table index overflow and underflow */ | ||
232 | if (stepindex[c] > 88) | ||
233 | stepindex[c] = 88; | ||
234 | else if (stepindex[c] < 0) | ||
235 | stepindex[c] = 0; | ||
236 | /* calculate the difference */ | ||
237 | #ifdef STRICT_IMA | ||
238 | diff = 0; | ||
239 | if (code & 2) | ||
240 | diff += step; | ||
241 | step = step >> 1; | ||
242 | if (code & 1) | ||
243 | diff += step; | ||
244 | step = step >> 1; | ||
245 | diff += step; | ||
246 | #else | ||
247 | diff = ((code + code + 1) * step) >> 3; /* faster */ | ||
248 | #endif | ||
249 | /* check the sign bit */ | ||
250 | /* check for overflow and underflow errors */ | ||
251 | if (code != codem) { | ||
252 | sample[c] -= diff; | ||
253 | if (sample[c] < -32768) | ||
254 | sample[c] = -32768; | ||
255 | } | ||
256 | else { | ||
257 | sample[c] += diff; | ||
258 | if (sample[c] > 32767) | ||
259 | sample[c] = 32767; | ||
260 | } | ||
261 | /* output the new sample */ | ||
262 | outbuf[nsamples] = sample[c] << 13; | ||
263 | nsamples++; | ||
264 | } | ||
265 | } | 153 | } |
266 | } | 154 | } |
155 | *outbuf += 32 * fmt->channels; | ||
156 | *inbuf += 12 * fmt->channels; | ||
267 | } | 157 | } |
158 | } | ||
268 | 159 | ||
269 | if (nsamples > *outbufcount) { | 160 | static inline void decode_4bit(const uint8_t **inbuf, |
270 | DEBUGF("decode_dvi_adpcm: output buffer overflow!\n"); | 161 | int32_t **outbuf, int *outbufcount) |
271 | return CODEC_ERROR; | 162 | { |
163 | int ch; | ||
164 | int i; | ||
165 | int32_t *pcmbuf; | ||
166 | int samples; | ||
167 | |||
168 | samples = fmt->blockalign / (4 * fmt->channels) - 1; | ||
169 | *outbufcount += (samples << 3); | ||
170 | while (samples-- > 0) | ||
171 | { | ||
172 | for (ch = 0; ch < fmt->channels; ch++) | ||
173 | { | ||
174 | pcmbuf = *outbuf + ch; | ||
175 | for (i = 0; i < 4; i++) | ||
176 | { | ||
177 | *pcmbuf = create_pcmdata_size4(ch, **inbuf ) << 13; | ||
178 | pcmbuf += fmt->channels; | ||
179 | *pcmbuf = create_pcmdata_size4(ch, **inbuf >> 4) << 13; | ||
180 | pcmbuf += fmt->channels; | ||
181 | (*inbuf)++; | ||
182 | } | ||
183 | } | ||
184 | *outbuf += 8 * fmt->channels; | ||
272 | } | 185 | } |
273 | *outbufcount = nsamples; | 186 | } |
274 | if (inbufsize != 0) { | 187 | |
275 | DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n", (int)inbufsize); | 188 | static inline void decode_5bit(const uint8_t **inbuf, |
189 | int32_t **outbuf, int *outbufcount) | ||
190 | { | ||
191 | const uint8_t *adpcmbuf; | ||
192 | uint64_t adpcms; | ||
193 | int ch; | ||
194 | int i; | ||
195 | int32_t *pcmbuf; | ||
196 | int samples; | ||
197 | |||
198 | samples = (fmt->blockalign - 4 * fmt->channels) / (20 * fmt->channels); | ||
199 | *outbufcount += (samples << 5); | ||
200 | while (samples--) | ||
201 | { | ||
202 | for (ch = 0; ch < fmt->channels; ch++) | ||
203 | { | ||
204 | adpcmbuf = *inbuf + ch * 4; | ||
205 | pcmbuf = *outbuf + ch; | ||
206 | adpcms = *adpcmbuf++; | ||
207 | adpcms |= (*adpcmbuf++) << 8; | ||
208 | adpcms |= (*adpcmbuf++) << 16; | ||
209 | adpcms |= (uint64_t)(*adpcmbuf++) << 24; | ||
210 | adpcmbuf += (fmt->channels - 1) * 4; | ||
211 | adpcms |= (uint64_t)(*adpcmbuf++) << 32; | ||
212 | for (i = 0; i < 8; i++) | ||
213 | { | ||
214 | *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; | ||
215 | pcmbuf += fmt->channels; | ||
216 | } | ||
217 | adpcms = *adpcmbuf++; | ||
218 | adpcms |= (*adpcmbuf++) << 8; | ||
219 | adpcms |= (*adpcmbuf++) << 16; | ||
220 | adpcmbuf += (fmt->channels - 1) * 4; | ||
221 | adpcms |= (uint64_t)(*adpcmbuf++) << 24; | ||
222 | adpcms |= (uint64_t)(*adpcmbuf++) << 32; | ||
223 | for (i = 0; i < 8; i++) | ||
224 | { | ||
225 | *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; | ||
226 | pcmbuf += fmt->channels; | ||
227 | } | ||
228 | adpcms = *adpcmbuf++; | ||
229 | adpcms |= (*adpcmbuf++) << 8; | ||
230 | adpcmbuf += (fmt->channels - 1) * 4; | ||
231 | adpcms |= (*adpcmbuf++) << 16; | ||
232 | adpcms |= (uint64_t)(*adpcmbuf++) << 24; | ||
233 | adpcms |= (uint64_t)(*adpcmbuf++) << 32; | ||
234 | for (i = 0; i < 8; i++) | ||
235 | { | ||
236 | *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; | ||
237 | pcmbuf += fmt->channels; | ||
238 | } | ||
239 | adpcms = *adpcmbuf++; | ||
240 | adpcmbuf += (fmt->channels - 1) * 4; | ||
241 | adpcms |= (*adpcmbuf++) << 8; | ||
242 | adpcms |= (*adpcmbuf++) << 16; | ||
243 | adpcms |= (uint64_t)(*adpcmbuf++) << 24; | ||
244 | adpcms |= (uint64_t)(*adpcmbuf++) << 32; | ||
245 | for (i = 0; i < 8; i++) | ||
246 | { | ||
247 | *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; | ||
248 | pcmbuf += fmt->channels; | ||
249 | } | ||
250 | } | ||
251 | *outbuf += 32 * fmt->channels; | ||
252 | *inbuf += 20 * fmt->channels; | ||
276 | } | 253 | } |
277 | return CODEC_OK; | ||
278 | } | 254 | } |
279 | 255 | ||
280 | static int decode(const uint8_t *inbuf, size_t inbufsize, | 256 | static int decode(const uint8_t *inbuf, size_t inbufsize, |
281 | int32_t *outbuf, int *outbufsize) | 257 | int32_t *outbuf, int *outbufcount) |
282 | { | 258 | { |
259 | int ch; | ||
283 | unsigned int i; | 260 | unsigned int i; |
261 | int32_t init_pcmdata[2]; | ||
262 | int8_t init_index[2]; | ||
284 | unsigned int nblocks = fmt->chunksize / fmt->blockalign; | 263 | unsigned int nblocks = fmt->chunksize / fmt->blockalign; |
285 | 264 | ||
286 | (void)inbufsize; | 265 | (void)inbufsize; |
287 | 266 | ||
267 | *outbufcount = 0; | ||
288 | for (i = 0; i < nblocks; i++) | 268 | for (i = 0; i < nblocks; i++) |
289 | { | 269 | { |
290 | size_t decodedsize = fmt->samplesperblock * fmt->channels; | 270 | for (ch = 0; ch < fmt->channels; ch++) |
291 | if (decode_dvi_adpcm(inbuf + i * fmt->blockalign, fmt->blockalign, | 271 | { |
292 | outbuf + i * fmt->samplesperblock * fmt->channels, | 272 | init_pcmdata[ch] = inbuf[0] | (inbuf[1] << 8); |
293 | &decodedsize) != CODEC_OK) { | 273 | if (init_pcmdata[ch] > 32767) |
294 | return CODEC_ERROR; | 274 | init_pcmdata[ch] -= 65536; |
275 | |||
276 | init_index[ch] = inbuf[2]; | ||
277 | if (init_index[ch] > 88 || init_index[ch] < 0) | ||
278 | { | ||
279 | DEBUGF("CODEC_ERROR: dvi adpcm illegal step index=%d > 88\n", | ||
280 | init_index[ch]); | ||
281 | return CODEC_ERROR; | ||
282 | } | ||
283 | inbuf += 4; | ||
284 | |||
285 | *outbuf++ = init_pcmdata[ch] << 13; | ||
295 | } | 286 | } |
287 | |||
288 | *outbufcount += 1; | ||
289 | set_decode_parameters(fmt->channels, init_pcmdata, init_index); | ||
290 | |||
291 | if (fmt->bitspersample == 4) | ||
292 | decode_4bit(&inbuf, &outbuf, outbufcount); | ||
293 | else if (fmt->bitspersample == 3) | ||
294 | decode_3bit(&inbuf, &outbuf, outbufcount); | ||
295 | else if (fmt->bitspersample == 5) | ||
296 | decode_5bit(&inbuf, &outbuf, outbufcount); | ||
297 | else /* fmt->bitspersample == 2 */ | ||
298 | decode_2bit(&inbuf, &outbuf, outbufcount); | ||
296 | } | 299 | } |
297 | *outbufsize = nblocks * fmt->samplesperblock; | ||
298 | return CODEC_OK; | 300 | return CODEC_OK; |
299 | } | 301 | } |
300 | 302 | ||
diff --git a/apps/codecs/libpcm/ieee_float.c b/apps/codecs/libpcm/ieee_float.c index c0e91a46cb..0530993f31 100644 --- a/apps/codecs/libpcm/ieee_float.c +++ b/apps/codecs/libpcm/ieee_float.c | |||
@@ -28,33 +28,38 @@ | |||
28 | 28 | ||
29 | static struct pcm_format *fmt; | 29 | static struct pcm_format *fmt; |
30 | 30 | ||
31 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | 31 | static bool set_format(struct pcm_format *format) |
32 | { | 32 | { |
33 | fmt = format; | 33 | fmt = format; |
34 | 34 | ||
35 | (void)fmtpos; | ||
36 | |||
37 | if (fmt->bitspersample != 32 && fmt->bitspersample != 64) | 35 | if (fmt->bitspersample != 32 && fmt->bitspersample != 64) |
38 | { | 36 | { |
39 | DEBUGF("CODEC_ERROR: ieee float must be 32 or 64 bitspersample %d\n", fmt->bitspersample); | 37 | DEBUGF("CODEC_ERROR: ieee float must be 32 or 64 bitspersample: %d\n", |
38 | fmt->bitspersample); | ||
40 | return false; | 39 | return false; |
41 | } | 40 | } |
42 | 41 | ||
43 | fmt->bytespersample = fmt->bitspersample >> 3; | 42 | fmt->bytespersample = fmt->bitspersample >> 3; |
44 | fmt->blockalign = fmt->bytespersample; | 43 | fmt->samplesperblock = fmt->blockalign / (fmt->bytespersample * fmt->channels); |
45 | 44 | ||
46 | /* chunksize is computed so that one chunk is about 1/50s. */ | 45 | /* chunksize = about 1/50[sec] data */ |
47 | fmt->chunksize = (ci->id3->frequency * fmt->channels / 50) * fmt->blockalign; | 46 | fmt->chunksize = (ci->id3->frequency / (50 * fmt->samplesperblock)) |
47 | * fmt->blockalign; | ||
48 | 48 | ||
49 | return true; | 49 | return true; |
50 | } | 50 | } |
51 | 51 | ||
52 | static uint32_t get_seek_pos(long seek_time) | 52 | static struct pcm_pos *get_seek_pos(long seek_time, |
53 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
53 | { | 54 | { |
54 | uint32_t newpos; | 55 | static struct pcm_pos newpos; |
55 | 56 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | |
56 | newpos = ((uint64_t)(seek_time * ci->id3->frequency * fmt->channels / 1000LL))*fmt->blockalign; | 57 | / (1000LL * fmt->samplesperblock); |
57 | return newpos; | 58 | |
59 | (void)read_buffer; | ||
60 | newpos.pos = newblock * fmt->blockalign; | ||
61 | newpos.samples = newblock * fmt->samplesperblock; | ||
62 | return &newpos; | ||
58 | } | 63 | } |
59 | 64 | ||
60 | static int decode(const uint8_t *inbuf, size_t inbufsize, | 65 | static int decode(const uint8_t *inbuf, size_t inbufsize, |
diff --git a/apps/codecs/libpcm/ima_adpcm_common.c b/apps/codecs/libpcm/ima_adpcm_common.c new file mode 100644 index 0000000000..ff5051f166 --- /dev/null +++ b/apps/codecs/libpcm/ima_adpcm_common.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | #include "ima_adpcm_common.h" | ||
24 | |||
25 | /* | ||
26 | * Functions for IMA ADPCM and IMA ADPCM series format | ||
27 | * | ||
28 | * References | ||
29 | * [1] The IMA Digital Audio Focus and Technical Working Groups, | ||
30 | * Recommended Practices for Enhancing Digital Audio Compatibility | ||
31 | * in Multimedia Systems Revision 3.00, 1992 | ||
32 | * [2] Microsoft Corporation, New Multimedia Data Types and Data Techniques, | ||
33 | * Revision:3.0, 1994 | ||
34 | * [3] ffmpeg source code, libavcodec/adpcm.c | ||
35 | */ | ||
36 | |||
37 | /* step table */ | ||
38 | static const uint16_t step_table[89] ICONST_ATTR = { | ||
39 | 7, 8, 9, 10, 11, 12, 13, 14, | ||
40 | 16, 17, 19, 21, 23, 25, 28, 31, | ||
41 | 34, 37, 41, 45, 50, 55, 60, 66, | ||
42 | 73, 80, 88, 97, 107, 118, 130, 143, | ||
43 | 157, 173, 190, 209, 230, 253, 279, 307, | ||
44 | 337, 371, 408, 449, 494, 544, 598, 658, | ||
45 | 724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||
46 | 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||
47 | 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||
48 | 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||
49 | 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||
50 | 32767 | ||
51 | }; | ||
52 | |||
53 | /* step index tables */ | ||
54 | static const int index_tables[4][16] ICONST_ATTR = { | ||
55 | /* adpcm data size is 2 */ | ||
56 | { -1, 2 }, | ||
57 | /* adpcm data size is 3 */ | ||
58 | { -1, -1, 1, 2 }, | ||
59 | /* adpcm data size is 4 */ | ||
60 | { -1, -1, -1, -1, 2, 4, 6, 8 }, | ||
61 | /* adpcm data size is 5 */ | ||
62 | { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 }, | ||
63 | }; | ||
64 | |||
65 | static int32_t pcmdata[2]; | ||
66 | static int8_t index[2]; | ||
67 | |||
68 | static int adpcm_data_size; | ||
69 | static uint8_t step_mask; | ||
70 | static uint8_t step_sign_mask; | ||
71 | static int8_t step_shift; | ||
72 | static const int *use_index_table; | ||
73 | |||
74 | /* | ||
75 | * Before first decoding, this function must be executed. | ||
76 | * | ||
77 | * params | ||
78 | * bit: adpcm data size (2 <= bit <= 5). | ||
79 | * index_table: step index table | ||
80 | * if index_table is null, then step index table | ||
81 | * is used index_tables[bit-2]. | ||
82 | */ | ||
83 | void init_ima_adpcm_decoder(int bit, const int *index_table) | ||
84 | { | ||
85 | adpcm_data_size = bit; | ||
86 | step_sign_mask = 1 << (adpcm_data_size - 1); | ||
87 | step_mask = step_sign_mask - 1; | ||
88 | step_shift = adpcm_data_size - 2; | ||
89 | if (index_table) | ||
90 | use_index_table = index_table; | ||
91 | else | ||
92 | use_index_table = index_tables[adpcm_data_size - 2]; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * When starting decoding for each block, this function must be executed. | ||
97 | * | ||
98 | * params | ||
99 | * channels: channel count | ||
100 | * init_pcmdata: array of init pcmdata | ||
101 | * init_index: array of init step indexes | ||
102 | */ | ||
103 | void set_decode_parameters(int channels, int32_t *init_pcmdata, int8_t *init_index) | ||
104 | { | ||
105 | int ch; | ||
106 | |||
107 | for (ch = 0; ch < channels; ch++) | ||
108 | { | ||
109 | pcmdata[ch] = init_pcmdata[ch]; | ||
110 | index[ch] = init_index[ch]; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * convert ADPCM to PCM for any adpcm data size. | ||
116 | * | ||
117 | * If adpcm_data_size is 4, then you use create_pcmdata_size4() | ||
118 | * in place of this functon. | ||
119 | */ | ||
120 | int16_t create_pcmdata(int ch, uint8_t nibble) | ||
121 | { | ||
122 | int check_bit = 1 << step_shift; | ||
123 | int32_t delta = 0; | ||
124 | int16_t step = step_table[index[ch]]; | ||
125 | |||
126 | do { | ||
127 | if (nibble & check_bit) | ||
128 | delta += step; | ||
129 | step >>= 1; | ||
130 | check_bit >>= 1; | ||
131 | } while (check_bit); | ||
132 | delta += step; | ||
133 | |||
134 | if (nibble & step_sign_mask) | ||
135 | pcmdata[ch] -= delta; | ||
136 | else | ||
137 | pcmdata[ch] += delta; | ||
138 | |||
139 | index[ch] += use_index_table[nibble & step_mask]; | ||
140 | CLIP(index[ch], 0, 88); | ||
141 | |||
142 | CLIP(pcmdata[ch], -32768, 32767); | ||
143 | |||
144 | return (int16_t)pcmdata[ch]; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * convert ADPCM to PCM when adpcm data size is 4. | ||
149 | */ | ||
150 | int16_t create_pcmdata_size4(int ch, uint8_t nibble) | ||
151 | { | ||
152 | int32_t delta; | ||
153 | int16_t step = step_table[index[ch]]; | ||
154 | |||
155 | delta = (step >> 3); | ||
156 | if (nibble & 4) delta += step; | ||
157 | if (nibble & 2) delta += (step >> 1); | ||
158 | if (nibble & 1) delta += (step >> 2); | ||
159 | |||
160 | if (nibble & 0x08) | ||
161 | pcmdata[ch] -= delta; | ||
162 | else | ||
163 | pcmdata[ch] += delta; | ||
164 | |||
165 | index[ch] += use_index_table[nibble & 0x07]; | ||
166 | CLIP(index[ch], 0, 88); | ||
167 | |||
168 | CLIP(pcmdata[ch], -32768, 32767); | ||
169 | |||
170 | return (int16_t)pcmdata[ch]; | ||
171 | } | ||
diff --git a/apps/codecs/libpcm/ima_adpcm_common.h b/apps/codecs/libpcm/ima_adpcm_common.h new file mode 100644 index 0000000000..65cfefcfa3 --- /dev/null +++ b/apps/codecs/libpcm/ima_adpcm_common.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef CODEC_LIBPCM_IMA_ADPCM_COMMON_H | ||
22 | #define CODEC_LIBPCM_IMA_ADPCM_COMMON_H | ||
23 | |||
24 | #include <sys/types.h> | ||
25 | #include <stdbool.h> | ||
26 | #include <inttypes.h> | ||
27 | |||
28 | void init_ima_adpcm_decoder(int bit, const int *index_table); | ||
29 | void set_decode_parameters(int channels, int32_t *init_pcmdata, int8_t *init_index); | ||
30 | int16_t create_pcmdata(int ch, uint8_t nibble); | ||
31 | int16_t create_pcmdata_size4(int ch, uint8_t nibble); | ||
32 | #endif | ||
diff --git a/apps/codecs/libpcm/itut_g711.c b/apps/codecs/libpcm/itut_g711.c index 520ca46a7a..9a38031882 100644 --- a/apps/codecs/libpcm/itut_g711.c +++ b/apps/codecs/libpcm/itut_g711.c | |||
@@ -109,49 +109,43 @@ static const int16_t ulaw2linear16[256] ICONST_ATTR = { | |||
109 | 109 | ||
110 | static struct pcm_format *fmt; | 110 | static struct pcm_format *fmt; |
111 | 111 | ||
112 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | 112 | static bool set_format(struct pcm_format *format) |
113 | { | 113 | { |
114 | fmt = format; | 114 | fmt = format; |
115 | 115 | ||
116 | (void)fmtpos; | ||
117 | |||
118 | if (fmt->bitspersample != 8) | 116 | if (fmt->bitspersample != 8) |
119 | { | 117 | { |
120 | DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample\n"); | 118 | DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample: %d\n", |
119 | fmt->bitspersample); | ||
121 | return false; | 120 | return false; |
122 | } | 121 | } |
123 | 122 | ||
124 | if (fmt->totalsamples == 0) | 123 | if (fmt->totalsamples == 0) |
125 | { | 124 | { |
126 | fmt->bytespersample = fmt->channels; | 125 | fmt->bytespersample = 1; |
127 | fmt->totalsamples = fmt->numbytes/fmt->bytespersample; | 126 | fmt->totalsamples = fmt->numbytes / (fmt->bytespersample * fmt->channels); |
128 | } | 127 | } |
129 | 128 | ||
130 | /* chunksize is computed so that one chunk is about 1/50s. | 129 | fmt->samplesperblock = fmt->blockalign / (fmt->bytespersample * fmt->channels); |
131 | * this make 4096 for 44.1kHz 16bits stereo. | ||
132 | * It also has to be a multiple of blockalign */ | ||
133 | fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; | ||
134 | 130 | ||
135 | /* check that the output buffer is big enough (convert to samplespersec, | 131 | /* chunksize = about 1/50[sec] data */ |
136 | then round to the blockalign multiple below) */ | 132 | fmt->chunksize = (ci->id3->frequency / (50 * fmt->samplesperblock)) |
137 | if ((((uint64_t)fmt->chunksize * ci->id3->frequency * fmt->channels * fmt->bitspersample)>>3) | 133 | * fmt->blockalign; |
138 | /(uint64_t)fmt->avgbytespersec >= PCM_CHUNK_SIZE) | ||
139 | fmt->chunksize = ((uint64_t)PCM_CHUNK_SIZE * fmt->avgbytespersec | ||
140 | /((uint64_t)ci->id3->frequency * fmt->channels * 2 | ||
141 | * fmt->blockalign)) * fmt->blockalign; | ||
142 | 134 | ||
143 | return true; | 135 | return true; |
144 | } | 136 | } |
145 | 137 | ||
146 | static uint32_t get_seek_pos(long seek_time) | 138 | static struct pcm_pos *get_seek_pos(long seek_time, |
139 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
147 | { | 140 | { |
148 | uint32_t newpos; | 141 | static struct pcm_pos newpos; |
149 | 142 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | |
150 | /* use avgbytespersec to round to the closest blockalign multiple, | 143 | / (1000LL * fmt->samplesperblock); |
151 | add firstblockposn. 64-bit casts to avoid overflows. */ | 144 | |
152 | newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) | 145 | (void)read_buffer; |
153 | / (1000LL*fmt->blockalign))*fmt->blockalign; | 146 | newpos.pos = newblock * fmt->blockalign; |
154 | return newpos; | 147 | newpos.samples = newblock * fmt->samplesperblock; |
148 | return &newpos; | ||
155 | } | 149 | } |
156 | 150 | ||
157 | static int decode_alaw(const uint8_t *inbuf, size_t inbufsize, | 151 | static int decode_alaw(const uint8_t *inbuf, size_t inbufsize, |
diff --git a/apps/codecs/libpcm/linear_pcm.c b/apps/codecs/libpcm/linear_pcm.c index 4db27ca2b3..5360d79901 100644 --- a/apps/codecs/libpcm/linear_pcm.c +++ b/apps/codecs/libpcm/linear_pcm.c | |||
@@ -29,12 +29,10 @@ | |||
29 | 29 | ||
30 | static struct pcm_format *fmt; | 30 | static struct pcm_format *fmt; |
31 | 31 | ||
32 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | 32 | static bool set_format(struct pcm_format *format) |
33 | { | 33 | { |
34 | fmt = format; | 34 | fmt = format; |
35 | 35 | ||
36 | (void)fmtpos; | ||
37 | |||
38 | if (fmt->bitspersample > 32) | 36 | if (fmt->bitspersample > 32) |
39 | { | 37 | { |
40 | DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample " | 38 | DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample " |
@@ -42,33 +40,34 @@ static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | |||
42 | return false; | 40 | return false; |
43 | } | 41 | } |
44 | 42 | ||
43 | fmt->bytespersample = fmt->bitspersample >> 3; | ||
44 | |||
45 | if (fmt->totalsamples == 0) | 45 | if (fmt->totalsamples == 0) |
46 | { | ||
47 | fmt->bytespersample = (((fmt->bitspersample - 1)/8 + 1)*fmt->channels); | ||
48 | fmt->totalsamples = fmt->numbytes/fmt->bytespersample; | 46 | fmt->totalsamples = fmt->numbytes/fmt->bytespersample; |
49 | } | ||
50 | 47 | ||
51 | /* chunksize is computed so that one chunk is about 1/50s. | 48 | fmt->samplesperblock = fmt->blockalign / (fmt->bytespersample * fmt->channels); |
52 | * this make 4096 for 44.1kHz 16bits stereo. | 49 | |
53 | * It also has to be a multiple of blockalign */ | 50 | /* chunksize = about 1/50[sec] data */ |
54 | fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; | 51 | fmt->chunksize = (ci->id3->frequency / (50 * fmt->samplesperblock)) |
52 | * fmt->blockalign; | ||
55 | 53 | ||
56 | return true; | 54 | return true; |
57 | } | 55 | } |
58 | 56 | ||
59 | static uint32_t get_seek_pos(long seek_time) | 57 | static struct pcm_pos *get_seek_pos(long seek_time, |
58 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
60 | { | 59 | { |
61 | uint32_t newpos; | 60 | static struct pcm_pos newpos; |
62 | 61 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | |
63 | /* use avgbytespersec to round to the closest blockalign multiple, | 62 | / (1000LL * fmt->samplesperblock); |
64 | add firstblockposn. 64-bit casts to avoid overflows. */ | 63 | |
65 | newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) | 64 | (void)read_buffer; |
66 | / (1000LL*fmt->blockalign))*fmt->blockalign; | 65 | newpos.pos = newblock * fmt->blockalign; |
67 | return newpos; | 66 | newpos.samples = newblock * fmt->samplesperblock; |
67 | return &newpos; | ||
68 | } | 68 | } |
69 | 69 | ||
70 | static int decode(const uint8_t *inbuf, size_t inbufsize, | 70 | static int decode(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf, int *outbufsize) |
71 | int32_t *outbuf, int *outbufsize) | ||
72 | { | 71 | { |
73 | uint32_t i; | 72 | uint32_t i; |
74 | 73 | ||
diff --git a/apps/codecs/libpcm/ms_adpcm.c b/apps/codecs/libpcm/ms_adpcm.c new file mode 100644 index 0000000000..899ecc2045 --- /dev/null +++ b/apps/codecs/libpcm/ms_adpcm.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | |||
24 | /* | ||
25 | * Microsoft ADPCM | ||
26 | * | ||
27 | * References | ||
28 | * [1] Microsoft, New Multimedia Data Types and Data Techniques Revision 3.0, 1994 | ||
29 | * [2] MulitimediaWiki, Microsoft ADPCM, 2006 | ||
30 | * (http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM) | ||
31 | * [3] ffmpeg source code, libavcodec/adpcm.c | ||
32 | */ | ||
33 | |||
34 | #define ADPCM_NUM_COEFF 7 | ||
35 | |||
36 | static int16_t dec_coeff[2][2]; | ||
37 | static uint16_t delta[2]; | ||
38 | static int16_t sample[2][2]; | ||
39 | |||
40 | static struct pcm_format *fmt; | ||
41 | |||
42 | static const int16_t adaptation_table[] ICONST_ATTR = { | ||
43 | 230, 230, 230, 230, 307, 409, 512, 614, | ||
44 | 768, 614, 512, 409, 307, 230, 230, 230 | ||
45 | }; | ||
46 | |||
47 | static bool set_format(struct pcm_format *format) | ||
48 | { | ||
49 | fmt = format; | ||
50 | |||
51 | if (fmt->bitspersample != 4) | ||
52 | { | ||
53 | DEBUGF("CODEC_ERROR: microsoft adpcm must be 4 bitspersample: %d\n", | ||
54 | fmt->bitspersample); | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | fmt->chunksize = fmt->blockalign; | ||
59 | |||
60 | return true; | ||
61 | } | ||
62 | |||
63 | static struct pcm_pos *get_seek_pos(long seek_time, | ||
64 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
65 | { | ||
66 | static struct pcm_pos newpos; | ||
67 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | ||
68 | / (1000LL * fmt->samplesperblock); | ||
69 | |||
70 | (void)read_buffer; | ||
71 | newpos.pos = newblock * fmt->blockalign; | ||
72 | newpos.samples = newblock * fmt->samplesperblock; | ||
73 | return &newpos; | ||
74 | } | ||
75 | |||
76 | static int16_t create_pcmdata(int ch, uint8_t nibble) | ||
77 | { | ||
78 | int32_t pcmdata; | ||
79 | |||
80 | pcmdata = (sample[ch][0] * dec_coeff[ch][0] + | ||
81 | sample[ch][1] * dec_coeff[ch][1]) / 256; | ||
82 | pcmdata += (delta[ch] * (nibble - ((nibble & 0x8) << 1))); | ||
83 | |||
84 | CLIP(pcmdata, -32768, 32767); | ||
85 | |||
86 | sample[ch][1] = sample[ch][0]; | ||
87 | sample[ch][0] = pcmdata; | ||
88 | |||
89 | delta[ch] = (adaptation_table[nibble] * delta[ch]) >> 8; | ||
90 | if (delta[ch] < 16) | ||
91 | delta[ch] = 16; | ||
92 | |||
93 | return (int16_t)pcmdata; | ||
94 | } | ||
95 | |||
96 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
97 | int32_t *outbuf, int *outbufcount) | ||
98 | { | ||
99 | int ch; | ||
100 | size_t nsamples = 0; | ||
101 | int size = fmt->samplesperblock; | ||
102 | |||
103 | /* read block header */ | ||
104 | for (ch = 0; ch < fmt->channels; ch++) | ||
105 | { | ||
106 | if (*inbuf >= ADPCM_NUM_COEFF) | ||
107 | { | ||
108 | DEBUGF("CODEC_ERROR: microsoft adpcm illegal initial coeff=%d > 7\n", | ||
109 | *inbuf); | ||
110 | return CODEC_ERROR; | ||
111 | } | ||
112 | dec_coeff[ch][0] = fmt->coeffs[*inbuf][0]; | ||
113 | dec_coeff[ch][1] = fmt->coeffs[*inbuf][1]; | ||
114 | inbuf++; | ||
115 | } | ||
116 | |||
117 | for (ch = 0; ch < fmt->channels; ch++) | ||
118 | { | ||
119 | delta[ch] = inbuf[0] | (SE(inbuf[1]) << 8); | ||
120 | inbuf += 2; | ||
121 | } | ||
122 | |||
123 | for (ch = 0; ch < fmt->channels; ch++) | ||
124 | { | ||
125 | sample[ch][0] = inbuf[0] | (SE(inbuf[1]) << 8); | ||
126 | inbuf += 2; | ||
127 | } | ||
128 | |||
129 | for (ch = 0; ch < fmt->channels; ch++) | ||
130 | { | ||
131 | sample[ch][1] = inbuf[0] | (SE(inbuf[1]) << 8); | ||
132 | inbuf += 2; | ||
133 | } | ||
134 | |||
135 | inbufsize -= 7 * fmt->channels; | ||
136 | ch = fmt->channels - 1; | ||
137 | |||
138 | while (size-- > 0) | ||
139 | { | ||
140 | *outbuf++ = create_pcmdata(0, *inbuf >> 4 ) << 13; | ||
141 | *outbuf++ = create_pcmdata(ch, *inbuf & 0xf) << 13; | ||
142 | nsamples += 2; | ||
143 | |||
144 | inbuf++; | ||
145 | inbufsize--; | ||
146 | if (inbufsize <= 0) | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | if (fmt->channels == 2) | ||
151 | nsamples >>= 1; | ||
152 | *outbufcount = nsamples; | ||
153 | |||
154 | return CODEC_OK; | ||
155 | } | ||
156 | |||
157 | static const struct pcm_codec codec = { | ||
158 | set_format, | ||
159 | get_seek_pos, | ||
160 | decode, | ||
161 | }; | ||
162 | |||
163 | const struct pcm_codec *get_ms_adpcm_codec(void) | ||
164 | { | ||
165 | return &codec; | ||
166 | } | ||
diff --git a/apps/codecs/libpcm/pcm_common.h b/apps/codecs/libpcm/pcm_common.h index 757d0ad5d9..d490a85e9f 100644 --- a/apps/codecs/libpcm/pcm_common.h +++ b/apps/codecs/libpcm/pcm_common.h | |||
@@ -18,8 +18,8 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #ifndef CODEC_LIBPCMS_PCM_COMMON_H | 21 | #ifndef CODEC_LIBPCM_PCM_COMMON_H |
22 | #define CODEC_LIBPCMS_PCM_COMMON_H | 22 | #define CODEC_LIBPCM_PCM_COMMON_H |
23 | 23 | ||
24 | #include <sys/types.h> | 24 | #include <sys/types.h> |
25 | #include <stdbool.h> | 25 | #include <stdbool.h> |
@@ -38,6 +38,19 @@ | |||
38 | /* Macro that shift to -0x80. (0 .. 127 to -128 .. -1, 128 .. 255 to 0 .. 127) */ | 38 | /* Macro that shift to -0x80. (0 .. 127 to -128 .. -1, 128 .. 255 to 0 .. 127) */ |
39 | #define SFT(x) ((int32_t)x-0x80) | 39 | #define SFT(x) ((int32_t)x-0x80) |
40 | 40 | ||
41 | /* Macro that clipping data */ | ||
42 | #define CLIP(data, min, max) \ | ||
43 | if ((data) > (max)) data = max; \ | ||
44 | else if ((data) < (min)) data = min; | ||
45 | |||
46 | /* nums of msadpcm coeffs | ||
47 | * In many case, nNumCoef is 7. | ||
48 | * Depending upon the encoder, as for this value there is a possibility | ||
49 | * of increasing more. | ||
50 | * If you found the file where this value exceeds 7, please report. | ||
51 | */ | ||
52 | #define MSADPCM_NUM_COEFF 7 | ||
53 | |||
41 | struct pcm_format { | 54 | struct pcm_format { |
42 | /* | 55 | /* |
43 | * RIFF: wFormatTag (in 'fmt ' chunk) | 56 | * RIFF: wFormatTag (in 'fmt ' chunk) |
@@ -103,13 +116,67 @@ struct pcm_format { | |||
103 | * true: signed, false: unsigned | 116 | * true: signed, false: unsigned |
104 | */ | 117 | */ |
105 | bool is_signed; | 118 | bool is_signed; |
119 | |||
120 | /* the following values are format speciffic parameters */ | ||
121 | |||
122 | /* microsoft adpcm: aCoeff */ | ||
123 | int16_t coeffs[MSADPCM_NUM_COEFF][2]; | ||
124 | }; | ||
125 | |||
126 | struct pcm_pos { | ||
127 | uint32_t pos; | ||
128 | uint32_t samples; | ||
106 | }; | 129 | }; |
107 | 130 | ||
108 | struct pcm_codec { | 131 | struct pcm_codec { |
109 | bool (*set_format)(struct pcm_format *format, const unsigned char *fmtpos); | 132 | /* |
110 | uint32_t (*get_seek_pos)(long seek_time); | 133 | * sets the format speciffic RIFF/AIFF header information and checks the pcm_format. |
134 | * | ||
135 | * [In/Out] format | ||
136 | * the structure which supplies RIFF/AIFF header information. | ||
137 | * | ||
138 | * return | ||
139 | * true: RIFF/AIFF header check OK | ||
140 | * false: RIFF/AIFF header check NG | ||
141 | */ | ||
142 | bool (*set_format)(struct pcm_format *format); | ||
143 | |||
144 | /* | ||
145 | * get seek position | ||
146 | * | ||
147 | * [In] seek_time | ||
148 | * seek time [ms] | ||
149 | * | ||
150 | * [In] read_buffer | ||
151 | * the function which reads the data from the file (chunksize bytes read). | ||
152 | * | ||
153 | * return | ||
154 | * position after the seeking. | ||
155 | */ | ||
156 | struct pcm_pos *(*get_seek_pos)(long seek_time, | ||
157 | uint8_t *(*read_buffer)(size_t *realsize)); | ||
158 | |||
159 | /* | ||
160 | * decode wave data. | ||
161 | * | ||
162 | * [In] inbuf | ||
163 | * the start pointer of wave data buffer. | ||
164 | * | ||
165 | * [In] inbufsize | ||
166 | * wave data buffer size (bytes). | ||
167 | * | ||
168 | * [Out] outbuf | ||
169 | * the start pointer of the buffer which supplies decoded pcm data. | ||
170 | * | ||
171 | * [Out] outbufcount | ||
172 | * decoded pcm data count. | ||
173 | * | ||
174 | * return | ||
175 | * CODEC_OK: decode succeed. | ||
176 | * CODEC_ERROR: decode failure. | ||
177 | */ | ||
111 | int (*decode)(const uint8_t *inbuf, size_t inbufsize, | 178 | int (*decode)(const uint8_t *inbuf, size_t inbufsize, |
112 | int32_t *outbuf, int *outbufsize); | 179 | int32_t *outbuf, int *outbufcount); |
113 | }; | 180 | }; |
114 | 181 | ||
115 | struct pcm_entry { | 182 | struct pcm_entry { |
diff --git a/apps/codecs/libpcm/qt_ima_adpcm.c b/apps/codecs/libpcm/qt_ima_adpcm.c new file mode 100644 index 0000000000..a34e0e86cd --- /dev/null +++ b/apps/codecs/libpcm/qt_ima_adpcm.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | #include "ima_adpcm_common.h" | ||
24 | |||
25 | /* | ||
26 | * Apple QuickTime IMA ADPCM | ||
27 | * | ||
28 | * References | ||
29 | * [1] Multimedia Wiki, Apple QuickTime IMA ADPCM | ||
30 | * URL:http://wiki.multimedia.cx/index.php?title=Apple_QuickTime_IMA_ADPCM | ||
31 | * [2] Apple Inc., Technical Note TN1081 Understanding the Differences Between | ||
32 | * Apple and Windows IMA-ADPCM Compressed Sound Files, 1996 | ||
33 | * [3] ffmpeg source code, libavcodec/adpcm.c | ||
34 | */ | ||
35 | |||
36 | static struct pcm_format *fmt; | ||
37 | |||
38 | static bool set_format(struct pcm_format *format) | ||
39 | { | ||
40 | fmt = format; | ||
41 | |||
42 | if (fmt->bitspersample != 4) | ||
43 | { | ||
44 | DEBUGF("CODEC_ERROR: quicktime ima adpcm must be 4 bitspersample: %d\n", | ||
45 | fmt->bitspersample); | ||
46 | return false; | ||
47 | } | ||
48 | |||
49 | fmt->blockalign = 34 * fmt->channels; | ||
50 | fmt->samplesperblock = 64; | ||
51 | |||
52 | /* chunksize = about 1/50[s] data */ | ||
53 | fmt->chunksize = (ci->id3->frequency / (50 * fmt->samplesperblock)) | ||
54 | * fmt->blockalign; | ||
55 | |||
56 | init_ima_adpcm_decoder(4, NULL); | ||
57 | return true; | ||
58 | } | ||
59 | |||
60 | static struct pcm_pos *get_seek_pos(long seek_time, | ||
61 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
62 | { | ||
63 | static struct pcm_pos newpos; | ||
64 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | ||
65 | / (1000LL * fmt->samplesperblock); | ||
66 | |||
67 | (void)read_buffer; | ||
68 | newpos.pos = newblock * fmt->blockalign; | ||
69 | newpos.samples = newblock * fmt->samplesperblock; | ||
70 | return &newpos; | ||
71 | } | ||
72 | |||
73 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
74 | int32_t *outbuf, int *outbufcount) | ||
75 | { | ||
76 | int ch; | ||
77 | size_t nsamples = 0; | ||
78 | int block_size; | ||
79 | int32_t *pcmbuf; | ||
80 | int32_t init_pcmdata; | ||
81 | int8_t init_index; | ||
82 | |||
83 | while (inbufsize > 0) | ||
84 | { | ||
85 | for (ch = 0; ch < fmt->channels; ch++) | ||
86 | { | ||
87 | /* read block header */ | ||
88 | init_pcmdata = (inbuf[0] << 8)|(inbuf[1] & 0x80); | ||
89 | if (init_pcmdata > 32767) | ||
90 | init_pcmdata -= 65536; | ||
91 | |||
92 | init_index = inbuf[1] & 0x7f; | ||
93 | if (init_index > 88) | ||
94 | { | ||
95 | DEBUGF("CODEC_ERROR: quicktime ima adpcm illegal step index=%d > 88\n", | ||
96 | init_index); | ||
97 | return CODEC_ERROR; | ||
98 | } | ||
99 | |||
100 | inbuf += 2; | ||
101 | inbufsize -= 2; | ||
102 | |||
103 | set_decode_parameters(1, &init_pcmdata, &init_index); | ||
104 | |||
105 | /* read block data */ | ||
106 | pcmbuf = outbuf + ch; | ||
107 | for (block_size = 32; block_size > 0 && inbufsize > 0; block_size--, inbufsize--) | ||
108 | { | ||
109 | *pcmbuf = create_pcmdata_size4(ch, *inbuf ) << 13; | ||
110 | pcmbuf += fmt->channels; | ||
111 | *pcmbuf = create_pcmdata_size4(ch, *inbuf >> 4) << 13; | ||
112 | pcmbuf += fmt->channels; | ||
113 | nsamples += 2; | ||
114 | inbuf++; | ||
115 | } | ||
116 | } | ||
117 | outbuf += 64 * fmt->channels; | ||
118 | } | ||
119 | |||
120 | if (fmt->channels == 2) | ||
121 | nsamples >>= 1; | ||
122 | *outbufcount = nsamples; | ||
123 | |||
124 | return CODEC_OK; | ||
125 | } | ||
126 | |||
127 | static const struct pcm_codec codec = { | ||
128 | set_format, | ||
129 | get_seek_pos, | ||
130 | decode, | ||
131 | }; | ||
132 | |||
133 | const struct pcm_codec *get_qt_ima_adpcm_codec(void) | ||
134 | { | ||
135 | return &codec; | ||
136 | } | ||
diff --git a/apps/codecs/libpcm/support_formats.h b/apps/codecs/libpcm/support_formats.h index 0a6ea339f4..b1e089e464 100644 --- a/apps/codecs/libpcm/support_formats.h +++ b/apps/codecs/libpcm/support_formats.h | |||
@@ -18,8 +18,8 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #ifndef CODEC_LIBPCMS_SUPPORT_FORMATS_H | 21 | #ifndef CODEC_LIBPCM_SUPPORT_FORMATS_H |
22 | #define CODEC_LIBPCMS_SUPPORT_FORMATS_H | 22 | #define CODEC_LIBPCM_SUPPORT_FORMATS_H |
23 | 23 | ||
24 | #include "pcm_common.h" | 24 | #include "pcm_common.h" |
25 | 25 | ||
@@ -32,9 +32,24 @@ const struct pcm_codec *get_itut_g711_alaw_codec(void); | |||
32 | /* ITU-T G.711 mu-law */ | 32 | /* ITU-T G.711 mu-law */ |
33 | const struct pcm_codec *get_itut_g711_mulaw_codec(void); | 33 | const struct pcm_codec *get_itut_g711_mulaw_codec(void); |
34 | 34 | ||
35 | /* Intel DVI ADPCM */ | 35 | /* Intel DVI ADPCM (IMA ADPCM) */ |
36 | const struct pcm_codec *get_dvi_adpcm_codec(void); | 36 | const struct pcm_codec *get_dvi_adpcm_codec(void); |
37 | 37 | ||
38 | /* IEEE float */ | 38 | /* IEEE float */ |
39 | const struct pcm_codec *get_ieee_float_codec(void); | 39 | const struct pcm_codec *get_ieee_float_codec(void); |
40 | |||
41 | /* Microsoft ADPCM */ | ||
42 | const struct pcm_codec *get_ms_adpcm_codec(void); | ||
43 | |||
44 | /* Dialogic OKI ADPCM */ | ||
45 | const struct pcm_codec *get_dialogic_oki_adpcm_codec(void); | ||
46 | |||
47 | /* YAMAHA ADPCM */ | ||
48 | const struct pcm_codec *get_yamaha_adpcm_codec(void); | ||
49 | |||
50 | /* Apple QuickTime IMA ADPCM */ | ||
51 | const struct pcm_codec *get_qt_ima_adpcm_codec(void); | ||
52 | |||
53 | /* Adobe SWF ADPCM */ | ||
54 | const struct pcm_codec *get_swf_adpcm_codec(void); | ||
40 | #endif | 55 | #endif |
diff --git a/apps/codecs/libpcm/swf_adpcm.c b/apps/codecs/libpcm/swf_adpcm.c new file mode 100644 index 0000000000..456e1cdd4c --- /dev/null +++ b/apps/codecs/libpcm/swf_adpcm.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | #include "ima_adpcm_common.h" | ||
24 | |||
25 | /* | ||
26 | * Adobe SWF ADPCM | ||
27 | * | ||
28 | * References | ||
29 | * [1] Adobe, SWF File Format Specification Version 10, 2008 | ||
30 | * [2] Jack Jansen, adpcm.c in adpcm.zip | ||
31 | * [3] ffmpeg source code, libavcodec/adpcm.c | ||
32 | */ | ||
33 | |||
34 | /* step index table when bitspersample is 3. | ||
35 | * (when bitspersample is 2, 4, 5, step index table uses the table | ||
36 | * which is defined ima_adpcm_common.c.) | ||
37 | */ | ||
38 | static const int index_table[4] ICONST_ATTR = { | ||
39 | -1, -1, 2, 4, | ||
40 | }; | ||
41 | |||
42 | static int validity_bits = 8; | ||
43 | static bool first_block = true; | ||
44 | static int blockbits = 0; | ||
45 | static int lastbytebits = 0; | ||
46 | static bool after_seek = false; | ||
47 | |||
48 | static struct pcm_format *fmt; | ||
49 | |||
50 | static bool set_format(struct pcm_format *format) | ||
51 | { | ||
52 | fmt = format; | ||
53 | |||
54 | if (fmt->bitspersample < 2 || fmt->bitspersample > 5) | ||
55 | { | ||
56 | DEBUGF("CODEC_ERROR: swf adpcm must be 2, 3, 4 or 5 bitspersample: %d\n", | ||
57 | fmt->bitspersample); | ||
58 | return false; | ||
59 | } | ||
60 | |||
61 | if (fmt->samplesperblock == 0) | ||
62 | fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) | ||
63 | / fmt->bitspersample + 1; | ||
64 | |||
65 | blockbits = ((fmt->samplesperblock - 1) * fmt->bitspersample + 22) * fmt->channels; | ||
66 | |||
67 | /* | ||
68 | * chunksize = about 93 [ms] data (frequency:44.1kHz, 4096 [sample/block]) | ||
69 | * chunksize changes depending upon the position of block. | ||
70 | */ | ||
71 | fmt->chunksize = (blockbits + 9) >> 3; | ||
72 | |||
73 | /* initialize for ima adpcm common functions */ | ||
74 | if (fmt->bitspersample == 3) | ||
75 | init_ima_adpcm_decoder(fmt->bitspersample, index_table); | ||
76 | else | ||
77 | init_ima_adpcm_decoder(fmt->bitspersample, NULL); | ||
78 | |||
79 | return true; | ||
80 | } | ||
81 | |||
82 | static struct pcm_pos *get_seek_pos(long seek_time, | ||
83 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
84 | { | ||
85 | static struct pcm_pos newpos; | ||
86 | uint32_t chunkbits = blockbits; | ||
87 | uint32_t seekbits = (((uint64_t)seek_time * ci->id3->frequency) | ||
88 | / (1000LL * fmt->samplesperblock)) * blockbits + 2; | ||
89 | |||
90 | (void)read_buffer; | ||
91 | |||
92 | newpos.pos = seekbits >> 3; | ||
93 | newpos.samples = (((uint64_t)seek_time * ci->id3->frequency) | ||
94 | / (1000LL * fmt->samplesperblock)) | ||
95 | * fmt->samplesperblock; | ||
96 | |||
97 | if (newpos.pos == 0) | ||
98 | { | ||
99 | first_block = true; | ||
100 | lastbytebits = 0; | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | first_block = false; | ||
105 | lastbytebits = seekbits & 0x07; | ||
106 | if (lastbytebits != 0) | ||
107 | chunkbits -= (8 - lastbytebits); | ||
108 | } | ||
109 | |||
110 | /* calculates next read bytes */ | ||
111 | fmt->chunksize = (chunkbits >> 3) + (((chunkbits & 0x07) > 0)?1:0) | ||
112 | + ((lastbytebits > 0)?1:0); | ||
113 | |||
114 | after_seek = true; | ||
115 | return &newpos; | ||
116 | } | ||
117 | |||
118 | static uint8_t get_data(const uint8_t **buf, int bit) | ||
119 | { | ||
120 | uint8_t res = 0; | ||
121 | uint8_t mask = (1 << bit) - 1; | ||
122 | |||
123 | if (validity_bits >= bit) | ||
124 | { | ||
125 | validity_bits -= bit; | ||
126 | return (**buf >> validity_bits) & mask; | ||
127 | } | ||
128 | |||
129 | if (validity_bits > 0) | ||
130 | res = **buf << (bit - validity_bits); | ||
131 | |||
132 | validity_bits += 8 - bit; | ||
133 | res = (res | (*(++(*buf)) >> validity_bits)) & mask; | ||
134 | return res; | ||
135 | } | ||
136 | |||
137 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
138 | int32_t *outbuf, int *outbufcount) | ||
139 | { | ||
140 | int ch; | ||
141 | int adpcm_code_size; | ||
142 | int count = fmt->samplesperblock; | ||
143 | int32_t init_pcmdata[2]; | ||
144 | int8_t init_index[2]; | ||
145 | static uint8_t lastbyte = 0; | ||
146 | |||
147 | (void)inbufsize; | ||
148 | |||
149 | validity_bits = 8; | ||
150 | |||
151 | /* read block header */ | ||
152 | ch = fmt->channels - 1; | ||
153 | if (first_block) | ||
154 | { | ||
155 | adpcm_code_size = get_data(&inbuf, 2) + 2; | ||
156 | if (fmt->bitspersample != adpcm_code_size) | ||
157 | { | ||
158 | DEBUGF("CODEC_ERROR: swf adpcm different adpcm code size=%d != %d\n", | ||
159 | adpcm_code_size, fmt->bitspersample); | ||
160 | return CODEC_ERROR; | ||
161 | } | ||
162 | init_pcmdata[0] = (get_data(&inbuf, 8) << 8) | get_data(&inbuf, 8); | ||
163 | |||
164 | lastbytebits = 0; | ||
165 | first_block = false; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if (after_seek && lastbytebits > 0) | ||
170 | { | ||
171 | lastbyte = *inbuf++; | ||
172 | after_seek = false; | ||
173 | } | ||
174 | if (lastbytebits > 0) | ||
175 | init_pcmdata[0] = ((lastbyte << (8 + lastbytebits)) | | ||
176 | (get_data(&inbuf, 8) << lastbytebits) | | ||
177 | get_data(&inbuf, lastbytebits)) & 65535; | ||
178 | else | ||
179 | init_pcmdata[0] = (get_data(&inbuf, 8) << 8) | get_data(&inbuf, 8); | ||
180 | } | ||
181 | after_seek = false; | ||
182 | |||
183 | init_index[0] = get_data(&inbuf, 6); | ||
184 | if (init_pcmdata[0] > 32767) | ||
185 | init_pcmdata[0] -= 65536; | ||
186 | |||
187 | if (ch > 0) | ||
188 | { | ||
189 | init_pcmdata[1] = (get_data(&inbuf, 8) << 8) | get_data(&inbuf, 8); | ||
190 | init_index[1] = get_data(&inbuf, 6); | ||
191 | if (init_pcmdata[1] > 32767) | ||
192 | init_pcmdata[1] -= 65536; | ||
193 | } | ||
194 | |||
195 | *outbuf++ = init_pcmdata[0] << 13; | ||
196 | if (ch > 0) | ||
197 | *outbuf++ = init_pcmdata[1] << 13; | ||
198 | |||
199 | set_decode_parameters(fmt->channels, init_pcmdata, init_index); | ||
200 | |||
201 | /* read block data */ | ||
202 | while (--count > 0) | ||
203 | { | ||
204 | *outbuf++ = create_pcmdata(0, get_data(&inbuf, fmt->bitspersample)) << 13; | ||
205 | if (ch > 0) | ||
206 | *outbuf++ = create_pcmdata(ch, get_data(&inbuf, fmt->bitspersample)) << 13; | ||
207 | } | ||
208 | |||
209 | *outbufcount = fmt->samplesperblock; | ||
210 | |||
211 | lastbyte = *inbuf; | ||
212 | lastbytebits = (8 - validity_bits) & 0x07; | ||
213 | |||
214 | /* calculates next read bytes */ | ||
215 | fmt->chunksize = (blockbits - validity_bits + 7) >> 3; | ||
216 | |||
217 | return CODEC_OK; | ||
218 | } | ||
219 | |||
220 | static const struct pcm_codec codec = { | ||
221 | set_format, | ||
222 | get_seek_pos, | ||
223 | decode, | ||
224 | }; | ||
225 | |||
226 | const struct pcm_codec *get_swf_adpcm_codec(void) | ||
227 | { | ||
228 | first_block = true; | ||
229 | lastbytebits = 0; | ||
230 | after_seek = false; | ||
231 | |||
232 | return &codec; | ||
233 | } | ||
diff --git a/apps/codecs/libpcm/yamaha_adpcm.c b/apps/codecs/libpcm/yamaha_adpcm.c new file mode 100644 index 0000000000..6b3daa8f83 --- /dev/null +++ b/apps/codecs/libpcm/yamaha_adpcm.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Yoshihisa Uchida | ||
11 | * | ||
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. | ||
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 "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | #include "adpcm_seek.h" | ||
24 | |||
25 | /* | ||
26 | * YAMAHA ADPCM | ||
27 | * | ||
28 | * References | ||
29 | * [1] YAMAHA, YAMAHA ADPCM ACM Driver Version 1.0.0.0, 2005 | ||
30 | * [2] BlendWorks, YM2608 ADPCM, | ||
31 | * http://web.archive.org/web/20050208190547/www.memb.jp/~dearna/ma/ym2608/adpcm.html | ||
32 | * [3] Naoyuki Sawa, ADPCM no shikumi #1, | ||
33 | * http://www.piece-me.org/piece-lab/adpcm/adpcm1.html | ||
34 | * [4] ffmpeg source code, libavcodec/adpcm.c | ||
35 | */ | ||
36 | |||
37 | /* ADPCM data block layout | ||
38 | * | ||
39 | * when the block header exists. (for example, encoding by YAMAHA ADPCM ACM Driver) | ||
40 | * blockAlign = (frequency / 60 + 4) * channels. | ||
41 | * | ||
42 | * block | ||
43 | * <Mono> (channels = 1) | ||
44 | * int16_t first value (Little endian) | ||
45 | * uint16_t first predictor (Little endian) | ||
46 | * uint8_t ADPCM data (1st data: 0-3 bit, 2nd data: 4-7 bit) | ||
47 | * .... | ||
48 | * | ||
49 | * <Stereo> (channels = 2) | ||
50 | * int16_t Left channel first value (Little endian) | ||
51 | * uint16_t Left channel first predictor (Little endian) | ||
52 | * int16_t Right channel first value (Little endian) | ||
53 | * uint16_t Right channel first predictor (Little endian) | ||
54 | * uint8_t ADPCM data (Left channel: 0-3 bit, Right channel: 4-7 bit) | ||
55 | * .... | ||
56 | * | ||
57 | * when the block header does not exist. (for example, encoding by ffmpeg) | ||
58 | * blockAlign = 8000 | ||
59 | * | ||
60 | * block | ||
61 | * <Mono> (channels = 1) | ||
62 | * uint8_t ADPCM data (1st data: 0-3 bit, 2nd data: 4-7 bit) | ||
63 | * .... | ||
64 | * | ||
65 | * <Stereo> (channels = 2) | ||
66 | * uint8_t ADPCM data (Left channel: 0-3 bit, Right channel: 4-7 bit) | ||
67 | * .... | ||
68 | */ | ||
69 | |||
70 | static const int32_t amplification_table[] ICONST_ATTR = { | ||
71 | 230, 230, 230, 230, 307, 409, 512, 614, 230, 230, 230, 230, 307, 409, 512, 614 | ||
72 | }; | ||
73 | |||
74 | static bool has_block_header = false; | ||
75 | |||
76 | static struct adpcm_data cur_data; | ||
77 | static int blocksperchunk; | ||
78 | |||
79 | static struct pcm_format *fmt; | ||
80 | |||
81 | static bool set_format(struct pcm_format *format) | ||
82 | { | ||
83 | fmt = format; | ||
84 | |||
85 | if (fmt->bitspersample != 4) | ||
86 | { | ||
87 | DEBUGF("CODEC_ERROR: yamaha adpcm must be 4 bitspersample: %d\n", | ||
88 | fmt->bitspersample); | ||
89 | return false; | ||
90 | } | ||
91 | |||
92 | /* check exists block header */ | ||
93 | if (fmt->blockalign == ((ci->id3->frequency / 60) + 4) * fmt->channels) | ||
94 | { | ||
95 | has_block_header = true; | ||
96 | |||
97 | /* chunksize = about 1/30 [sec] data */ | ||
98 | fmt->chunksize = fmt->blockalign; | ||
99 | blocksperchunk = 1; | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | uint32_t max_chunk_count; | ||
104 | |||
105 | has_block_header = false; | ||
106 | |||
107 | /* blockalign = 2 * channels samples */ | ||
108 | fmt->blockalign = fmt->channels; | ||
109 | fmt->samplesperblock = 2; | ||
110 | |||
111 | /* chunksize = about 1/32[sec] data */ | ||
112 | blocksperchunk = ci->id3->frequency >> 6; | ||
113 | fmt->chunksize = blocksperchunk * fmt->blockalign; | ||
114 | |||
115 | max_chunk_count = (uint64_t)ci->id3->length * ci->id3->frequency | ||
116 | / (2000LL * fmt->chunksize / fmt->channels); | ||
117 | |||
118 | /* initialize seek table */ | ||
119 | init_seek_table(max_chunk_count); | ||
120 | /* add first data */ | ||
121 | add_adpcm_data(&cur_data); | ||
122 | } | ||
123 | |||
124 | return true; | ||
125 | } | ||
126 | |||
127 | static int16_t create_pcmdata(int ch, uint8_t nibble) | ||
128 | { | ||
129 | int32_t tmp_pcmdata = cur_data.pcmdata[ch]; | ||
130 | int32_t step = cur_data.step[ch]; | ||
131 | int32_t delta = step >> 3; | ||
132 | |||
133 | if (nibble & 4) delta += step; | ||
134 | if (nibble & 2) delta += (step >> 1); | ||
135 | if (nibble & 1) delta += (step >> 2); | ||
136 | |||
137 | if (nibble & 0x08) | ||
138 | tmp_pcmdata -= delta; | ||
139 | else | ||
140 | tmp_pcmdata += delta; | ||
141 | |||
142 | CLIP(tmp_pcmdata, -32768, 32767); | ||
143 | cur_data.pcmdata[ch] = tmp_pcmdata; | ||
144 | |||
145 | step = (step * amplification_table[nibble & 0x07]) >> 8; | ||
146 | CLIP(step, 127, 24576); | ||
147 | cur_data.step[ch] = step; | ||
148 | |||
149 | return cur_data.pcmdata[ch]; | ||
150 | } | ||
151 | |||
152 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
153 | int32_t *outbuf, int *outbufcount) | ||
154 | { | ||
155 | int ch; | ||
156 | size_t nsamples = 0; | ||
157 | |||
158 | /* read block header */ | ||
159 | if (has_block_header) | ||
160 | { | ||
161 | for (ch = 0; ch < fmt->channels; ch++) | ||
162 | { | ||
163 | cur_data.pcmdata[ch] = inbuf[0] | (SE(inbuf[1]) << 8); | ||
164 | cur_data.step[ch] = inbuf[2] | (inbuf[3] << 8); | ||
165 | |||
166 | inbuf += 4; | ||
167 | inbufsize -= 4; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /* read block data */ | ||
172 | ch = fmt->channels - 1; | ||
173 | while (inbufsize) | ||
174 | { | ||
175 | *outbuf++ = create_pcmdata(0, *inbuf ) << 13; | ||
176 | *outbuf++ = create_pcmdata(ch, *inbuf >> 4) << 13; | ||
177 | nsamples += 2; | ||
178 | |||
179 | inbuf++; | ||
180 | inbufsize--; | ||
181 | } | ||
182 | |||
183 | if (fmt->channels == 2) | ||
184 | nsamples >>= 1; | ||
185 | *outbufcount = nsamples; | ||
186 | |||
187 | if (!has_block_header) | ||
188 | add_adpcm_data(&cur_data); | ||
189 | |||
190 | return CODEC_OK; | ||
191 | } | ||
192 | |||
193 | static int decode_for_seek(const uint8_t *inbuf, size_t inbufsize) | ||
194 | { | ||
195 | int ch = fmt->channels - 1; | ||
196 | |||
197 | while (inbufsize) | ||
198 | { | ||
199 | create_pcmdata(0, *inbuf ); | ||
200 | create_pcmdata(ch, *inbuf >> 4); | ||
201 | |||
202 | inbuf++; | ||
203 | inbufsize--; | ||
204 | } | ||
205 | |||
206 | add_adpcm_data(&cur_data); | ||
207 | |||
208 | return CODEC_OK; | ||
209 | } | ||
210 | |||
211 | static struct pcm_pos *get_seek_pos(long seek_time, | ||
212 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
213 | { | ||
214 | static struct pcm_pos newpos; | ||
215 | uint32_t new_count= 0; | ||
216 | |||
217 | if (seek_time > 0) | ||
218 | new_count = ((uint64_t)seek_time * ci->id3->frequency | ||
219 | / (1000LL * fmt->samplesperblock)) / blocksperchunk; | ||
220 | |||
221 | if (!has_block_header) | ||
222 | { | ||
223 | new_count = seek(new_count, &cur_data, read_buffer, &decode_for_seek); | ||
224 | } | ||
225 | newpos.pos = new_count * fmt->chunksize; | ||
226 | newpos.samples = new_count * blocksperchunk * fmt->samplesperblock; | ||
227 | return &newpos; | ||
228 | } | ||
229 | |||
230 | static struct pcm_codec codec = { | ||
231 | set_format, | ||
232 | get_seek_pos, | ||
233 | decode, | ||
234 | }; | ||
235 | |||
236 | const struct pcm_codec *get_yamaha_adpcm_codec(void) | ||
237 | { | ||
238 | /* initialize first step, pcm data */ | ||
239 | cur_data.pcmdata[0] = 0; | ||
240 | cur_data.pcmdata[1] = 0; | ||
241 | cur_data.step[0] = 127; | ||
242 | cur_data.step[1] = 127; | ||
243 | |||
244 | return &codec; | ||
245 | } | ||
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index a642f99a0f..293089a737 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c | |||
@@ -45,27 +45,37 @@ enum | |||
45 | { | 45 | { |
46 | WAVE_FORMAT_UNKNOWN = 0x0000, /* Microsoft Unknown Wave Format */ | 46 | WAVE_FORMAT_UNKNOWN = 0x0000, /* Microsoft Unknown Wave Format */ |
47 | WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ | 47 | WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ |
48 | WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */ | ||
48 | WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */ | 49 | WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */ |
49 | WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */ | 50 | WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */ |
50 | WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */ | 51 | WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */ |
51 | WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ | 52 | WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ |
53 | WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */ | ||
54 | WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */ | ||
55 | WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */ | ||
52 | IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ | 56 | IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ |
53 | IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ | 57 | IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ |
58 | WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */ | ||
54 | WAVE_FORMAT_EXTENSIBLE = 0xFFFE | 59 | WAVE_FORMAT_EXTENSIBLE = 0xFFFE |
55 | }; | 60 | }; |
56 | 61 | ||
57 | const struct pcm_entry wave_codecs[] = { | 62 | const struct pcm_entry wave_codecs[] = { |
58 | { WAVE_FORMAT_UNKNOWN, 0 }, | 63 | { WAVE_FORMAT_UNKNOWN, 0 }, |
59 | { WAVE_FORMAT_PCM, get_linear_pcm_codec }, | 64 | { WAVE_FORMAT_PCM, get_linear_pcm_codec }, |
65 | { WAVE_FORMAT_ADPCM, get_ms_adpcm_codec }, | ||
60 | { WAVE_FORMAT_IEEE_FLOAT, get_ieee_float_codec }, | 66 | { WAVE_FORMAT_IEEE_FLOAT, get_ieee_float_codec }, |
61 | { WAVE_FORMAT_ALAW, get_itut_g711_alaw_codec }, | 67 | { WAVE_FORMAT_ALAW, get_itut_g711_alaw_codec }, |
62 | { WAVE_FORMAT_MULAW, get_itut_g711_mulaw_codec }, | 68 | { WAVE_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
63 | { WAVE_FORMAT_DVI_ADPCM, get_dvi_adpcm_codec }, | 69 | { WAVE_FORMAT_DVI_ADPCM, get_dvi_adpcm_codec }, |
70 | { WAVE_FORMAT_DIALOGIC_OKI_ADPCM, get_dialogic_oki_adpcm_codec }, | ||
71 | { WAVE_FORMAT_YAMAHA_ADPCM, get_yamaha_adpcm_codec }, | ||
72 | { WAVE_FORMAT_XBOX_ADPCM, get_dvi_adpcm_codec }, | ||
64 | { IBM_FORMAT_MULAW, get_itut_g711_mulaw_codec }, | 73 | { IBM_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
65 | { IBM_FORMAT_ALAW, get_itut_g711_alaw_codec }, | 74 | { IBM_FORMAT_ALAW, get_itut_g711_alaw_codec }, |
75 | { WAVE_FORMAT_SWF_ADPCM, get_swf_adpcm_codec }, | ||
66 | }; | 76 | }; |
67 | 77 | ||
68 | #define NUM_FORMATS 8 | 78 | #define NUM_FORMATS 13 |
69 | 79 | ||
70 | static const struct pcm_codec *get_wave_codec(uint32_t formattag) | 80 | static const struct pcm_codec *get_wave_codec(uint32_t formattag) |
71 | { | 81 | { |
@@ -83,13 +93,67 @@ static const struct pcm_codec *get_wave_codec(uint32_t formattag) | |||
83 | return 0; | 93 | return 0; |
84 | } | 94 | } |
85 | 95 | ||
96 | static struct pcm_format format; | ||
97 | static uint32_t bytesdone; | ||
98 | |||
99 | static bool set_msadpcm_coeffs(const uint8_t *buf) | ||
100 | { | ||
101 | int i; | ||
102 | int num; | ||
103 | int size; | ||
104 | |||
105 | buf += 4; /* skip 'fmt ' */ | ||
106 | size = buf[0] | (buf[1] << 8) | (buf[1] << 16) | (buf[1] << 24); | ||
107 | if (size < 50) | ||
108 | { | ||
109 | DEBUGF("CODEC_ERROR: microsoft adpcm 'fmt ' chunk size=%lu < 50\n", | ||
110 | (unsigned long)size); | ||
111 | return false; | ||
112 | } | ||
113 | |||
114 | /* get nNumCoef */ | ||
115 | buf += 24; | ||
116 | num = buf[0] | (buf[1] << 8); | ||
117 | |||
118 | /* | ||
119 | * In many case, nNumCoef is 7. | ||
120 | * Depending upon the encoder, as for this value there is a possibility of | ||
121 | * increasing more. | ||
122 | * If you found the file where this value exceeds 7, please report. | ||
123 | */ | ||
124 | if (num != MSADPCM_NUM_COEFF) | ||
125 | { | ||
126 | DEBUGF("CODEC_ERROR: microsoft adpcm nNumCoef=%d != 7\n", num); | ||
127 | return false; | ||
128 | } | ||
129 | |||
130 | /* get aCoeffs */ | ||
131 | buf += 2; | ||
132 | for (i = 0; i < MSADPCM_NUM_COEFF; i++) | ||
133 | { | ||
134 | format.coeffs[i][0] = buf[0] | (SE(buf[1]) << 8); | ||
135 | format.coeffs[i][1] = buf[2] | (SE(buf[3]) << 8); | ||
136 | buf += 4; | ||
137 | } | ||
138 | |||
139 | return true; | ||
140 | } | ||
141 | |||
142 | static uint8_t *read_buffer(size_t *realsize) | ||
143 | { | ||
144 | uint8_t *buffer = (uint8_t *)ci->request_buffer(realsize, format.chunksize); | ||
145 | if (bytesdone + (*realsize) > format.numbytes) | ||
146 | *realsize = format.numbytes - bytesdone; | ||
147 | bytesdone += *realsize; | ||
148 | ci->advance_buffer(*realsize); | ||
149 | return buffer; | ||
150 | } | ||
86 | 151 | ||
87 | /* this is the codec entry point */ | 152 | /* this is the codec entry point */ |
88 | enum codec_status codec_main(void) | 153 | enum codec_status codec_main(void) |
89 | { | 154 | { |
90 | int status = CODEC_OK; | 155 | int status = CODEC_OK; |
91 | struct pcm_format format; | 156 | uint32_t decodedsamples; |
92 | uint32_t bytesdone, decodedbytes; | ||
93 | uint32_t i; | 157 | uint32_t i; |
94 | size_t n; | 158 | size_t n; |
95 | int bufcount; | 159 | int bufcount; |
@@ -125,6 +189,7 @@ next_track: | |||
125 | goto done; | 189 | goto done; |
126 | } | 190 | } |
127 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { | 191 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { |
192 | DEBUGF("CODEC_ERROR: missing riff header\n"); | ||
128 | status = CODEC_ERROR; | 193 | status = CODEC_ERROR; |
129 | goto done; | 194 | goto done; |
130 | } | 195 | } |
@@ -137,7 +202,7 @@ next_track: | |||
137 | format.is_signed = true; | 202 | format.is_signed = true; |
138 | format.is_little_endian = true; | 203 | format.is_little_endian = true; |
139 | 204 | ||
140 | decodedbytes = 0; | 205 | decodedsamples = 0; |
141 | codec = 0; | 206 | codec = 0; |
142 | 207 | ||
143 | /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */ | 208 | /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */ |
@@ -200,11 +265,21 @@ next_track: | |||
200 | } | 265 | } |
201 | } | 266 | } |
202 | 267 | ||
268 | /* msadpcm specific */ | ||
269 | if (format.formattag == WAVE_FORMAT_ADPCM) | ||
270 | { | ||
271 | if (!set_msadpcm_coeffs(buf)) | ||
272 | { | ||
273 | status = CODEC_ERROR; | ||
274 | goto done; | ||
275 | } | ||
276 | } | ||
277 | |||
203 | /* get codec */ | 278 | /* get codec */ |
204 | codec = get_wave_codec(format.formattag); | 279 | codec = get_wave_codec(format.formattag); |
205 | if (!codec) | 280 | if (!codec) |
206 | { | 281 | { |
207 | DEBUGF("CODEC_ERROR: unsupported wave format %x\n", | 282 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", |
208 | (unsigned int) format.formattag); | 283 | (unsigned int) format.formattag); |
209 | status = CODEC_ERROR; | 284 | status = CODEC_ERROR; |
210 | goto done; | 285 | goto done; |
@@ -215,7 +290,7 @@ next_track: | |||
215 | format.is_signed = false; | 290 | format.is_signed = false; |
216 | 291 | ||
217 | /* set format, parse codec specific tag, check format, and calculate chunk size */ | 292 | /* set format, parse codec specific tag, check format, and calculate chunk size */ |
218 | if (!codec->set_format(&format, buf)) | 293 | if (!codec->set_format(&format)) |
219 | { | 294 | { |
220 | status = CODEC_ERROR; | 295 | status = CODEC_ERROR; |
221 | goto done; | 296 | goto done; |
@@ -256,12 +331,34 @@ next_track: | |||
256 | status = CODEC_ERROR; | 331 | status = CODEC_ERROR; |
257 | goto done; | 332 | goto done; |
258 | } | 333 | } |
334 | if (format.samplesperblock == 0) { | ||
335 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); | ||
336 | status = CODEC_ERROR; | ||
337 | goto done; | ||
338 | } | ||
339 | if (format.blockalign == 0) | ||
340 | { | ||
341 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); | ||
342 | i = CODEC_ERROR; | ||
343 | goto done; | ||
344 | } | ||
259 | if (format.numbytes == 0) { | 345 | if (format.numbytes == 0) { |
260 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | 346 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
261 | status = CODEC_ERROR; | 347 | status = CODEC_ERROR; |
262 | goto done; | 348 | goto done; |
263 | } | 349 | } |
264 | 350 | ||
351 | /* check chunksize */ | ||
352 | if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels | ||
353 | > PCM_CHUNK_SIZE) | ||
354 | format.chunksize = (PCM_CHUNK_SIZE / format.blockalign) * format.blockalign; | ||
355 | if (format.chunksize == 0) | ||
356 | { | ||
357 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | ||
358 | i = CODEC_ERROR; | ||
359 | goto done; | ||
360 | } | ||
361 | |||
265 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 362 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
266 | if (format.channels == 2) { | 363 | if (format.channels == 2) { |
267 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); | 364 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); |
@@ -295,13 +392,14 @@ next_track: | |||
295 | } | 392 | } |
296 | 393 | ||
297 | if (ci->seek_time) { | 394 | if (ci->seek_time) { |
298 | uint32_t newpos = codec->get_seek_pos(ci->seek_time); | 395 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, &read_buffer); |
299 | 396 | ||
300 | if (newpos > format.numbytes) | 397 | decodedsamples = newpos->samples; |
398 | if (newpos->pos > format.numbytes) | ||
301 | break; | 399 | break; |
302 | if (ci->seek_buffer(firstblockposn + newpos)) | 400 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
303 | { | 401 | { |
304 | bytesdone = newpos; | 402 | bytesdone = newpos->pos; |
305 | } | 403 | } |
306 | ci->seek_complete(); | 404 | ci->seek_complete(); |
307 | } | 405 | } |
@@ -324,11 +422,11 @@ next_track: | |||
324 | ci->pcmbuf_insert(samples, NULL, bufcount); | 422 | ci->pcmbuf_insert(samples, NULL, bufcount); |
325 | ci->advance_buffer(n); | 423 | ci->advance_buffer(n); |
326 | bytesdone += n; | 424 | bytesdone += n; |
327 | decodedbytes += bufcount; | 425 | decodedsamples += bufcount; |
328 | 426 | ||
329 | if (bytesdone >= format.numbytes) | 427 | if (bytesdone >= format.numbytes) |
330 | endofstream = 1; | 428 | endofstream = 1; |
331 | ci->set_elapsed(decodedbytes*1000LL/ci->id3->frequency); | 429 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
332 | } | 430 | } |
333 | status = CODEC_OK; | 431 | status = CODEC_OK; |
334 | 432 | ||
diff --git a/apps/metadata/aiff.c b/apps/metadata/aiff.c index 67fb43b8c6..aba327f8c8 100644 --- a/apps/metadata/aiff.c +++ b/apps/metadata/aiff.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include "metadata_common.h" | 29 | #include "metadata_common.h" |
30 | #include "metadata_parsers.h" | 30 | #include "metadata_parsers.h" |
31 | 31 | ||
32 | /* compressionType: AIFC QuickTime IMA ADPCM */ | ||
33 | #define AIFC_FORMAT_QT_IMA_ADPCM "ima4" | ||
34 | |||
32 | bool get_aiff_metadata(int fd, struct mp3entry* id3) | 35 | bool get_aiff_metadata(int fd, struct mp3entry* id3) |
33 | { | 36 | { |
34 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 37 | /* Use the trackname part of the id3 structure as a temporary buffer */ |
@@ -40,6 +43,7 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
40 | unsigned long numbytes = 0; | 43 | unsigned long numbytes = 0; |
41 | int read_bytes; | 44 | int read_bytes; |
42 | int i; | 45 | int i; |
46 | bool is_aifc = false; | ||
43 | 47 | ||
44 | if ((lseek(fd, 0, SEEK_SET) < 0) | 48 | if ((lseek(fd, 0, SEEK_SET) < 0) |
45 | || ((read_bytes = read(fd, buf, sizeof(id3->path))) < 54)) | 49 | || ((read_bytes = read(fd, buf, sizeof(id3->path))) < 54)) |
@@ -47,10 +51,15 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
47 | return false; | 51 | return false; |
48 | } | 52 | } |
49 | 53 | ||
50 | if ((memcmp(buf, "FORM",4) != 0) | 54 | if (memcmp(buf, "FORM",4) != 0) |
51 | || ((memcmp(&buf[8], "AIFF", 4) !=0) && (memcmp(&buf[8], "AIFC", 4) !=0))) | ||
52 | { | ||
53 | return false; | 55 | return false; |
56 | |||
57 | if (memcmp(&buf[8], "AIFF", 4) != 0) | ||
58 | { | ||
59 | if (memcmp(&buf[8], "AIFC", 4) != 0) | ||
60 | return false; | ||
61 | |||
62 | is_aifc = true; | ||
54 | } | 63 | } |
55 | 64 | ||
56 | buf += 12; | 65 | buf += 12; |
@@ -75,7 +84,13 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
75 | /* save format infos */ | 84 | /* save format infos */ |
76 | id3->bitrate = (sampleSize * numChannels * sampleRate) / 1000; | 85 | id3->bitrate = (sampleSize * numChannels * sampleRate) / 1000; |
77 | id3->frequency = sampleRate; | 86 | id3->frequency = sampleRate; |
78 | id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; | 87 | if (!is_aifc || memcmp(&buf[26], AIFC_FORMAT_QT_IMA_ADPCM, 4) != 0) |
88 | id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; | ||
89 | else | ||
90 | { | ||
91 | /* QuickTime IMA ADPCM is 1block = 64 data for each channel */ | ||
92 | id3->length = (int64_t)(numSampleFrames * 64000LL) / id3->frequency; | ||
93 | } | ||
79 | 94 | ||
80 | id3->vbr = false; /* AIFF files are CBR */ | 95 | id3->vbr = false; /* AIFF files are CBR */ |
81 | id3->filesize = filesize(fd); | 96 | id3->filesize = filesize(fd); |
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c index acef32dd38..79bb8178bd 100644 --- a/apps/metadata/wave.c +++ b/apps/metadata/wave.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "metadata.h" | 28 | #include "metadata.h" |
29 | #include "metadata_common.h" | 29 | #include "metadata_common.h" |
30 | #include "metadata_parsers.h" | 30 | #include "metadata_parsers.h" |
31 | #include "logf.h" | ||
31 | 32 | ||
32 | # define AV_WL32(p, d) do { \ | 33 | # define AV_WL32(p, d) do { \ |
33 | ((uint8_t*)(p))[0] = (d); \ | 34 | ((uint8_t*)(p))[0] = (d); \ |
@@ -40,29 +41,101 @@ | |||
40 | ((uint8_t*)(p))[1] = (d)>>8; \ | 41 | ((uint8_t*)(p))[1] = (d)>>8; \ |
41 | } while(0) | 42 | } while(0) |
42 | 43 | ||
44 | enum | ||
45 | { | ||
46 | WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ | ||
47 | WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */ | ||
48 | WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */ | ||
49 | WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */ | ||
50 | WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */ | ||
51 | WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ | ||
52 | WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */ | ||
53 | WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */ | ||
54 | WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */ | ||
55 | IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ | ||
56 | IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ | ||
57 | WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */ | ||
58 | WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */ | ||
59 | }; | ||
60 | |||
61 | struct wave_fmt { | ||
62 | unsigned int formattag; | ||
63 | unsigned long channels; | ||
64 | unsigned int blockalign; | ||
65 | unsigned long bitspersample; | ||
66 | unsigned int samplesperblock; | ||
67 | unsigned long numbytes; | ||
68 | }; | ||
69 | |||
70 | static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3) | ||
71 | { | ||
72 | unsigned long totalsamples = 0; | ||
73 | |||
74 | switch (fmt->formattag) | ||
75 | { | ||
76 | case WAVE_FORMAT_PCM: | ||
77 | case WAVE_FORMAT_IEEE_FLOAT: | ||
78 | case WAVE_FORMAT_ALAW: | ||
79 | case WAVE_FORMAT_MULAW: | ||
80 | case IBM_FORMAT_ALAW: | ||
81 | case IBM_FORMAT_MULAW: | ||
82 | totalsamples = | ||
83 | fmt->numbytes / ((((fmt->bitspersample - 1) / 8) + 1) * fmt->channels); | ||
84 | break; | ||
85 | case WAVE_FORMAT_ADPCM: | ||
86 | case WAVE_FORMAT_DVI_ADPCM: | ||
87 | case WAVE_FORMAT_XBOX_ADPCM: | ||
88 | totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
89 | break; | ||
90 | case WAVE_FORMAT_YAMAHA_ADPCM: | ||
91 | if (fmt->samplesperblock == 0) | ||
92 | { | ||
93 | if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels) | ||
94 | fmt->samplesperblock = id3->frequency / 30; | ||
95 | else | ||
96 | fmt->samplesperblock = fmt->blockalign * 2 / fmt->channels; | ||
97 | } | ||
98 | totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
99 | break; | ||
100 | case WAVE_FORMAT_DIALOGIC_OKI_ADPCM: | ||
101 | totalsamples = 2 * fmt->numbytes; | ||
102 | break; | ||
103 | case WAVE_FORMAT_SWF_ADPCM: | ||
104 | if (fmt->samplesperblock == 0) | ||
105 | fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) | ||
106 | / fmt->bitspersample; | ||
107 | |||
108 | totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
109 | break; | ||
110 | default: | ||
111 | totalsamples = 0; | ||
112 | break; | ||
113 | } | ||
114 | return totalsamples; | ||
115 | } | ||
116 | |||
43 | bool get_wave_metadata(int fd, struct mp3entry* id3) | 117 | bool get_wave_metadata(int fd, struct mp3entry* id3) |
44 | { | 118 | { |
45 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 119 | /* Use the trackname part of the id3 structure as a temporary buffer */ |
46 | unsigned char* buf = (unsigned char *)id3->path; | 120 | unsigned char* buf = (unsigned char *)id3->path; |
121 | struct wave_fmt fmt; | ||
47 | unsigned long totalsamples = 0; | 122 | unsigned long totalsamples = 0; |
48 | unsigned long channels = 0; | ||
49 | unsigned long bitspersample = 0; | ||
50 | unsigned long numbytes = 0; | ||
51 | unsigned long offset = 0; | 123 | unsigned long offset = 0; |
52 | int read_bytes; | 124 | int read_bytes; |
53 | int i; | 125 | int i; |
54 | 126 | ||
127 | memset(&fmt, 0, sizeof(struct wave_fmt)); | ||
128 | |||
55 | /* get RIFF chunk header */ | 129 | /* get RIFF chunk header */ |
56 | if ((lseek(fd, 0, SEEK_SET) < 0) | 130 | if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 12) < 12)) |
57 | || ((read_bytes = read(fd, buf, 12)) < 12)) | ||
58 | { | 131 | { |
59 | return false; | 132 | return false; |
60 | } | 133 | } |
61 | offset += 12; | 134 | offset += 12; |
62 | 135 | ||
63 | if ((memcmp(buf, "RIFF",4) != 0) | 136 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) |
64 | || (memcmp(&buf[8], "WAVE", 4) !=0 )) | ||
65 | { | 137 | { |
138 | DEBUGF("metadata error: missing riff header.\n"); | ||
66 | return false; | 139 | return false; |
67 | } | 140 | } |
68 | 141 | ||
@@ -70,7 +143,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
70 | while (true) | 143 | while (true) |
71 | { | 144 | { |
72 | /* get chunk header */ | 145 | /* get chunk header */ |
73 | if ((read_bytes = read(fd, buf, 8)) < 8) | 146 | if (read(fd, buf, 8) < 8) |
74 | return false; | 147 | return false; |
75 | offset += 8; | 148 | offset += 8; |
76 | 149 | ||
@@ -80,26 +153,41 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
80 | if (memcmp(buf, "fmt ", 4) == 0) | 153 | if (memcmp(buf, "fmt ", 4) == 0) |
81 | { | 154 | { |
82 | /* get rest of chunk */ | 155 | /* get rest of chunk */ |
83 | if ((read_bytes = read(fd, buf, 16)) < 16) | 156 | if (i < 16) |
84 | return false; | 157 | return false; |
85 | offset += 16; | ||
86 | i -= 16; | ||
87 | 158 | ||
159 | read_bytes = 16; | ||
160 | if (i > 19) | ||
161 | read_bytes = 20; | ||
88 | 162 | ||
89 | /* skipping wFormatTag */ | 163 | if (read(fd, buf, read_bytes) != read_bytes) |
164 | return false; | ||
165 | |||
166 | offset += read_bytes; | ||
167 | i -= read_bytes; | ||
168 | |||
169 | /* wFormatTag */ | ||
170 | fmt.formattag = buf[0] | (buf[1] << 8); | ||
90 | /* wChannels */ | 171 | /* wChannels */ |
91 | channels = buf[2] | (buf[3] << 8); | 172 | fmt.channels = buf[2] | (buf[3] << 8); |
92 | /* dwSamplesPerSec */ | 173 | /* dwSamplesPerSec */ |
93 | id3->frequency = get_long_le(&buf[4]); | 174 | id3->frequency = get_long_le(&buf[4]); |
94 | /* dwAvgBytesPerSec */ | 175 | /* dwAvgBytesPerSec */ |
95 | id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; | 176 | id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; |
96 | /* wBlockAlign */ | 177 | /* wBlockAlign */ |
97 | id3->bytesperframe = buf[12] | (buf[13] << 8); | 178 | fmt.blockalign = buf[12] | (buf[13] << 8); |
179 | id3->bytesperframe = fmt.blockalign; | ||
98 | /* wBitsPerSample */ | 180 | /* wBitsPerSample */ |
99 | bitspersample = buf[14] | (buf[15] << 8); | 181 | fmt.bitspersample = buf[14] | (buf[15] << 8); |
182 | if (read_bytes > 19) | ||
183 | { | ||
184 | /* wSamplesPerBlock */ | ||
185 | fmt.samplesperblock = buf[18] | (buf[19] << 8); | ||
186 | } | ||
187 | |||
100 | /* Check for ATRAC3 stream */ | 188 | /* Check for ATRAC3 stream */ |
101 | if((buf[0] | (buf[1] << 8)) == 0x0270) | 189 | if (fmt.formattag == WAVE_FORMAT_ATRAC3) |
102 | { | 190 | { |
103 | int jsflag = 0; | 191 | int jsflag = 0; |
104 | if(id3->bitrate == 66 || id3->bitrate == 94) | 192 | if(id3->bitrate == 66 || id3->bitrate == 94) |
105 | jsflag = 1; | 193 | jsflag = 1; |
@@ -107,7 +195,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
107 | id3->extradata_size = 14; | 195 | id3->extradata_size = 14; |
108 | id3->channels = 2; | 196 | id3->channels = 2; |
109 | id3->codectype = AFMT_OMA_ATRAC3; | 197 | id3->codectype = AFMT_OMA_ATRAC3; |
110 | /* Store the extradata for the codec */ | 198 | /* Store the extradata for the codec */ |
111 | AV_WL16(&id3->id3v2buf[0], 1); // always 1 | 199 | AV_WL16(&id3->id3v2buf[0], 1); // always 1 |
112 | AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate | 200 | AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate |
113 | AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode | 201 | AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode |
@@ -118,8 +206,9 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
118 | } | 206 | } |
119 | else if (memcmp(buf, "data", 4) == 0) | 207 | else if (memcmp(buf, "data", 4) == 0) |
120 | { | 208 | { |
121 | numbytes = i; | 209 | fmt.numbytes = i; |
122 | id3->first_frame_offset = offset; | 210 | if (fmt.formattag == WAVE_FORMAT_ATRAC3) |
211 | id3->first_frame_offset = offset; | ||
123 | break; | 212 | break; |
124 | } | 213 | } |
125 | else if (memcmp(buf, "fact", 4) == 0) | 214 | else if (memcmp(buf, "fact", 4) == 0) |
@@ -128,7 +217,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
128 | if (i >= 4) | 217 | if (i >= 4) |
129 | { | 218 | { |
130 | /* get rest of chunk */ | 219 | /* get rest of chunk */ |
131 | if ((read_bytes = read(fd, buf, 4)) < 4) | 220 | if (read(fd, buf, 4) < 4) |
132 | return false; | 221 | return false; |
133 | offset += 4; | 222 | offset += 4; |
134 | i -= 4; | 223 | i -= 4; |
@@ -145,16 +234,15 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
145 | offset += i; | 234 | offset += i; |
146 | } | 235 | } |
147 | 236 | ||
148 | if ((numbytes == 0) || (channels == 0)) | 237 | if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0)) |
149 | { | 238 | { |
239 | DEBUGF("metadata error: numbytes, channels, or blockalign is 0.\n"); | ||
150 | return false; | 240 | return false; |
151 | } | 241 | } |
152 | 242 | ||
153 | if (totalsamples == 0) | 243 | if (totalsamples == 0) |
154 | { | 244 | { |
155 | /* for PCM only */ | 245 | totalsamples = get_totalsamples(&fmt, id3); |
156 | totalsamples = numbytes | ||
157 | / ((((bitspersample - 1) / 8) + 1) * channels); | ||
158 | } | 246 | } |
159 | 247 | ||
160 | id3->vbr = false; /* All WAV files are CBR */ | 248 | id3->vbr = false; /* All WAV files are CBR */ |