1ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh/* 2ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * Copyrightm (C) 2010 The Android Open Source Project 3ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * 4ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 5ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * you may not use this file except in compliance with the License. 6ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * You may obtain a copy of the License at 7ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * 8ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 9ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * 10ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 11ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 12ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * See the License for the specific language governing permissions and 14ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh * limitations under the License. 15ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh */ 16ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 172437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh#include <string.h> 182437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 19ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh#include "AudioCodec.h" 20ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 21ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh#include "gsmamr_dec.h" 22ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh#include "gsmamr_enc.h" 23ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 24ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yehnamespace { 25ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 262437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yehconst int gFrameBits[8] = {95, 103, 118, 134, 148, 159, 204, 244}; 272437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 282437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh//------------------------------------------------------------------------------ 292437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 302437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh// See RFC 4867 for the encoding details. 312437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 322437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yehclass AmrCodec : public AudioCodec 332437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh{ 342437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yehpublic: 352437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh AmrCodec() { 362437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (AMREncodeInit(&mEncoder, &mSidSync, false)) { 372437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mEncoder = NULL; 382437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 392437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) { 402437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mDecoder = NULL; 412437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 422437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 432437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 442437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh ~AmrCodec() { 452437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (mEncoder) { 462437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh AMREncodeExit(&mEncoder, &mSidSync); 472437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 482437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (mDecoder) { 492437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh GSMDecodeFrameExit(&mDecoder); 502437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 512437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 522437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 532437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int set(int sampleRate, const char *fmtp); 542437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int encode(void *payload, int16_t *samples); 55418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh int decode(int16_t *samples, int count, void *payload, int length); 562437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 572437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yehprivate: 582437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh void *mEncoder; 592437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh void *mSidSync; 602437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh void *mDecoder; 612437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 622437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int mMode; 632437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int mModeSet; 642437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bool mOctetAligned; 652437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh}; 662437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 672437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yehint AmrCodec::set(int sampleRate, const char *fmtp) 682437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh{ 692437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // These parameters are not supported. 702437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (strcasestr(fmtp, "crc=1") || strcasestr(fmtp, "robust-sorting=1") || 712437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh strcasestr(fmtp, "interleaving=")) { 722437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 732437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 742437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 752437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // Handle mode-set and octet-align. 76a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh const char *modes = strcasestr(fmtp, "mode-set="); 772437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (modes) { 782437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mMode = 0; 792437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mModeSet = 0; 802437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh for (char c = *modes; c && c != ' '; c = *++modes) { 812437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (c >= '0' && c <= '7') { 822437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int mode = c - '0'; 832437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (mode > mMode) { 842437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mMode = mode; 852437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 862437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mModeSet |= 1 << mode; 872437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 882437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 892437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } else { 902437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mMode = 7; 912437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mModeSet = 0xFF; 922437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 932437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mOctetAligned = (strcasestr(fmtp, "octet-align=1") != NULL); 942437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 952437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // TODO: handle mode-change-*. 962437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 972437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1; 982437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh} 992437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1002437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yehint AmrCodec::encode(void *payload, int16_t *samples) 1012437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh{ 1022437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 1032437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh Frame_Type_3GPP type; 1042437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1052437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int length = AMREncode(mEncoder, mSidSync, (Mode)mMode, 1062437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh samples, bytes + 1, &type, AMR_TX_WMF); 1072437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1082437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (type != mMode || length != (8 + gFrameBits[mMode] + 7) >> 3) { 1092437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1102437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1112437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1122437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (mOctetAligned) { 1132437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[0] = 0xF0; 1142437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[1] = (mMode << 3) | 0x04; 1152437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh ++length; 1162437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } else { 1172437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // CMR = 15 (4-bit), F = 0 (1-bit), FT = mMode (4-bit), Q = 1 (1-bit). 1182437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[0] = 0xFF; 1192437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[1] = 0xC0 | (mMode << 1) | 1; 1202437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1212437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // Shift left 6 bits and update the length. 1222437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[length + 1] = 0; 1232437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh for (int i = 0; i <= length; ++i) { 1242437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[i] = (bytes[i] << 6) | (bytes[i + 1] >> 2); 1252437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1262437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh length = (10 + gFrameBits[mMode] + 7) >> 3; 1272437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1282437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return length; 1292437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh} 1302437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 131418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yehint AmrCodec::decode(int16_t *samples, int count, void *payload, int length) 1322437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh{ 1332437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 1342437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh Frame_Type_3GPP type; 1352437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (length < 2) { 1362437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1372437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1382437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh int request = bytes[0] >> 4; 1392437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1402437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (mOctetAligned) { 1412437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if ((bytes[1] & 0xC4) != 0x04) { 1422437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1432437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1442437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh type = (Frame_Type_3GPP)(bytes[1] >> 3); 1452437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (length != (16 + gFrameBits[type] + 7) >> 3) { 1462437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1472437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1482437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh length -= 2; 1492437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes += 2; 1502437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } else { 1512437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if ((bytes[0] & 0x0C) || !(bytes[1] & 0x40)) { 1522437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1532437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1542437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh type = (Frame_Type_3GPP)((bytes[0] << 1 | bytes[1] >> 7) & 0x07); 1552437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (length != (10 + gFrameBits[type] + 7) >> 3) { 1562437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1572437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1582437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1592437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // Shift left 2 bits and update the length. 1602437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh --length; 1612437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh for (int i = 1; i < length; ++i) { 1622437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[i] = (bytes[i] << 2) | (bytes[i + 1] >> 6); 1632437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1642437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh bytes[length] <<= 2; 1652437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh length = (gFrameBits[type] + 7) >> 3; 1662437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh ++bytes; 1672437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1682437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1692437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (AMRDecode(mDecoder, type, bytes, samples, MIME_IETF) != length) { 1702437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return -1; 1712437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1722437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1732437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh // Handle CMR 1742437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (request < 8 && request != mMode) { 1752437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh for (int i = request; i >= 0; --i) { 1762437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh if (mModeSet & (1 << i)) { 1772437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh mMode = request; 1782437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh break; 1792437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1802437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1812437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh } 1822437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1832437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return 160; 1842437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh} 1852437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1862437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh//------------------------------------------------------------------------------ 1872437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 1882437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh// See RFC 3551 for the encoding details. 1892437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 190ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yehclass GsmEfrCodec : public AudioCodec 191ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh{ 192ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yehpublic: 193ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh GsmEfrCodec() { 194ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh if (AMREncodeInit(&mEncoder, &mSidSync, false)) { 195ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh mEncoder = NULL; 196ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 197ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) { 198ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh mDecoder = NULL; 199ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 200ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 201ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 202ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh ~GsmEfrCodec() { 203ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh if (mEncoder) { 204ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh AMREncodeExit(&mEncoder, &mSidSync); 205ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 206ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh if (mDecoder) { 207ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh GSMDecodeFrameExit(&mDecoder); 208ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 209ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 210ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 211ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh int set(int sampleRate, const char *fmtp) { 212ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1; 213ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 214ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 215ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh int encode(void *payload, int16_t *samples); 216418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh int decode(int16_t *samples, int count, void *payload, int length); 217ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 218ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yehprivate: 219ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh void *mEncoder; 220ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh void *mSidSync; 221ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh void *mDecoder; 222ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh}; 223ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 224ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yehint GsmEfrCodec::encode(void *payload, int16_t *samples) 225ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh{ 226ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 227ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh Frame_Type_3GPP type; 228ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 229ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh int length = AMREncode(mEncoder, mSidSync, MR122, 230ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh samples, bytes, &type, AMR_TX_WMF); 231ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 232ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh if (type == AMR_122 && length == 32) { 233ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh bytes[0] = 0xC0 | (bytes[1] >> 4); 234ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh for (int i = 1; i < 31; ++i) { 235ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); 236ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 237ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh return 31; 238ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 239ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh return -1; 240ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh} 241ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 242418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yehint GsmEfrCodec::decode(int16_t *samples, int count, void *payload, int length) 243ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh{ 244ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh unsigned char *bytes = (unsigned char *)payload; 245418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh int n = 0; 246418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh while (n + 160 <= count && length >= 31 && (bytes[0] >> 4) == 0x0C) { 247ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh for (int i = 0; i < 30; ++i) { 248ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); 249ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 250ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh bytes[30] <<= 4; 251ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 252418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh if (AMRDecode(mDecoder, AMR_122, bytes, &samples[n], MIME_IETF) != 31) { 253418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh break; 254ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 255418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh n += 160; 256418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh length -= 31; 257418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh bytes += 31; 258ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh } 259418b5f04c2eb3ceff046328ba23a16b89a5a3306Chia-chi Yeh return n; 260ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh} 261ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 262ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh} // namespace 263ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh 2642437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi YehAudioCodec *newAmrCodec() 2652437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh{ 2662437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh return new AmrCodec; 2672437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh} 2682437b7d03ce3c0c63ffe04e15a53174d15ee8479Chia-chi Yeh 269ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi YehAudioCodec *newGsmEfrCodec() 270ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh{ 271ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh return new GsmEfrCodec; 272ac8b0e5a92e1a9abdaa543656fba0cf52ca8d786Chia-chi Yeh} 273