1 /* This file was written by Bill Cox in 2010, and is licensed under the Apache
2 2.0 license.
3
4 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. */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "sonic.h"
12 #include "wave.h"
13
14 #define BUFFER_SIZE 2048
15
16 /* Run sonic. */
runSonic(waveFile inFile,waveFile outFile,float speed,float pitch,float rate,float volume,int emulateChordPitch,int quality,int sampleRate,int numChannels)17 static void runSonic(
18 waveFile inFile,
19 waveFile outFile,
20 float speed,
21 float pitch,
22 float rate,
23 float volume,
24 int emulateChordPitch,
25 int quality,
26 int sampleRate,
27 int numChannels)
28 {
29 sonicStream stream = sonicCreateStream(sampleRate, numChannels);
30 short inBuffer[BUFFER_SIZE], outBuffer[BUFFER_SIZE];
31 int samplesRead, samplesWritten;
32
33 sonicSetSpeed(stream, speed);
34 sonicSetPitch(stream, pitch);
35 sonicSetRate(stream, rate);
36 sonicSetVolume(stream, volume);
37 sonicSetChordPitch(stream, emulateChordPitch);
38 sonicSetQuality(stream, quality);
39 do {
40 samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels);
41 if(samplesRead == 0) {
42 sonicFlushStream(stream);
43 } else {
44 sonicWriteShortToStream(stream, inBuffer, samplesRead);
45 }
46 do {
47 samplesWritten = sonicReadShortFromStream(stream, outBuffer,
48 BUFFER_SIZE/numChannels);
49 if(samplesWritten > 0) {
50 writeToWaveFile(outFile, outBuffer, samplesWritten);
51 }
52 } while(samplesWritten > 0);
53 } while(samplesRead > 0);
54 sonicDestroyStream(stream);
55 }
56
57 /* Print the usage. */
usage(void)58 static void usage(void)
59 {
60 fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n"
61 " -c -- Modify pitch by emulating vocal chords vibrating\n"
62 " faster or slower.\n"
63 " -p pitch -- Set pitch scaling factor. 1.3 means 30%% higher.\n"
64 " -q -- Disable speed-up heuristics. May increase quality.\n"
65 " -r rate -- Set playback rate. 2.0 means 2X faster, and 2X pitch.\n"
66 " -s speed -- Set speed up factor. 2.0 means 2X faster.\n"
67 " -v volume -- Scale volume by a constant factor.\n");
68 exit(1);
69 }
70
main(int argc,char ** argv)71 int main(
72 int argc,
73 char **argv)
74 {
75 waveFile inFile, outFile;
76 char *inFileName, *outFileName;
77 float speed = 1.0f;
78 float pitch = 1.0f;
79 float rate = 1.0f;
80 float volume = 1.0f;
81 int emulateChordPitch = 0;
82 int quality = 0;
83 int sampleRate, numChannels;
84 int xArg = 1;
85
86 while(xArg < argc && *(argv[xArg]) == '-') {
87 if(!strcmp(argv[xArg], "-c")) {
88 emulateChordPitch = 1;
89 printf("Scaling pitch linearly.\n");
90 } else if(!strcmp(argv[xArg], "-p")) {
91 xArg++;
92 if(xArg < argc) {
93 pitch = atof(argv[xArg]);
94 printf("Setting pitch to %0.2fX\n", pitch);
95 }
96 } else if(!strcmp(argv[xArg], "-q")) {
97 quality = 1;
98 printf("Disabling speed-up heuristics\n");
99 } 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 }
105 } else if(!strcmp(argv[xArg], "-s")) {
106 xArg++;
107 if(xArg < argc) {
108 speed = atof(argv[xArg]);
109 printf("Setting speed to %0.2fX\n", speed);
110 }
111 } else if(!strcmp(argv[xArg], "-v")) {
112 xArg++;
113 if(xArg < argc) {
114 volume = atof(argv[xArg]);
115 printf("Setting volume to %0.2f\n", volume);
116 }
117 }
118 xArg++;
119 }
120 if(argc - xArg != 2) {
121 usage();
122 }
123 inFileName = argv[xArg];
124 outFileName = argv[xArg + 1];
125 inFile = openInputWaveFile(inFileName, &sampleRate, &numChannels);
126 if(inFile == NULL) {
127 return 1;
128 }
129 outFile = openOutputWaveFile(outFileName, sampleRate, numChannels);
130 if(outFile == NULL) {
131 closeWaveFile(inFile);
132 return 1;
133 }
134 runSonic(inFile, outFile, speed, pitch, rate, volume, emulateChordPitch, quality,
135 sampleRate, numChannels);
136 closeWaveFile(inFile);
137 closeWaveFile(outFile);
138 return 0;
139 }
140