victor@3: /* victor@3: * main.cpp victor@3: * victor@3: * Created on: Oct 24, 2014 victor@3: * Author: Andrew McPherson and Victor Zappi victor@3: */ victor@3: victor@3: #include victor@3: #include victor@3: #include victor@3: #include victor@3: #include andrewm@5: #include victor@3: #include // to load audio files victor@3: #include "../../include/RTAudio.h" victor@3: #include "SampleData.h" victor@3: victor@3: using namespace std; victor@3: victor@3: float gCutFreq = 100; victor@3: victor@3: // Load samples from file victor@3: int initFile(string file, SampleData *smp)//float *& smp) victor@3: { victor@3: SNDFILE *sndfile ; victor@3: SF_INFO sfinfo ; victor@3: victor@3: if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) { victor@3: cout << "Couldn't open file " << file << endl; victor@3: return 1; victor@3: } victor@3: victor@3: int numChan = sfinfo.channels; victor@3: if(numChan != 1) victor@3: { victor@3: cout << "Error: " << file << " is not a mono file" << endl; victor@3: return 1; victor@3: } victor@3: victor@3: smp->sampleLen = sfinfo.frames * numChan; victor@3: smp->samples = new float[smp->sampleLen]; victor@3: if(smp == NULL){ victor@3: cout << "Could not allocate buffer" << endl; victor@3: return 1; victor@3: } victor@3: victor@3: int subformat = sfinfo.format & SF_FORMAT_SUBMASK; victor@3: int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen); victor@3: victor@3: // Pad with zeros in case we couldn't read whole file victor@3: for(int k = readcount; k sampleLen; k++) victor@3: smp->samples[k] = 0; victor@3: victor@3: if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) { victor@3: double scale ; victor@3: int m ; victor@3: victor@3: sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ; victor@3: if (scale < 1e-10) victor@3: scale = 1.0 ; victor@3: else victor@3: scale = 32700.0 / scale ; victor@3: cout << "File samples scale = " << scale << endl; victor@3: victor@3: for (m = 0; m < smp->sampleLen; m++) victor@3: smp->samples[m] *= scale; victor@3: } victor@3: victor@3: sf_close(sndfile); victor@3: victor@3: return 0; victor@3: } victor@3: victor@3: // Handle Ctrl-C by requesting that the audio rendering stop victor@3: void interrupt_handler(int var) victor@3: { victor@3: //rt_task_delete ((RT_TASK *) &gTriggerSamplesTask); victor@3: gShouldStop = true; victor@3: } victor@3: victor@3: // Print usage information victor@3: void usage(const char * processName) victor@3: { andrewm@5: cerr << "Usage: " << processName << " [options]" << endl; andrewm@5: andrewm@5: BeagleRT_usage(); andrewm@5: andrewm@5: cerr << " --file [-f] filename: Name of the file to load (default is \"longsample.wav\")\n"; andrewm@5: cerr << " --cutfreq [-c] freq: Set the cut off frequency of the filter in Hz\n"; andrewm@5: cerr << " --help [-h]: Print this menu\n"; victor@3: } victor@3: victor@3: int main(int argc, char *argv[]) victor@3: { andrewm@5: RTAudioSettings settings; // Standard audio settings victor@3: string fileName; // Name of the sample to load victor@3: victor@3: SampleData sampleData; // User define structure to pass data retrieved from file to render function victor@3: sampleData.samples = 0; victor@3: sampleData.sampleLen = -1; victor@3: andrewm@5: andrewm@5: struct option customOptions[] = andrewm@5: { andrewm@5: {"help", 0, NULL, 'h'}, andrewm@5: {"cutfreq", 1, NULL, 'c'}, andrewm@5: {"file", 1, NULL, 'f'}, andrewm@5: {NULL, 0, NULL, 0} andrewm@5: }; andrewm@5: andrewm@5: // Set default settings andrewm@5: BeagleRT_defaultSettings(&settings); andrewm@5: victor@3: // Parse command-line arguments victor@3: while (1) { victor@3: int c; andrewm@5: if ((c = BeagleRT_getopt_long(argc, argv, "hf:c:", customOptions, &settings)) < 0) victor@3: break; victor@3: switch (c) { victor@3: case 'h': victor@3: usage(basename(argv[0])); victor@3: exit(0); victor@3: case 'f': victor@3: fileName = string((char *)optarg); victor@3: break; victor@3: case 'c': victor@3: gCutFreq = atof(optarg); victor@3: break; victor@3: case '?': victor@3: default: victor@3: usage(basename(argv[0])); victor@3: exit(1); victor@3: } victor@3: } victor@3: victor@3: if(fileName.empty()){ andrewm@5: fileName = "longsample.wav"; victor@3: } victor@3: andrewm@5: if(settings.verbose) { victor@3: cout << "Loading file " << fileName << endl; victor@3: } victor@3: victor@3: // Load file victor@3: if(initFile(fileName, &sampleData) != 0) victor@3: { victor@3: cout << "Error: unable to load samples " << endl; victor@3: return -1; victor@3: } victor@3: andrewm@5: if(settings.verbose) victor@3: cout << "File contains " << sampleData.sampleLen << " samples" << endl; victor@3: andrewm@5: victor@3: // Initialise the PRU audio device andrewm@5: if(BeagleRT_initAudio(&settings, &sampleData) != 0) { victor@3: cout << "Error: unable to initialise audio" << endl; victor@3: return -1; victor@3: } victor@3: victor@3: // Start the audio device running andrewm@5: if(BeagleRT_startAudio()) { victor@3: cout << "Error: unable to start real-time audio" << endl; victor@3: return -1; victor@3: } victor@3: victor@3: // Set up interrupt handler to catch Control-C victor@3: signal(SIGINT, interrupt_handler); victor@3: victor@3: // Run until told to stop victor@3: while(!gShouldStop) { victor@3: usleep(100000); victor@3: } victor@3: victor@3: // Stop the audio device andrewm@5: BeagleRT_stopAudio(); victor@3: victor@3: // Clean up any resources allocated for audio andrewm@5: BeagleRT_cleanupAudio(); victor@3: victor@3: // All done! victor@3: return 0; victor@3: } andrewm@5: