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