blob: 77829c2f3ae437ae10c0c3418f1ec0a9a98f32a0 [file] [log] [blame]
Bill Cox60eeb062015-02-27 10:17:45 -08001/* This file was written by Bill Cox in 2010, and is licensed under the Apache
2 2.0 license.
Bill Coxca02d872010-11-02 15:10:52 -04003
Bill Cox9d140212011-01-09 11:45:41 -05004 This file is meant as a simple example for how to use libsonic. It is also a
5 useful utility on it's own, which can speed up or slow down wav files, change
6 pitch, and scale volume. */
Bill Coxca02d872010-11-02 15:10:52 -04007
8#include <stdio.h>
9#include <stdlib.h>
Bill Cox0e4ec5e2010-11-09 13:26:40 -050010#include <string.h>
Bill Coxca02d872010-11-02 15:10:52 -040011#include "sonic.h"
12#include "wave.h"
13
Bill Cox1a299bb2010-11-19 15:07:17 -050014#define BUFFER_SIZE 2048
Bill Coxca02d872010-11-02 15:10:52 -040015
16/* Run sonic. */
17static void runSonic(
Bill Cox0c4cade2010-11-09 05:54:54 -050018 waveFile inFile,
19 waveFile outFile,
Bill Coxd544fdb2010-11-23 14:13:46 -050020 float speed,
21 float pitch,
Bill Cox3276bb02011-01-11 07:39:26 -050022 float rate,
Bill Coxd544fdb2010-11-23 14:13:46 -050023 float volume,
Bill Cox3276bb02011-01-11 07:39:26 -050024 int emulateChordPitch,
Bill Coxc978c392010-12-17 05:04:06 -050025 int quality,
Bill Cox1a299bb2010-11-19 15:07:17 -050026 int sampleRate,
27 int numChannels)
Bill Coxca02d872010-11-02 15:10:52 -040028{
Bill Coxd544fdb2010-11-23 14:13:46 -050029 sonicStream stream = sonicCreateStream(sampleRate, numChannels);
Bill Cox0c4c0602010-11-08 11:46:30 -050030 short inBuffer[BUFFER_SIZE], outBuffer[BUFFER_SIZE];
Bill Cox0c4cade2010-11-09 05:54:54 -050031 int samplesRead, samplesWritten;
Bill Coxca02d872010-11-02 15:10:52 -040032
Bill Coxd544fdb2010-11-23 14:13:46 -050033 sonicSetSpeed(stream, speed);
34 sonicSetPitch(stream, pitch);
Bill Cox3276bb02011-01-11 07:39:26 -050035 sonicSetRate(stream, rate);
Bill Coxd544fdb2010-11-23 14:13:46 -050036 sonicSetVolume(stream, volume);
Bill Cox3276bb02011-01-11 07:39:26 -050037 sonicSetChordPitch(stream, emulateChordPitch);
Bill Coxc978c392010-12-17 05:04:06 -050038 sonicSetQuality(stream, quality);
Bill Cox0c4cade2010-11-09 05:54:54 -050039 do {
Bill Cox1a299bb2010-11-19 15:07:17 -050040 samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels);
Bill Cox0c4cade2010-11-09 05:54:54 -050041 if(samplesRead == 0) {
Bill Coxca02d872010-11-02 15:10:52 -040042 sonicFlushStream(stream);
Bill Cox0c4cade2010-11-09 05:54:54 -050043 } else {
44 sonicWriteShortToStream(stream, inBuffer, samplesRead);
Bill Coxca02d872010-11-02 15:10:52 -040045 }
Bill Cox882fb1d2010-11-02 16:27:20 -040046 do {
Bill Cox1a299bb2010-11-19 15:07:17 -050047 samplesWritten = sonicReadShortFromStream(stream, outBuffer,
48 BUFFER_SIZE/numChannels);
Bill Cox0c4cade2010-11-09 05:54:54 -050049 if(samplesWritten > 0) {
50 writeToWaveFile(outFile, outBuffer, samplesWritten);
Bill Cox882fb1d2010-11-02 16:27:20 -040051 }
Bill Cox0c4cade2010-11-09 05:54:54 -050052 } while(samplesWritten > 0);
53 } while(samplesRead > 0);
54 sonicDestroyStream(stream);
Bill Coxca02d872010-11-02 15:10:52 -040055}
56
57/* Print the usage. */
58static void usage(void)
59{
Bill Coxc978c392010-12-17 05:04:06 -050060 fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n"
Bill Cox3276bb02011-01-11 07:39:26 -050061 " -c -- Modify pitch by emulating vocal chords vibrating\n"
62 " faster or slower.\n"
Bill Coxc978c392010-12-17 05:04:06 -050063 " -p pitch -- Set pitch scaling factor. 1.3 means 30%% higher.\n"
64 " -q -- Disable speed-up heuristics. May increase quality.\n"
Bill Cox3276bb02011-01-11 07:39:26 -050065 " -r rate -- Set playback rate. 2.0 means 2X faster, and 2X pitch.\n"
Bill Coxc978c392010-12-17 05:04:06 -050066 " -s speed -- Set speed up factor. 2.0 means 2X faster.\n"
67 " -v volume -- Scale volume by a constant factor.\n");
Bill Cox3a7abf92010-11-06 15:18:49 -040068 exit(1);
Bill Coxca02d872010-11-02 15:10:52 -040069}
70
71int main(
72 int argc,
73 char **argv)
74{
Bill Cox0c4cade2010-11-09 05:54:54 -050075 waveFile inFile, outFile;
Bill Coxca02d872010-11-02 15:10:52 -040076 char *inFileName, *outFileName;
Bill Cox3276bb02011-01-11 07:39:26 -050077 float speed = 1.0f;
78 float pitch = 1.0f;
79 float rate = 1.0f;
80 float volume = 1.0f;
81 int emulateChordPitch = 0;
Bill Coxc978c392010-12-17 05:04:06 -050082 int quality = 0;
Bill Cox1a299bb2010-11-19 15:07:17 -050083 int sampleRate, numChannels;
Bill Cox0e4ec5e2010-11-09 13:26:40 -050084 int xArg = 1;
Bill Coxca02d872010-11-02 15:10:52 -040085
Bill Cox0e4ec5e2010-11-09 13:26:40 -050086 while(xArg < argc && *(argv[xArg]) == '-') {
Bill Cox3276bb02011-01-11 07:39:26 -050087 if(!strcmp(argv[xArg], "-c")) {
88 emulateChordPitch = 1;
89 printf("Scaling pitch linearly.\n");
90 } else if(!strcmp(argv[xArg], "-p")) {
Bill Coxd544fdb2010-11-23 14:13:46 -050091 xArg++;
92 if(xArg < argc) {
93 pitch = atof(argv[xArg]);
Bill Cox3276bb02011-01-11 07:39:26 -050094 printf("Setting pitch to %0.2fX\n", pitch);
Bill Coxd544fdb2010-11-23 14:13:46 -050095 }
Bill Coxc978c392010-12-17 05:04:06 -050096 } else if(!strcmp(argv[xArg], "-q")) {
Bill Coxc978c392010-12-17 05:04:06 -050097 quality = 1;
98 printf("Disabling speed-up heuristics\n");
Bill Cox3276bb02011-01-11 07:39:26 -050099 } else if(!strcmp(argv[xArg], "-r")) {
100 xArg++;
101 if(xArg < argc) {
102 rate = atof(argv[xArg]);
103 printf("Setting rate to %0.2fX\n", rate);
104 }
Bill Coxd544fdb2010-11-23 14:13:46 -0500105 } else if(!strcmp(argv[xArg], "-s")) {
Bill Cox0e4ec5e2010-11-09 13:26:40 -0500106 xArg++;
107 if(xArg < argc) {
108 speed = atof(argv[xArg]);
Bill Cox3276bb02011-01-11 07:39:26 -0500109 printf("Setting speed to %0.2fX\n", speed);
Bill Cox0e4ec5e2010-11-09 13:26:40 -0500110 }
111 } else if(!strcmp(argv[xArg], "-v")) {
112 xArg++;
113 if(xArg < argc) {
Bill Cox0e4ec5e2010-11-09 13:26:40 -0500114 volume = atof(argv[xArg]);
Bill Coxc978c392010-12-17 05:04:06 -0500115 printf("Setting volume to %0.2f\n", volume);
Bill Cox0e4ec5e2010-11-09 13:26:40 -0500116 }
117 }
118 xArg++;
119 }
Bill Coxd544fdb2010-11-23 14:13:46 -0500120 if(argc - xArg != 2) {
Bill Coxca02d872010-11-02 15:10:52 -0400121 usage();
122 }
Bill Cox0e4ec5e2010-11-09 13:26:40 -0500123 inFileName = argv[xArg];
124 outFileName = argv[xArg + 1];
Bill Cox1a299bb2010-11-19 15:07:17 -0500125 inFile = openInputWaveFile(inFileName, &sampleRate, &numChannels);
Bill Cox0c4cade2010-11-09 05:54:54 -0500126 if(inFile == NULL) {
127 return 1;
128 }
Bill Cox1a299bb2010-11-19 15:07:17 -0500129 outFile = openOutputWaveFile(outFileName, sampleRate, numChannels);
Bill Cox0c4cade2010-11-09 05:54:54 -0500130 if(outFile == NULL) {
131 closeWaveFile(inFile);
132 return 1;
133 }
Bill Cox3276bb02011-01-11 07:39:26 -0500134 runSonic(inFile, outFile, speed, pitch, rate, volume, emulateChordPitch, quality,
135 sampleRate, numChannels);
Bill Cox0c4cade2010-11-09 05:54:54 -0500136 closeWaveFile(inFile);
137 closeWaveFile(outFile);
Bill Coxca02d872010-11-02 15:10:52 -0400138 return 0;
139}