1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <stdio.h> 30#include <stdint.h> 31#include <string.h> 32#include <assert.h> 33#include <stdlib.h> 34 35#include "pvamrwbdecoder.h" 36#include <audio_utils/sndfile.h> 37 38// Constants for AMR-WB. 39enum { 40 kInputBufferSize = 64, 41 kSamplesPerFrame = 320, 42 kBitsPerSample = 16, 43 kOutputBufferSize = kSamplesPerFrame * kBitsPerSample/8, 44 kSampleRate = 16000, 45 kChannels = 1, 46 kFileHeaderSize = 9, 47 kMaxSourceDataUnitSize = 477 * sizeof(int16_t) 48}; 49 50const uint32_t kFrameSizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60 }; 51 52int main(int argc, char *argv[]) { 53 54 if (argc != 3) { 55 fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]); 56 return EXIT_FAILURE; 57 } 58 59 // Open the input file. 60 FILE* fpInput = fopen(argv[1], "rb"); 61 if (fpInput == NULL) { 62 fprintf(stderr, "Could not open %s\n", argv[1]); 63 return EXIT_FAILURE; 64 } 65 66 // Validate the input AMR file. 67 char header[kFileHeaderSize]; 68 int bytesRead = fread(header, 1, kFileHeaderSize, fpInput); 69 if ((bytesRead != kFileHeaderSize) || 70 (memcmp(header, "#!AMR-WB\n", kFileHeaderSize) != 0)) { 71 fprintf(stderr, "Invalid AMR-WB file\n"); 72 fclose(fpInput); 73 return EXIT_FAILURE; 74 } 75 76 // Open the output file. 77 SF_INFO sfInfo; 78 memset(&sfInfo, 0, sizeof(SF_INFO)); 79 sfInfo.channels = kChannels; 80 sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; 81 sfInfo.samplerate = kSampleRate; 82 SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo); 83 if (handle == NULL) { 84 fprintf(stderr, "Could not create %s\n", argv[2]); 85 fclose(fpInput); 86 return EXIT_FAILURE; 87 } 88 89 // Allocate the decoder memory. 90 uint32_t memRequirements = pvDecoder_AmrWbMemRequirements(); 91 void *decoderBuf = malloc(memRequirements); 92 assert(decoderBuf != NULL); 93 94 // Create AMR-WB decoder instance. 95 void *amrHandle; 96 int16_t *decoderCookie; 97 pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie); 98 99 // Allocate input buffer. 100 uint8_t *inputBuf = (uint8_t*) malloc(kInputBufferSize); 101 assert(inputBuf != NULL); 102 103 // Allocate input sample buffer. 104 int16_t *inputSampleBuf = (int16_t*) malloc(kMaxSourceDataUnitSize); 105 assert(inputSampleBuf != NULL); 106 107 // Allocate output buffer. 108 int16_t *outputBuf = (int16_t*) malloc(kOutputBufferSize); 109 assert(outputBuf != NULL); 110 111 // Decode loop. 112 int retVal = EXIT_SUCCESS; 113 while (1) { 114 // Read mode. 115 uint8_t modeByte; 116 bytesRead = fread(&modeByte, 1, 1, fpInput); 117 if (bytesRead != 1) break; 118 int16 mode = ((modeByte >> 3) & 0x0f); 119 120 // AMR-WB file format cannot have mode 10, 11, 12 and 13. 121 if (mode >= 10 && mode <= 13) { 122 fprintf(stderr, "Encountered illegal frame type %d\n", mode); 123 retVal = EXIT_FAILURE; 124 break; 125 } 126 127 if (mode >= 9) { 128 // Produce silence for comfort noise, speech lost and no data. 129 memset(outputBuf, 0, kOutputBufferSize); 130 } else /* if (mode < 9) */ { 131 // Read rest of the frame. 132 int32_t frameSize = kFrameSizes[mode]; 133 bytesRead = fread(inputBuf, 1, frameSize, fpInput); 134 if (bytesRead != frameSize) break; 135 136 int16 frameType, frameMode; 137 RX_State_wb rx_state; 138 frameMode = mode; 139 mime_unsorting( 140 (uint8_t *)inputBuf, 141 inputSampleBuf, 142 &frameType, &frameMode, 1, &rx_state); 143 144 int16_t numSamplesOutput; 145 pvDecoder_AmrWb( 146 frameMode, inputSampleBuf, 147 outputBuf, 148 &numSamplesOutput, 149 decoderBuf, frameType, decoderCookie); 150 151 if (numSamplesOutput != kSamplesPerFrame) { 152 fprintf(stderr, "Decoder encountered error\n"); 153 retVal = EXIT_FAILURE; 154 break; 155 } 156 157 for (int i = 0; i < kSamplesPerFrame; ++i) { 158 outputBuf[i] &= 0xfffC; 159 } 160 } 161 162 // Write output to wav. 163 sf_writef_short(handle, outputBuf, kSamplesPerFrame / kChannels); 164 } 165 166 // Close input and output file. 167 fclose(fpInput); 168 sf_close(handle); 169 170 // Free allocated memory. 171 free(inputBuf); 172 free(inputSampleBuf); 173 free(outputBuf); 174 175 return retVal; 176} 177