diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-02-20 02:04:56 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-02-20 02:04:56 +0000 |
commit | 3716abba9274f544dd31cdf4e6c83a845bf2a801 (patch) | |
tree | 07bca7cdd3e40bb176e938fcb5ea8eb2f7c3e9cb /apps/codecs/libpcm/qt_ima_adpcm.c | |
parent | 93caf52db5e0afe826278c148936bdfa563724f1 (diff) | |
download | rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.tar.gz rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.zip |
commit FS#10424 and FS#10425
- wav(RIFF) supports Microsoft ADPCM, Dialogic OKI ADPCM, YAMAHA ADPCM, Adobe SWF ADPCM.
- AIFF supports QuickTime IMA ADPCM.
- DVI ADPCM(IMA ADPCM) reworks.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24782 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libpcm/qt_ima_adpcm.c')
-rw-r--r-- | apps/codecs/libpcm/qt_ima_adpcm.c | 136 |
1 files changed, 136 insertions, 0 deletions
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 | } | ||