160eeb064f62a106069d2ce148fabd724f9df9780Bill Cox/* This file was written by Bill Cox in 2010, and is licensed under the Apache 260eeb064f62a106069d2ce148fabd724f9df9780Bill Cox 2.0 license. 3ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 49d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox This file is meant as a simple example for how to use libsonic. It is also a 59d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox useful utility on it's own, which can speed up or slow down wav files, change 69d1402171689d5b13869fe3f9d8ef753996a6fb5Bill Cox pitch, and scale volume. */ 7ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 8ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include <stdio.h> 9ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include <stdlib.h> 100e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox#include <string.h> 11ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include "sonic.h" 12ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox#include "wave.h" 13ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 141a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox#define BUFFER_SIZE 2048 15ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 16ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox/* Run sonic. */ 17ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Coxstatic void runSonic( 180c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox waveFile inFile, 190c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox waveFile outFile, 20d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox float speed, 21d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox float pitch, 223276bb0eab2af227631cd376d649ff6766b9291fBill Cox float rate, 23d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox float volume, 243276bb0eab2af227631cd376d649ff6766b9291fBill Cox int emulateChordPitch, 25c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox int quality, 261a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox int sampleRate, 271a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox int numChannels) 28ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox{ 29d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox sonicStream stream = sonicCreateStream(sampleRate, numChannels); 300c4c06089176345f408613c8da6a5585a9af9615Bill Cox short inBuffer[BUFFER_SIZE], outBuffer[BUFFER_SIZE]; 310c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox int samplesRead, samplesWritten; 32ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 33d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox sonicSetSpeed(stream, speed); 34d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox sonicSetPitch(stream, pitch); 353276bb0eab2af227631cd376d649ff6766b9291fBill Cox sonicSetRate(stream, rate); 36d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox sonicSetVolume(stream, volume); 373276bb0eab2af227631cd376d649ff6766b9291fBill Cox sonicSetChordPitch(stream, emulateChordPitch); 38c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox sonicSetQuality(stream, quality); 390c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox do { 401a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels); 410c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox if(samplesRead == 0) { 42ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox sonicFlushStream(stream); 430c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox } else { 440c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox sonicWriteShortToStream(stream, inBuffer, samplesRead); 45ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox } 46882fb1db2700b48a33c11783635e936780199840Bill Cox do { 471a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox samplesWritten = sonicReadShortFromStream(stream, outBuffer, 481a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox BUFFER_SIZE/numChannels); 490c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox if(samplesWritten > 0) { 500c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox writeToWaveFile(outFile, outBuffer, samplesWritten); 51882fb1db2700b48a33c11783635e936780199840Bill Cox } 520c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox } while(samplesWritten > 0); 530c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox } while(samplesRead > 0); 540c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox sonicDestroyStream(stream); 55ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox} 56ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 57ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox/* Print the usage. */ 58ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Coxstatic void usage(void) 59ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox{ 60c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n" 613276bb0eab2af227631cd376d649ff6766b9291fBill Cox " -c -- Modify pitch by emulating vocal chords vibrating\n" 623276bb0eab2af227631cd376d649ff6766b9291fBill Cox " faster or slower.\n" 63c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox " -p pitch -- Set pitch scaling factor. 1.3 means 30%% higher.\n" 64c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox " -q -- Disable speed-up heuristics. May increase quality.\n" 653276bb0eab2af227631cd376d649ff6766b9291fBill Cox " -r rate -- Set playback rate. 2.0 means 2X faster, and 2X pitch.\n" 66c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox " -s speed -- Set speed up factor. 2.0 means 2X faster.\n" 67c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox " -v volume -- Scale volume by a constant factor.\n"); 683a7abf9306e470963a422881af62811633fede47Bill Cox exit(1); 69ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox} 70ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 71ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Coxint main( 72ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox int argc, 73ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox char **argv) 74ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox{ 750c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox waveFile inFile, outFile; 76ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox char *inFileName, *outFileName; 773276bb0eab2af227631cd376d649ff6766b9291fBill Cox float speed = 1.0f; 783276bb0eab2af227631cd376d649ff6766b9291fBill Cox float pitch = 1.0f; 793276bb0eab2af227631cd376d649ff6766b9291fBill Cox float rate = 1.0f; 803276bb0eab2af227631cd376d649ff6766b9291fBill Cox float volume = 1.0f; 813276bb0eab2af227631cd376d649ff6766b9291fBill Cox int emulateChordPitch = 0; 82c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox int quality = 0; 831a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox int sampleRate, numChannels; 840e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox int xArg = 1; 85ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox 860e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox while(xArg < argc && *(argv[xArg]) == '-') { 873276bb0eab2af227631cd376d649ff6766b9291fBill Cox if(!strcmp(argv[xArg], "-c")) { 883276bb0eab2af227631cd376d649ff6766b9291fBill Cox emulateChordPitch = 1; 893276bb0eab2af227631cd376d649ff6766b9291fBill Cox printf("Scaling pitch linearly.\n"); 903276bb0eab2af227631cd376d649ff6766b9291fBill Cox } else if(!strcmp(argv[xArg], "-p")) { 91d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox xArg++; 92d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox if(xArg < argc) { 93d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox pitch = atof(argv[xArg]); 943276bb0eab2af227631cd376d649ff6766b9291fBill Cox printf("Setting pitch to %0.2fX\n", pitch); 95d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox } 96c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox } else if(!strcmp(argv[xArg], "-q")) { 97c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox quality = 1; 98c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox printf("Disabling speed-up heuristics\n"); 993276bb0eab2af227631cd376d649ff6766b9291fBill Cox } else if(!strcmp(argv[xArg], "-r")) { 1003276bb0eab2af227631cd376d649ff6766b9291fBill Cox xArg++; 1013276bb0eab2af227631cd376d649ff6766b9291fBill Cox if(xArg < argc) { 1023276bb0eab2af227631cd376d649ff6766b9291fBill Cox rate = atof(argv[xArg]); 1033276bb0eab2af227631cd376d649ff6766b9291fBill Cox printf("Setting rate to %0.2fX\n", rate); 1043276bb0eab2af227631cd376d649ff6766b9291fBill Cox } 105d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox } else if(!strcmp(argv[xArg], "-s")) { 1060e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox xArg++; 1070e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox if(xArg < argc) { 1080e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox speed = atof(argv[xArg]); 1093276bb0eab2af227631cd376d649ff6766b9291fBill Cox printf("Setting speed to %0.2fX\n", speed); 1100e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox } 1110e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox } else if(!strcmp(argv[xArg], "-v")) { 1120e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox xArg++; 1130e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox if(xArg < argc) { 1140e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox volume = atof(argv[xArg]); 115c978c39e1abbdf7bd650a4a74d5936fd0d2b0f0dBill Cox printf("Setting volume to %0.2f\n", volume); 1160e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox } 1170e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox } 1180e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox xArg++; 1190e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox } 120d544fdb83eee1360eedfdcbd1e24a983403bb314Bill Cox if(argc - xArg != 2) { 121ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox usage(); 122ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox } 1230e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox inFileName = argv[xArg]; 1240e4ec5e65f696f6648feeeace9adc77dd69e2532Bill Cox outFileName = argv[xArg + 1]; 1251a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox inFile = openInputWaveFile(inFileName, &sampleRate, &numChannels); 1260c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox if(inFile == NULL) { 1270c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox return 1; 1280c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox } 1291a299bb54901f02ef8cd0d9f3774e2a67b85e938Bill Cox outFile = openOutputWaveFile(outFileName, sampleRate, numChannels); 1300c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox if(outFile == NULL) { 1310c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox closeWaveFile(inFile); 1320c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox return 1; 1330c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox } 1343276bb0eab2af227631cd376d649ff6766b9291fBill Cox runSonic(inFile, outFile, speed, pitch, rate, volume, emulateChordPitch, quality, 1353276bb0eab2af227631cd376d649ff6766b9291fBill Cox sampleRate, numChannels); 1360c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox closeWaveFile(inFile); 1370c4cade6939162c0700dd5d701bf91095bcc9eddBill Cox closeWaveFile(outFile); 138ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox return 0; 139ca02d872cc6cb963d438ceae6d011bd04c658b3Bill Cox} 140