annotate projects/samples/main.cpp @ 45:579c86316008 newapi

Major API overhaul. Moved to a single data structure for handling render functions. Functionally, generally similar except for scheduling within PRU loop function, which now uses interrupts from the PRU rather than polling. This requires an updated kernel.
author andrewm
date Thu, 28 May 2015 14:35:55 -0400
parents 901d205d1a3c
children a6d223473ea2
rev   line source
victor@1 1 /*
victor@1 2 * main.cpp
victor@1 3 *
victor@1 4 * Created on: Oct 24, 2014
victor@1 5 * Author: Andrew McPherson and Victor Zappi
victor@1 6 */
victor@1 7
victor@1 8 #include <iostream>
victor@1 9 #include <cstdlib>
victor@1 10 #include <libgen.h>
victor@1 11 #include <signal.h>
victor@1 12 #include <string>
andrewm@5 13 #include <getopt.h>
victor@1 14 #include <sndfile.h> // to load audio files
victor@1 15 #include "../../include/RTAudio.h"
victor@1 16 #include "SampleData.h"
victor@1 17
victor@1 18 using namespace std;
victor@1 19
victor@1 20 // Load samples from file
victor@1 21 int initFile(string file, SampleData *smp)//float *& smp)
victor@1 22 {
victor@1 23 SNDFILE *sndfile ;
victor@1 24 SF_INFO sfinfo ;
victor@1 25
victor@1 26 if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
victor@1 27 cout << "Couldn't open file " << file << endl;
victor@1 28 return 1;
victor@1 29 }
victor@1 30
victor@1 31 int numChan = sfinfo.channels;
victor@1 32 if(numChan != 1)
victor@1 33 {
victor@1 34 cout << "Error: " << file << " is not a mono file" << endl;
victor@1 35 return 1;
victor@1 36 }
victor@1 37
victor@1 38 smp->sampleLen = sfinfo.frames * numChan;
victor@1 39 smp->samples = new float[smp->sampleLen];
victor@1 40 if(smp == NULL){
victor@1 41 cout << "Could not allocate buffer" << endl;
victor@1 42 return 1;
victor@1 43 }
victor@1 44
victor@1 45 int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
victor@1 46 int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
victor@1 47
victor@1 48 // Pad with zeros in case we couldn't read whole file
victor@1 49 for(int k = readcount; k <smp->sampleLen; k++)
victor@1 50 smp->samples[k] = 0;
victor@1 51
victor@1 52 if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
victor@1 53 double scale ;
victor@1 54 int m ;
victor@1 55
victor@1 56 sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
victor@1 57 if (scale < 1e-10)
victor@1 58 scale = 1.0 ;
victor@1 59 else
victor@1 60 scale = 32700.0 / scale ;
victor@1 61 cout << "File samples scale = " << scale << endl;
victor@1 62
victor@1 63 for (m = 0; m < smp->sampleLen; m++)
victor@1 64 smp->samples[m] *= scale;
victor@1 65 }
victor@1 66
victor@1 67 sf_close(sndfile);
victor@1 68
victor@1 69 return 0;
victor@1 70 }
victor@1 71
victor@1 72
victor@1 73 // Handle Ctrl-C by requesting that the audio rendering stop
victor@1 74 void interrupt_handler(int var)
victor@1 75 {
victor@1 76 //rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
victor@1 77 gShouldStop = true;
victor@1 78 }
victor@1 79
victor@1 80 // Print usage information
victor@1 81 void usage(const char * processName)
victor@1 82 {
andrewm@5 83 cerr << "Usage: " << processName << " [options]" << endl;
andrewm@5 84
andrewm@5 85 BeagleRT_usage();
andrewm@5 86
andrewm@5 87 cerr << " --file [-f] filename: Name of the file to load (default is \"sample.wav\")\n";
andrewm@5 88 cerr << " --help [-h]: Print this menu\n";
victor@1 89 }
victor@1 90
victor@1 91 int main(int argc, char *argv[])
victor@1 92 {
andrewm@5 93 RTAudioSettings settings; // Standard audio settings
victor@1 94 string fileName; // Name of the sample to load
victor@1 95
victor@1 96 SampleData sampleData; // User define structure to pass data retrieved from file to render function
victor@1 97 sampleData.samples = 0;
victor@1 98 sampleData.sampleLen = -1;
victor@1 99
andrewm@5 100
andrewm@5 101 struct option customOptions[] =
andrewm@5 102 {
andrewm@5 103 {"help", 0, NULL, 'h'},
andrewm@5 104 {"file", 1, NULL, 'f'},
andrewm@5 105 {NULL, 0, NULL, 0}
andrewm@5 106 };
andrewm@5 107
andrewm@5 108 // Set default settings
andrewm@5 109 BeagleRT_defaultSettings(&settings);
andrewm@5 110
victor@1 111 // Parse command-line arguments
victor@1 112 while (1) {
victor@1 113 int c;
andrewm@5 114 if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
victor@1 115 break;
victor@1 116 switch (c) {
victor@1 117 case 'h':
victor@1 118 usage(basename(argv[0]));
victor@1 119 exit(0);
victor@1 120 case 'f':
victor@1 121 fileName = string((char *)optarg);
victor@1 122 break;
victor@1 123 case '?':
victor@1 124 default:
victor@1 125 usage(basename(argv[0]));
victor@1 126 exit(1);
victor@1 127 }
victor@1 128 }
victor@1 129
victor@1 130 if(fileName.empty()){
victor@8 131 fileName = "samples/sample.wav";
victor@1 132 }
victor@1 133
andrewm@5 134 if(settings.verbose) {
victor@1 135 cout << "Loading file " << fileName << endl;
victor@1 136 }
victor@1 137
victor@1 138 // Load file
victor@1 139 if(initFile(fileName, &sampleData) != 0)
victor@1 140 {
victor@1 141 cout << "Error: unable to load samples " << endl;
victor@1 142 return -1;
victor@1 143 }
victor@1 144
andrewm@5 145 if(settings.verbose)
victor@1 146 cout << "File contains " << sampleData.sampleLen << " samples" << endl;
victor@1 147
andrewm@5 148
victor@1 149 // Initialise the PRU audio device
andrewm@5 150 if(BeagleRT_initAudio(&settings, &sampleData) != 0) {
victor@1 151 cout << "Error: unable to initialise audio" << endl;
victor@1 152 return -1;
victor@1 153 }
victor@1 154
victor@1 155 // Start the audio device running
andrewm@5 156 if(BeagleRT_startAudio()) {
victor@1 157 cout << "Error: unable to start real-time audio" << endl;
victor@1 158 return -1;
victor@1 159 }
victor@1 160
andrewm@15 161 // Set up interrupt handler to catch Control-C and SIGTERM
victor@1 162 signal(SIGINT, interrupt_handler);
andrewm@15 163 signal(SIGTERM, interrupt_handler);
victor@1 164
victor@1 165 // Run until told to stop
victor@1 166 while(!gShouldStop) {
victor@1 167 usleep(100000);
victor@1 168 }
victor@1 169
victor@1 170 // Stop the audio device
andrewm@5 171 BeagleRT_stopAudio();
victor@1 172
victor@1 173 // Clean up any resources allocated for audio
andrewm@5 174 BeagleRT_cleanupAudio();
victor@1 175
victor@1 176 // All done!
victor@1 177 return 0;
victor@1 178 }