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 <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.
     39 enum {
     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 
     50 const uint32_t kFrameSizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60 };
     51 
     52 int 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