mirror of
https://github.com/thestk/stk
synced 2026-01-11 12:01:52 +00:00
129 lines
3.5 KiB
C++
129 lines
3.5 KiB
C++
/******************************************/
|
|
/*
|
|
Example program to play an N channel
|
|
soundfile.
|
|
|
|
This program will load WAV, SND, AIF, and
|
|
MAT-file formatted files of various data
|
|
types. If the audio system does not support
|
|
the number of channels or sample rate of
|
|
the soundfile, the program will stop.
|
|
|
|
By Gary P. Scavone, 2000 - 2004.
|
|
*/
|
|
/******************************************/
|
|
|
|
#include "FileWvIn.h"
|
|
#include "RtAudio.h"
|
|
|
|
#include <signal.h>
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
|
|
using namespace stk;
|
|
|
|
// Eewww ... global variables! :-)
|
|
bool done = false;
|
|
StkFrames frames;
|
|
static void finish(int ignore){ done = true; }
|
|
|
|
void usage(void) {
|
|
// Error function in case of incorrect command-line
|
|
// argument specifications.
|
|
std::cout << "\nuseage: play file sr <rate>\n";
|
|
std::cout << " where file = the file to play,\n";
|
|
std::cout << " where sr = sample rate,\n";
|
|
std::cout << " and rate = an optional playback rate.\n";
|
|
std::cout << " (default = 1.0, can be negative)\n\n";
|
|
exit( 0 );
|
|
}
|
|
|
|
// This tick() function handles sample computation only. It will be
|
|
// called automatically when the system needs a new buffer of audio
|
|
// samples.
|
|
int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
|
|
double streamTime, RtAudioStreamStatus status, void *userData )
|
|
{
|
|
FileWvIn *input = (FileWvIn *) userData;
|
|
StkFloat *samples = (StkFloat *) outputBuffer;
|
|
|
|
input->tick( frames );
|
|
|
|
for ( unsigned int i=0; i<frames.size(); i++ ) {
|
|
*samples++ = frames[i];
|
|
if ( input->channelsOut() == 1 ) *samples++ = frames[i]; // play mono files in stereo
|
|
}
|
|
|
|
if ( input->isFinished() ) {
|
|
done = true;
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
// Minimal command-line checking.
|
|
if ( argc < 3 || argc > 4 ) usage();
|
|
|
|
// Set the global sample rate before creating class instances.
|
|
Stk::setSampleRate( (StkFloat) atof( argv[2] ) );
|
|
|
|
// Initialize our WvIn and RtAudio pointers.
|
|
RtAudio dac;
|
|
FileWvIn input;
|
|
|
|
// Try to load the soundfile.
|
|
try {
|
|
input.openFile( argv[1] );
|
|
}
|
|
catch ( StkError & ) {
|
|
exit( 1 );
|
|
}
|
|
|
|
// Set input read rate based on the default STK sample rate.
|
|
double rate = 1.0;
|
|
rate = input.getFileRate() / Stk::sampleRate();
|
|
if ( argc == 4 ) rate *= atof( argv[3] );
|
|
input.setRate( rate );
|
|
|
|
input.ignoreSampleRateChange();
|
|
|
|
// Find out how many channels we have.
|
|
int channels = input.channelsOut();
|
|
|
|
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
|
|
RtAudio::StreamParameters parameters;
|
|
parameters.deviceId = dac.getDefaultOutputDevice();
|
|
parameters.nChannels = ( channels == 1 ) ? 2 : channels; // Play mono files as stereo.
|
|
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
|
|
unsigned int bufferFrames = RT_BUFFER_SIZE;
|
|
if ( dac.openStream( ¶meters, NULL, format, (unsigned int)Stk::sampleRate(), &bufferFrames, &tick, (void *)&input ) ) {
|
|
std::cout << dac.getErrorText() << std::endl;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Install an interrupt handler function.
|
|
(void) signal(SIGINT, finish);
|
|
|
|
// Resize the StkFrames object appropriately.
|
|
frames.resize( bufferFrames, channels );
|
|
|
|
if ( dac.startStream() ) {
|
|
std::cout << dac.getErrorText() << std::endl;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Block waiting until callback signals done.
|
|
while ( !done )
|
|
Stk::sleep( 100 );
|
|
|
|
// By returning a non-zero value in the callback above, the stream
|
|
// is automatically stopped. But we should still close it.
|
|
dac.closeStream();
|
|
|
|
cleanup:
|
|
return 0;
|
|
}
|