@williamzujkowski/strudel-mcp-server
Version:
Advanced MCP server for AI-powered music generation with Strudel.cc
88 lines (87 loc) • 4.41 kB
JavaScript
export class AudioAnalyzer {
async inject(page) {
await page.evaluate(() => {
window.strudelAudioAnalyzer = {
analyser: null,
dataArray: null,
isConnected: false,
connect() {
const originalGainConnect = GainNode.prototype.connect;
let intercepted = false;
GainNode.prototype.connect = function (...args) {
if (!intercepted && args[0] && args[0].context) {
intercepted = true;
const ctx = args[0].context;
window.strudelAudioAnalyzer.analyser = ctx.createAnalyser();
window.strudelAudioAnalyzer.analyser.fftSize = 2048;
window.strudelAudioAnalyzer.dataArray = new Uint8Array(window.strudelAudioAnalyzer.analyser.frequencyBinCount);
const result = originalGainConnect.apply(this, args);
originalGainConnect.call(this, window.strudelAudioAnalyzer.analyser);
window.strudelAudioAnalyzer.isConnected = true;
console.log('Audio analyzer connected to Strudel');
return result;
}
return originalGainConnect.apply(this, args);
};
},
analyze() {
if (!this.analyser || !this.isConnected) {
return {
connected: false,
error: 'Analyzer not connected'
};
}
this.analyser.getByteFrequencyData(this.dataArray);
const data = Array.from(this.dataArray);
const sum = data.reduce((a, b) => a + b, 0);
const average = sum / data.length;
const bass = data.slice(0, 8).reduce((a, b) => a + b, 0) / 8;
const lowMid = data.slice(8, 32).reduce((a, b) => a + b, 0) / 24;
const mid = data.slice(32, 128).reduce((a, b) => a + b, 0) / 96;
const highMid = data.slice(128, 256).reduce((a, b) => a + b, 0) / 128;
const treble = data.slice(256, 512).reduce((a, b) => a + b, 0) / 256;
const peak = Math.max(...data);
const peakIndex = data.indexOf(peak);
const peakFreq = (peakIndex / data.length) * 22050;
let weightedSum = 0;
let magnitudeSum = 0;
data.forEach((mag, i) => {
weightedSum += i * mag;
magnitudeSum += mag;
});
const centroid = magnitudeSum > 0 ? weightedSum / magnitudeSum : 0;
const isPlaying = average > 5;
const isSilent = average < 1;
return {
connected: true,
timestamp: Date.now(),
features: {
average: Math.round(average * 10) / 10,
peak,
peakFrequency: Math.round(peakFreq),
centroid: Math.round(centroid * 10) / 10,
bass: Math.round(bass),
lowMid: Math.round(lowMid),
mid: Math.round(mid),
highMid: Math.round(highMid),
treble: Math.round(treble),
isPlaying,
isSilent,
bassToTrebleRatio: treble > 0 ? (bass / treble).toFixed(2) : 'N/A',
brightness: centroid > 500 ? 'bright' : centroid > 200 ? 'balanced' : 'dark'
}
};
}
};
window.strudelAudioAnalyzer.connect();
});
}
async getAnalysis(page) {
return await page.evaluate(() => {
if (window.strudelAudioAnalyzer) {
return window.strudelAudioAnalyzer.analyze();
}
return { error: 'Analyzer not initialized' };
});
}
}