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