Hello ,
I am new to Juce, and I’m trying to develop a program where I can stream the inputs from my audio interface to another audio interface over my local network.
Concretely, I have Computer A with audio interface A and Computer B with audio interface B. And I want that whatever audio that is captured on input channel 1 on the audio interface A is sent to output channel 1 on audio interface B. (and vice versa)
I decided to use Juce for this, as it seemed very practical to control audio interfaces. So what I did is I created a standalone Audio Application with the Projucer. And I followed the tutorial on OSCReceiver / Sender to create my network communication and send my Audio Buffers.
So my implementation is as follows:
-
In
getNextAudioBlock()
of myMainComponent
, I get the input buffer (I have only one channel active) and pass the raw input buffer to myConnectionManager
(which sends it) like this//================================= LOCAL INPUTS ================================= int i = 0; // Used for sending to the corresponding freq diagramm component for (auto inputChannel = 0; inputChannel < maxInputChannels; inputChannel++) { if (! activeInputChannels[inputChannel]) // Individual input channels may be inactive so we don't want to store the data { bufferToFill.buffer->clear (inputChannel, bufferToFill.startSample, bufferToFill.numSamples); } else { // Here we get pointer to the input and send it to the network auto* inBuffer = bufferToFill.buffer->getReadPointer (inputChannel, bufferToFill.startSample); // If we are connected, we send data to the distant instance and we play the data if(networkManager.isConnected()){ networkManager.sendAudioBuffer(i, inBuffer, bufferToFill.numSamples); } i++; } }
-
In my
sendAudioBuffer()
function of myNetworkManager
, I create an OSC message object where I add the channel (ch0) as an Int argument and then I add all the samples of the buffer as Float arguments (e.g with buffer size 512 the message has a length of 513)
juce::OSCMessage msg(juce::OSCAddressPattern("/creepy-table")); // Declare and initialize message
msg.addArgument(juce::OSCArgument(inputID)); // Add the channel id
for(int i=0; i<bufferSize; ++i){
msg.addArgument(juce::OSCArgument(buffer[i])); // Add every sample
}
- My
NetworkManager
implementsOSCReceiver
and in theoscMessageReceived()
method, (on the other machine) I get the message get the channel and buffer out and put it in ajuce::AudioBuffer
void NetworkManager::processOSCMessage(juce::OSCMessage message){
if (message.size() > 2){
// Case where it starts with int, then it's an audio buffer with first argument as channel
if (message[0].isInt32()){
int channel = message[0].getInt32(); // Declare channel to use
// Channel has to be positive and msg length has to be inferior or equal to buffer size
if (channel >= 0 && message.size()-1 <= distantAudioBuffer->getNumSamples()) {
juce::Array<float> buffer; // Declare a temporary buffer for practicality
for (int i=1; i<message.size(); ++i){ // Starts at 1 because in this formatted OSC messsages the float arguments start after 1 (0 is for channel)
if (message[i].isFloat32()) buffer.add(message[i].getFloat32());
}
distantAudioBuffer->copyFrom(channel, 0, buffer.data(), buffer.size()); // Put the samples in distantAudioBuffer then used by distantAudioSource object in mainComponent
}
}
}
}
- The same
AudioBuffer
is then read ingetNextAudioBlock()
and the content of my distant received buffer is copied in theoutBuffer
to be played
auto* outBuffer = bufferToFill.buffer->getWritePointer (outputChannel, bufferToFill.startSample); // Buffer to output
auto* distantBuffer = distantAudioBuffer.getReadPointer(outputChannel); // Distant input buffer
for (auto sample = 0; sample < bufferToFill.numSamples; ++sample)
outBuffer[sample] = distantBuffer[sample];
So it kinda works, I manage to send and receive the messages, however my problem is that the signal received is …weird. I tried to send the signal from an electric guitar connected to my audio interface A, and basically it sounds horrible. Notes are still somehow recognisable, but there is a huge buzzing sound on top whenevever there is sound to be played.
(If you want to listen to it you can check it here, but it’s horrible)
https://sndup.net/9zxn
I display (like on of the juce tutorials does) the signal I output to the speakers. And it looks similar to the signal originally sent, but the received signal looks imprecise. I don’t know if my weird sound comes from this.
I am a bit stuck, and I’m not sure how to fix my issue as I don’t have much experience in audio processing and Juce.
- Does the use of OSCMessages make sense to send Audio Buffers via network? Does it even make sense to send Audio Buffers?
- Do you have an idea why the received signal looks less accurate and sharp then what is originally sent? Could it be from the way I read my buffer?
As additional infos: I use a samplerate of 44100Hz and buffer size of 512 with bit depth of 24
If someone could help me figure out ways to continue, or give hints / opinions on the methods I use / my implementation, it would be greatly appreciated
Cheers,
P