Allow using standard input/output pipes for processing

This commit is contained in:
oparviai 2008-12-25 12:38:45 +00:00
parent eb4c84fb14
commit c7bbaa4dbe
5 changed files with 813 additions and 724 deletions

File diff suppressed because it is too large Load Diff

View File

@ -77,7 +77,10 @@ static const char whatText[] =
static const char usage[] =
"Usage :\n"
" soundstretch infile.wav outfile.wav [switches]\n\n"
" soundstretch infilename outfilename [switches]\n"
"\n"
"To use standard input/output pipes, give 'stdin' and 'stdout' as filenames.\n"
"\n"
"Available switches are:\n"
" -tempo=n : Change sound tempo by n percents (n=-95..+5000 %)\n"
" -pitch=n : Change sound pitch by n semitones (n=-60..+60 semitones)\n"

View File

@ -140,8 +140,6 @@ const static char dataStr[] = "data";
WavInFile::WavInFile(const char *fileName)
{
int hdrsOk;
// Try to open the file for reading
fptr = fopen(fileName, "rb");
if (fptr == NULL)
@ -153,22 +151,45 @@ WavInFile::WavInFile(const char *fileName)
throw runtime_error(msg);
}
init();
}
WavInFile::WavInFile(FILE *file)
{
// Try to open the file for reading
fptr = file;
if (!file)
{
// didn't succeed
string msg = "Error : Unable to access input stream for reading";
throw runtime_error(msg);
}
init();
}
/// Init the WAV file stream
void WavInFile::init()
{
int hdrsOk;
// assume file stream is already open
assert(fptr);
// Read the file headers
hdrsOk = readWavHeaders();
if (hdrsOk != 0)
{
// Something didn't match in the wav file headers
string msg = "File \"";
msg += fileName;
msg += "\" is corrupt or not a WAV file";
string msg = "Input file is corrupt or not a WAV file";
throw runtime_error(msg);
}
if (header.format.fixed != 1)
{
string msg = "File \"";
msg += fileName;
msg += "\" uses unsupported encoding.";
string msg = "Input file uses unsupported encoding.";
throw runtime_error(msg);
}
@ -537,6 +558,21 @@ WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int chann
}
WavOutFile::WavOutFile(FILE *file, int sampleRate, int bits, int channels)
{
bytesWritten = 0;
fptr = file;
if (fptr == NULL)
{
string msg = "Error : Unable to access output file stream.";
throw runtime_error(msg);
}
fillInHeader(sampleRate, bits, channels);
writeHeader();
}
WavOutFile::~WavOutFile()
{

View File

@ -105,6 +105,9 @@ private:
/// WAV header information
WavHeader header;
/// Init the WAV file stream
void init();
/// Read WAV file headers.
/// \return zero if all ok, nonzero if file format is invalid.
int readWavHeaders();
@ -125,6 +128,8 @@ public:
/// throws 'runtime_error' exception.
WavInFile(const char *filename);
WavInFile(FILE *file);
/// Destructor: Closes the file.
~WavInFile();
@ -222,6 +227,8 @@ public:
int channels ///< Number of channels (1=mono, 2=stereo)
);
WavOutFile(FILE *file, int sampleRate, int bits, int channels);
/// Destructor: Finalizes & closes the WAV file.
~WavOutFile();

View File

@ -49,12 +49,25 @@ using namespace std;
// Processing chunk size
#define BUFF_SIZE 2048
#if WIN32
#include <io.h>
#include <fcntl.h>
// Macro for Win32 standard input/output stream support: Sets a file stream into binary mode
#define SET_STREAM_TO_BIN_MODE(f) (_setmode(fileno(f), _O_BINARY))
#else
// Not needed for GNU environment... ?
#define SET_STREAM_TO_BIN_MODE(f) ()
#endif
static const char _helloText[] =
"\n"
" SoundStretch v%s - Written by Olli Parviainen 2001 - 2008\n"
"==================================================================\n"
"author e-mail: <oparviai@iki.fi> - WWW: http://www.surina.net/soundtouch\n"
"author e-mail: <oparviai"
"@"
"iki.fi> - WWW: http://www.surina.net/soundtouch\n"
"\n"
"This program is subject to (L)GPL license. Run \"soundstretch -license\" for\n"
"more information.\n"
@ -64,8 +77,17 @@ static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParamet
{
int bits, samplerate, channels;
// open input file...
*inFile = new WavInFile(params->inFileName);
if (strcmp(params->inFileName, "stdin") == 0)
{
// used 'stdin' as input file
SET_STREAM_TO_BIN_MODE(stdin);
*inFile = new WavInFile(stdin);
}
else
{
// open input file...
*inFile = new WavInFile(params->inFileName);
}
// ... open output file with same sound parameters
bits = (*inFile)->getNumBits();
@ -74,7 +96,15 @@ static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParamet
if (params->outFileName)
{
*outFile = new WavOutFile(params->outFileName, samplerate, bits, channels);
if (strcmp(params->outFileName, "stdout") == 0)
{
SET_STREAM_TO_BIN_MODE(stdout);
*outFile = new WavOutFile(stdout, samplerate, bits, channels);
}
else
{
*outFile = new WavOutFile(params->outFileName, samplerate, bits, channels);
}
}
else
{
@ -107,27 +137,27 @@ static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunPar
if (params->outFileName)
{
#ifdef INTEGER_SAMPLES
printf("Uses 16bit integer sample type in processing.\n\n");
fprintf(stderr, "Uses 16bit integer sample type in processing.\n\n");
#else
#ifndef FLOAT_SAMPLES
#error "Sampletype not defined"
#endif
printf("Uses 32bit floating point sample type in processing.\n\n");
fprintf(stderr, "Uses 32bit floating point sample type in processing.\n\n");
#endif
// print processing information only if outFileName given i.e. some processing will happen
printf("Processing the file with the following changes:\n");
printf(" tempo change = %+g %%\n", params->tempoDelta);
printf(" pitch change = %+g semitones\n", params->pitchDelta);
printf(" rate change = %+g %%\n\n", params->rateDelta);
printf("Working...");
fprintf(stderr, "Processing the file with the following changes:\n");
fprintf(stderr, " tempo change = %+g %%\n", params->tempoDelta);
fprintf(stderr, " pitch change = %+g semitones\n", params->pitchDelta);
fprintf(stderr, " rate change = %+g %%\n\n", params->rateDelta);
fprintf(stderr, "Working...");
}
else
{
// outFileName not given
printf("Warning: output file name missing, won't output anything.\n\n");
fprintf(stderr, "Warning: output file name missing, won't output anything.\n\n");
}
fflush(stdout);
fflush(stderr);
}
@ -194,8 +224,8 @@ static void detectBPM(WavInFile *inFile, RunParameters *params)
SAMPLETYPE sampleBuffer[BUFF_SIZE];
// detect bpm rate
printf("Detecting BPM rate...");
fflush(stdout);
fprintf(stderr, "Detecting BPM rate...");
fflush(stderr);
nChannels = inFile->getNumChannels();
@ -215,18 +245,18 @@ static void detectBPM(WavInFile *inFile, RunParameters *params)
// Now the whole song data has been analyzed. Read the resulting bpm.
bpmValue = bpm.getBpm();
printf("Done!\n");
fprintf(stderr, "Done!\n");
// rewind the file after bpm detection
inFile->rewind();
if (bpmValue > 0)
{
printf("Detected BPM rate %.1f\n\n", bpmValue);
fprintf(stderr, "Detected BPM rate %.1f\n\n", bpmValue);
}
else
{
printf("Couldn't detect BPM rate.\n\n");
fprintf(stderr, "Couldn't detect BPM rate.\n\n");
return;
}
@ -234,7 +264,7 @@ static void detectBPM(WavInFile *inFile, RunParameters *params)
{
// adjust tempo to given bpm
params->tempoDelta = (params->goalBPM / bpmValue - 1.0f) * 100.0f;
printf("The file will be converted to %.1f BPM\n\n", params->goalBPM);
fprintf(stderr, "The file will be converted to %.1f BPM\n\n", params->goalBPM);
}
}
@ -247,7 +277,7 @@ int main(const int nParams, const char *paramStr[])
RunParameters *params;
SoundTouch SoundTouch;
printf(_helloText, SoundTouch::getVersionString());
fprintf(stderr, _helloText, SoundTouch::getVersionString());
try
{
@ -275,12 +305,12 @@ int main(const int nParams, const char *paramStr[])
delete outFile;
delete params;
printf("Done!\n");
fprintf(stderr, "Done!\n");
}
catch (runtime_error &e)
{
// An exception occurred during processing, display an error message
printf("%s\n", e.what());
fprintf(stderr, "%s\n", e.what());
return -1;
}