Skip to content

Instantly share code, notes, and snippets.

@AliBarber
Last active June 25, 2017 15:02
Show Gist options
  • Save AliBarber/a4077b558b66b3f6285d8bd069a06e2f to your computer and use it in GitHub Desktop.
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.
/*
* 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