summaryrefslogtreecommitdiff
path: root/apps/codecs/libpcm/dialogic_oki_adpcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libpcm/dialogic_oki_adpcm.c')
-rw-r--r--apps/codecs/libpcm/dialogic_oki_adpcm.c183
1 files changed, 183 insertions, 0 deletions
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
35static 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
42static const int index_table[] ICONST_ATTR = {
43 -1, -1, -1, -1, 2, 4, 6, 8
44};
45
46static struct adpcm_data cur_data;
47
48static struct pcm_format *fmt;
49
50static 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
87static 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
112static 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
133static 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
149static 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
166static const struct pcm_codec codec = {
167 set_format,
168 get_seek_pos,
169 decode,
170 };
171
172const 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}