140 lines
3.9 KiB
C
140 lines
3.9 KiB
C
/* This file was written by Bill Cox in 2010, and is licensed under the Apache
|
|
2.0 license.
|
|
|
|
This file is meant as a simple example for how to use libsonic. It is also a
|
|
useful utility on it's own, which can speed up or slow down wav files, change
|
|
pitch, and scale volume. */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "sonic.h"
|
|
#include "wave.h"
|
|
|
|
#define BUFFER_SIZE 2048
|
|
|
|
/* Run sonic. */
|
|
static void runSonic(
|
|
waveFile inFile,
|
|
waveFile outFile,
|
|
float speed,
|
|
float pitch,
|
|
float rate,
|
|
float volume,
|
|
int emulateChordPitch,
|
|
int quality,
|
|
int sampleRate,
|
|
int numChannels)
|
|
{
|
|
sonicStream stream = sonicCreateStream(sampleRate, numChannels);
|
|
short inBuffer[BUFFER_SIZE], outBuffer[BUFFER_SIZE];
|
|
int samplesRead, samplesWritten;
|
|
|
|
sonicSetSpeed(stream, speed);
|
|
sonicSetPitch(stream, pitch);
|
|
sonicSetRate(stream, rate);
|
|
sonicSetVolume(stream, volume);
|
|
sonicSetChordPitch(stream, emulateChordPitch);
|
|
sonicSetQuality(stream, quality);
|
|
do {
|
|
samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels);
|
|
if(samplesRead == 0) {
|
|
sonicFlushStream(stream);
|
|
} else {
|
|
sonicWriteShortToStream(stream, inBuffer, samplesRead);
|
|
}
|
|
do {
|
|
samplesWritten = sonicReadShortFromStream(stream, outBuffer,
|
|
BUFFER_SIZE/numChannels);
|
|
if(samplesWritten > 0) {
|
|
writeToWaveFile(outFile, outBuffer, samplesWritten);
|
|
}
|
|
} while(samplesWritten > 0);
|
|
} while(samplesRead > 0);
|
|
sonicDestroyStream(stream);
|
|
}
|
|
|
|
/* Print the usage. */
|
|
static void usage(void)
|
|
{
|
|
fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n"
|
|
" -c -- Modify pitch by emulating vocal chords vibrating\n"
|
|
" faster or slower.\n"
|
|
" -p pitch -- Set pitch scaling factor. 1.3 means 30%% higher.\n"
|
|
" -q -- Disable speed-up heuristics. May increase quality.\n"
|
|
" -r rate -- Set playback rate. 2.0 means 2X faster, and 2X pitch.\n"
|
|
" -s speed -- Set speed up factor. 2.0 means 2X faster.\n"
|
|
" -v volume -- Scale volume by a constant factor.\n");
|
|
exit(1);
|
|
}
|
|
|
|
int main(
|
|
int argc,
|
|
char **argv)
|
|
{
|
|
waveFile inFile, outFile;
|
|
char *inFileName, *outFileName;
|
|
float speed = 1.0f;
|
|
float pitch = 1.0f;
|
|
float rate = 1.0f;
|
|
float volume = 1.0f;
|
|
int emulateChordPitch = 0;
|
|
int quality = 0;
|
|
int sampleRate, numChannels;
|
|
int xArg = 1;
|
|
|
|
while(xArg < argc && *(argv[xArg]) == '-') {
|
|
if(!strcmp(argv[xArg], "-c")) {
|
|
emulateChordPitch = 1;
|
|
printf("Scaling pitch linearly.\n");
|
|
} else if(!strcmp(argv[xArg], "-p")) {
|
|
xArg++;
|
|
if(xArg < argc) {
|
|
pitch = atof(argv[xArg]);
|
|
printf("Setting pitch to %0.2fX\n", pitch);
|
|
}
|
|
} else if(!strcmp(argv[xArg], "-q")) {
|
|
quality = 1;
|
|
printf("Disabling speed-up heuristics\n");
|
|
} else if(!strcmp(argv[xArg], "-r")) {
|
|
xArg++;
|
|
if(xArg < argc) {
|
|
rate = atof(argv[xArg]);
|
|
printf("Setting rate to %0.2fX\n", rate);
|
|
}
|
|
} else if(!strcmp(argv[xArg], "-s")) {
|
|
xArg++;
|
|
if(xArg < argc) {
|
|
speed = atof(argv[xArg]);
|
|
printf("Setting speed to %0.2fX\n", speed);
|
|
}
|
|
} else if(!strcmp(argv[xArg], "-v")) {
|
|
xArg++;
|
|
if(xArg < argc) {
|
|
volume = atof(argv[xArg]);
|
|
printf("Setting volume to %0.2f\n", volume);
|
|
}
|
|
}
|
|
xArg++;
|
|
}
|
|
if(argc - xArg != 2) {
|
|
usage();
|
|
}
|
|
inFileName = argv[xArg];
|
|
outFileName = argv[xArg + 1];
|
|
inFile = openInputWaveFile(inFileName, &sampleRate, &numChannels);
|
|
if(inFile == NULL) {
|
|
return 1;
|
|
}
|
|
outFile = openOutputWaveFile(outFileName, sampleRate, numChannels);
|
|
if(outFile == NULL) {
|
|
closeWaveFile(inFile);
|
|
return 1;
|
|
}
|
|
runSonic(inFile, outFile, speed, pitch, rate, volume, emulateChordPitch, quality,
|
|
sampleRate, numChannels);
|
|
closeWaveFile(inFile);
|
|
closeWaveFile(outFile);
|
|
return 0;
|
|
}
|