198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat/* 298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * Copyright (C) 2014 The Android Open Source Project 398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * All rights reserved. 498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * 598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * Redistribution and use in source and binary forms, with or without 698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * modification, are permitted provided that the following conditions 798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * are met: 898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * * Redistributions of source code must retain the above copyright 998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * notice, this list of conditions and the following disclaimer. 1098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * * Redistributions in binary form must reproduce the above copyright 1198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * notice, this list of conditions and the following disclaimer in 1298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * the documentation and/or other materials provided with the 1398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * distribution. 1498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * 1598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 1898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 1998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat * SUCH DAMAGE. 2798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat */ 2898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 2998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include <stdio.h> 3098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include <stdint.h> 3198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include <string.h> 3298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include <assert.h> 3398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include <stdlib.h> 3498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 3598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include "pvamrwbdecoder.h" 3698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat#include <audio_utils/sndfile.h> 3798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 3898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat// Constants for AMR-WB. 3998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhatenum { 4098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kInputBufferSize = 64, 4198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kSamplesPerFrame = 320, 4298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kBitsPerSample = 16, 4398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kOutputBufferSize = kSamplesPerFrame * kBitsPerSample/8, 4498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kSampleRate = 16000, 4598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kChannels = 1, 4698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kFileHeaderSize = 9, 4798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat kMaxSourceDataUnitSize = 477 * sizeof(int16_t) 4898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat}; 4998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 5098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhatconst uint32_t kFrameSizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60 }; 5198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 5298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhatint main(int argc, char *argv[]) { 5398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 5498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (argc != 3) { 5598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]); 5698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat return EXIT_FAILURE; 5798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 5898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 5998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Open the input file. 6098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat FILE* fpInput = fopen(argv[1], "rb"); 6198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (fpInput == NULL) { 6298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fprintf(stderr, "Could not open %s\n", argv[1]); 6398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat return EXIT_FAILURE; 6498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 6598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 6698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Validate the input AMR file. 6798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat char header[kFileHeaderSize]; 6898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int bytesRead = fread(header, 1, kFileHeaderSize, fpInput); 6998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if ((bytesRead != kFileHeaderSize) || 7098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat (memcmp(header, "#!AMR-WB\n", kFileHeaderSize) != 0)) { 7198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fprintf(stderr, "Invalid AMR-WB file\n"); 7298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fclose(fpInput); 7398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat return EXIT_FAILURE; 7498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 7598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 7698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Open the output file. 7798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat SF_INFO sfInfo; 7898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat memset(&sfInfo, 0, sizeof(SF_INFO)); 7998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat sfInfo.channels = kChannels; 8098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; 8198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat sfInfo.samplerate = kSampleRate; 8298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo); 8398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (handle == NULL) { 8498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fprintf(stderr, "Could not create %s\n", argv[2]); 8598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fclose(fpInput); 8698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat return EXIT_FAILURE; 8798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 8898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 8998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Allocate the decoder memory. 9098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat uint32_t memRequirements = pvDecoder_AmrWbMemRequirements(); 9198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat void *decoderBuf = malloc(memRequirements); 9298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat assert(decoderBuf != NULL); 9398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 9498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Create AMR-WB decoder instance. 9598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat void *amrHandle; 9698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int16_t *decoderCookie; 9798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie); 9898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 9998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Allocate input buffer. 10098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat uint8_t *inputBuf = (uint8_t*) malloc(kInputBufferSize); 10198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat assert(inputBuf != NULL); 10298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 10398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Allocate input sample buffer. 10498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int16_t *inputSampleBuf = (int16_t*) malloc(kMaxSourceDataUnitSize); 10598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat assert(inputSampleBuf != NULL); 10698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 10798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Allocate output buffer. 10898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int16_t *outputBuf = (int16_t*) malloc(kOutputBufferSize); 10998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat assert(outputBuf != NULL); 11098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 11198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Decode loop. 11298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int retVal = EXIT_SUCCESS; 11398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat while (1) { 11498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Read mode. 11598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat uint8_t modeByte; 11698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat bytesRead = fread(&modeByte, 1, 1, fpInput); 11798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (bytesRead != 1) break; 11898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int16 mode = ((modeByte >> 3) & 0x0f); 11998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 12098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // AMR-WB file format cannot have mode 10, 11, 12 and 13. 12198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (mode >= 10 && mode <= 13) { 12298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fprintf(stderr, "Encountered illegal frame type %d\n", mode); 12398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat retVal = EXIT_FAILURE; 12498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat break; 12598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 12698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 12798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (mode >= 9) { 12898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Produce silence for comfort noise, speech lost and no data. 12998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat memset(outputBuf, 0, kOutputBufferSize); 13098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } else /* if (mode < 9) */ { 13198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Read rest of the frame. 13298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int32_t frameSize = kFrameSizes[mode]; 13398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat bytesRead = fread(inputBuf, 1, frameSize, fpInput); 13498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (bytesRead != frameSize) break; 13598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 13698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int16 frameType, frameMode; 13798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat RX_State_wb rx_state; 13898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat frameMode = mode; 13998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat mime_unsorting( 14098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat (uint8_t *)inputBuf, 14198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat inputSampleBuf, 14298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat &frameType, &frameMode, 1, &rx_state); 14398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 14498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat int16_t numSamplesOutput; 14598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat pvDecoder_AmrWb( 14698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat frameMode, inputSampleBuf, 14798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat outputBuf, 14898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat &numSamplesOutput, 14998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat decoderBuf, frameType, decoderCookie); 15098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 15198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat if (numSamplesOutput != kSamplesPerFrame) { 15298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fprintf(stderr, "Decoder encountered error\n"); 15398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat retVal = EXIT_FAILURE; 15498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat break; 15598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 15698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 15798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat for (int i = 0; i < kSamplesPerFrame; ++i) { 15898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat outputBuf[i] &= 0xfffC; 15998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 16098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 16198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 16298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Write output to wav. 16398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat sf_writef_short(handle, outputBuf, kSamplesPerFrame / kChannels); 16498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat } 16598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 16698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Close input and output file. 16798ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat fclose(fpInput); 16898ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat sf_close(handle); 16998ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 17098ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat // Free allocated memory. 17198ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat free(inputBuf); 17298ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat free(inputSampleBuf); 17398ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat free(outputBuf); 17498ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat 17598ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat return retVal; 17698ec7d4997f061e45b997b4795a153bff08101b9Ashok Bhat} 177