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 <malloc.h> 30#include <stdio.h> 31#include <stdint.h> 32#include <string.h> 33#include <assert.h> 34 35#include "gsmamr_dec.h" 36#include <audio_utils/sndfile.h> 37 38// Constants for AMR-NB 39enum { 40 kInputBufferSize = 64, 41 kSamplesPerFrame = 160, 42 kBitsPerSample = 16, 43 kOutputBufferSize = kSamplesPerFrame * kBitsPerSample/8, 44 kSampleRate = 8000, 45 kChannels = 1, 46 kFileHeaderSize = 6 47}; 48const uint32_t kFrameSizes[] = {12, 13, 15, 17, 19, 20, 26, 31}; 49 50 51int main(int argc, char *argv[]) { 52 53 if(argc != 3) { 54 fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]); 55 return 1; 56 } 57 58 // Open the input file 59 FILE* fpInput = fopen(argv[1], "rb"); 60 if (!fpInput) { 61 fprintf(stderr, "Could not open %s\n", argv[1]); 62 return 1; 63 } 64 65 // Validate the input AMR file 66 char header[kFileHeaderSize]; 67 int bytesRead = fread(header, 1, kFileHeaderSize, fpInput); 68 if (bytesRead != kFileHeaderSize || memcmp(header, "#!AMR\n", kFileHeaderSize)) { 69 fprintf(stderr, "Invalid AMR-NB file\n"); 70 return 1; 71 } 72 73 // Open the output file 74 SF_INFO sfInfo; 75 memset(&sfInfo, 0, sizeof(SF_INFO)); 76 sfInfo.channels = kChannels; 77 sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; 78 sfInfo.samplerate = kSampleRate; 79 SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo); 80 if(!handle){ 81 fprintf(stderr, "Could not create %s\n", argv[2]); 82 return 1; 83 } 84 85 // Create AMR-NB decoder instance 86 void* amrHandle; 87 int err = GSMInitDecode(&amrHandle, (Word8*)"AMRNBDecoder"); 88 if(err != 0){ 89 fprintf(stderr, "Error creating AMR-NB decoder instance\n"); 90 return 1; 91 } 92 93 //Allocate input buffer 94 void *inputBuf = malloc(kInputBufferSize); 95 assert(inputBuf != NULL); 96 97 //Allocate output buffer 98 void *outputBuf = malloc(kOutputBufferSize); 99 assert(outputBuf != NULL); 100 101 102 // Decode loop 103 uint32_t retVal = 0; 104 while (1) { 105 // Read mode 106 uint8_t mode; 107 bytesRead = fread(&mode, 1, 1, fpInput); 108 if (bytesRead != 1) break; 109 110 // Find frame type 111 Frame_Type_3GPP frameType = (Frame_Type_3GPP)((mode >> 3) & 0x0f); 112 if (frameType >= AMR_SID){ 113 fprintf(stderr, "Frame type %d not supported\n",frameType); 114 retVal = 1; 115 break; 116 } 117 118 // Find frame type 119 int32_t frameSize = kFrameSizes[frameType]; 120 bytesRead = fread(inputBuf, 1, frameSize, fpInput); 121 if (bytesRead != frameSize) break; 122 123 //Decode frame 124 int32_t decodeStatus; 125 decodeStatus = AMRDecode(amrHandle, frameType, (uint8_t*)inputBuf, 126 (int16_t*)outputBuf, MIME_IETF); 127 if(decodeStatus == -1) { 128 fprintf(stderr, "Decoder encountered error\n"); 129 retVal = 1; 130 break; 131 } 132 133 //Write output to wav 134 sf_writef_short(handle, (int16_t*)outputBuf, kSamplesPerFrame); 135 136 } 137 138 // Close input and output file 139 fclose(fpInput); 140 sf_close(handle); 141 142 //Free allocated memory 143 free(inputBuf); 144 free(outputBuf); 145 146 // Close decoder instance 147 GSMDecodeFrameExit(&amrHandle); 148 149 return retVal; 150} 151