summaryrefslogtreecommitdiffstats
path: root/voip/jni/rtp/AudioCodec.cpp
diff options
context:
space:
mode:
authorChia-chi Yeh <chiachi@android.com>2010-08-06 14:12:05 +0800
committerChia-chi Yeh <chiachi@android.com>2010-08-06 14:12:05 +0800
commit4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8 (patch)
tree0c6b5c7973f57d56b6c55130356cae06f5c09954 /voip/jni/rtp/AudioCodec.cpp
parent1d62c7737c33f92e79f0a180b05969f52484e64c (diff)
downloadframeworks_base-4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8.zip
frameworks_base-4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8.tar.gz
frameworks_base-4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8.tar.bz2
RTP: move into frameworks.
Change-Id: Ic9c17b460448c746b21526ac10b647f281ae48e9
Diffstat (limited to 'voip/jni/rtp/AudioCodec.cpp')
-rw-r--r--voip/jni/rtp/AudioCodec.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/voip/jni/rtp/AudioCodec.cpp b/voip/jni/rtp/AudioCodec.cpp
new file mode 100644
index 0000000..ddd07fc
--- /dev/null
+++ b/voip/jni/rtp/AudioCodec.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyrightm (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#include "AudioCodec.h"
+
+namespace {
+
+int8_t gExponents[128] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+};
+
+//------------------------------------------------------------------------------
+
+class UlawCodec : public AudioCodec
+{
+public:
+ bool set(int sampleRate, int sampleCount) {
+ mSampleCount = sampleCount;
+ return sampleCount > 0;
+ }
+ int encode(void *payload, int16_t *samples);
+ int decode(int16_t *samples, void *payload, int length);
+private:
+ int mSampleCount;
+};
+
+int UlawCodec::encode(void *payload, int16_t *samples)
+{
+ int8_t *ulaws = (int8_t *)payload;
+ for (int i = 0; i < mSampleCount; ++i) {
+ int sample = samples[i];
+ int sign = (sample >> 8) & 0x80;
+ if (sample < 0) {
+ sample = -sample;
+ }
+ sample += 132;
+ if (sample > 32767) {
+ sample = 32767;
+ }
+ int exponent = gExponents[sample >> 8];
+ int mantissa = (sample >> (exponent + 3)) & 0x0F;
+ ulaws[i] = ~(sign | (exponent << 4) | mantissa);
+ }
+ return mSampleCount;
+}
+
+int UlawCodec::decode(int16_t *samples, void *payload, int length)
+{
+ int8_t *ulaws = (int8_t *)payload;
+ for (int i = 0; i < length; ++i) {
+ int ulaw = ~ulaws[i];
+ int exponent = (ulaw >> 4) & 0x07;
+ int mantissa = ulaw & 0x0F;
+ int sample = (((mantissa << 3) + 132) << exponent) - 132;
+ samples[i] = (ulaw < 0 ? -sample : sample);
+ }
+ return length;
+}
+
+AudioCodec *newUlawCodec()
+{
+ return new UlawCodec;
+}
+
+//------------------------------------------------------------------------------
+
+class AlawCodec : public AudioCodec
+{
+public:
+ bool set(int sampleRate, int sampleCount) {
+ mSampleCount = sampleCount;
+ return sampleCount > 0;
+ }
+ int encode(void *payload, int16_t *samples);
+ int decode(int16_t *samples, void *payload, int length);
+private:
+ int mSampleCount;
+};
+
+int AlawCodec::encode(void *payload, int16_t *samples)
+{
+ int8_t *alaws = (int8_t *)payload;
+ for (int i = 0; i < mSampleCount; ++i) {
+ int sample = samples[i];
+ int sign = (sample >> 8) & 0x80;
+ if (sample < 0) {
+ sample = -sample;
+ }
+ if (sample > 32767) {
+ sample = 32767;
+ }
+ int exponent = gExponents[sample >> 8];
+ int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F;
+ alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5;
+ }
+ return mSampleCount;
+}
+
+int AlawCodec::decode(int16_t *samples, void *payload, int length)
+{
+ int8_t *alaws = (int8_t *)payload;
+ for (int i = 0; i < length; ++i) {
+ int alaw = alaws[i] ^ 0x55;
+ int exponent = (alaw >> 4) & 0x07;
+ int mantissa = alaw & 0x0F;
+ int sample = (exponent == 0 ? (mantissa << 4) + 8 :
+ ((mantissa << 3) + 132) << exponent);
+ samples[i] = (alaw < 0 ? sample : -sample);
+ }
+ return length;
+}
+
+AudioCodec *newAlawCodec()
+{
+ return new AlawCodec;
+}
+
+struct AudioCodecType {
+ const char *name;
+ AudioCodec *(*create)();
+} gAudioCodecTypes[] = {
+ {"PCMA", newAlawCodec},
+ {"PCMU", newUlawCodec},
+ {NULL, NULL},
+};
+
+} // namespace
+
+AudioCodec *newAudioCodec(const char *codecName)
+{
+ AudioCodecType *type = gAudioCodecTypes;
+ while (type->name != NULL) {
+ if (strcmp(codecName, type->name) == 0) {
+ return type->create();
+ }
+ ++type;
+ }
+ return NULL;
+}