C-Sound-File-Programs / Sound File Programs GH / remvocals.c
remvocals.c
Raw
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include <ar.h>

#define HEADER_SIZE 44 // header of a .wav is 44 bytes as short

/* Removes vocals from a .wav file (specified by argv[1] through command-line),
   and saves the altered version as a .wav file whose name is
   specified by argv[2] */
int main(int argc, char *argv[]) {
    char *input_name, *output_name; // provided input/output file names
    FILE *input_wav, *output_wav;
    short sample[2]; // stores subsequent left and right speaker samples of a stereo PCM .wav file
    short header[HEADER_SIZE]; // stores header info that is 44 bytes in an array
    int error; // stores error code return values as part of error-checking

    // if user inputs incorrect # of arguments
    if (argc != 3) {
        fprintf(stderr, "Correct usage should be: %s input_file output_file\n", argv[0]);
        return 1;
    }

    input_name = argv[1];
    output_name = argv[2];

    // check if input/output files exist and are in proper format
    input_wav = fopen(input_name, "rb");
    if (input_wav == NULL) {
        fprintf(stderr, "Error: unable to open input file\n");
        return 2;
    }

    output_wav = fopen(output_name, "wb");
    if (output_wav == NULL) {
        fprintf(stderr, "Error: unable to open output file\n");
        return 2;
    }

    // read the header from the input .wav and store in header array
    fread(header, HEADER_SIZE, 1, input_wav);
    // copying the same header to output file
    error = fwrite(header, HEADER_SIZE, 1, output_wav);
    if (error != 1) {
        fprintf(stderr, "Error: unable to write the full header\n");
        return 3;
    }

    /* now we move onto the actual file data past the header, here we read two samples
    at a time because we are expecting stereo .wav files, the first sample corresponds
    to left speaker while second to right */
    while (fread(sample, sizeof(short), 2, input_wav) == 2) {
        // computation to remove all that is 'in common' between both speakers to ideally remove vocals
        short combined = (sample[0] - sample[1]) / 2;

        // write two copies of combined to the output file
        error = fwrite(&combined, sizeof(short), 1, output_wav);
        if (error != 1) {
            fprintf(stderr, "Error: could not write samples\n");
            return 4;
        }
        error = fwrite(&combined, sizeof(short), 1, output_wav);
        if (error != 1) {
            fprintf(stderr, "Error: could not write samples\n");
            return 4;
        }
    }

    // close files after use and error-check
    error = fclose(input_wav);
    if (error != 0) {
        fprintf(stderr, "Error: fclose failed to close input file\n");
        return 5;
    }

    error = fclose(output_wav);
    if (error != 0) {
        fprintf(stderr, "Error: fclose failed to close output file\n");
        return 5;
    }

    return 0;
}