blob: ef54863d1c469d248c3cfd046373287ee95dcc0a [file] [log] [blame]
Chia-chi Yeh78c11b32010-09-29 05:46:19 +08001/*
2 * Copyrightm (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "AudioCodec.h"
18
19namespace {
20
Chia-chi Yeh21ae1ad2010-09-30 16:07:44 +080021const int8_t gExponents[128] = {
Chia-chi Yeh78c11b32010-09-29 05:46:19 +080022 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
23 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
24 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
25 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
26 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
27 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
28 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
29 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
30};
31
32//------------------------------------------------------------------------------
33
34class UlawCodec : public AudioCodec
35{
36public:
37 int set(int sampleRate, const char *fmtp) {
38 mSampleCount = sampleRate / 50;
39 return mSampleCount;
40 }
41 int encode(void *payload, int16_t *samples);
Chia-chi Yeh35d05dc2011-09-06 14:18:37 -070042 int decode(int16_t *samples, int count, void *payload, int length);
Chia-chi Yeh78c11b32010-09-29 05:46:19 +080043private:
44 int mSampleCount;
45};
46
47int UlawCodec::encode(void *payload, int16_t *samples)
48{
49 int8_t *ulaws = (int8_t *)payload;
50 for (int i = 0; i < mSampleCount; ++i) {
51 int sample = samples[i];
52 int sign = (sample >> 8) & 0x80;
53 if (sample < 0) {
54 sample = -sample;
55 }
56 sample += 132;
57 if (sample > 32767) {
58 sample = 32767;
59 }
60 int exponent = gExponents[sample >> 8];
61 int mantissa = (sample >> (exponent + 3)) & 0x0F;
62 ulaws[i] = ~(sign | (exponent << 4) | mantissa);
63 }
64 return mSampleCount;
65}
66
Chia-chi Yeh35d05dc2011-09-06 14:18:37 -070067int UlawCodec::decode(int16_t *samples, int count, void *payload, int length)
Chia-chi Yeh78c11b32010-09-29 05:46:19 +080068{
69 int8_t *ulaws = (int8_t *)payload;
Chia-chi Yeh35d05dc2011-09-06 14:18:37 -070070 if (length > count) {
71 length = count;
72 }
Chia-chi Yeh78c11b32010-09-29 05:46:19 +080073 for (int i = 0; i < length; ++i) {
74 int ulaw = ~ulaws[i];
75 int exponent = (ulaw >> 4) & 0x07;
76 int mantissa = ulaw & 0x0F;
77 int sample = (((mantissa << 3) + 132) << exponent) - 132;
78 samples[i] = (ulaw < 0 ? -sample : sample);
79 }
80 return length;
81}
82
83//------------------------------------------------------------------------------
84
85class AlawCodec : public AudioCodec
86{
87public:
88 int set(int sampleRate, const char *fmtp) {
89 mSampleCount = sampleRate / 50;
90 return mSampleCount;
91 }
92 int encode(void *payload, int16_t *samples);
Chia-chi Yeh35d05dc2011-09-06 14:18:37 -070093 int decode(int16_t *samples, int count, void *payload, int length);
Chia-chi Yeh78c11b32010-09-29 05:46:19 +080094private:
95 int mSampleCount;
96};
97
98int AlawCodec::encode(void *payload, int16_t *samples)
99{
100 int8_t *alaws = (int8_t *)payload;
101 for (int i = 0; i < mSampleCount; ++i) {
102 int sample = samples[i];
103 int sign = (sample >> 8) & 0x80;
104 if (sample < 0) {
105 sample = -sample;
106 }
107 if (sample > 32767) {
108 sample = 32767;
109 }
110 int exponent = gExponents[sample >> 8];
111 int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F;
112 alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5;
113 }
114 return mSampleCount;
115}
116
Chia-chi Yeh35d05dc2011-09-06 14:18:37 -0700117int AlawCodec::decode(int16_t *samples, int count, void *payload, int length)
Chia-chi Yeh78c11b32010-09-29 05:46:19 +0800118{
119 int8_t *alaws = (int8_t *)payload;
Chia-chi Yeh35d05dc2011-09-06 14:18:37 -0700120 if (length > count) {
121 length = count;
122 }
Chia-chi Yeh78c11b32010-09-29 05:46:19 +0800123 for (int i = 0; i < length; ++i) {
124 int alaw = alaws[i] ^ 0x55;
125 int exponent = (alaw >> 4) & 0x07;
126 int mantissa = alaw & 0x0F;
127 int sample = (exponent == 0 ? (mantissa << 4) + 8 :
128 ((mantissa << 3) + 132) << exponent);
129 samples[i] = (alaw < 0 ? sample : -sample);
130 }
131 return length;
132}
133
134} // namespace
135
136AudioCodec *newUlawCodec()
137{
138 return new UlawCodec;
139}
140
141AudioCodec *newAlawCodec()
142{
143 return new AlawCodec;
144}