1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AmrnbDecoderTest"
19 #define OUTPUT_FILE "/data/local/tmp/amrnbDecode.out"
20 
21 #include <utils/Log.h>
22 
23 #include <audio_utils/sndfile.h>
24 #include <stdio.h>
25 
26 #include "gsmamr_dec.h"
27 
28 #include "AmrnbDecTestEnvironment.h"
29 
30 // Constants for AMR-NB
31 constexpr int32_t kInputBufferSize = 64;
32 constexpr int32_t kSamplesPerFrame = L_FRAME;
33 constexpr int32_t kBitsPerSample = 16;
34 constexpr int32_t kSampleRate = 8000;
35 constexpr int32_t kChannels = 1;
36 constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
37 const int32_t kFrameSizes[] = {12, 13, 15, 17, 19, 20, 26, 31, -1, -1, -1, -1, -1, -1, -1, -1};
38 
39 constexpr int32_t kNumFrameReset = 150;
40 
41 static AmrnbDecTestEnvironment *gEnv = nullptr;
42 
43 class AmrnbDecoderTest : public ::testing::TestWithParam<string> {
44   public:
AmrnbDecoderTest()45     AmrnbDecoderTest() : mFpInput(nullptr) {}
46 
~AmrnbDecoderTest()47     ~AmrnbDecoderTest() {
48         if (mFpInput) {
49             fclose(mFpInput);
50             mFpInput = nullptr;
51         }
52     }
53 
54     FILE *mFpInput;
55     SNDFILE *openOutputFile(SF_INFO *sfInfo);
56     int32_t DecodeFrames(void *amrHandle, SNDFILE *outFileHandle, int32_t frameCount = INT32_MAX);
57 };
58 
openOutputFile(SF_INFO * sfInfo)59 SNDFILE *AmrnbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
60     memset(sfInfo, 0, sizeof(SF_INFO));
61     sfInfo->channels = kChannels;
62     sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
63     sfInfo->samplerate = kSampleRate;
64     SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
65     return outFileHandle;
66 }
67 
DecodeFrames(void * amrHandle,SNDFILE * outFileHandle,int32_t frameCount)68 int32_t AmrnbDecoderTest::DecodeFrames(void *amrHandle, SNDFILE *outFileHandle,
69                                        int32_t frameCount) {
70     uint8_t inputBuf[kInputBufferSize];
71     int16_t outputBuf[kOutputBufferSize];
72 
73     while (frameCount > 0) {
74         uint8_t mode;
75         int32_t bytesRead = fread(&mode, 1, 1, mFpInput);
76         if (bytesRead != 1) break;
77 
78         // Find frame type
79         Frame_Type_3GPP frameType = (Frame_Type_3GPP)((mode >> 3) & 0x0f);
80         int32_t frameSize = kFrameSizes[frameType];
81         if (frameSize < 0) {
82             ALOGE("Illegal frame type");
83             return -1;
84         }
85         bytesRead = fread(inputBuf, 1, frameSize, mFpInput);
86         if (bytesRead != frameSize) break;
87 
88         int32_t bytesDecoded = AMRDecode(amrHandle, frameType, inputBuf, outputBuf, MIME_IETF);
89         if (bytesDecoded == -1) {
90             ALOGE("Failed to decode the input file");
91             return -1;
92         }
93 
94         sf_writef_short(outFileHandle, outputBuf, kSamplesPerFrame);
95         frameCount--;
96     }
97     return 0;
98 }
99 
TEST_F(AmrnbDecoderTest,CreateAmrnbDecoderTest)100 TEST_F(AmrnbDecoderTest, CreateAmrnbDecoderTest) {
101     void *amrHandle;
102     int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
103     ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
104     GSMDecodeFrameExit(&amrHandle);
105     ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
106 }
107 
TEST_P(AmrnbDecoderTest,DecodeTest)108 TEST_P(AmrnbDecoderTest, DecodeTest) {
109     string inputFile = gEnv->getRes() + GetParam();
110     mFpInput = fopen(inputFile.c_str(), "rb");
111     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
112 
113     // Open the output file.
114     SF_INFO sfInfo;
115     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
116     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
117 
118     void *amrHandle;
119     int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
120     ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
121 
122     // Decode
123     int32_t decoderErr = DecodeFrames(amrHandle, outFileHandle);
124     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
125 
126     sf_close(outFileHandle);
127     GSMDecodeFrameExit(&amrHandle);
128     ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
129 }
130 
TEST_P(AmrnbDecoderTest,ResetDecodeTest)131 TEST_P(AmrnbDecoderTest, ResetDecodeTest) {
132     string inputFile = gEnv->getRes() + GetParam();
133     mFpInput = fopen(inputFile.c_str(), "rb");
134     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
135 
136     // Open the output file.
137     SF_INFO sfInfo;
138     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
139     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
140 
141     void *amrHandle;
142     int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
143     ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
144 
145     // Decode kNumFrameReset first
146     int32_t decoderErr = DecodeFrames(amrHandle, outFileHandle, kNumFrameReset);
147     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
148 
149     status = Speech_Decode_Frame_reset(amrHandle);
150     ASSERT_EQ(status, 0) << "Error resting AMR-NB decoder";
151 
152     // Start decoding again
153     decoderErr = DecodeFrames(amrHandle, outFileHandle);
154     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
155 
156     sf_close(outFileHandle);
157     GSMDecodeFrameExit(&amrHandle);
158     ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
159 }
160 
161 INSTANTIATE_TEST_SUITE_P(AmrnbDecoderTestAll, AmrnbDecoderTest,
162                          ::testing::Values(("bbb_8000hz_1ch_8kbps_amrnb_30sec.amrnb"),
163                                            ("sine_amrnb_1ch_12kbps_8000hz.amrnb")));
164 
main(int argc,char ** argv)165 int main(int argc, char **argv) {
166     gEnv = new AmrnbDecTestEnvironment();
167     ::testing::AddGlobalTestEnvironment(gEnv);
168     ::testing::InitGoogleTest(&argc, argv);
169     int status = gEnv->initFromOptions(argc, argv);
170     if (status == 0) {
171         status = RUN_ALL_TESTS();
172         ALOGV("Test result = %d\n", status);
173     }
174     return status;
175 }
176