/* This file was written by Bill Cox in 2010, and is licensed under the Apache
   2.0 license.

   This file is meant as a simple example for how to use libsonic.  It is also a
   useful utility on it's own, which can speed up or slow down wav files, change
   pitch, and scale volume. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sonic.h"
#include "wave.h"

#define BUFFER_SIZE 2048

/* Run sonic. */
static void runSonic(
    waveFile inFile,
    waveFile outFile,
    float speed,
    float pitch,
    float rate,
    float volume,
    int emulateChordPitch,
    int quality,
    int sampleRate,
    int numChannels)
{
    sonicStream stream = sonicCreateStream(sampleRate, numChannels);
    short inBuffer[BUFFER_SIZE], outBuffer[BUFFER_SIZE];
    int samplesRead, samplesWritten;

    sonicSetSpeed(stream, speed);
    sonicSetPitch(stream, pitch);
    sonicSetRate(stream, rate);
    sonicSetVolume(stream, volume);
    sonicSetChordPitch(stream, emulateChordPitch);
    sonicSetQuality(stream, quality);
    do {
        samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels);
	if(samplesRead == 0) {
	    sonicFlushStream(stream);
	} else {
	    sonicWriteShortToStream(stream, inBuffer, samplesRead);
	}
	do {
	    samplesWritten = sonicReadShortFromStream(stream, outBuffer,
	        BUFFER_SIZE/numChannels);
	    if(samplesWritten > 0) {
		writeToWaveFile(outFile, outBuffer, samplesWritten);
	    }
	} while(samplesWritten > 0);
    } while(samplesRead > 0);
    sonicDestroyStream(stream);
}

/* Print the usage. */
static void usage(void)
{
    fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n"
        "    -c         -- Modify pitch by emulating vocal chords vibrating\n"
	"                  faster or slower.\n"
        "    -p pitch   -- Set pitch scaling factor.  1.3 means 30%% higher.\n"
        "    -q         -- Disable speed-up heuristics.  May increase quality.\n"
        "    -r rate    -- Set playback rate.  2.0 means 2X faster, and 2X pitch.\n"
        "    -s speed   -- Set speed up factor.  2.0 means 2X faster.\n"
	"    -v volume  -- Scale volume by a constant factor.\n");
    exit(1);
}

int main(
    int argc,
    char **argv)
{
    waveFile inFile, outFile;
    char *inFileName, *outFileName;
    float speed = 1.0f;
    float pitch = 1.0f;
    float rate = 1.0f;
    float volume = 1.0f;
    int emulateChordPitch = 0;
    int quality = 0;
    int sampleRate, numChannels;
    int xArg = 1;

    while(xArg < argc && *(argv[xArg]) == '-') {
	if(!strcmp(argv[xArg], "-c")) {
	    emulateChordPitch = 1;
	    printf("Scaling pitch linearly.\n");
	} else if(!strcmp(argv[xArg], "-p")) {
	    xArg++;
	    if(xArg < argc) {
	        pitch = atof(argv[xArg]);
                printf("Setting pitch to %0.2fX\n", pitch);
	    }
	} else if(!strcmp(argv[xArg], "-q")) {
	    quality = 1;
	    printf("Disabling speed-up heuristics\n");
	} else if(!strcmp(argv[xArg], "-r")) {
	    xArg++;
	    if(xArg < argc) {
	        rate = atof(argv[xArg]);
                printf("Setting rate to %0.2fX\n", rate);
	    }
	} else if(!strcmp(argv[xArg], "-s")) {
	    xArg++;
	    if(xArg < argc) {
	        speed = atof(argv[xArg]);
                printf("Setting speed to %0.2fX\n", speed);
	    }
	} else if(!strcmp(argv[xArg], "-v")) {
	    xArg++;
	    if(xArg < argc) {
	        volume = atof(argv[xArg]);
                printf("Setting volume to %0.2f\n", volume);
	    }
	}
	xArg++;
    }
    if(argc - xArg != 2) {
	usage();
    }
    inFileName = argv[xArg];
    outFileName = argv[xArg + 1];
    inFile = openInputWaveFile(inFileName, &sampleRate, &numChannels);
    if(inFile == NULL) {
	return 1;
    }
    outFile = openOutputWaveFile(outFileName, sampleRate, numChannels);
    if(outFile == NULL) {
	closeWaveFile(inFile);
	return 1;
    }
    runSonic(inFile, outFile, speed, pitch, rate, volume, emulateChordPitch, quality,
        sampleRate, numChannels);
    closeWaveFile(inFile);
    closeWaveFile(outFile);
    return 0;
}