compile static method
Implementation
static FaustSequencer compile(Map<String, dynamic> spec) {
final double tempo = (spec['tempo'] ?? 120.0).toDouble();
final double grid = (spec['grid'] ?? 4.0).toDouble(); // Steps per beat
final Map<String, String> tracks = spec['tracks'] as Map<String, String>;
final sequencer = FaustSequencer(tempoBpm: tempo);
final double stepDuration = 1.0 / grid;
tracks.forEach((instName, patternStr) {
final int? instId = _instrumentMap[instName.toLowerCase()];
if (instId == null) return;
final List<String> steps = patternStr.trim().split(RegExp(r'\s+'));
for (int i = 0; i < steps.length; i++) {
final String step = steps[i];
final double currentBeat = i * stepDuration;
if (step == '.') continue;
if (step == 'X' || step == 'x') {
// Rhythmic Strike
sequencer.addNote(
instrumentId: instId,
pitch: 0,
beat: currentBeat,
duration: stepDuration * 0.9,
velocity: (step == 'X') ? 0.8 : 0.3,
);
} else if (_noteMap.containsKey(step)) {
// Melodic Note
bool isLegato = false;
if (i + 1 < steps.length && steps[i + 1] == '-') {
isLegato = true;
}
sequencer.addNote(
instrumentId: instId,
pitch: _noteMap[step]!,
beat: currentBeat,
duration: stepDuration * (isLegato ? 1.0 : 0.85),
velocity: 0.8,
legato: isLegato,
);
} else if (step.startsWith('(')) {
// Parameter notation like (p=1)
if (step.contains('p=')) {
final pVal = int.tryParse(step.replaceAll(RegExp(r'[()p=]'), '')) ?? 0;
sequencer.addNote(
instrumentId: instId,
pitch: 0,
beat: currentBeat,
duration: stepDuration,
velocity: 0.8,
paramId: pVal,
);
}
}
}
});
return sequencer;
}