summaryrefslogtreecommitdiff
path: root/apps/codecs/libpcm/ima_adpcm_common.c
blob: 724cce31b099da2bce74ace7b6e5767717336456 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2010 Yoshihisa Uchida
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include "codeclib.h"
#include "pcm_common.h"
#include "ima_adpcm_common.h"

/*
 * Functions for IMA ADPCM and IMA ADPCM series format
 *
 * References
 * [1] The IMA Digital Audio Focus and Technical Working Groups,
 *     Recommended Practices for Enhancing Digital Audio Compatibility
 *     in Multimedia Systems Revision 3.00, 1992
 * [2] Microsoft Corporation, New Multimedia Data Types and Data Techniques,
 *     Revision:3.0, 1994
 * [3] ffmpeg source code, libavcodec/adpcm.c
 */

/* step table */
static const uint16_t step_table[89] ICONST_ATTR = {
    7, 8, 9, 10, 11, 12, 13, 14,
    16, 17, 19, 21, 23, 25, 28, 31,
    34, 37, 41, 45, 50, 55, 60, 66,
    73, 80, 88, 97, 107, 118, 130, 143,
    157, 173, 190, 209, 230, 253, 279, 307,
    337, 371, 408, 449, 494, 544, 598, 658,
    724, 796, 876, 963, 1060, 1166, 1282, 1411,
    1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
    3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
    7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
    32767
};

/* step index tables */
static const int index_tables[4][16] ICONST_ATTR = {
    /* adpcm data size is 2 */
    { -1, 2 },
    /* adpcm data size is 3 */
    { -1, -1, 1, 2 },
    /* adpcm data size is 4 */
    { -1, -1, -1, -1, 2, 4, 6, 8 },
    /* adpcm data size is 5 */
    { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 },
};

static int32_t pcmdata[2];
static int8_t indices[2];

static int adpcm_data_size;
static uint8_t step_mask;
static uint8_t step_sign_mask;
static int8_t step_shift;
static const int *use_index_table;

/*
 * Before first decoding, this function must be executed.
 *
 * params
 *     bit: adpcm data size (2 <= bit <= 5).
 *     index_table: step index table
 *                  if index_table is null, then step index table
 *                  is used index_tables[bit-2].
 */
void init_ima_adpcm_decoder(int bit, const int *index_table)
{
    adpcm_data_size = bit;
    step_sign_mask = 1 << (adpcm_data_size - 1);
    step_mask = step_sign_mask - 1;
    step_shift = adpcm_data_size - 2;
    if (index_table)
        use_index_table = index_table;
    else
        use_index_table = index_tables[adpcm_data_size - 2];
}

/*
 * When starting decoding for each block, this function must be executed.
 *
 * params
 *     channels: channel count
 *     init_pcmdata: array of init pcmdata
 *     init_index:   array of init step indexes
 */
void set_decode_parameters(int channels, int32_t *init_pcmdata, int8_t *init_index)
{
    int ch;

    for (ch = 0; ch < channels; ch++)
    {
        pcmdata[ch] = init_pcmdata[ch];
        indices[ch] = init_index[ch];
    }
}

/*
 * convert ADPCM to PCM for any adpcm data size.
 *
 * If adpcm_data_size is 4, then you use create_pcmdata_size4()
 * in place of this functon.
 */
int16_t create_pcmdata(int ch, uint8_t nibble)
{
    int check_bit = 1 << step_shift;
    int32_t delta = 0;
    int16_t step = step_table[indices[ch]];

    do {
        if (nibble & check_bit)
            delta += step;
        step >>= 1;
        check_bit >>= 1;
    } while (check_bit);
    delta += step;

    if (nibble & step_sign_mask)
        pcmdata[ch] -= delta;
    else
        pcmdata[ch] += delta;

    indices[ch] += use_index_table[nibble & step_mask];
    CLIP(indices[ch], 0, 88);

    CLIP(pcmdata[ch], -32768, 32767);

    return (int16_t)pcmdata[ch];
}

/*
 * convert ADPCM to PCM when adpcm data size is 4.
 */
int16_t create_pcmdata_size4(int ch, uint8_t nibble)
{
    int32_t delta;
    int16_t step = step_table[indices[ch]];

    delta = (step >> 3);
    if (nibble & 4) delta += step;
    if (nibble & 2) delta += (step >> 1);
    if (nibble & 1) delta += (step >> 2);

    if (nibble & 0x08)
        pcmdata[ch] -= delta;
    else
        pcmdata[ch] += delta;

    indices[ch] += use_index_table[nibble & 0x07];
    CLIP(indices[ch], 0, 88);

    CLIP(pcmdata[ch], -32768, 32767);

    return (int16_t)pcmdata[ch];
}