annotate core/RTAudioCommandLine.cpp @ 537:bfcbeb437869 API-update

Updated RTAudioSettings with in/out, ported some examples and libpd
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 24 Jun 2016 01:36:07 +0100
parents e4392164b458
children
rev   line source
andrewm@5 1 /*
andrewm@5 2 * RTAudioCommandLine.cpp
andrewm@5 3 *
andrewm@5 4 * Created on: Nov 8, 2014
andrewm@5 5 * Author: parallels
andrewm@5 6 */
andrewm@5 7
andrewm@5 8 #include <iostream>
andrewm@5 9 #include <cstdlib>
andrewm@5 10 #include <cstring>
andrewm@5 11 #include <getopt.h>
giuliomoro@301 12 #include "../include/Bela.h"
giuliomoro@24 13
giuliomoro@171 14 #define OPT_PRU_FILE 1000
giuliomoro@171 15 #define OPT_PGA_GAIN_LEFT 1001
giuliomoro@171 16 #define OPT_PGA_GAIN_RIGHT 1002
andrewm@280 17 #define OPT_PRU_NUMBER 1003
giuliomoro@171 18
andrewm@5 19
andrewm@47 20 enum {
andrewm@47 21 kAmplifierMutePin = 61 // P8-26 controls amplifier mute
andrewm@47 22 };
andrewm@47 23
andrewm@5 24 // Default command-line options for RTAudio
andrewm@5 25 struct option gDefaultLongOptions[] =
andrewm@5 26 {
andrewm@5 27 {"period", 1, NULL, 'p'},
andrewm@5 28 {"verbose", 0, NULL, 'v'},
andrewm@50 29 {"use-analog", 1, NULL, 'N'},
andrewm@50 30 {"use-digital", 1, NULL, 'G'},
giuliomoro@19 31 {"analog-channels", 1, NULL, 'C'},
andrewm@50 32 {"digital-channels", 1, NULL, 'B'},
andrewm@5 33 {"mute-speaker", 1, NULL, 'M'},
andrewm@5 34 {"dac-level", 1, NULL, 'D'},
andrewm@5 35 {"adc-level", 1, NULL, 'A'},
giuliomoro@171 36 {"pga-gain-left", 1, NULL, OPT_PGA_GAIN_LEFT},
giuliomoro@171 37 {"pga-gain-right", 1, NULL, OPT_PGA_GAIN_RIGHT},
andrewm@5 38 {"hp-level", 1, NULL, 'H'},
andrewm@50 39 {"receive-port", 1, NULL, 'R'},
andrewm@50 40 {"transmit-port", 1, NULL, 'T'},
andrewm@50 41 {"server-name", 1, NULL, 'S'},
andrewm@45 42 {"pru-file", 1, NULL, OPT_PRU_FILE},
andrewm@280 43 {"pru-number", 1, NULL, OPT_PRU_NUMBER},
andrewm@5 44 {NULL, 0, NULL, 0}
andrewm@5 45 };
giuliomoro@24 46
andrewm@50 47 const char gDefaultShortOptions[] = "p:vN:M:C:D:A:H:G:B:R:T:S:";
andrewm@5 48
giuliomoro@301 49 // This function sets the default settings for the BelaInitSettings structure
giuliomoro@301 50 void Bela_defaultSettings(BelaInitSettings *settings)
andrewm@5 51 {
andrewm@5 52 // Set default values for settings
giuliomoro@178 53 settings->periodSize = 16;
andrewm@45 54 settings->useAnalog = 1;
andrewm@45 55 settings->useDigital = 1;
giuliomoro@537 56 settings->numAudioInChannels = 2;
giuliomoro@537 57 settings->numAudioOutChannels = 2;
giuliomoro@537 58
giuliomoro@537 59 settings->numAnalogInChannels = 8;
giuliomoro@537 60 settings->numAnalogOutChannels = 8;
andrewm@45 61 settings->numDigitalChannels = 16;
andrewm@45 62
andrewm@5 63 settings->beginMuted = 0;
andrewm@5 64 settings->dacLevel = DEFAULT_DAC_LEVEL;
andrewm@5 65 settings->adcLevel = DEFAULT_ADC_LEVEL;
giuliomoro@171 66 for(int n = 0; n < 2; n++)
giuliomoro@171 67 settings->pgaGain[n] = DEFAULT_PGA_GAIN;
andrewm@5 68 settings->headphoneLevel = DEFAULT_HP_LEVEL;
andrewm@280 69 settings->numMuxChannels = 0;
andrewm@45 70
andrewm@5 71 settings->verbose = 0;
andrewm@280 72 settings->pruNumber = 0;
andrewm@45 73 settings->pruFilename[0] = '\0';
andrewm@45 74
andrewm@45 75 // These two deliberately have no command-line flags by default.
andrewm@45 76 // A given program might prefer one mode or another, but it's unlikely
andrewm@45 77 // the user would want to switch at runtime
andrewm@45 78 settings->interleave = 1;
andrewm@45 79 settings->analogOutputsPersist = 1;
andrewm@45 80
andrewm@5 81 settings->codecI2CAddress = CODEC_I2C_ADDRESS;
andrewm@45 82 settings->receivePort = 9998;
andrewm@45 83 settings->transmitPort = 9999;
giuliomoro@24 84 strcpy(settings->serverName, "127.0.0.1");
andrewm@5 85 settings->ampMutePin = kAmplifierMutePin;
andrewm@5 86 }
andrewm@5 87
andrewm@5 88 // This function drops in place of getopt() in the main() function
andrewm@5 89 // and handles the initialisation of the RTAudio settings using
andrewm@5 90 // standard command-line arguments. System default arguments will
andrewm@5 91 // be stored in settings, otherwise arguments will be returned
andrewm@5 92 // as getopt() normally does.
andrewm@5 93
giuliomoro@301 94 int Bela_getopt_long(int argc, char *argv[], const char *customShortOptions, const struct option *customLongOptions, BelaInitSettings *settings)
andrewm@5 95 {
andrewm@5 96 static int firstRun = 1;
andrewm@5 97 static char totalShortOptions[256];
andrewm@5 98 static struct option totalLongOptions[256];
andrewm@5 99
andrewm@5 100 int c;
andrewm@5 101
andrewm@5 102 // Prep total option string the first time this is
andrewm@5 103 // run. As a getopt() substitute, it will be called repeatedly working its
andrewm@5 104 // way through argc and argv.
andrewm@5 105 if(firstRun) {
andrewm@5 106 firstRun = 0;
andrewm@5 107
andrewm@5 108 // Copy short options into one string
andrewm@5 109 strcpy(totalShortOptions, gDefaultShortOptions);
andrewm@5 110 strncat(totalShortOptions, customShortOptions, 256 - strlen(gDefaultShortOptions) - 1);
andrewm@5 111
andrewm@5 112 // Copy long options into one array
andrewm@5 113 int n = 0;
andrewm@5 114 while(1) {
andrewm@5 115 if(gDefaultLongOptions[n].name == NULL)
andrewm@5 116 break;
andrewm@5 117 totalLongOptions[n].name = gDefaultLongOptions[n].name;
andrewm@5 118 totalLongOptions[n].has_arg = gDefaultLongOptions[n].has_arg;
andrewm@5 119 totalLongOptions[n].flag = gDefaultLongOptions[n].flag;
andrewm@5 120 totalLongOptions[n].val = gDefaultLongOptions[n].val;
andrewm@5 121 n++;
andrewm@5 122 }
andrewm@5 123
andrewm@5 124 // Copy custom options into the array, if present
andrewm@5 125 if(customLongOptions == 0) {
andrewm@5 126 // Terminate the array
andrewm@5 127 totalLongOptions[n].name = NULL;
andrewm@5 128 totalLongOptions[n].has_arg = 0;
andrewm@5 129 totalLongOptions[n].flag = NULL;
andrewm@5 130 totalLongOptions[n].val = 0;
andrewm@5 131 }
andrewm@5 132 else {
andrewm@5 133 int customIndex = 0;
andrewm@5 134 while(n < 256) {
andrewm@5 135 if(customLongOptions[customIndex].name == NULL)
andrewm@5 136 break;
andrewm@5 137 totalLongOptions[n].name = customLongOptions[customIndex].name;
andrewm@5 138 totalLongOptions[n].has_arg = customLongOptions[customIndex].has_arg;
andrewm@5 139 totalLongOptions[n].flag = customLongOptions[customIndex].flag;
andrewm@5 140 totalLongOptions[n].val = customLongOptions[customIndex].val;
andrewm@5 141 n++;
andrewm@5 142 customIndex++;
andrewm@5 143 }
andrewm@5 144
andrewm@5 145 // Terminate the array
andrewm@5 146 totalLongOptions[n].name = NULL;
andrewm@5 147 totalLongOptions[n].has_arg = 0;
andrewm@5 148 totalLongOptions[n].flag = NULL;
andrewm@5 149 totalLongOptions[n].val = 0;
andrewm@5 150 }
andrewm@5 151 }
andrewm@5 152
andrewm@5 153 while(1) {
andrewm@5 154 if ((c = getopt_long(argc, argv, totalShortOptions, totalLongOptions, NULL)) < 0)
andrewm@5 155 return c;
andrewm@5 156
andrewm@5 157 switch (c) {
andrewm@5 158 case 'p':
andrewm@5 159 settings->periodSize = atoi(optarg);
andrewm@5 160 if(settings->periodSize < 1)
andrewm@5 161 settings->periodSize = 1;
andrewm@5 162 break;
andrewm@5 163 case 'v':
andrewm@5 164 settings->verbose = 1;
andrewm@5 165 break;
andrewm@50 166 case 'N':
giuliomoro@19 167 settings->useAnalog = atoi(optarg);
andrewm@5 168 break;
andrewm@50 169 case 'G':
giuliomoro@19 170 settings->useDigital = atoi(optarg);
giuliomoro@240 171 if(settings->useDigital == 0){
giuliomoro@240 172 settings->numDigitalChannels = 0;
giuliomoro@240 173 }
giuliomoro@16 174 break;
giuliomoro@537 175 case 'C': {
giuliomoro@537 176 // TODO: a different number of channels for inputs and outputs is not yet supported
giuliomoro@537 177 unsigned int numAnalogChannels = atoi(optarg);
giuliomoro@537 178 settings->numAnalogInChannels = numAnalogChannels;
giuliomoro@537 179 settings->numAnalogOutChannels = numAnalogChannels;
giuliomoro@537 180 if(numAnalogChannels >= 8) {
giuliomoro@537 181 // TODO: a different number of channels for inputs and outputs is not yet supported
giuliomoro@537 182
andrewm@280 183 // Use multiplexer capelet to run larger numbers of channels
giuliomoro@537 184 if(settings->numAnalogInChannels >= 64)
andrewm@280 185 settings->numMuxChannels = 8;
giuliomoro@537 186 else if(settings->numAnalogInChannels >= 32)
andrewm@280 187 settings->numMuxChannels = 4;
giuliomoro@537 188 else if(settings->numAnalogInChannels >= 16)
andrewm@280 189 settings->numMuxChannels = 2;
giuliomoro@537 190 settings->numAnalogInChannels = 8;
andrewm@280 191 }
giuliomoro@537 192 else if(numAnalogChannels >= 4){
giuliomoro@537 193 // TODO: a different number of channels for inputs and outputs is not yet supported
giuliomoro@537 194 settings->numAnalogInChannels = 4;
giuliomoro@537 195 settings->numAnalogOutChannels = 4;
giuliomoro@537 196 }
giuliomoro@537 197 else{
giuliomoro@537 198 // TODO: a different number of channels for inputs and outputs is not yet supported
giuliomoro@537 199 settings->numAnalogInChannels = 2;
giuliomoro@537 200 settings->numAnalogOutChannels = 2;
giuliomoro@537 201 }
andrewm@12 202 break;
giuliomoro@537 203 }
andrewm@50 204 case 'B':
giuliomoro@19 205 settings->numDigitalChannels = atoi(optarg);
giuliomoro@19 206 if(settings->numDigitalChannels >= 16)
giuliomoro@19 207 settings->numDigitalChannels = 16;
giuliomoro@19 208 else if (settings->numDigitalChannels < 1){
giuliomoro@19 209 settings->numDigitalChannels = 0;
giuliomoro@19 210 settings->useDigital = 0; //TODO: this actually works only if -G 0 is specified after -g 1.
giuliomoro@19 211 //No worries, though: disabling numDigital will only prevent the pins from being exported.
giuliomoro@16 212 }
giuliomoro@16 213 break;
andrewm@5 214 case 'M':
andrewm@5 215 settings->beginMuted = atoi(optarg);
andrewm@5 216 break;
andrewm@5 217 case 'D':
andrewm@5 218 settings->dacLevel = atof(optarg);
andrewm@5 219 break;
andrewm@5 220 case 'A':
andrewm@5 221 settings->adcLevel = atof(optarg);
andrewm@5 222 break;
andrewm@5 223 case 'H':
andrewm@5 224 settings->headphoneLevel = atof(optarg);
andrewm@5 225 break;
andrewm@50 226 case 'R':
giuliomoro@24 227 settings->receivePort = atoi(optarg);
giuliomoro@24 228 break;
andrewm@50 229 case 'T':
giuliomoro@24 230 settings->transmitPort = atoi(optarg);
giuliomoro@24 231 break;
andrewm@50 232 case 'S':
giuliomoro@24 233 if(strlen(optarg)<MAX_SERVERNAME_LENGTH)
giuliomoro@24 234 strcpy(settings->serverName, optarg);
giuliomoro@24 235 else
giuliomoro@24 236 std::cerr << "Warning: server name is too long (>" << MAX_SERVERNAME_LENGTH << " characters)."
giuliomoro@24 237 " Using default severName Instead ( " << settings->serverName << " ).\n";
giuliomoro@24 238 break;
giuliomoro@29 239 case OPT_PRU_FILE:
andrewm@45 240 if(strlen(optarg) < MAX_PRU_FILENAME_LENGTH)
giuliomoro@16 241 strcpy(settings->pruFilename, optarg);
giuliomoro@16 242 else
giuliomoro@16 243 std::cerr << "Warning: filename for the PRU code is too long (>" << MAX_PRU_FILENAME_LENGTH << " characters). Using embedded PRU code instead\n";
giuliomoro@16 244 break;
giuliomoro@171 245 case OPT_PGA_GAIN_LEFT:
giuliomoro@171 246 settings->pgaGain[0] = atof(optarg);
giuliomoro@171 247 break;
giuliomoro@171 248 case OPT_PGA_GAIN_RIGHT:
giuliomoro@171 249 settings->pgaGain[1] = atof(optarg);
giuliomoro@171 250 break;
andrewm@280 251 case OPT_PRU_NUMBER:
andrewm@280 252 settings->pruNumber = atoi(optarg);
andrewm@280 253 break;
andrewm@5 254 case '?':
andrewm@5 255 default:
andrewm@5 256 return c;
andrewm@5 257 }
andrewm@5 258 }
andrewm@5 259 }
andrewm@5 260
andrewm@5 261 // This function prints standard usage information for default arguments
andrewm@5 262 // Call from within your own usage function
giuliomoro@301 263 void Bela_usage()
andrewm@5 264 {
giuliomoro@19 265 std::cerr << " --period [-p] period: Set the hardware period (buffer) size in analog samples\n";
giuliomoro@16 266 std::cerr << " --dac-level [-D] dBs: Set the DAC output level (0dB max; -63.5dB min)\n";
giuliomoro@16 267 std::cerr << " --adc-level [-A] dBs: Set the ADC input level (0dB max; -12dB min)\n";
giuliomoro@171 268 std::cerr << " --pga-gain-left dBs: Set the Programmable Gain Amplifier for the left audio channel (0dBmin; 59.5dB max; default: 16dB)\n";
giuliomoro@171 269 std::cerr << " --pga-gain-right dBs: Set the Programmable Gain Amplifier for the right audio channel (0dBmin; 59.5dB max; default: 16dB)\n";
giuliomoro@16 270 std::cerr << " --hp-level [-H] dBs: Set the headphone output level (0dB max; -63.5dB min)\n";
giuliomoro@16 271 std::cerr << " --mute-speaker [-M] val: Set whether to mute the speaker initially (default: no)\n";
andrewm@52 272 std::cerr << " --use-analog [-N] val: Set whether to use ADC/DAC analog (default: yes)\n";
andrewm@52 273 std::cerr << " --use-digital [-G] val: Set whether to use digital GPIO channels (default: yes)\n";
giuliomoro@19 274 std::cerr << " --analog-channels [-C] val: Set the number of ADC/DAC channels (default: 8)\n";
andrewm@52 275 std::cerr << " --digital-channels [-B] val: Set the number of GPIO channels (default: 16)\n";
andrewm@52 276 std::cerr << " --receive-port [-R] val: Set the receive port (default: 9998)\n";
andrewm@52 277 std::cerr << " --transmit-port [-T] val: Set the transmit port (default: 9999)\n";
andrewm@52 278 std::cerr << " --server-name [-S] val: Set the destination server name (default: '127.0.0.1')\n";
giuliomoro@24 279 std::cerr << " --pru-file val: Set an optional external file to use for the PRU binary code\n";
andrewm@280 280 std::cerr << " --pru-number val: Set the PRU to use for I/O (options: 0 or 1, default: 0)\n";
giuliomoro@16 281 std::cerr << " --verbose [-v]: Enable verbose logging information\n";
andrewm@5 282 }
giuliomoro@16 283