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