AmrCodec.cpp revision f4ae94229d736c7dbd3c5c36d484213d51545702
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
17f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh#include "AudioCodec.h"
18f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
19f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh#include "gsmamr_dec.h"
20f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh#include "gsmamr_enc.h"
21f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
22f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehnamespace {
23f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
24f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehclass GsmEfrCodec : public AudioCodec
25f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{
26f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehpublic:
27f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    GsmEfrCodec() {
28f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        if (AMREncodeInit(&mEncoder, &mSidSync, false)) {
29f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            mEncoder = NULL;
30f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
31f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) {
32f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            mDecoder = NULL;
33f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
34f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    }
35f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
36f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    ~GsmEfrCodec() {
37f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        if (mEncoder) {
38f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            AMREncodeExit(&mEncoder, &mSidSync);
39f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
40f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        if (mDecoder) {
41f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            GSMDecodeFrameExit(&mDecoder);
42f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
43f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    }
44f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
45f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    int set(int sampleRate, const char *fmtp) {
46f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1;
47f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    }
48f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
49f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    int encode(void *payload, int16_t *samples);
50f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    int decode(int16_t *samples, void *payload, int length);
51f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
52f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehprivate:
53f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    void *mEncoder;
54f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    void *mSidSync;
55f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    void *mDecoder;
56f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh};
57f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
58f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehint GsmEfrCodec::encode(void *payload, int16_t *samples)
59f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{
60f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    unsigned char *bytes = (unsigned char *)payload;
61f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    Frame_Type_3GPP type;
62f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
63f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    int length = AMREncode(mEncoder, mSidSync, MR122,
64f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        samples, bytes, &type, AMR_TX_WMF);
65f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
66f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    if (type == AMR_122 && length == 32) {
67f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        bytes[0] = 0xC0 | (bytes[1] >> 4);
68f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        for (int i = 1; i < 31; ++i) {
69f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
70f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
71f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        return 31;
72f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    }
73f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    return -1;
74f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh}
75f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
76f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yehint GsmEfrCodec::decode(int16_t *samples, void *payload, int length)
77f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{
78f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    unsigned char *bytes = (unsigned char *)payload;
79f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    if (length == 31 && (bytes[0] >> 4) == 0x0C) {
80f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        for (int i = 0; i < 30; ++i) {
81f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
82f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
83f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        bytes[30] <<= 4;
84f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
85f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) {
86f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh            return 160;
87f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh        }
88f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    }
89f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    return -1;
90f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh}
91f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
92f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh} // namespace
93f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh
94f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi YehAudioCodec *newGsmEfrCodec()
95f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh{
96f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh    return new GsmEfrCodec;
97f4ae94229d736c7dbd3c5c36d484213d51545702Chia-chi Yeh}
98