blob: ddd07fc45f1f0b726dae41a768722d72dc39e9de [file] [log] [blame]
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +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 <string.h>
18
19#include "AudioCodec.h"
20
21namespace {
22
23int8_t gExponents[128] = {
24 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
25 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
26 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
27 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
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 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
31 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
32};
33
34//------------------------------------------------------------------------------
35
36class UlawCodec : public AudioCodec
37{
38public:
39 bool set(int sampleRate, int sampleCount) {
40 mSampleCount = sampleCount;
41 return sampleCount > 0;
42 }
43 int encode(void *payload, int16_t *samples);
44 int decode(int16_t *samples, void *payload, int length);
45private:
46 int mSampleCount;
47};
48
49int UlawCodec::encode(void *payload, int16_t *samples)
50{
51 int8_t *ulaws = (int8_t *)payload;
52 for (int i = 0; i < mSampleCount; ++i) {
53 int sample = samples[i];
54 int sign = (sample >> 8) & 0x80;
55 if (sample < 0) {
56 sample = -sample;
57 }
58 sample += 132;
59 if (sample > 32767) {
60 sample = 32767;
61 }
62 int exponent = gExponents[sample >> 8];
63 int mantissa = (sample >> (exponent + 3)) & 0x0F;
64 ulaws[i] = ~(sign | (exponent << 4) | mantissa);
65 }
66 return mSampleCount;
67}
68
69int UlawCodec::decode(int16_t *samples, void *payload, int length)
70{
71 int8_t *ulaws = (int8_t *)payload;
72 for (int i = 0; i < length; ++i) {
73 int ulaw = ~ulaws[i];
74 int exponent = (ulaw >> 4) & 0x07;
75 int mantissa = ulaw & 0x0F;
76 int sample = (((mantissa << 3) + 132) << exponent) - 132;
77 samples[i] = (ulaw < 0 ? -sample : sample);
78 }
79 return length;
80}
81
82AudioCodec *newUlawCodec()
83{
84 return new UlawCodec;
85}
86
87//------------------------------------------------------------------------------
88
89class AlawCodec : public AudioCodec
90{
91public:
92 bool set(int sampleRate, int sampleCount) {
93 mSampleCount = sampleCount;
94 return sampleCount > 0;
95 }
96 int encode(void *payload, int16_t *samples);
97 int decode(int16_t *samples, void *payload, int length);
98private:
99 int mSampleCount;
100};
101
102int AlawCodec::encode(void *payload, int16_t *samples)
103{
104 int8_t *alaws = (int8_t *)payload;
105 for (int i = 0; i < mSampleCount; ++i) {
106 int sample = samples[i];
107 int sign = (sample >> 8) & 0x80;
108 if (sample < 0) {
109 sample = -sample;
110 }
111 if (sample > 32767) {
112 sample = 32767;
113 }
114 int exponent = gExponents[sample >> 8];
115 int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F;
116 alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5;
117 }
118 return mSampleCount;
119}
120
121int AlawCodec::decode(int16_t *samples, void *payload, int length)
122{
123 int8_t *alaws = (int8_t *)payload;
124 for (int i = 0; i < length; ++i) {
125 int alaw = alaws[i] ^ 0x55;
126 int exponent = (alaw >> 4) & 0x07;
127 int mantissa = alaw & 0x0F;
128 int sample = (exponent == 0 ? (mantissa << 4) + 8 :
129 ((mantissa << 3) + 132) << exponent);
130 samples[i] = (alaw < 0 ? sample : -sample);
131 }
132 return length;
133}
134
135AudioCodec *newAlawCodec()
136{
137 return new AlawCodec;
138}
139
140struct AudioCodecType {
141 const char *name;
142 AudioCodec *(*create)();
143} gAudioCodecTypes[] = {
144 {"PCMA", newAlawCodec},
145 {"PCMU", newUlawCodec},
146 {NULL, NULL},
147};
148
149} // namespace
150
151AudioCodec *newAudioCodec(const char *codecName)
152{
153 AudioCodecType *type = gAudioCodecTypes;
154 while (type->name != NULL) {
155 if (strcmp(codecName, type->name) == 0) {
156 return type->create();
157 }
158 ++type;
159 }
160 return NULL;
161}