| robert@493 | 1 /* | 
| robert@493 | 2  * main.cpp | 
| robert@493 | 3  * | 
| robert@493 | 4  *  Created on: Oct 24, 2014 | 
| robert@493 | 5  *      Author: parallels | 
| robert@493 | 6  */ | 
| robert@493 | 7 | 
| robert@493 | 8 #include <iostream> | 
| robert@493 | 9 #include <cstdlib> | 
| robert@493 | 10 #include <libgen.h> | 
| robert@493 | 11 #include <signal.h> | 
| robert@493 | 12 #include <getopt.h> | 
| robert@493 | 13 #include <sndfile.h> | 
| robert@493 | 14 #include <Bela.h> | 
| robert@493 | 15 | 
| robert@493 | 16 extern int gScreenFramesPerSecond; | 
| robert@493 | 17 | 
| robert@493 | 18 float *gMusicBuffer = 0; | 
| robert@493 | 19 int gMusicBufferLength = 0; | 
| robert@493 | 20 float *gSoundBoomBuffer = 0; | 
| robert@493 | 21 int gSoundBoomBufferLength = 0; | 
| robert@493 | 22 float *gSoundHitBuffer = 0; | 
| robert@493 | 23 int gSoundHitBufferLength = 0; | 
| robert@493 | 24 | 
| robert@493 | 25 | 
| robert@493 | 26 using namespace std; | 
| robert@493 | 27 | 
| robert@493 | 28 // Load a sound sample from file | 
| robert@493 | 29 int loadSoundFile(const string& path, float **buffer, int *bufferLength) | 
| robert@493 | 30 { | 
| robert@493 | 31 	SNDFILE *sndfile ; | 
| robert@493 | 32 	SF_INFO sfinfo ; | 
| robert@493 | 33 | 
| robert@493 | 34 	if (!(sndfile = sf_open (path.c_str(), SFM_READ, &sfinfo))) { | 
| robert@493 | 35 		cout << "Couldn't open file " << path << endl; | 
| robert@493 | 36 		return 1; | 
| robert@493 | 37 	} | 
| robert@493 | 38 | 
| robert@493 | 39 	int numChan = sfinfo.channels; | 
| robert@493 | 40 	if(numChan != 1) | 
| robert@493 | 41 	{ | 
| robert@493 | 42 		cout << "Error: " << path << " is not a mono file" << endl; | 
| robert@493 | 43 		return 1; | 
| robert@493 | 44 	} | 
| robert@493 | 45 | 
| robert@493 | 46 	*bufferLength = sfinfo.frames * numChan; | 
| robert@493 | 47 	*buffer = new float[*bufferLength]; | 
| robert@493 | 48 	if(*buffer == 0){ | 
| robert@493 | 49 		cout << "Could not allocate buffer" << endl; | 
| robert@493 | 50 		return 1; | 
| robert@493 | 51 	} | 
| robert@493 | 52 | 
| robert@493 | 53 	int subformat = sfinfo.format & SF_FORMAT_SUBMASK; | 
| robert@493 | 54 	int readcount = sf_read_float(sndfile, *buffer, *bufferLength); | 
| robert@493 | 55 | 
| robert@493 | 56 	// Pad with zeros in case we couldn't read whole file | 
| robert@493 | 57 	for(int k = readcount; k < *bufferLength; k++) | 
| robert@493 | 58 		(*buffer)[k] = 0; | 
| robert@493 | 59 | 
| robert@493 | 60 	sf_close(sndfile); | 
| robert@493 | 61 	return 0; | 
| robert@493 | 62 } | 
| robert@493 | 63 | 
| robert@493 | 64 // Handle Ctrl-C by requesting that the audio rendering stop | 
| robert@493 | 65 void interrupt_handler(int var) | 
| robert@493 | 66 { | 
| robert@493 | 67 	gShouldStop = true; | 
| robert@493 | 68 } | 
| robert@493 | 69 | 
| robert@493 | 70 // Print usage information | 
| robert@493 | 71 void usage(const char * processName) | 
| robert@493 | 72 { | 
| robert@493 | 73 	cerr << "Usage: " << processName << " [options]" << endl; | 
| robert@493 | 74 | 
| robert@493 | 75 	Bela_usage(); | 
| robert@493 | 76 | 
| robert@493 | 77 	cerr << "   --fps [-f] value:           Set target frames per second\n"; | 
| robert@493 | 78 	cerr << "   --help [-h]:                Print this menu\n"; | 
| robert@493 | 79 } | 
| robert@493 | 80 | 
| robert@493 | 81 int main(int argc, char *argv[]) | 
| robert@493 | 82 { | 
| robert@493 | 83 	BelaInitSettings settings;	// Standard audio settings | 
| robert@493 | 84 	string musicFileName = "music.wav"; | 
| robert@493 | 85 	string soundBoomFileName = "boom.wav"; | 
| robert@493 | 86 	string soundHitFileName = "hit.wav"; | 
| robert@493 | 87 | 
| robert@493 | 88 	struct option customOptions[] = | 
| robert@493 | 89 	{ | 
| robert@493 | 90 		{"help", 0, NULL, 'h'}, | 
| robert@493 | 91 		{"fps", 1, NULL, 'f'}, | 
| robert@493 | 92 		{NULL, 0, NULL, 0} | 
| robert@493 | 93 	}; | 
| robert@493 | 94 | 
| robert@493 | 95 	// Set default settings | 
| robert@493 | 96 	Bela_defaultSettings(&settings); | 
| robert@493 | 97 | 
| robert@493 | 98 	// Parse command-line arguments | 
| robert@493 | 99 	while (1) { | 
| robert@493 | 100 		int c; | 
| robert@493 | 101 		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0) | 
| robert@493 | 102 				break; | 
| robert@493 | 103 		switch (c) { | 
| robert@493 | 104 		case 'f': | 
| robert@493 | 105 				gScreenFramesPerSecond = atoi(optarg); | 
| robert@493 | 106 				if(gScreenFramesPerSecond < 1) | 
| robert@493 | 107 					gScreenFramesPerSecond = 1; | 
| robert@493 | 108 				if(gScreenFramesPerSecond > 100) | 
| robert@493 | 109 					gScreenFramesPerSecond = 100; | 
| robert@493 | 110 				break; | 
| robert@493 | 111 		case 'h': | 
| robert@493 | 112 				usage(basename(argv[0])); | 
| robert@493 | 113 				exit(0); | 
| robert@493 | 114 		case '?': | 
| robert@493 | 115 		default: | 
| robert@493 | 116 				usage(basename(argv[0])); | 
| robert@493 | 117 				exit(1); | 
| robert@493 | 118 		} | 
| robert@493 | 119 	} | 
| robert@493 | 120 | 
| robert@493 | 121 	// Load the sound files | 
| robert@493 | 122 	if(loadSoundFile(musicFileName, &gMusicBuffer, &gMusicBufferLength) != 0) { | 
| robert@493 | 123 		cout << "Warning: unable to load sound file " << musicFileName << endl; | 
| robert@493 | 124 	} | 
| robert@493 | 125 	if(loadSoundFile(soundBoomFileName, &gSoundBoomBuffer, &gSoundBoomBufferLength) != 0) { | 
| robert@493 | 126 		cout << "Warning: unable to load sound file " << soundBoomFileName << endl; | 
| robert@493 | 127 	} | 
| robert@493 | 128 	if(loadSoundFile(soundHitFileName, &gSoundHitBuffer, &gSoundHitBufferLength) != 0) { | 
| robert@493 | 129 		cout << "Warning: unable to load sound file " << soundHitFileName << endl; | 
| robert@493 | 130 	} | 
| robert@493 | 131 | 
| robert@493 | 132 	// Initialise the PRU audio device | 
| robert@493 | 133 	if(Bela_initAudio(&settings, 0) != 0) { | 
| robert@493 | 134 		cout << "Error: unable to initialise audio" << endl; | 
| robert@493 | 135 		return -1; | 
| robert@493 | 136 	} | 
| robert@493 | 137 | 
| robert@493 | 138 	// Start the audio device running | 
| robert@493 | 139 	if(Bela_startAudio()) { | 
| robert@493 | 140 		cout << "Error: unable to start real-time audio" << endl; | 
| robert@493 | 141 		return -1; | 
| robert@493 | 142 	} | 
| robert@493 | 143 | 
| robert@493 | 144 	// Set up interrupt handler to catch Control-C and SIGTERM | 
| robert@493 | 145 	signal(SIGINT, interrupt_handler); | 
| robert@493 | 146 	signal(SIGTERM, interrupt_handler); | 
| robert@493 | 147 | 
| robert@493 | 148 	// Run until told to stop | 
| robert@493 | 149 	while(!gShouldStop) { | 
| robert@493 | 150 		usleep(100000); | 
| robert@493 | 151 	} | 
| robert@493 | 152 | 
| robert@493 | 153 	// Stop the audio device | 
| robert@493 | 154 	Bela_stopAudio(); | 
| robert@493 | 155 | 
| robert@493 | 156 	// Clean up any resources allocated for audio | 
| robert@493 | 157 	Bela_cleanupAudio(); | 
| robert@493 | 158 | 
| robert@493 | 159 	// Release sound files | 
| robert@493 | 160 	if(gMusicBuffer != 0) | 
| robert@493 | 161 		free(gMusicBuffer); | 
| robert@493 | 162 	if(gSoundBoomBuffer != 0) | 
| robert@493 | 163 		free(gSoundBoomBuffer); | 
| robert@493 | 164 	if(gSoundHitBuffer != 0) | 
| robert@493 | 165 		free(gSoundHitBuffer); | 
| robert@493 | 166 | 
| robert@493 | 167 	// All done! | 
| robert@493 | 168 	return 0; | 
| robert@493 | 169 } |