对彼此独立工作的按钮重复使用功能



我正试图用P5.js创建一个类似于音频循环器的东西——也就是说,你录制一段音频片段,它作为循环播放给你,然后你可以录制其他音频片段一起播放来创作一首歌。

我想好了如何录制音频,将其作为循环播放,然后停止循环,但我不确定重复该功能的最佳方式,这样它就可以用于相互独立的按钮,并录制单独的音频文件,因为我想录制多个循环。

我对P5.js还很陌生,所以可能有一个简单的方法可以做到这一点——任何想法都有帮助!总的来说,如果你对如何实现这个项目(音频活套(有任何想法,我很乐意听到。

这是我的代码:

let mic, recorder, soundFile, button;
let state = 0;
function setup() {
createCanvas(windowWidth, windowHeight);
background(200);
mic = new p5.AudioIn();
mic.start();
recorder = new p5.SoundRecorder();
recorder.setInput(mic);
soundFile = new p5.SoundFile();
button = createButton("record");
button.size(200, 100);
button.style("font-family", "Bodoni");
button.style("font-size", "48px");
button.position(10, 10, 10);
button.mouseClicked(loopRecord);
}

// this is the looper
function loopRecord() {
if (state === 0 && mic.enabled) {
recorder.record(soundFile);
background(255, 0, 0);
state++;
} else if (state === 1) {
recorder.stop();
background(0, 255, 0);
state++;
} else if (state === 2) {
soundFile.loop();
state++;
} else if (state === 3) {
soundFile.stop();
state++;
} else if (state === 4) {
state === 0;
}
} 

您应该以某种方式构建数据,使每个按钮都有自己的状态(以及其他参数,这些参数不应该是全局的,而是每个循环唯一的(。

下面是一个使用轨迹对象数组的示例:https://editor.p5js.org/RemyDekor/sketches/gM75vBYmk

我也会在这里复制代码

let mic
// this array will be filled afterwards
let tracksArray = [];
function setup() {
createCanvas(400, 400);
background(200);

// we need only one mic (it is still global)
mic = new p5.AudioIn();
mic.start();

// we call a function that creates a custom "track" object and puts it in the tracksArray (which you could use for some other things, but is currently un-used)
createTrack();

// we create a button that call the same function when we click on it
const addTrackButton = createButton("add track");
addTrackButton.mouseClicked(createTrack)
addTrackButton.position(10, 10)
}
// We now use names (strings) instead of abstract numbers to set the state of the track
function handleTrackButtonClick(trackObject) {
if (trackObject.state === "idle" && mic.enabled) {
trackObject.recorder.record(trackObject.soundFile);
background(255, 0, 0);

trackObject.state = "recording";
console.dir(trackObject.button.elt.innerText = "[recording..]");

} else if (trackObject.state === "recording") {
trackObject.recorder.stop();
background(0, 255, 0);

trackObject.state = "stopped";
console.dir(trackObject.button.elt.innerText = "play");

} else if (trackObject.state === "stopped") {
trackObject.soundFile.loop();

trackObject.state = "playing";
console.dir(trackObject.button.elt.innerText = "[playing..] stop")

} else if (trackObject.state === "playing") {
trackObject.soundFile.stop();

trackObject.state = "stopped";
console.dir(trackObject.button.elt.innerText = "[stopped..] play")
}
}

function createTrack() {
const newButton = createButton("record");
newButton.style("font-family", "Bodoni");
newButton.style("font-size", "48px");
// we do not position this button anymore, and use the "flow" of the html document
newButton.style("display", "block");

// this is the "track" object we create, and we attach the previously global parameters/states on it
const newTrackObject = {
button: newButton,
state: "idle",
recorder: new p5.SoundRecorder(),
soundFile: new p5.SoundFile()
};

newButton.mouseClicked(function() {
handleTrackButtonClick(newTrackObject)
});

newTrackObject.recorder.setInput(mic);

tracksArray.push(newTrackObject);
}