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