Error when trying to save output audio in P5js sound

The documentation for p5.SoundRecorder is pretty clear when it says what is going to record:

Record sounds for playback and/or to save as a .wav file. The p5.SoundRecorder records all sound output from your sketch, or can be assigned a specific source with setInput().

And the only example I had seen out there is using the microphone as an input (for example reference | p5.js).

I was expecting sound recorder to record the output from the output sound in the system but trying to do that will end up in an error:

p5.sound.min.js:2 Uncaught TypeError: Cannot read property 'getChannelData' of null

When trying to save the recorded audio with the save method. To show what I mean I have a simple example made in this link index.html · GitHub.

now that is clear what is the problem, my question is simple: How to record the generated audio from the sketch? clearly SoundRecorder is not working.

I tried adding p5.soundOut as the input with setInput, the same problem is still there.

P5js version 1.3.1
P5js sound version 0.3.12

1 Like

I haven’t looked at how SoundRecorder.setInput works, but try calling .connect(recorder) on all of your sound generating elements before you call .record(outputSound) on your SoundRecorder. Live example: Recording Experiments - OpenProcessing

let tada, ding;
let tone;

let recordedSound;
let recorder;
let isRecording = false;
let tonePlaying = false;

let toneBtn;
let tadaBtn;
let dingBtn;
let recordBtn;
let replayBtn;

function preload() {
	tada = loadSound('https://www.paulwheeler.us/files/TADA.WAV');
	ding = loadSound('https://www.paulwheeler.us/files/DING.WAV');
}

function setup() {
	noCanvas();
	
	tone = new p5.Oscillator('sine');
	tone.freq(261.63);
	tone.amp(0);
	
	toneBtn = createButton('Play Tone');
	toneBtn.mouseClicked(() => {
		if (!tonePlaying) {
			tone.start();
			tone.amp(0.5, 0.5);
			toneBtn.html('Stop Tone');
			tonePlaying = true;
		} else {
			tone.amp(0, 0.5);
			toneBtn.html('Play Tone');
			tonePlaying = false;
		}
	});
	
	tadaBtn = createButton('Tada');
	tadaBtn.mouseClicked(() => {
		if (!tada.isPlaying()) {
			tada.play();
			tadaBtn.html('Stop');
		} else {
			tada.stop();
		}
	});
	
	tada.onended(() => {
		tadaBtn.html('Tada');
	});
	
	dingBtn = createButton('Ding');
	dingBtn.mouseClicked(() => {
		if (!ding.isPlaying()) {
			ding.play();
			dingBtn.html('Stop');
		} else {
			ding.stop();
		}
	});
	
	ding.onended(() => {
		dingBtn.html('Ding');
	});
	
	recordButton = createButton('Record');
	recordButton.mouseClicked(() => {
		if (!isRecording) {
			recordedSound = new p5.SoundFile();
			recorder = new p5.SoundRecorder();
			tada.connect(recorder);
			ding.connect(recorder);
			tone.connect(recorder);
			recorder.record(recordedSound);
			recordButton.html('Stop Recording');
			isRecording = true;
		} else {
			recorder.stop();
			recordedSound.onended(() => {
				replayBtn.html('Replay');
			});
			recordButton.html('Record');
			isRecording = false;
		}
	});
	
	replayBtn = createButton('Replay');
	replayBtn.mouseClicked(() => {
		if (!isRecording) {
			if (recordedSound) {
				if (!recordedSound.isPlaying()) {
					recordedSound.play();
					replayBtn.html('Stop Replay');
				} else {
					recordedSound.stop();
				}
			} else {
				print('Nothing has been recorded yet!');
			}
		} else {
			print('Can\'t replay while recording!');
		}
	});
	
	noLoop();
}

function draw() {
}