generate_drum_groups
Create DecentSampler drum kit XML configurations by organizing samples into groups with velocity layers, muting, and optional advanced controls for realistic drum presets.
Instructions
Generate DecentSampler XML for drum kits.
This tool supports two configuration types:
BasicDrumKitConfig:
For simple presets with minimal features
No UI controls, effects, or routing
Only supports basic sample mapping and optional velocity layers
Recommended for straightforward drum kits
AdvancedDrumKitConfig:
For complex setups combining multiple features
Supports UI controls, effects, and routing
Integrates with other tools (configure_drum_controls, configure_mic_routing, etc.)
Use when you need advanced features like round robin or multi-mic setups
Best Practices:
IMPORTANT: Always use absolute paths (e.g., 'C:/Users/username/Documents/Samples/kick.wav')
Group all samples for a drum piece into a single group
When using multiple mic positions, include them all in the same group
Use velocity layers within a group to control dynamics
Error Handling:
Validates all sample paths exist
Checks for valid MIDI note numbers
Ensures velocity layers don't overlap
Verifies muting group configurations
Returns specific errors for any invalid settings
Example Configurations:
Basic Configuration (simple drum kit): { "globalSettings": { "velocityLayers": [ { "low": 1, "high": 42, "name": "soft" }, { "low": 43, "high": 85, "name": "medium" }, { "low": 86, "high": 127, "name": "hard" } ] }, "drumPieces": [{ "name": "Kick", "rootNote": 36, "samples": [ {"path": "C:/Samples/Kick_Soft.wav"}, {"path": "C:/Samples/Kick_Medium.wav"}, {"path": "C:/Samples/Kick_Hard.wav"} ] }] }
Advanced Configuration (multi-mic kit with controls): { "globalSettings": { "velocityLayers": [ { "low": 1, "high": 127, "name": "full" } ], "drumControls": { "kick": { "pitch": { "default": 0, "min": -12, "max": 12 }, "envelope": { "attack": 0.001, "decay": 0.5, "sustain": 0, "release": 0.1 } } }, "micBuses": [ { "name": "Close Mic", "outputTarget": "MAIN_OUTPUT", "volume": { "default": 0, "midiCC": 20 } } ] }, "drumPieces": [{ "name": "Kick", "rootNote": 36, "samples": [ { "path": "C:/Samples/Kick_Close.wav", "micConfig": { "position": "close", "busIndex": 0 } } ], "muting": { "tags": ["kick"], "silencedByTags": [] } }] }
Success Response: Returns complete XML structure with:
Organized sample groups
Velocity layer mappings
Muting group configurations
All sample references and settings
Advanced features when using AdvancedDrumKitConfig
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| globalSettings | Yes | ||
| drumPieces | Yes |
Implementation Reference
- src/index.ts:676-713 (handler)MCP CallToolRequestSchema handler case for 'generate_drum_groups'. Validates input using type guards for BasicDrumKitConfig or AdvancedDrumKitConfig and calls generateGroupsXml to produce the XML output.case "generate_drum_groups": { // Validate input matches our expected type const args = request.params.arguments; if (!args || typeof args !== 'object') { throw new McpError( ErrorCode.InvalidParams, "Invalid arguments: expected object" ); } // Try advanced configuration first if (isAdvancedDrumKitConfig(args)) { const xml = generateGroupsXml(args); return { content: [{ type: "text", text: xml }] }; } // Fall back to basic configuration if (isBasicDrumKitConfig(args)) { const config: BasicDrumKitConfig = args; const xml = generateGroupsXml(config); return { content: [{ type: "text", text: xml }] }; } throw new McpError( ErrorCode.InvalidParams, "Invalid arguments: does not match either BasicDrumKitConfig or AdvancedDrumKitConfig schema" ); }
- src/xml-generation.ts:5-114 (helper)Core helper function that implements the drum groups XML generation logic. Processes drum pieces, samples, applies velocity layers, muting, round-robin, envelopes, pitch controls, and mic bus routing based on the configuration type.export function generateGroupsXml(config: BasicDrumKitConfig | AdvancedDrumKitConfig): string { const { globalSettings, drumPieces } = config; // Generate buses XML if mic routing is configured (advanced only) const busesXml = 'micBuses' in globalSettings && globalSettings.micBuses ? configureMicBuses(globalSettings.micBuses) : ''; // Add round robin attributes to top-level groups if configured const roundRobinAttrs = 'roundRobin' in globalSettings && globalSettings.roundRobin ? ` seqMode="${globalSettings.roundRobin.mode}"${ globalSettings.roundRobin.length ? ` seqLength="${globalSettings.roundRobin.length}"` : '' }` : ''; const groups: string[] = []; for (const piece of drumPieces) { // Combine muting and round robin attributes for group (advanced only) let groupAttrs = 'muting' in piece && piece.muting ? ` tags="${piece.muting.tags.join(',')}" silencedByTags="${piece.muting.silencedByTags.join(',')}" silencingMode="fast"` : ''; // Add group-level round robin settings if present if ('seqMode' in piece && piece.seqMode) { groupAttrs += ` seqMode="${piece.seqMode}"`; } if ('seqLength' in piece && piece.seqLength) { groupAttrs += ` seqLength="${piece.seqLength}"`; } if ('seqPosition' in piece && piece.seqPosition) { groupAttrs += ` seqPosition="${piece.seqPosition}"`; } // Add drum controls if configured (advanced only) const drumControls = 'drumControls' in globalSettings && globalSettings.drumControls?.[piece.name]; let envelopeAttrs = ''; let pitchControl = ''; if (drumControls) { // Add envelope attributes if configured if (drumControls.envelope) { const env = drumControls.envelope; envelopeAttrs = ` attack="${env.attack}" decay="${env.decay}" sustain="${env.sustain}" release="${env.release}"`; if (env.attackCurve !== undefined) envelopeAttrs += ` attackCurve="${env.attackCurve}"`; if (env.decayCurve !== undefined) envelopeAttrs += ` decayCurve="${env.decayCurve}"`; if (env.releaseCurve !== undefined) envelopeAttrs += ` releaseCurve="${env.releaseCurve}"`; } // Add pitch control if configured if (drumControls.pitch) { const pitch = drumControls.pitch; groupAttrs += ` tuning="${pitch.default}"`; pitchControl = ` <control type="pitch" name="${piece.name} Pitch" default="${pitch.default}"` + (pitch.min !== undefined ? ` minimum="${pitch.min}"` : '') + (pitch.max !== undefined ? ` maximum="${pitch.max}"` : '') + `>\n <binding type="general" level="group" position="0" parameter="groupTuning" />\n </control>\n`; } } const sampleElements: string[] = []; for (const sample of piece.samples) { const volumeAttr = sample.volume ? ` volume="${sample.volume}"` : ''; let velocityAttrs = ''; if (globalSettings.velocityLayers) { const layerIndex = piece.samples.indexOf(sample); if (layerIndex < globalSettings.velocityLayers.length) { const layer = globalSettings.velocityLayers[layerIndex]; velocityAttrs = ` loVel="${layer.low}" hiVel="${layer.high}"`; } } // Add sample-level round robin settings let sampleRRAttrs = ''; if ('seqMode' in sample && sample.seqMode) { sampleRRAttrs += ` seqMode="${sample.seqMode}"`; } if ('seqLength' in sample && sample.seqLength) { sampleRRAttrs += ` seqLength="${sample.seqLength}"`; } if ('seqPosition' in sample && sample.seqPosition) { sampleRRAttrs += ` seqPosition="${sample.seqPosition}"`; } // Generate sample element with bus routing if configured (advanced only) const sampleXml = 'micConfig' in sample && sample.micConfig ? generateSampleBusRouting(sample.path, sample.micConfig.busIndex, sample.micConfig.volume) : ` <sample path="${sample.path}"${volumeAttr} rootNote="${piece.rootNote}" ` + `loNote="${piece.rootNote}" hiNote="${piece.rootNote}"${velocityAttrs}${sampleRRAttrs} />`; sampleElements.push(sampleXml); } groups.push( ` <group name="${piece.name}" ampVelTrack="1"${groupAttrs}${envelopeAttrs}>\n` + (pitchControl ? pitchControl : '') + `${sampleElements.join('\n')}\n` + ` </group>` ); } // Combine buses and groups XML const xml = []; if (busesXml) xml.push(busesXml); xml.push(`<groups${roundRobinAttrs}>\n${groups.join('\n\n')}\n</groups>`); return xml.join('\n\n'); }
- src/index.ts:386-544 (registration)Registration of the 'generate_drum_groups' tool in the ListToolsRequestSchema response, including comprehensive description and input schema defining the expected structure for globalSettings and drumPieces.{ name: "generate_drum_groups", description: `Generate DecentSampler <groups> XML for drum kits. This tool supports two configuration types: BasicDrumKitConfig: - For simple presets with minimal features - No UI controls, effects, or routing - Only supports basic sample mapping and optional velocity layers - Recommended for straightforward drum kits AdvancedDrumKitConfig: - For complex setups combining multiple features - Supports UI controls, effects, and routing - Integrates with other tools (configure_drum_controls, configure_mic_routing, etc.) - Use when you need advanced features like round robin or multi-mic setups Best Practices: - IMPORTANT: Always use absolute paths (e.g., 'C:/Users/username/Documents/Samples/kick.wav') - Group all samples for a drum piece into a single group - When using multiple mic positions, include them all in the same group - Use velocity layers within a group to control dynamics Error Handling: - Validates all sample paths exist - Checks for valid MIDI note numbers - Ensures velocity layers don't overlap - Verifies muting group configurations - Returns specific errors for any invalid settings Example Configurations: 1. Basic Configuration (simple drum kit): { "globalSettings": { "velocityLayers": [ { "low": 1, "high": 42, "name": "soft" }, { "low": 43, "high": 85, "name": "medium" }, { "low": 86, "high": 127, "name": "hard" } ] }, "drumPieces": [{ "name": "Kick", "rootNote": 36, "samples": [ {"path": "C:/Samples/Kick_Soft.wav"}, {"path": "C:/Samples/Kick_Medium.wav"}, {"path": "C:/Samples/Kick_Hard.wav"} ] }] } 2. Advanced Configuration (multi-mic kit with controls): { "globalSettings": { "velocityLayers": [ { "low": 1, "high": 127, "name": "full" } ], "drumControls": { "kick": { "pitch": { "default": 0, "min": -12, "max": 12 }, "envelope": { "attack": 0.001, "decay": 0.5, "sustain": 0, "release": 0.1 } } }, "micBuses": [ { "name": "Close Mic", "outputTarget": "MAIN_OUTPUT", "volume": { "default": 0, "midiCC": 20 } } ] }, "drumPieces": [{ "name": "Kick", "rootNote": 36, "samples": [ { "path": "C:/Samples/Kick_Close.wav", "micConfig": { "position": "close", "busIndex": 0 } } ], "muting": { "tags": ["kick"], "silencedByTags": [] } }] } Success Response: Returns complete XML structure with: - Organized sample groups - Velocity layer mappings - Muting group configurations - All sample references and settings - Advanced features when using AdvancedDrumKitConfig`, inputSchema: { type: "object", properties: { globalSettings: { type: "object", properties: { velocityLayers: { type: "array", items: { type: "object", properties: { low: { type: "number" }, high: { type: "number" }, name: { type: "string" } }, required: ["low", "high", "name"] } } }, required: [] }, drumPieces: { type: "array", items: { type: "object", properties: { name: { type: "string" }, rootNote: { type: "number" }, samples: { type: "array", items: { type: "object", properties: { path: { type: "string" }, volume: { type: "string" } }, required: ["path"] } }, muting: { type: "object", properties: { tags: { type: "array", items: { type: "string" } }, silencedByTags: { type: "array", items: { type: "string" } } }, required: ["tags", "silencedByTags"] } }, required: ["name", "rootNote", "samples"] } } }, required: ["globalSettings", "drumPieces"] } }
- src/index.ts:490-543 (schema)JSON schema for tool input validation, specifying structure for global settings (velocity layers) and drum pieces (name, rootNote, samples with path/volume, optional muting).inputSchema: { type: "object", properties: { globalSettings: { type: "object", properties: { velocityLayers: { type: "array", items: { type: "object", properties: { low: { type: "number" }, high: { type: "number" }, name: { type: "string" } }, required: ["low", "high", "name"] } } }, required: [] }, drumPieces: { type: "array", items: { type: "object", properties: { name: { type: "string" }, rootNote: { type: "number" }, samples: { type: "array", items: { type: "object", properties: { path: { type: "string" }, volume: { type: "string" } }, required: ["path"] } }, muting: { type: "object", properties: { tags: { type: "array", items: { type: "string" } }, silencedByTags: { type: "array", items: { type: "string" } } }, required: ["tags", "silencedByTags"] } }, required: ["name", "rootNote", "samples"] } } }, required: ["globalSettings", "drumPieces"] }
- src/basic-drum-kit.ts:17-90 (helper)Type guard helper used in handler to validate BasicDrumKitConfig inputs, ensuring no advanced features are present and basic structure is correct.// Type guard for BasicDrumKitConfig export function isBasicDrumKitConfig(obj: unknown): obj is BasicDrumKitConfig { if (!obj || typeof obj !== 'object') return false; const config = obj as Partial<BasicDrumKitConfig>; // Check globalSettings and ensure no advanced features if (!config.globalSettings || typeof config.globalSettings !== 'object') { return false; } // Check for advanced features in globalSettings const globalSettings = config.globalSettings as any; if ( globalSettings.drumControls !== undefined || globalSettings.roundRobin !== undefined || globalSettings.micBuses !== undefined ) { return false; } // Validate velocity layers if they exist if (config.globalSettings.velocityLayers !== undefined) { if (!Array.isArray(config.globalSettings.velocityLayers)) { return false; } if (!config.globalSettings.velocityLayers.every(layer => layer && typeof layer === 'object' && typeof layer.low === 'number' && typeof layer.high === 'number' && typeof layer.name === 'string' )) { return false; } } // Check drumPieces if (!Array.isArray(config.drumPieces)) { return false; } return config.drumPieces.every(piece => piece && typeof piece === 'object' && typeof piece.name === 'string' && typeof piece.rootNote === 'number' && Array.isArray(piece.samples) && piece.samples.every(sample => { if (!sample || typeof sample !== 'object' || typeof sample.path !== 'string') { return false; } // Optional volume validation if (sample.volume !== undefined && typeof sample.volume !== 'string') { return false; } // Check for advanced sample features const sampleObj = sample as any; if ( sampleObj.seqPosition !== undefined || sampleObj.micConfig !== undefined ) { return false; } return true; }) && // Check for advanced drum piece features !(piece as any).muting ); }