annotate projects/basic_FFT_phase_vocoder/main.cpp @ 250:aec268b5d1b4

Added phase vocoder example (optionally Midi controllable)
author Giulio Moro <giuliomoro@yahoo.it>
date Thu, 28 Apr 2016 19:30:12 +0100
parents
children
rev   line source
giuliomoro@250 1 /*
giuliomoro@250 2 * main.cpp
giuliomoro@250 3 *
giuliomoro@250 4 * Created on: Oct 24, 2014
giuliomoro@250 5 * Author: parallels
giuliomoro@250 6 */
giuliomoro@250 7
giuliomoro@250 8 #include <iostream>
giuliomoro@250 9 #include <cstdlib>
giuliomoro@250 10 #include <cstdio>
giuliomoro@250 11 #include <libgen.h>
giuliomoro@250 12 #include <signal.h>
giuliomoro@250 13 #include <getopt.h>
giuliomoro@250 14 #include <unistd.h>
giuliomoro@250 15 #include <sys/time.h>
giuliomoro@250 16 #include <sndfile.h> // to load audio files
giuliomoro@250 17 #include "SampleData.h"
giuliomoro@250 18 #include <BeagleRT.h>
giuliomoro@250 19
giuliomoro@250 20 using namespace std;
giuliomoro@250 21
giuliomoro@250 22 // Global variables used by getCurrentTime()
giuliomoro@250 23 unsigned long long gFirstSeconds, gFirstMicroseconds;
giuliomoro@250 24
giuliomoro@250 25 // Load samples from file
giuliomoro@250 26 int initFile(string file, SampleData *smp)//float *& smp)
giuliomoro@250 27 {
giuliomoro@250 28 SNDFILE *sndfile ;
giuliomoro@250 29 SF_INFO sfinfo ;
giuliomoro@250 30
giuliomoro@250 31 if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
giuliomoro@250 32 cout << "Couldn't open file " << file << endl;
giuliomoro@250 33 return 1;
giuliomoro@250 34 }
giuliomoro@250 35
giuliomoro@250 36 int numChan = sfinfo.channels;
giuliomoro@250 37 if(numChan != 1)
giuliomoro@250 38 {
giuliomoro@250 39 cout << "Error: " << file << " is not a mono file" << endl;
giuliomoro@250 40 return 1;
giuliomoro@250 41 }
giuliomoro@250 42
giuliomoro@250 43 smp->sampleLen = sfinfo.frames * numChan;
giuliomoro@250 44 smp->samples = new float[smp->sampleLen];
giuliomoro@250 45 if(smp == NULL){
giuliomoro@250 46 cout << "Could not allocate buffer" << endl;
giuliomoro@250 47 return 1;
giuliomoro@250 48 }
giuliomoro@250 49
giuliomoro@250 50 int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
giuliomoro@250 51 int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
giuliomoro@250 52
giuliomoro@250 53 // Pad with zeros in case we couldn't read whole file
giuliomoro@250 54 for(int k = readcount; k <smp->sampleLen; k++)
giuliomoro@250 55 smp->samples[k] = 0;
giuliomoro@250 56
giuliomoro@250 57 if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
giuliomoro@250 58 double scale ;
giuliomoro@250 59 int m ;
giuliomoro@250 60
giuliomoro@250 61 sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
giuliomoro@250 62 if (scale < 1e-10)
giuliomoro@250 63 scale = 1.0 ;
giuliomoro@250 64 else
giuliomoro@250 65 scale = 32700.0 / scale ;
giuliomoro@250 66 cout << "File samples scale = " << scale << endl;
giuliomoro@250 67
giuliomoro@250 68 for (m = 0; m < smp->sampleLen; m++)
giuliomoro@250 69 smp->samples[m] *= scale;
giuliomoro@250 70 }
giuliomoro@250 71
giuliomoro@250 72 sf_close(sndfile);
giuliomoro@250 73
giuliomoro@250 74 return 0;
giuliomoro@250 75 }
giuliomoro@250 76
giuliomoro@250 77
giuliomoro@250 78 // Handle Ctrl-C by requesting that the audio rendering stop
giuliomoro@250 79 void interrupt_handler(int var)
giuliomoro@250 80 {
giuliomoro@250 81 gShouldStop = true;
giuliomoro@250 82 }
giuliomoro@250 83
giuliomoro@250 84 // Print usage information
giuliomoro@250 85 void usage(const char * processName)
giuliomoro@250 86 {
giuliomoro@250 87 cerr << "Usage: " << processName << " [options]" << endl;
giuliomoro@250 88
giuliomoro@250 89 BeagleRT_usage();
giuliomoro@250 90
giuliomoro@250 91 cerr << " --help [-h]: Print this menu\n";
giuliomoro@250 92 }
giuliomoro@250 93
giuliomoro@250 94 /* Function which returns the time since start of the program
giuliomoro@250 95 * in (fractional) seconds.
giuliomoro@250 96 */
giuliomoro@250 97 double getCurrentTime(void) {
giuliomoro@250 98 unsigned long long result;
giuliomoro@250 99 struct timeval tv;
giuliomoro@250 100
giuliomoro@250 101 gettimeofday(&tv, NULL);
giuliomoro@250 102 result = (tv.tv_sec - gFirstSeconds) * 1000000ULL + (tv.tv_usec - gFirstMicroseconds);
giuliomoro@250 103 return (double)result / 1000000.0;
giuliomoro@250 104 }
giuliomoro@250 105 extern SampleData gSampleData;
giuliomoro@250 106 int main(int argc, char *argv[])
giuliomoro@250 107 {
giuliomoro@250 108 BeagleRTInitSettings settings; // Standard audio settings
giuliomoro@250 109 struct timeval tv;
giuliomoro@250 110 string fileName; // Name of the sample to load
giuliomoro@250 111
giuliomoro@250 112 struct option customOptions[] =
giuliomoro@250 113 {
giuliomoro@250 114 {"help", 0, NULL, 'h'},
giuliomoro@250 115 {"file", 1, NULL, 'f'},
giuliomoro@250 116 {NULL, 0, NULL, 0}
giuliomoro@250 117 };
giuliomoro@250 118
giuliomoro@250 119 gSampleData.samples = 0;
giuliomoro@250 120 gSampleData.sampleLen = -1;
giuliomoro@250 121
giuliomoro@250 122 // Set default settings
giuliomoro@250 123 BeagleRT_defaultSettings(&settings);
giuliomoro@250 124
giuliomoro@250 125 settings.periodSize = 32; // Larger period size by default, for testing
giuliomoro@250 126
giuliomoro@250 127 // Parse command-line arguments
giuliomoro@250 128 while (1) {
giuliomoro@250 129 int c;
giuliomoro@250 130 if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
giuliomoro@250 131 break;
giuliomoro@250 132 switch (c) {
giuliomoro@250 133 case 'h':
giuliomoro@250 134 usage(basename(argv[0]));
giuliomoro@250 135 exit(0);
giuliomoro@250 136 case 'f':
giuliomoro@250 137 fileName = string((char *)optarg);
giuliomoro@250 138 break;
giuliomoro@250 139 case '?':
giuliomoro@250 140 default:
giuliomoro@250 141 usage(basename(argv[0]));
giuliomoro@250 142 exit(1);
giuliomoro@250 143 }
giuliomoro@250 144 }
giuliomoro@250 145
giuliomoro@250 146 if(fileName.empty()){
giuliomoro@250 147 fileName = "sample.wav";
giuliomoro@250 148 }
giuliomoro@250 149
giuliomoro@250 150
giuliomoro@250 151 // Load file
giuliomoro@250 152 if(initFile(fileName, &gSampleData) != 0)
giuliomoro@250 153 {
giuliomoro@250 154 cout << "Error: unable to load samples " << endl;
giuliomoro@250 155 return -1;
giuliomoro@250 156 }
giuliomoro@250 157
giuliomoro@250 158 if(settings.verbose)
giuliomoro@250 159 cout << "File contains " << gSampleData.sampleLen << " samples" << endl;
giuliomoro@250 160
giuliomoro@250 161
giuliomoro@250 162 // Initialise the PRU audio device
giuliomoro@250 163 if(BeagleRT_initAudio(&settings, &gSampleData) != 0) {
giuliomoro@250 164 cout << "Error: unable to initialise audio" << endl;
giuliomoro@250 165 return -1;
giuliomoro@250 166 }
giuliomoro@250 167
giuliomoro@250 168 // Initialise time
giuliomoro@250 169 gettimeofday(&tv, NULL);
giuliomoro@250 170 gFirstSeconds = tv.tv_sec;
giuliomoro@250 171 gFirstMicroseconds = tv.tv_usec;
giuliomoro@250 172
giuliomoro@250 173 // Start the audio device running
giuliomoro@250 174 if(BeagleRT_startAudio()) {
giuliomoro@250 175 cout << "Error: unable to start real-time audio" << endl;
giuliomoro@250 176 return -1;
giuliomoro@250 177 }
giuliomoro@250 178
giuliomoro@250 179 // Set up interrupt handler to catch Control-C
giuliomoro@250 180 signal(SIGINT, interrupt_handler);
giuliomoro@250 181 signal(SIGTERM, interrupt_handler);
giuliomoro@250 182
giuliomoro@250 183 // Run until told to stop
giuliomoro@250 184 while(!gShouldStop) {
giuliomoro@250 185 usleep(100000);
giuliomoro@250 186 }
giuliomoro@250 187
giuliomoro@250 188 // Stop the audio device
giuliomoro@250 189 BeagleRT_stopAudio();
giuliomoro@250 190
giuliomoro@250 191 // Clean up any resources allocated for audio
giuliomoro@250 192 BeagleRT_cleanupAudio();
giuliomoro@250 193
giuliomoro@250 194 // All done!
giuliomoro@250 195 return 0;
giuliomoro@250 196 }