Last active
June 25, 2017 15:02
-
-
Save AliBarber/a4077b558b66b3f6285d8bd069a06e2f to your computer and use it in GitHub Desktop.
Pipe audio from an input device to another input device using PortAudio. Tested / Built on Mac, should be cross platform. Not the most efficient - working on callback based method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* AudioPipe.cpp - Alastair Barber 2017. | |
* Will open a device, read from it, and write the audio to another device. Eg. Mic -> HDMI sound output | |
*/ | |
#include "portaudio.h" | |
#include <iostream> | |
#include <signal.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
using namespace std; | |
#define NUM_CHANNELS 2 | |
#define SAMPLE_RATE (44100) | |
#define FRAMES_PER_BUFFER (128) | |
//Not great - put it here so our signal catching method | |
// can shut it down when CTRL-C is caught | |
PaStream *stream; | |
//Little utility that should try and handle errors | |
void PA(PaError err, int shouldExit) | |
{ | |
if(err == paNoError) return; | |
std::cerr << "PortAudio error: " << Pa_GetErrorText(err) << "\n"; | |
if(shouldExit == 1) | |
{ | |
std::cout << "Shutting down due to error.\n"; | |
err = Pa_Terminate(); | |
exit(1); | |
} | |
} | |
int selectDevice(int showList, string message) | |
{ | |
//Assumes PortAudio has been initialised | |
if(showList == 1) | |
{ | |
int numDevices; | |
int i; | |
numDevices = Pa_GetDeviceCount(); | |
cout << "Found the following devices:\n"; | |
for(i = 0; i < numDevices; i++) | |
{ | |
cout << "\t" << i << ": " << Pa_GetDeviceInfo(i)->name; | |
if(Pa_GetDeviceInfo(i)->maxInputChannels > 0) | |
{ | |
cout << " (Input)"; | |
} | |
if(Pa_GetDeviceInfo(i)->maxOutputChannels > 0) | |
{ | |
cout << " (Output)"; | |
} | |
cout << "\n"; | |
} | |
} | |
cout << "Select " << message << " device: "; | |
string buffer; | |
cin >> buffer; | |
return atoi(buffer.c_str()); | |
} | |
void shutDown() | |
{ | |
cout << "Stopping\n"; | |
PA(Pa_StopStream(stream),0); | |
PA(Pa_CloseStream(stream),0); | |
Pa_Terminate(); | |
} | |
void sigHandler(int s) | |
{ | |
// std::cout << "\nCaught signal " << s << "\nTerminating\n"; | |
shutDown(); | |
exit(0); | |
} | |
int main(int argc, char** argv) | |
{ | |
PA(Pa_Initialize(),1); | |
// Set up a sigint handler to exit cleanly and terminate port audio | |
struct sigaction sigIntHandler; | |
sigIntHandler.sa_handler = sigHandler; | |
sigemptyset(&sigIntHandler.sa_mask); | |
sigIntHandler.sa_flags = 0; | |
sigaction(SIGINT, &sigIntHandler, NULL); | |
int inputDeviceNumber = selectDevice(1,"Input"); | |
int outputDeviceNumber = selectDevice(0,"Output"); | |
PaStreamParameters inParameters; | |
PaStreamParameters outParameters; | |
bzero(&inParameters, sizeof(inParameters)); | |
bzero(&outParameters, sizeof(outParameters)); | |
inParameters.device = inputDeviceNumber; | |
inParameters.channelCount = NUM_CHANNELS; | |
inParameters.sampleFormat = paFloat32; | |
inParameters.hostApiSpecificStreamInfo = NULL; | |
inParameters.suggestedLatency = Pa_GetDeviceInfo(inParameters.device)->defaultLowInputLatency; | |
outParameters.device = outputDeviceNumber; | |
outParameters.channelCount = NUM_CHANNELS; | |
outParameters.sampleFormat = paFloat32; | |
outParameters.suggestedLatency = Pa_GetDeviceInfo(outParameters.device)->defaultLowOutputLatency; | |
outParameters.hostApiSpecificStreamInfo = NULL; | |
//Open a stream | |
PA(Pa_OpenStream( | |
&stream, | |
&inParameters, | |
&outParameters, | |
SAMPLE_RATE, | |
FRAMES_PER_BUFFER, | |
paClipOff, | |
NULL, | |
NULL),1); | |
//Start the stream | |
PA(Pa_StartStream(stream),1); | |
cout << "Opened - Sending Audio from: " << Pa_GetDeviceInfo(inputDeviceNumber)->name << " to: " << Pa_GetDeviceInfo(outputDeviceNumber)->name <<"\n"; | |
cout << "CTRL-C to stop\n"; | |
float sampleBlock[FRAMES_PER_BUFFER * NUM_CHANNELS] = {0}; | |
while(1) | |
{ | |
PA(Pa_WriteStream(stream, sampleBlock, FRAMES_PER_BUFFER),0); | |
PA(Pa_ReadStream(stream, sampleBlock, FRAMES_PER_BUFFER),0); | |
} | |
shutDown(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment