Improving an audio pass through

Hy there,

I’m trying to make a good audio pass through with OF.
The purpose is to get a good sound quality, even with some buffer delays, control the audio level, use it with a magewell usb capture card as input, …
I’m starting with this
the ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{

	public:

		void setup();
		void update();
		void draw();

		void keyPressed  (int key);
		
		void audioOut(ofSoundBuffer & buffer);
		void audioIn(ofSoundBuffer & input);
		ofSoundBuffer lastBuffer;

		ofSoundStream soundStream;
		float volume;
		int		sampleRate;
	

};

the ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

	ofBackground(34, 34, 34);
	
	int bufferSize		= 512;
	sampleRate 			= 44100;
	
	soundStream.printDeviceList();

	ofSoundStreamSettings settings;

	auto devices = soundStream.getMatchingDevices("default");
	if (!devices.empty()) {
		settings.setInDevice(devices[0]);
	}

	settings.setOutListener(this);
	settings.setInListener(this);
	settings.sampleRate = sampleRate;
	settings.numOutputChannels = 2;
	settings.numInputChannels = 2;
	settings.bufferSize = bufferSize;
	soundStream.setup(settings);

	lastBuffer.allocate(bufferSize, 2);

	volume = 0.15;
}

//--------------------------------------------------------------
void ofApp::update(){
}

//--------------------------------------------------------------
void ofApp::draw(){
}

//--------------------------------------------------------------
void ofApp::keyPressed  (int key){
	if (key == '-' || key == '_' ){
		volume -= 0.05;
		volume = MAX(volume, 0);
	} else if (key == '+' || key == '=' ){
		volume += 0.05;
		volume = MIN(volume, 1);
	}
}

//--------------------------------------------------------------
void ofApp::audioOut(ofSoundBuffer & buffer){
	if (lastBuffer.getNumFrames() > 0) { 
		buffer = lastBuffer;
	}
	else {
		buffer.set(0);
		cout << " lost ";
	}
}

//--------------------------------------------------------------
void ofApp::audioIn(ofSoundBuffer & input) {
	lastBuffer = input;
}


When I compile it in vs it’s almost good (cracking sometimes).
When I run the release exe it’s really cracking constantly. The behaviour is not the same.
Is there a way to improve this ?

Changing

if (lastBuffer.getNumFrames() > 0)

to

if (lastBuffer.getTickCount() > 4)

and does not seems to add delays

Actually it’s every time the same :
Sometimes the audio start correctly (no cracks or glitches)
Most of the time (90%) the audio is cracking and glitching (seems to have the right buffer one out of two) permanently and become correct one or two minutes later.
I have to run the app from vs to make it works correctly.
And then, after I have launched it from vs, I can launch the exe and it works (almost) correctly (75% success).
Is there a way to make it works every time ?

Not sure if it helps but I would try to use threads to avoid buffer being written while read,
There is some info here:
https://openframeworks.cc/ofBook/chapters/sound.html

maybe you can use more than one buffer (lastbuffer) so you just lock the thread the minimum time to copy one buffer to the other.

1 Like

Thank you Dimitre.
Indeed, this is the way.
I use an

ofThreadChannel<ofSoundBuffer> channel;

and change audioIn and audioOut to

//--------------------------------------------------------------
void ofApp::audioOut(ofSoundBuffer & buffer){
	if (buffer.getTickCount() > 4) {
		channel.receive(buffer);
	}
	else {
		buffer.set(0);
		cout << " lost ";
	}
}

//--------------------------------------------------------------
void ofApp::audioIn(ofSoundBuffer & input) {
	channel.send(input*volume);
}

It really improves (it works one time of 2)
and when I change the choice of the devices in setup to

auto devices = soundStream.getDeviceList(ofSoundDevice::Api::MS_DS);
	settings.setInDevice(devices[3]);
	settings.setOutDevice(devices[1]);

and then it works every time

2 Likes