ComfyUI-KJNodes/web/js/jsnodes.js
2023-12-10 20:07:03 +02:00

147 lines
6.1 KiB
JavaScript

import { app } from "../../../scripts/app.js";
app.registerExtension({
name: "KJNodes.ConditioningMultiCombine",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
switch (nodeData.name) {
case "ConditioningMultiCombine":
nodeType.prototype.onNodeMoved = function () {
console.log(this.pos[0])
}
nodeType.prototype.onNodeCreated = function () {
//this.inputs_offset = nodeData.name.includes("selective")?1:0
this.cond_type = "CONDITIONING"
this.inputs_offset = nodeData.name.includes("selective")?1:0
this.addWidget("button", "Update inputs", null, () => {
if (!this.inputs) {
this.inputs = [];
}
const target_number_of_inputs = this.widgets.find(w => w.name === "inputcount")["value"];
if(target_number_of_inputs===this.inputs.length)return; // already set, do nothing
if(target_number_of_inputs < this.inputs.length){
for(let i = this.inputs.length; i>=this.inputs_offset+target_number_of_inputs; i--)
this.removeInput(i)
}
else{
for(let i = this.inputs.length+1-this.inputs_offset; i <= target_number_of_inputs; ++i)
this.addInput(`conditioning_${i}`, this.cond_type)
}
});
}
case "SoundReactive":
nodeType.prototype.onNodeCreated = function () {
let audioContext;
let microphoneStream;
let animationFrameId;
let analyser;
let dataArray;
let lowRangeHz;
let midRangeHz;
// Function to update the widget value in real-time
const updateWidgetValueInRealTime = () => {
// Ensure analyser and dataArray are defined before using them
if (analyser && dataArray) {
analyser.getByteFrequencyData(dataArray);
// Calculate frequency bin width (frequency resolution)
const frequencyBinWidth = audioContext.sampleRate / analyser.fftSize;
// Convert the widget values from Hz to indices
const lowRangeIndex = Math.floor(lowRangeHz / frequencyBinWidth);
const midRangeIndex = Math.floor(midRangeHz / frequencyBinWidth);
// Define frequency ranges for low, mid, and high
const frequencyRanges = {
low: { start: 0, end: lowRangeIndex },
mid: { start: lowRangeIndex, end: midRangeIndex },
high: { start: midRangeIndex, end: dataArray.length }
};
const lowRangeHzWidget = this.widgets.find(w => w.name === "low_range_hz");
if (lowRangeHzWidget) lowRangeHz = lowRangeHzWidget.value;
const midRangeHzWidget = this.widgets.find(w => w.name === "mid_range_hz");
if (midRangeHzWidget) midRangeHz = midRangeHzWidget.value;
// Function to calculate the average value for a frequency range
const calculateAverage = (start, end) => {
const sum = dataArray.slice(start, end).reduce((acc, val) => acc + val, 0);
return sum / (end - start);
};
// Calculate the average levels for each frequency range
const lowLevel = calculateAverage(frequencyRanges.low.start, frequencyRanges.low.end);
const midLevel = calculateAverage(frequencyRanges.low.end, frequencyRanges.mid.end); // mid starts where low ends
const highLevel = calculateAverage(frequencyRanges.mid.end, frequencyRanges.high.end); // high starts where mid ends
const averageLevel = dataArray.reduce((sum, averageLevel) => sum + averageLevel, 0) / dataArray.length;
// Update the widget values
const averageLevelWidget = this.widgets.find(w => w.name === "average_level");
if (averageLevelWidget) averageLevelWidget.value = averageLevel;
const lowLevelWidget = this.widgets.find(w => w.name === "low_level");
if (lowLevelWidget) lowLevelWidget.value = lowLevel;
const midLevelWidget = this.widgets.find(w => w.name === "mid_level");
if (midLevelWidget) midLevelWidget.value = midLevel;
const highLevelWidget = this.widgets.find(w => w.name === "high_level");
if (highLevelWidget) highLevelWidget.value = highLevel;
animationFrameId = requestAnimationFrame(updateWidgetValueInRealTime);
}
};
// Function to start capturing audio from the microphone
const startMicrophoneCapture = () => {
// Only create the audio context and analyser once
if (!audioContext) {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
// Access the sample rate of the audio context
console.log(`Sample rate: ${audioContext.sampleRate}Hz`);
analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
dataArray = new Uint8Array(analyser.frequencyBinCount);
// Get the range values from widgets (assumed to be in Hz)
const lowRangeWidget = this.widgets.find(w => w.name === "low_range_hz");
if (lowRangeWidget) lowRangeHz = lowRangeWidget.value;
const midRangeWidget = this.widgets.find(w => w.name === "mid_range_hz");
if (midRangeWidget) midRangeHz = midRangeWidget.value;
}
navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
microphoneStream = stream;
const microphone = audioContext.createMediaStreamSource(stream);
microphone.connect(analyser);
updateWidgetValueInRealTime();
}).catch(error => {
console.error('Access to microphone was denied or an error occurred:', error);
});
};
// Function to stop capturing audio from the microphone
const stopMicrophoneCapture = () => {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
if (microphoneStream) {
microphoneStream.getTracks().forEach(track => track.stop());
}
if (audioContext) {
audioContext.close();
// Reset audioContext to ensure it can be created again when starting
audioContext = null;
}
};
// Add start button
this.addWidget("button", "Start mic capture", null, startMicrophoneCapture);
// Add stop button
this.addWidget("button", "Stop mic capture", null, stopMicrophoneCapture);
};
break;
}
},
});