|
|
|
@ -25,6 +25,7 @@ typedef struct { |
|
|
|
|
PmStream* pmStream; |
|
|
|
|
} State; |
|
|
|
|
|
|
|
|
|
// PortAudio callback for audio I/O
|
|
|
|
|
static int paCallback( |
|
|
|
|
const void *inputBuffer, |
|
|
|
|
void *outputBuffer, |
|
|
|
@ -53,6 +54,7 @@ static int paCallback( |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// PortTimer callback for MIDI I/O
|
|
|
|
|
static void ptCallback(PtTimestamp timestamp, void* userData) { |
|
|
|
|
State* state = (State*) userData; |
|
|
|
|
PmEvent events[8]; |
|
|
|
@ -116,6 +118,7 @@ int main(void) { |
|
|
|
|
state.filter.setQ(1); |
|
|
|
|
state.time = 0; |
|
|
|
|
|
|
|
|
|
// Initialise PortMIDI and PortAudio libraries
|
|
|
|
|
PmError pmErr = Pm_Initialize(); |
|
|
|
|
if(pmErr != pmNoError) { |
|
|
|
|
handlePMError(pmErr); |
|
|
|
@ -134,17 +137,18 @@ int main(void) { |
|
|
|
|
} |
|
|
|
|
cout << i << ". " << deviceInfo->name << endl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int pmDeviceIndex; |
|
|
|
|
for(;;) { |
|
|
|
|
for(;;) { // loop for input until valid choice is made
|
|
|
|
|
string input; |
|
|
|
|
getline(cin, input); |
|
|
|
|
try { |
|
|
|
|
pmDeviceIndex = stoi(input); |
|
|
|
|
if(pmDeviceIndex >= 0 && pmDeviceIndex < pmDeviceCount) { |
|
|
|
|
if( pmDeviceIndex >= 0 && |
|
|
|
|
pmDeviceIndex < pmDeviceCount && |
|
|
|
|
Pm_GetDeviceInfo(pmDeviceIndex)->input) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} catch(...) { } |
|
|
|
|
} catch(...) { } // stoi() throws an exeption for invalid integers
|
|
|
|
|
cout << "Invalid selection" << endl;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -158,32 +162,34 @@ int main(void) { |
|
|
|
|
cout << i << ". " << deviceInfo->name << " (" << Pa_GetHostApiInfo(deviceInfo->hostApi)->name << ")" << endl; |
|
|
|
|
} |
|
|
|
|
PaHostApiIndex paDeviceIndex; |
|
|
|
|
for(;;) { |
|
|
|
|
for(;;) { // loop for input until valid choice is made
|
|
|
|
|
string input; |
|
|
|
|
getline(cin, input); |
|
|
|
|
try { |
|
|
|
|
paDeviceIndex = stoi(input); |
|
|
|
|
if(paDeviceIndex >= 0 && paDeviceIndex < paDeviceCount) { |
|
|
|
|
if( paDeviceIndex >= 0 && |
|
|
|
|
paDeviceIndex < paDeviceCount && |
|
|
|
|
Pa_GetDeviceInfo(paDeviceIndex)->maxOutputChannels >= 2) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} catch(...) { } |
|
|
|
|
} catch(...) { } // stoi() throws an exeption for invalid integers
|
|
|
|
|
cout << "Invalid selection" << endl;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Start MIDI timer and open MIDI input
|
|
|
|
|
Pt_Start(1, ptCallback, &state); |
|
|
|
|
|
|
|
|
|
PmError pmError = Pm_OpenInput( |
|
|
|
|
&state.pmStream, |
|
|
|
|
pmDeviceIndex, |
|
|
|
|
NULL, |
|
|
|
|
256, |
|
|
|
|
8, |
|
|
|
|
NULL, |
|
|
|
|
NULL); |
|
|
|
|
if(pmErr != pmNoError) { |
|
|
|
|
handlePMError(pmErr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Open an audio I/O stream. */ |
|
|
|
|
// Configure/start audio output stream
|
|
|
|
|
PaStream *paStream; |
|
|
|
|
PaStreamParameters paStreamParams; |
|
|
|
|
paStreamParams.device = paDeviceIndex; |
|
|
|
@ -193,17 +199,16 @@ int main(void) { |
|
|
|
|
paStreamParams.hostApiSpecificStreamInfo = NULL; |
|
|
|
|
paErr = Pa_OpenStream( |
|
|
|
|
&paStream, |
|
|
|
|
NULL, /* no input channels */ |
|
|
|
|
&paStreamParams, /* stereo output */ |
|
|
|
|
NULL, /* no input channels */ |
|
|
|
|
&paStreamParams, /* stereo output */ |
|
|
|
|
SAMPLE_RATE, |
|
|
|
|
0, /* frames per buffer */ |
|
|
|
|
0, /* frames per buffer */ |
|
|
|
|
paNoFlag, |
|
|
|
|
paCallback, |
|
|
|
|
&state); |
|
|
|
|
if(paErr != paNoError) { |
|
|
|
|
handlePAError(paErr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
paErr = Pa_StartStream(paStream); |
|
|
|
|
if(paErr != paNoError) {
|
|
|
|
|
handlePAError(paErr); |
|
|
|
@ -212,7 +217,7 @@ int main(void) { |
|
|
|
|
const PaStreamInfo *paStreamInfo = Pa_GetStreamInfo(paStream); |
|
|
|
|
cout << "Latency: " << round(1000 * paStreamInfo->outputLatency) << " ms" << endl; |
|
|
|
|
|
|
|
|
|
/* Wait for Return key */ |
|
|
|
|
// Wait for Return key
|
|
|
|
|
cout << "Running - press Enter to exit" << endl; |
|
|
|
|
getchar(); |
|
|
|
|
|
|
|
|
|