compile static method

FaustSequencer compile(
  1. Map<String, dynamic> spec
)

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;
}