1536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh/*
2536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * Copyrightm (C) 2010 The Android Open Source Project
3536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh *
4536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
5536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * you may not use this file except in compliance with the License.
6536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * You may obtain a copy of the License at
7536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh *
8536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
9536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh *
10536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software
11536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
12536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * See the License for the specific language governing permissions and
14536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh * limitations under the License.
15536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh */
16536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
17536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh#include "AudioCodec.h"
18536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
19536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehnamespace {
20536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
21d85beac45c12a65076a1c157681de9a5b03bdec7Chia-chi Yehconst int8_t gExponents[128] = {
22536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
23536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
24536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
25536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
26536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
27536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
28536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
29536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
30536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh};
31536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
32536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh//------------------------------------------------------------------------------
33536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
34536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehclass UlawCodec : public AudioCodec
35536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
36536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehpublic:
37536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int set(int sampleRate, const char *fmtp) {
38536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        mSampleCount = sampleRate / 50;
39536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        return mSampleCount;
40536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    }
41536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int encode(void *payload, int16_t *samples);
42418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh    int decode(int16_t *samples, int count, void *payload, int length);
43536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehprivate:
44536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int mSampleCount;
45536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh};
46536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
47536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehint UlawCodec::encode(void *payload, int16_t *samples)
48536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
49536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int8_t *ulaws = (int8_t *)payload;
50536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    for (int i = 0; i < mSampleCount; ++i) {
51536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int sample = samples[i];
52536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int sign = (sample >> 8) & 0x80;
53536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        if (sample < 0) {
54536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh            sample = -sample;
55536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        }
56536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        sample += 132;
57536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        if (sample > 32767) {
58536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh            sample = 32767;
59536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        }
60536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int exponent = gExponents[sample >> 8];
61536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int mantissa = (sample >> (exponent + 3)) & 0x0F;
62536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        ulaws[i] = ~(sign | (exponent << 4) | mantissa);
63536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    }
64536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    return mSampleCount;
65536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh}
66536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
67418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yehint UlawCodec::decode(int16_t *samples, int count, void *payload, int length)
68536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
69536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int8_t *ulaws = (int8_t *)payload;
70418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh    if (length > count) {
71418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh        length = count;
72418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh    }
73536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    for (int i = 0; i < length; ++i) {
74536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int ulaw = ~ulaws[i];
75536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int exponent = (ulaw >> 4) & 0x07;
76536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int mantissa = ulaw & 0x0F;
77536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int sample = (((mantissa << 3) + 132) << exponent) - 132;
78536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        samples[i] = (ulaw < 0 ? -sample : sample);
79536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    }
80536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    return length;
81536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh}
82536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
83536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh//------------------------------------------------------------------------------
84536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
85536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehclass AlawCodec : public AudioCodec
86536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
87536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehpublic:
88536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int set(int sampleRate, const char *fmtp) {
89536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        mSampleCount = sampleRate / 50;
90536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        return mSampleCount;
91536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    }
92536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int encode(void *payload, int16_t *samples);
93418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh    int decode(int16_t *samples, int count, void *payload, int length);
94536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehprivate:
95536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int mSampleCount;
96536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh};
97536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
98536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yehint AlawCodec::encode(void *payload, int16_t *samples)
99536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
100536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int8_t *alaws = (int8_t *)payload;
101536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    for (int i = 0; i < mSampleCount; ++i) {
102536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int sample = samples[i];
103536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int sign = (sample >> 8) & 0x80;
104536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        if (sample < 0) {
105536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh            sample = -sample;
106536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        }
107536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        if (sample > 32767) {
108536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh            sample = 32767;
109536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        }
110536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int exponent = gExponents[sample >> 8];
111536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F;
112536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5;
113536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    }
114536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    return mSampleCount;
115536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh}
116536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
117418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yehint AlawCodec::decode(int16_t *samples, int count, void *payload, int length)
118536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
119536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    int8_t *alaws = (int8_t *)payload;
120418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh    if (length > count) {
121418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh        length = count;
122418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh    }
123536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    for (int i = 0; i < length; ++i) {
124536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int alaw = alaws[i] ^ 0x55;
125536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int exponent = (alaw >> 4) & 0x07;
126536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int mantissa = alaw & 0x0F;
127536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        int sample = (exponent == 0 ? (mantissa << 4) + 8 :
128536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh            ((mantissa << 3) + 132) << exponent);
129536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh        samples[i] = (alaw < 0 ? sample : -sample);
130536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    }
131536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    return length;
132536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh}
133536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
134536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh} // namespace
135536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
136536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi YehAudioCodec *newUlawCodec()
137536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
138536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    return new UlawCodec;
139536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh}
140536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh
141536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi YehAudioCodec *newAlawCodec()
142536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh{
143536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh    return new AlawCodec;
144536a451f5cf9f4bcf38968366cf62368f3d4d2f8Chia-chi Yeh}
145