//  -----------------------------------------------------------------------
//  Copyright 2007  Alfred Steffens Jr.
//  -----------------------------------------------------------------------
//  -----------------------------------------------------------------------
//    Copying Permission:
//
//    This is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation.
//
//    This software is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    (see file called "COPYING"); if not, write to the Free
//    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//    02111-1307  USA
//  ------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------
//
//  The following C code reads in a sound file that has be converted
//  into an ASCII data file of 3 columns: time, left data, right data
//  (you can use the Sox program to convert a WAV file into ASCII data)
//
//  Usage:
//
//      resamp  rawfile  newfile  sample_rate old_freq new_freq
//
//  example:
//
//      resamp sq440.dat sq480.dat 44100 440 480
//
//  compiling instructions:
//      gcc -o resamp resamp.c
//
//
//  To convert the wav file into an ASCII file use,
//
//      sox file.wav file.dat
//
//  and delete the first 2 lines of the resulting file.
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char sep[5] = {9, 10, 13, 32, 0};

void main(int argc, char *argv[])
{
FILE *infile=NULL, *outfile=NULL;
double Fs, base_frequency, new_frequency, freq_factor;
static char infilename[128], outfilename[128];
char *perr;
int err;
unsigned long numsamples, index;
double *leftdata=NULL, *rightdata=NULL, *timedata=NULL;
double time_inc, curr_time;


    if (argc < 6) {
        printf("ERROR: there must be 5 command-line arguments:"
            "rawfile  newfile  sample_rate old_freq new_freq\n");
        exit(1);
    }

    //
    //  command-line argument #1 is the data file with sound samples
    //
    strcpy(infilename, argv[1]);
    //
    //  command-line argument #2 is the data file to be created
    //
    strcpy(outfilename, argv[2]);
    //
    //  command-line argument #3 is the sample rate, Fs
    //
    Fs = atof(argv[3]);
    if (Fs == 0.0) {
        printf("ERROR: invalid sample rate of 0.0\n");
        exit(1);
    }
    //
    //  command-line argument #4 is the frequency of the old file
    //
    base_frequency = atof(argv[4]);
    if (base_frequency == 0.0) {
        printf("ERROR: invalid base frequency of 0.0\n");
        exit(1);
    }
    //
    //  command-line argument #5 is the desired frequency
    //
    new_frequency = atof(argv[5]);
    if (new_frequency == 0.0) {
        printf("ERROR: invalid new frequency of 0.0\n");
        exit(1);
    }

    //
    //  open the input file
    //
    infile = fopen(infilename, "r");
    if (infile == NULL) {
        printf("ERROR: cannot find input file (%s)\n", infilename);
    }


    freq_factor = new_frequency / base_frequency;


    //
    //  read input file sample-by-sample
    //  first-time thru, just see how many samples it has
    //
    numsamples = 0;
    while (feof(infile)==0) {
        static char line[256];

        //
        //  read a line from the input file
        //
        perr = fgets(line, 255, infile);
        if (perr == NULL) {

            if (feof(infile)) {
                break;
            }
            else {
                printf("ERROR: problem reading input file\n");
                goto Error;
            }

        } // if -- perr

        numsamples++;
    } // while --- feof
    fclose(infile); // reset the file
    infile = fopen(infilename, "r");
    if (infile == NULL) {
        printf("ERROR: cannot find input file (%s) the second time\n", infilename);
    }


    //
    //  allocate memory for the time samples
    //
    timedata = (double *)malloc( numsamples * sizeof(double) );
    if (timedata == NULL) {
        printf("ERROR: memory allocation of time data\n");
        goto Error;
    }
    //
    //  allocate memory for the input samples
    //
    leftdata = (double *)malloc( numsamples * sizeof(double) );
    if (leftdata == NULL) {
        printf("ERROR: memory allocation of left data\n");
        goto Error;
    }
    //
    //  allocate memory for the input samples
    //
    rightdata = (double *)malloc( numsamples * sizeof(double) );
    if (rightdata == NULL) {
        printf("ERROR: memory allocation of right data\n");
        goto Error;
    }


    //
    //  read input file sample-by-sample
    //
    index = 0;
    while (feof(infile)==0) {
        static char line[256];
        double time_value, left_value, right_value;
        char *ptok;

        //
        //  read a line from the input file
        //
        perr = fgets(line, 255, infile);
        if (perr == NULL) {

            if (feof(infile)) {
                break;
            }
            else {
                printf("ERROR: problem reading input file\n");
                exit(1);
            }

        } // if -- perr

        //
        //  file should have three columns (stereo file)
        //

        ptok = strtok(line, sep);
        if (ptok) {
            time_value = atof(ptok);
        }
        else {
            printf("ERROR: no time value at line %ld\n", index+1);
            goto Error;
        }
        ptok = strtok(NULL, sep);
        if (ptok) {
            left_value = atof(ptok);
        }
        else {
            printf("ERROR: no left value at line %ld\n", index+1);
            goto Error;
        }
        ptok = strtok(NULL, sep);
        if (ptok) {
            right_value = atof(ptok);
        }
        else {
            printf("ERROR: no right value at line %ld\n", index+1);
            goto Error;
        }

        //
        //  save the data to an array
        //
        timedata[index] = time_value;
        leftdata[index] = left_value;
        rightdata[index] = right_value;


        index++;
    } // while --- feof


    //
    //  close the input file
    //
    fclose(infile);
    infile = NULL;


    //
    //  create an output file
    //
    outfile = fopen(outfilename, "w");
    if (outfile == NULL) {
        printf("ERROR: cannot create output file (%s)\n", outfilename);
    }


    //
    //  loop thru the samples at the new frequency
    //
    time_inc = 1.0 / Fs;
    curr_time = 0.0;
    for (index=0; index < (numsamples-1); index++) {
        double slope_left, offset_left;
        double slope_right, offset_right;
        double newtime0, newtime1, newleft, newright;

        //
        //  these are the times that the samples SHOULD occur at if the
        //  file were played back at the new frequency
        //
        newtime0 = timedata[index] / freq_factor;
        newtime1 = timedata[index+1] / freq_factor;


        //
        //  equation of line through this point and the next
        //
        slope_left = (leftdata[index+1] - leftdata[index]) /
                        (newtime1 - newtime0);
        offset_left = leftdata[index] - (slope_left*newtime0);
        slope_right = (rightdata[index+1] - rightdata[index]) /
                        (newtime1 - newtime0);
        offset_right = rightdata[index] - (slope_right*newtime0);

        //
        //  interpolate between samples
        //
        while (curr_time < newtime1) {

            //
            //  calculate the new value
            //
            newleft = slope_left * curr_time + offset_left;
            newright = slope_right * curr_time + offset_right;

            //
            //  output to the new file
            //
            fprintf(outfile, "%g %g %g\n", curr_time, newleft, newright);

            curr_time += time_inc;
        }

    } // for -- index


    //
    //  close output file
    //
    fclose(outfile);

Error:

    if (timedata)
        free(timedata);
    if (leftdata)
        free(leftdata);
    if (rightdata)
        free(rightdata);
    if (infile)
        fclose(infile);
}
//---------------------------------------------------------------------------
// End   C code
//---------------------------------------------------------------------------

