Home | History | Annotate | Download | only in test
      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
     39 enum {
     40     kInputBufferSize = 64,
     41     kSamplesPerFrame = 160,
     42     kBitsPerSample = 16,
     43     kOutputBufferSize = kSamplesPerFrame * kBitsPerSample/8,
     44     kSampleRate = 8000,
     45     kChannels = 1,
     46     kFileHeaderSize = 6
     47 };
     48 const uint32_t kFrameSizes[] = {12, 13, 15, 17, 19, 20, 26, 31};
     49 
     50 
     51 int 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