victor@1: /* victor@1: * main.cpp victor@1: * victor@1: * Created on: Oct 24, 2014 victor@1: * Author: Andrew McPherson and Victor Zappi victor@1: */ victor@1: victor@1: #include victor@1: #include victor@1: #include victor@1: #include victor@1: #include victor@1: #include // to load audio files victor@1: #include "../../include/RTAudio.h" victor@1: //#include // to kill sample trigger task victor@1: #include "SampleData.h" victor@1: victor@1: using namespace std; victor@1: victor@1: //extern AuxiliaryTask gTriggerSamplesTask; victor@1: victor@1: // Load samples from file victor@1: int initFile(string file, SampleData *smp)//float *& smp) victor@1: { victor@1: SNDFILE *sndfile ; victor@1: SF_INFO sfinfo ; victor@1: victor@1: if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) { victor@1: cout << "Couldn't open file " << file << endl; victor@1: return 1; victor@1: } victor@1: victor@1: int numChan = sfinfo.channels; victor@1: if(numChan != 1) victor@1: { victor@1: cout << "Error: " << file << " is not a mono file" << endl; victor@1: return 1; victor@1: } victor@1: victor@1: smp->sampleLen = sfinfo.frames * numChan; victor@1: smp->samples = new float[smp->sampleLen]; victor@1: if(smp == NULL){ victor@1: cout << "Could not allocate buffer" << endl; victor@1: return 1; victor@1: } victor@1: victor@1: int subformat = sfinfo.format & SF_FORMAT_SUBMASK; victor@1: int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen); victor@1: victor@1: // Pad with zeros in case we couldn't read whole file victor@1: for(int k = readcount; k sampleLen; k++) victor@1: smp->samples[k] = 0; victor@1: victor@1: if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) { victor@1: double scale ; victor@1: int m ; victor@1: victor@1: sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ; victor@1: if (scale < 1e-10) victor@1: scale = 1.0 ; victor@1: else victor@1: scale = 32700.0 / scale ; victor@1: cout << "File samples scale = " << scale << endl; victor@1: victor@1: for (m = 0; m < smp->sampleLen; m++) victor@1: smp->samples[m] *= scale; victor@1: } victor@1: victor@1: sf_close(sndfile); victor@1: victor@1: return 0; victor@1: } victor@1: victor@1: victor@1: // Handle Ctrl-C by requesting that the audio rendering stop victor@1: void interrupt_handler(int var) victor@1: { victor@1: //rt_task_delete ((RT_TASK *) &gTriggerSamplesTask); victor@1: gShouldStop = true; victor@1: } victor@1: victor@1: // Print usage information victor@1: void usage(const char * processName) victor@1: { victor@1: cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f frequency]" << endl; victor@1: cerr << " -h: Print this menu\n"; victor@1: cerr << " -v: Enable verbose messages\n"; victor@1: cerr << " -p period: Set the period (hardware buffer) size in sensor frames\n"; victor@1: cerr << " -m: Enable the matrix (ADC and DAC) as well as audio\n"; victor@1: cerr << " -f filename: Name of the file to load (default is \"sample.wav\")\n"; victor@1: } victor@1: victor@1: int main(int argc, char *argv[]) victor@1: { victor@1: int periodSize = 8; // Period size in sensor frames victor@1: int verbose = 0; // Verbose printing level victor@1: int useMatrix = 0; // Whether to use the matrix or just audio victor@1: string fileName; // Name of the sample to load victor@1: victor@1: SampleData sampleData; // User define structure to pass data retrieved from file to render function victor@1: sampleData.samples = 0; victor@1: sampleData.sampleLen = -1; victor@1: victor@1: // Parse command-line arguments victor@1: while (1) { victor@1: int c; victor@1: if ((c = getopt(argc, argv, "hp:vms:")) < 0) victor@1: break; victor@1: switch (c) { victor@1: case 'h': victor@1: usage(basename(argv[0])); victor@1: exit(0); victor@1: case 'p': victor@1: periodSize = atoi(optarg); victor@1: if(periodSize < 1) victor@1: periodSize = 1; victor@1: break; victor@1: case 'v': victor@1: verbose = 1; victor@1: break; victor@1: case 'm': victor@1: useMatrix = 1; victor@1: break; victor@1: case 'f': victor@1: fileName = string((char *)optarg); victor@1: break; victor@1: case '?': victor@1: default: victor@1: usage(basename(argv[0])); victor@1: exit(1); victor@1: } victor@1: } victor@1: victor@1: if(fileName.empty()){ victor@1: fileName = "samples/sample.wav"; victor@1: } victor@1: victor@1: // Set verbose logging information (optional by using value > 0; default is 0) victor@1: setVerboseLevel(verbose); victor@1: victor@1: if(verbose) { victor@1: cout << "Starting with period size " << periodSize << endl; victor@1: if(useMatrix) victor@1: cout << "Matrix enabled\n"; victor@1: else victor@1: cout << "Matrix disabled\n"; victor@1: cout << "Loading file " << fileName << endl; victor@1: } victor@1: victor@1: // Load file victor@1: if(initFile(fileName, &sampleData) != 0) victor@1: { victor@1: cout << "Error: unable to load samples " << endl; victor@1: return -1; victor@1: } victor@1: victor@1: if(verbose) victor@1: cout << "File contains " << sampleData.sampleLen << " samples" << endl; victor@1: victor@1: // Initialise the PRU audio device victor@1: if(initAudio(periodSize, useMatrix, &sampleData) != 0) { victor@1: cout << "Error: unable to initialise audio" << endl; victor@1: return -1; victor@1: } victor@1: victor@1: // Start the audio device running victor@1: if(startAudio()) { victor@1: cout << "Error: unable to start real-time audio" << endl; victor@1: return -1; victor@1: } victor@1: victor@1: // Set up interrupt handler to catch Control-C victor@1: signal(SIGINT, interrupt_handler); victor@1: victor@1: // Run until told to stop victor@1: while(!gShouldStop) { victor@1: usleep(100000); victor@1: } victor@1: victor@1: // Stop the audio device victor@1: stopAudio(); victor@1: victor@1: if(verbose) { victor@1: cout << "Cleaning up..." << endl; victor@1: } victor@1: victor@1: // Clean up any resources allocated for audio victor@1: cleanupAudio(); victor@1: victor@1: // All done! victor@1: return 0; victor@1: }