diff options
author | Chia-chi Yeh <chiachi@android.com> | 2010-08-06 14:12:05 +0800 |
---|---|---|
committer | Chia-chi Yeh <chiachi@android.com> | 2010-08-06 14:12:05 +0800 |
commit | 4c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8 (patch) | |
tree | 0c6b5c7973f57d56b6c55130356cae06f5c09954 /voip/jni/rtp/AudioCodec.cpp | |
parent | 1d62c7737c33f92e79f0a180b05969f52484e64c (diff) | |
download | frameworks_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.cpp | 161 |
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; +} |