13508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat/*
23508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * Copyright (C) 2014 The Android Open Source Project
33508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * All rights reserved.
43508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *
53508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * Redistribution and use in source and binary forms, with or without
63508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * modification, are permitted provided that the following conditions
73508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * are met:
83508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *  * Redistributions of source code must retain the above copyright
93508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *    notice, this list of conditions and the following disclaimer.
103508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *  * Redistributions in binary form must reproduce the above copyright
113508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *    notice, this list of conditions and the following disclaimer in
123508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *    the documentation and/or other materials provided with the
133508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *    distribution.
143508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat *
153508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
183508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
193508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
203508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
213508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
223508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
233508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
243508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
253508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
263508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat * SUCH DAMAGE.
273508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat */
283508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
293508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include <stdlib.h>
303508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include <stdio.h>
313508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include <assert.h>
323508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include <string.h>
333508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
343508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include "pvmp3decoder_api.h"
353508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include "mp3reader.h"
363508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat#include <audio_utils/sndfile.h>
373508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
383508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhatusing namespace std;
393508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
403508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhatenum {
413508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    kInputBufferSize = 10 * 1024,
423508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    kOutputBufferSize = 4608 * 2,
433508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat};
443508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
453508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhatint main(int argc, const char **argv) {
463508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
473508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    if (argc != 3) {
483508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]);
493508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        return EXIT_FAILURE;
503508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    }
513508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
523508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Initialize the config.
533508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    tPVMP3DecoderExternal config;
543508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    config.equalizerType = flat;
553508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    config.crcEnabled = false;
563508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
573508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Allocate the decoder memory.
583508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    uint32_t memRequirements = pvmp3_decoderMemRequirements();
593508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    void *decoderBuf = malloc(memRequirements);
603508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    assert(decoderBuf != NULL);
613508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
623508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Initialize the decoder.
633508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    pvmp3_InitDecoder(&config, decoderBuf);
643508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
653508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Open the input file.
663508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    Mp3Reader mp3Reader;
673508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    bool success = mp3Reader.init(argv[1]);
683508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    if (!success) {
693508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        fprintf(stderr, "Encountered error reading %s\n", argv[1]);
703508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        free(decoderBuf);
713508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        return EXIT_FAILURE;
723508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    }
733508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
743508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Open the output file.
753508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    SF_INFO sfInfo;
763508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    memset(&sfInfo, 0, sizeof(SF_INFO));
773508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    sfInfo.channels = mp3Reader.getNumChannels();
783508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
793508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    sfInfo.samplerate = mp3Reader.getSampleRate();
803508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo);
813508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    if (handle == NULL) {
823508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        fprintf(stderr, "Encountered error writing %s\n", argv[2]);
833508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        mp3Reader.close();
843508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        free(decoderBuf);
853508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        return EXIT_FAILURE;
863508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    }
873508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
883508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Allocate input buffer.
893508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    uint8_t *inputBuf = static_cast<uint8_t*>(malloc(kInputBufferSize));
903508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    assert(inputBuf != NULL);
913508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
923508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Allocate output buffer.
933508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    int16_t *outputBuf = static_cast<int16_t*>(malloc(kOutputBufferSize));
943508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    assert(outputBuf != NULL);
953508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
963508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Decode loop.
973508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    int retVal = EXIT_SUCCESS;
983508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    while (1) {
993508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        // Read input from the file.
1003508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        uint32_t bytesRead;
1013508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        bool success = mp3Reader.getFrame(inputBuf, &bytesRead);
1023508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        if (!success) break;
1033508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
1043508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        // Set the input config.
1053508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        config.inputBufferCurrentLength = bytesRead;
1063508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        config.inputBufferMaxLength = 0;
1073508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        config.inputBufferUsedLength = 0;
1083508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        config.pInputBuffer = inputBuf;
1093508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        config.pOutputBuffer = outputBuf;
1103508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        config.outputFrameSize = kOutputBufferSize / sizeof(int16_t);
1113508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
1123508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        ERROR_CODE decoderErr;
1133508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        decoderErr = pvmp3_framedecoder(&config, decoderBuf);
1143508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        if (decoderErr != NO_DECODING_ERROR) {
1153508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat            fprintf(stderr, "Decoder encountered error\n");
1163508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat            retVal = EXIT_FAILURE;
1173508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat            break;
1183508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        }
1193508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat        sf_writef_short(handle, outputBuf,
1203508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat                        config.outputFrameSize / sfInfo.channels);
1213508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    }
1223508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
1233508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Close input reader and output writer.
1243508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    mp3Reader.close();
1253508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    sf_close(handle);
1263508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
1273508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    // Free allocated memory.
1283508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    free(inputBuf);
1293508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    free(outputBuf);
1303508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    free(decoderBuf);
1313508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat
1323508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat    return retVal;
1333508d77cf7b619d33d236533a45eea1a7321cc5aAshok Bhat}
134