main.c revision 9d1402171689d5b13869fe3f9d8ef753996a6fb5
19d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox/* This file, main.c, was written by Bill Cox in 2010, and placed into the public domain.
29d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox   Feel free to copy and paste code from this file into your application.  Note,
39d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox   however, that the other source files, sonic.c and sonic.h, are LGPL.
4ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
59d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox   This file is meant as a simple example for how to use libsonic.  It is also a
69d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox   useful utility on it's own, which can speed up or slow down wav files, change
79d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox   pitch, and scale volume. */
8ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
9ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include <stdio.h>
10ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include <stdlib.h>
110e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox#include <string.h>
12ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include "sonic.h"
13ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include "wave.h"
14ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
151a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox#define BUFFER_SIZE 2048
16ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
17ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox/* Run sonic. */
18ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Coxstatic void runSonic(
190c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    waveFile inFile,
200c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    waveFile outFile,
21d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    float speed,
22d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    float pitch,
23d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    float volume,
24c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox    int quality,
251a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox    int sampleRate,
261a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox    int numChannels)
27ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox{
28d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    sonicStream stream = sonicCreateStream(sampleRate, numChannels);
290c4c06089176345f408613c8da6a5585a9af9615Bill Cox    short inBuffer[BUFFER_SIZE], outBuffer[BUFFER_SIZE];
300c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    int samplesRead, samplesWritten;
31ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
32d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    sonicSetSpeed(stream, speed);
33d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    sonicSetPitch(stream, pitch);
34d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    sonicSetVolume(stream, volume);
35c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox    sonicSetQuality(stream, quality);
360c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    do {
371a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox        samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels);
380c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	if(samplesRead == 0) {
39ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox	    sonicFlushStream(stream);
400c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	} else {
410c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	    sonicWriteShortToStream(stream, inBuffer, samplesRead);
42ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox	}
43882fb1db2700b48a33c11783635e936780199840Bill Cox	do {
441a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox	    samplesWritten = sonicReadShortFromStream(stream, outBuffer,
451a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox	        BUFFER_SIZE/numChannels);
460c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	    if(samplesWritten > 0) {
470c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox		writeToWaveFile(outFile, outBuffer, samplesWritten);
48882fb1db2700b48a33c11783635e936780199840Bill Cox	    }
490c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	} while(samplesWritten > 0);
500c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    } while(samplesRead > 0);
510c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    sonicDestroyStream(stream);
52ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox}
53ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
54ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox/* Print the usage. */
55ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Coxstatic void usage(void)
56ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox{
57c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox    fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n"
58c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox        "    -p pitch   -- Set pitch scaling factor.  1.3 means 30%% higher.\n"
59c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox        "    -q         -- Disable speed-up heuristics.  May increase quality.\n"
60c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox        "    -s speed   -- Set speed up factor.  2.0 means 2X faster.\n"
61c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox	"    -v volume  -- Scale volume by a constant factor.\n");
623a7abf9306e470963a422881af62811633fede47Bill Cox    exit(1);
63ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox}
64ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
65ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Coxint main(
66ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox    int argc,
67ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox    char **argv)
68ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox{
690c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    waveFile inFile, outFile;
70ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox    char *inFileName, *outFileName;
71d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    float speed = 1.0;
72d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    float pitch = 1.0;
73d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    float volume = 1.0;
74c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox    int quality = 0;
751a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox    int sampleRate, numChannels;
760e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox    int xArg = 1;
77ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox
78d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    if(argc < 2 || *(argv[xArg]) != '-') {
79d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	fprintf(stderr, "You must provide at least one option to change speed,"
80d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	    "pitch, or volume.\n");
81d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	usage();
82d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	return 1;
83d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    }
840e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox    while(xArg < argc && *(argv[xArg]) == '-') {
85d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	if(!strcmp(argv[xArg], "-p")) {
86d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	    xArg++;
87d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	    if(xArg < argc) {
88d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	        pitch = atof(argv[xArg]);
89d76d222882a9e098d148278592d155842326909bBill Cox                printf("Setting pitch to %0.2f%%\n", pitch*100.0f);
90d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	    }
91c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox	} else if(!strcmp(argv[xArg], "-q")) {
92c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox	    quality = 1;
93c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox	    printf("Disabling speed-up heuristics\n");
94d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox	} else if(!strcmp(argv[xArg], "-s")) {
950e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	    xArg++;
960e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	    if(xArg < argc) {
970e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	        speed = atof(argv[xArg]);
98d76d222882a9e098d148278592d155842326909bBill Cox                printf("Setting speed to %0.2f%%\n", speed*100.0f);
990e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	    }
1000e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	} else if(!strcmp(argv[xArg], "-v")) {
1010e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	    xArg++;
1020e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	    if(xArg < argc) {
1030e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	        volume = atof(argv[xArg]);
104c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox                printf("Setting volume to %0.2f\n", volume);
1050e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	    }
1060e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	}
1070e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox	xArg++;
1080e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox    }
109d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox    if(argc - xArg != 2) {
110ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox	usage();
111ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox    }
1120e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox    inFileName = argv[xArg];
1130e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox    outFileName = argv[xArg + 1];
1141a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox    inFile = openInputWaveFile(inFileName, &sampleRate, &numChannels);
1150c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    if(inFile == NULL) {
1160c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	return 1;
1170c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    }
1181a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox    outFile = openOutputWaveFile(outFileName, sampleRate, numChannels);
1190c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    if(outFile == NULL) {
1200c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	closeWaveFile(inFile);
1210c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox	return 1;
1220c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    }
123c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox    runSonic(inFile, outFile, speed, pitch, volume, quality, sampleRate, numChannels);
1240c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    closeWaveFile(inFile);
1250c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox    closeWaveFile(outFile);
126ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox    return 0;
127ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox}
128