Skip to main content
Glama

SuperCollider MCP Server

by BradA1878
synth-library.ts6.84 kB
/** * Library of common SynthDefs for high-level sound synthesis * These are optimized for LLM-driven sound design */ export interface SynthParams { freq?: number; amp?: number; duration?: number; pan?: number; [key: string]: number | undefined; } export const SYNTH_DEFS = { // Simple sine wave tone sine: ` SynthDef(\\sine, { |freq=440, amp=0.3, pan=0, gate=1| var sig = SinOsc.ar(freq, 0, amp); var env = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, // Plucked string sound pluck: ` SynthDef(\\pluck, { |freq=440, amp=0.3, pan=0, decay=2| var sig = Pluck.ar( WhiteNoise.ar(amp), Impulse.kr(0), freq.reciprocal, freq.reciprocal, decay, coef: 0.1 ); var env = EnvGen.kr(Env.linen(0, decay, 0), doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, // Bell-like FM tone bell: ` SynthDef(\\bell, { |freq=440, amp=0.3, pan=0, duration=2| var modulator = SinOsc.ar(freq * 2.4, 0, freq * 0.8); var carrier = SinOsc.ar(freq + modulator, 0, amp); var env = EnvGen.kr(Env.perc(0.01, duration, 1, -4), doneAction: 2); Out.ar(0, Pan2.ar(carrier * env, pan)); }).add; `, // Bass tone bass: ` SynthDef(\\bass, { |freq=110, amp=0.4, pan=0, duration=1, cutoff=1000| var sig = LPF.ar(Saw.ar(freq), cutoff); var env = EnvGen.kr(Env.perc(0.01, duration), doneAction: 2); Out.ar(0, Pan2.ar(sig * env * amp, pan)); }).add; `, // Pad sound pad: ` SynthDef(\\pad, { |freq=220, amp=0.2, pan=0, gate=1, cutoff=2000| var sig = RLPF.ar( Saw.ar([freq, freq * 1.01], amp), cutoff, 0.5 ); var env = EnvGen.kr(Env.asr(0.5, 1, 2), gate, doneAction: 2); Out.ar(0, Pan2.ar(Mix(sig) * env, pan)); }).add; `, // Kick drum kick: ` SynthDef(\\kick, { |amp=0.5, pan=0| var freqEnv = EnvGen.kr(Env.perc(0.001, 0.3), 1, 60, 50); var sig = SinOsc.ar(freqEnv, 0, amp); var env = EnvGen.kr(Env.perc(0.001, 0.5), doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, // Snare drum snare: ` SynthDef(\\snare, { |amp=0.3, pan=0| var sig = WhiteNoise.ar(amp) + SinOsc.ar(180, 0, amp); var env = EnvGen.kr(Env.perc(0.001, 0.2), doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, // Hi-hat hihat: ` SynthDef(\\hihat, { |amp=0.2, pan=0| var sig = HPF.ar(WhiteNoise.ar(amp), 8000); var env = EnvGen.kr(Env.perc(0.001, 0.1), doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, // Atmospheric noise atmosphere: ` SynthDef(\\atmosphere, { |amp=0.15, pan=0, gate=1, cutoff=3000| var sig = RHPF.ar( PinkNoise.ar(amp), LFNoise1.kr(0.5).range(cutoff * 0.5, cutoff), 0.2 ); var env = EnvGen.kr(Env.asr(2, 1, 3), gate, doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, // Sweep/riser sweep: ` SynthDef(\\sweep, { |startFreq=100, endFreq=2000, amp=0.3, pan=0, duration=2| var freq = Line.kr(startFreq, endFreq, duration); var sig = Saw.ar(freq, amp); var env = EnvGen.kr(Env.linen(0.1, duration - 0.2, 0.1), doneAction: 2); Out.ar(0, Pan2.ar(sig * env, pan)); }).add; `, }; /** * Get the initialization code that loads all SynthDefs */ export function getSynthDefInitCode(): string { return Object.values(SYNTH_DEFS).join('\n\n'); } /** * Map common descriptive terms to synth names and parameters */ export function parseSynthDescription(description: string): { synthName: string; params: SynthParams; } { const lowerDesc = description.toLowerCase(); // Default params const params: SynthParams = { freq: 440, amp: 0.3, duration: 1, pan: 0, }; // Determine synth type let synthName = 'sine'; if (lowerDesc.includes('bell') || lowerDesc.includes('chime')) { synthName = 'bell'; } else if (lowerDesc.includes('pluck') || lowerDesc.includes('guitar') || lowerDesc.includes('string')) { synthName = 'pluck'; params.decay = 2; } else if (lowerDesc.includes('bass') || lowerDesc.includes('low')) { synthName = 'bass'; params.freq = 110; params.cutoff = 800; } else if (lowerDesc.includes('pad') || lowerDesc.includes('ambient') || lowerDesc.includes('warm')) { synthName = 'pad'; params.freq = 220; params.cutoff = 2000; } else if (lowerDesc.includes('kick') || lowerDesc.includes('drum')) { synthName = 'kick'; } else if (lowerDesc.includes('snare')) { synthName = 'snare'; } else if (lowerDesc.includes('hihat') || lowerDesc.includes('hi-hat')) { synthName = 'hihat'; } else if (lowerDesc.includes('atmosphere') || lowerDesc.includes('noise') || lowerDesc.includes('wind')) { synthName = 'atmosphere'; } else if (lowerDesc.includes('sweep') || lowerDesc.includes('riser') || lowerDesc.includes('swell')) { synthName = 'sweep'; } // Parse frequency/pitch const noteMatch = lowerDesc.match(/\b([a-g]#?)\s*(\d+)\b/i); if (noteMatch) { const note = noteMatch[1]; const octave = parseInt(noteMatch[2]); params.freq = noteToFreq(note, octave); } else { // Look for frequency in Hz const freqMatch = lowerDesc.match(/(\d+)\s*hz/i); if (freqMatch) { params.freq = parseInt(freqMatch[1]); } } // Parse descriptive pitch terms if (lowerDesc.includes('high') || lowerDesc.includes('bright')) { params.freq = (params.freq || 440) * 2; } else if (lowerDesc.includes('low') || lowerDesc.includes('deep')) { params.freq = (params.freq || 440) / 2; } // Parse duration const durMatch = lowerDesc.match(/(\d+(?:\.\d+)?)\s*(?:second|sec|s)\b/i); if (durMatch) { params.duration = parseFloat(durMatch[1]); } else if (lowerDesc.includes('short')) { params.duration = 0.3; } else if (lowerDesc.includes('long')) { params.duration = 3; } // Parse amplitude/volume if (lowerDesc.includes('loud') || lowerDesc.includes('forte')) { params.amp = 0.6; } else if (lowerDesc.includes('quiet') || lowerDesc.includes('soft') || lowerDesc.includes('piano')) { params.amp = 0.15; } // Parse panning if (lowerDesc.includes('left')) { params.pan = -0.7; } else if (lowerDesc.includes('right')) { params.pan = 0.7; } return { synthName, params }; } /** * Convert note name and octave to frequency */ function noteToFreq(note: string, octave: number): number { const noteMap: { [key: string]: number } = { 'c': -9, 'c#': -8, 'db': -8, 'd': -7, 'd#': -6, 'eb': -6, 'e': -5, 'f': -4, 'f#': -3, 'gb': -3, 'g': -2, 'g#': -1, 'ab': -1, 'a': 0, 'a#': 1, 'bb': 1, 'b': 2, }; const semitones = noteMap[note.toLowerCase()]; const a4 = 440; const semitonesFromA4 = (octave - 4) * 12 + semitones; return a4 * Math.pow(2, semitonesFromA4 / 12); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/BradA1878/mcp-wave'

If you have feedback or need assistance with the MCP directory API, please join our Discord server