AmrCodec.cpp revision f88fc1fa907f720df4a3e915509e688e9e4cf1f8
1f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh/* 2f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * Copyrightm (C) 2010 The Android Open Source Project 3f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * 4f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 5f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * you may not use this file except in compliance with the License. 6f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * You may obtain a copy of the License at 7f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * 8f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 9f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * 10f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 11f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 12f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * See the License for the specific language governing permissions and 14f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh * limitations under the License. 15f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh */ 16f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 17f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh#include <string.h> 18f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 19f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh#include "AudioCodec.h" 20f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 21f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh#include "gsmamr_dec.h" 22f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh#include "gsmamr_enc.h" 23f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 24f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehnamespace { 25f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 26f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehconst int gFrameBits[8] = {95, 103, 118, 134, 148, 159, 204, 244}; 27f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 28f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh//------------------------------------------------------------------------------ 29f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 30f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh// See RFC 4867 for the encoding details. 31f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 32f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehclass AmrCodec : public AudioCodec 33f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh{ 34f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehpublic: 35f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh AmrCodec() { 36f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (AMREncodeInit(&mEncoder, &mSidSync, false)) { 37f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mEncoder = NULL; 38f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 39f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) { 40f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mDecoder = NULL; 41f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 42f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 43f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 44f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh ~AmrCodec() { 45f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (mEncoder) { 46f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh AMREncodeExit(&mEncoder, &mSidSync); 47f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 48f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (mDecoder) { 49f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh GSMDecodeFrameExit(&mDecoder); 50f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 51f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 52f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 53f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int set(int sampleRate, const char *fmtp); 54f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int encode(void *payload, int16_t *samples); 55f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int decode(int16_t *samples, void *payload, int length); 56f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 57f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehprivate: 58f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh void *mEncoder; 59f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh void *mSidSync; 60f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh void *mDecoder; 61f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 62f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int mMode; 63f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int mModeSet; 64f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bool mOctetAligned; 65f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh}; 66f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 67f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehint AmrCodec::set(int sampleRate, const char *fmtp) 68f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh{ 69f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // These parameters are not supported. 70f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (strcasestr(fmtp, "crc=1") || strcasestr(fmtp, "robust-sorting=1") || 71f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh strcasestr(fmtp, "interleaving=")) { 72f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 73f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 74f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 75f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // Handle mode-set and octet-align. 76f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh char *modes = strcasestr(fmtp, "mode-set="); 77f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (modes) { 78f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mMode = 0; 79f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mModeSet = 0; 80f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh for (char c = *modes; c && c != ' '; c = *++modes) { 81f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (c >= '0' && c <= '7') { 82f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int mode = c - '0'; 83f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (mode > mMode) { 84f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mMode = mode; 85f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 86f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mModeSet |= 1 << mode; 87f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 88f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 89f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } else { 90f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mMode = 7; 91f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mModeSet = 0xFF; 92f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 93f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mOctetAligned = (strcasestr(fmtp, "octet-align=1") != NULL); 94f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 95f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // TODO: handle mode-change-*. 96f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 97f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1; 98f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh} 99f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 100f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehint AmrCodec::encode(void *payload, int16_t *samples) 101f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh{ 102f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 103f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh Frame_Type_3GPP type; 104f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 105f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int length = AMREncode(mEncoder, mSidSync, (Mode)mMode, 106f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh samples, bytes + 1, &type, AMR_TX_WMF); 107f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 108f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (type != mMode || length != (8 + gFrameBits[mMode] + 7) >> 3) { 109f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 110f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 111f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 112f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (mOctetAligned) { 113f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[0] = 0xF0; 114f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[1] = (mMode << 3) | 0x04; 115f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh ++length; 116f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } else { 117f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // CMR = 15 (4-bit), F = 0 (1-bit), FT = mMode (4-bit), Q = 1 (1-bit). 118f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[0] = 0xFF; 119f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[1] = 0xC0 | (mMode << 1) | 1; 120f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 121f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // Shift left 6 bits and update the length. 122f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[length + 1] = 0; 123f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh for (int i = 0; i <= length; ++i) { 124f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[i] = (bytes[i] << 6) | (bytes[i + 1] >> 2); 125f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 126f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh length = (10 + gFrameBits[mMode] + 7) >> 3; 127f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 128f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return length; 129f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh} 130f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 131f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yehint AmrCodec::decode(int16_t *samples, void *payload, int length) 132f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh{ 133f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 134f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh Frame_Type_3GPP type; 135f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (length < 2) { 136f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 137f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 138f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh int request = bytes[0] >> 4; 139f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 140f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (mOctetAligned) { 141f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if ((bytes[1] & 0xC4) != 0x04) { 142f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 143f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 144f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh type = (Frame_Type_3GPP)(bytes[1] >> 3); 145f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (length != (16 + gFrameBits[type] + 7) >> 3) { 146f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 147f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 148f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh length -= 2; 149f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes += 2; 150f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } else { 151f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if ((bytes[0] & 0x0C) || !(bytes[1] & 0x40)) { 152f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 153f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 154f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh type = (Frame_Type_3GPP)((bytes[0] << 1 | bytes[1] >> 7) & 0x07); 155f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (length != (10 + gFrameBits[type] + 7) >> 3) { 156f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 157f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 158f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 159f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // Shift left 2 bits and update the length. 160f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh --length; 161f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh for (int i = 1; i < length; ++i) { 162f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[i] = (bytes[i] << 2) | (bytes[i + 1] >> 6); 163f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 164f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh bytes[length] <<= 2; 165f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh length = (gFrameBits[type] + 7) >> 3; 166f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh ++bytes; 167f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 168f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 169f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (AMRDecode(mDecoder, type, bytes, samples, MIME_IETF) != length) { 170f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return -1; 171f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 172f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 173f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh // Handle CMR 174f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (request < 8 && request != mMode) { 175f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh for (int i = request; i >= 0; --i) { 176f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh if (mModeSet & (1 << i)) { 177f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh mMode = request; 178f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh break; 179f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 180f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 181f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh } 182f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 183f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return 160; 184f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh} 185f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 186f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh//------------------------------------------------------------------------------ 187f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 188f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh// See RFC 3551 for the encoding details. 189f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 190f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehclass GsmEfrCodec : public AudioCodec 191f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{ 192f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehpublic: 193f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh GsmEfrCodec() { 194f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (AMREncodeInit(&mEncoder, &mSidSync, false)) { 195f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh mEncoder = NULL; 196f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 197f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) { 198f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh mDecoder = NULL; 199f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 200f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 201f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 202f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh ~GsmEfrCodec() { 203f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (mEncoder) { 204f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh AMREncodeExit(&mEncoder, &mSidSync); 205f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 206f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (mDecoder) { 207f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh GSMDecodeFrameExit(&mDecoder); 208f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 209f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 210f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 211f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh int set(int sampleRate, const char *fmtp) { 212f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1; 213f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 214f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 215f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh int encode(void *payload, int16_t *samples); 216f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh int decode(int16_t *samples, void *payload, int length); 217f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 218f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehprivate: 219f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh void *mEncoder; 220f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh void *mSidSync; 221f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh void *mDecoder; 222f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh}; 223f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 224f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehint GsmEfrCodec::encode(void *payload, int16_t *samples) 225f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{ 226f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 227f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh Frame_Type_3GPP type; 228f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 229f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh int length = AMREncode(mEncoder, mSidSync, MR122, 230f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh samples, bytes, &type, AMR_TX_WMF); 231f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 232f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (type == AMR_122 && length == 32) { 233f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh bytes[0] = 0xC0 | (bytes[1] >> 4); 234f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh for (int i = 1; i < 31; ++i) { 235f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); 236f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 237f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh return 31; 238f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 239f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh return -1; 240f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh} 241f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 242f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehint GsmEfrCodec::decode(int16_t *samples, void *payload, int length) 243f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{ 244f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 245f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (length == 31 && (bytes[0] >> 4) == 0x0C) { 246f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh for (int i = 0; i < 30; ++i) { 247f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); 248f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 249f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh bytes[30] <<= 4; 250f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 251f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) { 252f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh return 160; 253f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 254f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh } 255f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh return -1; 256f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh} 257f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 258f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh} // namespace 259f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh 260f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi YehAudioCodec *newAmrCodec() 261f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh{ 262f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh return new AmrCodec; 263f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh} 264f88fc1fa907f720df4a3e915509e688e9e4cf1f8Chia-chi Yeh 265f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi YehAudioCodec *newGsmEfrCodec() 266f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{ 267f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh return new GsmEfrCodec; 268f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh} 269