1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Yoshihisa Uchida
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "pcm_common.h"
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
34 #define ADPCM_NUM_COEFF 7
36 static int16_t dec_coeff
[2][2];
37 static uint16_t delta
[2];
38 static int16_t sample
[2][2];
40 static struct pcm_format
*fmt
;
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
47 static bool set_format(struct pcm_format
*format
)
51 if (fmt
->bitspersample
!= 4)
53 DEBUGF("CODEC_ERROR: microsoft adpcm must be 4 bitspersample: %d\n",
58 fmt
->chunksize
= fmt
->blockalign
;
63 static struct pcm_pos
*get_seek_pos(long seek_time
,
64 uint8_t *(*read_buffer
)(size_t *realsize
))
66 static struct pcm_pos newpos
;
67 uint32_t newblock
= ((uint64_t)seek_time
* ci
->id3
->frequency
)
68 / (1000LL * fmt
->samplesperblock
);
71 newpos
.pos
= newblock
* fmt
->blockalign
;
72 newpos
.samples
= newblock
* fmt
->samplesperblock
;
76 static int16_t create_pcmdata(int ch
, uint8_t nibble
)
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)));
84 CLIP(pcmdata
, -32768, 32767);
86 sample
[ch
][1] = sample
[ch
][0];
87 sample
[ch
][0] = pcmdata
;
89 delta
[ch
] = (adaptation_table
[nibble
] * delta
[ch
]) >> 8;
93 return (int16_t)pcmdata
;
96 static int decode(const uint8_t *inbuf
, size_t inbufsize
,
97 int32_t *outbuf
, int *outbufcount
)
101 int size
= fmt
->samplesperblock
;
103 /* read block header */
104 for (ch
= 0; ch
< fmt
->channels
; ch
++)
106 if (*inbuf
>= ADPCM_NUM_COEFF
)
108 DEBUGF("CODEC_ERROR: microsoft adpcm illegal initial coeff=%d > 7\n",
112 dec_coeff
[ch
][0] = fmt
->coeffs
[*inbuf
][0];
113 dec_coeff
[ch
][1] = fmt
->coeffs
[*inbuf
][1];
117 for (ch
= 0; ch
< fmt
->channels
; ch
++)
119 delta
[ch
] = inbuf
[0] | (SE(inbuf
[1]) << 8);
123 for (ch
= 0; ch
< fmt
->channels
; ch
++)
125 sample
[ch
][0] = inbuf
[0] | (SE(inbuf
[1]) << 8);
129 for (ch
= 0; ch
< fmt
->channels
; ch
++)
131 sample
[ch
][1] = inbuf
[0] | (SE(inbuf
[1]) << 8);
135 inbufsize
-= 7 * fmt
->channels
;
136 ch
= fmt
->channels
- 1;
140 *outbuf
++ = create_pcmdata(0, *inbuf
>> 4 ) << 13;
141 *outbuf
++ = create_pcmdata(ch
, *inbuf
& 0xf) << 13;
150 if (fmt
->channels
== 2)
152 *outbufcount
= nsamples
;
157 static const struct pcm_codec codec
= {
163 const struct pcm_codec
*get_ms_adpcm_codec(void)