I'm working on p5.js web editor to create a program that from a an input audio files, divide it in segment, random shuffle them, and recompose them. this part of the program is working well and the new output audio generate with random order segments is played. the problem is that I can't add the audio effects to the new audio source from the output buffer.
let audioFile;
let audioBuffer;
let segmentLength = 100; // length of each segment in milliseconds
let segments = [];
let audioContext;
function preload() {
audioFile = loadSound('sounds/02ContortYourself.mp3');
}
function setup() {
createCanvas(400, 400);
// Create a new AudioContext object
audioContext = new AudioContext();
// Load the audio file and decode it into an AudioBuffer object
audioFile.play();
audioBuffer = audioFile.buffer;
// Split the audio buffer into segments of the specified length
let numSegments = Math.ceil(audioBuffer.duration * 1000 / segmentLength);
for(let i = 0; i < numSegments; i++) {
let go = i * segmentLength / 1000;
let end = go + segmentLength / 1000;
let segment = audioBuffer.getChannelData(0).subarray(go * audioBuffer.sampleRate, end * audioBuffer.sampleRate);
segments.push(segment);
// Print the length of the segment in milliseconds
console.log(`Segment ${i}: ${segmentLength}ms`);
}
// Shuffle the segments array using the Fisher-Yates shuffle algorithm
for (let i = segments.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[segments[i], segments[j]] = [segments[j], segments[i]];
}
// Create a new audio buffer for the output song
let outputBuffer = new AudioBuffer({
numberOfChannels: 1,
length: audioBuffer.length,
sampleRate: audioBuffer.sampleRate
});
// Copy each segment into the output buffer in their shuffled order
for (let i = 0; i < segments.length; i++) {
let offset = i * segmentLength * audioBuffer.sampleRate / 1000;
outputBuffer.copyToChannel(segments[i], 0, offset);
}
// Create a new audio source from the output buffer and play it
let outputSource = new AudioBufferSourceNode(audioContext, { buffer: outputBuffer });
outputSource.connect(audioContext.destination);
outputSource.start();
}
my idea is to add the effects to the outputSource before it is played by the start function. in this way, in the next pahase of the project, I think I can easily implement on/off button to apply or not the effects.
this is what I have tried but it is not working.
let audioFile;
let audioBuffer;
let segmentLength = 100; // length of each segment in milliseconds
let patternLength = 15; // length of each pattern in segments
let numPatterns; // number of patterns in the final output
let numSegments; // total number of segments in the output
let segments = [];
let patterns = [];
let audioContext;
function preload() {
console.log('Loading audio file...');
audioFile = loadSound('sounds/02ContortYourself.mp3', onAudioLoaded, onAudioLoadError);
}
function onAudioLoaded() {
console.log('Audio file loaded successfully!');
// Create a new AudioContext object
audioContext = new AudioContext();
// Get the decoded audio buffer from the loaded audio file
audioBuffer = audioFile.buffer;
// Calculate the maximum number of patterns and segments that fit within 1 minute
let maxDuration = 60; // maximum duration of the output song in seconds
numPatterns = Math.floor(maxDuration * 1000 / (segmentLength * patternLength));
numSegments = numPatterns * patternLength;
// Split the audio buffer into segments of the specified length, up to the maximum duration
for(let i = 0; i < numSegments; i++) {
let go = i * segmentLength / 1000;
let end = go + segmentLength / 1000;
let segment = audioBuffer.getChannelData(0).subarray(go * audioBuffer.sampleRate, end * audioBuffer.sampleRate);
segments.push(segment);
// Print the length of the segment in milliseconds
console.log(`Segment ${i}: ${segmentLength}ms`);
}
// Shuffle the segments array using the Fisher-Yates shuffle algorithm
for (let i = segments.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[segments[i], segments[j]] = [segments[j], segments[i]];
}
// Group segments into patterns
for (let i = 0; i < numPatterns; i++) {
let pattern = [];
for (let j = 0; j < patternLength; j++) {
pattern.push(segments[i * patternLength + j]);
}
patterns.push(pattern);
}
// Arrange patterns in a specific sequence
let patternSequence = [0, 0, 2, 2, 1, 1, 3, 3, 3, 3, 2, 0, 1]; // example pattern sequence
let outputSegments = [];
while (outputSegments.length < numSegments) {
outputSegments = outputSegments.concat(patternSequence.map(index => patterns[index]).flat());
}
outputSegments = outputSegments.slice(0, numSegments);
// Create a new audio buffer for the output song
let outputBuffer = new AudioBuffer({
numberOfChannels: 1,
length: outputSegments.length * segmentLength * audioBuffer.sampleRate / 1000,
sampleRate: audioBuffer.sampleRate
});
// Copy each segment into the output buffer in their arranged order
for (let i = 0; i < outputSegments.length; i++) {
let offset = i * segmentLength * audioBuffer.sampleRate / 1000;
outputBuffer.copyToChannel(outputSegments[i], 0, offset);
}
// Create a new audio source from the output buffer and play it
let outputSource = new AudioBufferSourceNode(audioContext, { buffer: outputBuffer });
outputSource.connect(audioContext.destination);
// Resume the audio context to allow audio playback
audioContext.resume();
// Apply a reverb effect to the output source
let reverb = new p5.Reverb();
reverb.set(3, 2); // set the decay time to 3 seconds and the wet/dry mix to 2:1
outputSource.connect(reverb);
reverb.connect(audioContext.destination);
reverb.process(outputSource);
console.log('Output song generated successfully!');
}
function onAudioLoadError() {
console.error('Error loading audio file!');
}
function setup() {
createCanvas(400, 400);
}
this is the error I get: p5.sound.min.js:2 Uncaught Error: error connecting to node: [object GainNode] InvalidAccessError: Failed to execute 'connect' on 'AudioNode': cannot connect to an AudioNode belonging to a different audio context. at AudioBufferSourceNode.t [as connect] (p5.sound.min.js:2:20784) at AudioBufferSourceNode.t [as connect] (p5.sound.min.js:2:20680) at p5.onAudioLoaded (119a770a-9f38-49e8-befa-b7046f10e9d7:87:14) at p5.sound.min.js:2:198861 at AudioContext. (p5.sound.min.js:2:102726)
I don't know if this is the correct way of doing that. I appreciate any suggestion on how to solve the problem or better ways to apply effects from p5.js sound library.
i have already installed all the necessary library.
thanks you very much for helping!