Непонятка с таймером

Добрый день!
Сразу скажу — что-то внятное «сыграть» на встроенном бузере, к сожалению, не получится.
Тоже в своё время пытался воспроизвести имперский марш, но в итоге пришёл к выводу, что лучше подключить внешнюю звуковую карту и нормальные колонки на случай ЧП.

У вас получилось так, что потоки частот идут параллельно и не формируют нормальную мелодию.
Чтобы всё звучало более правильно, нужно:

  • отключать бузер после каждой ноты,
  • переключать частоту,
  • и только потом включать звук для новой ноты.

Примерно так это должно выглядеть для корректного воспроизведения мелодии.

// Определение частот нот
var nC = 261.7;
var nC$ = 277.2;
var nD = 293.7;
var nD$ = 311.1;
var nE = 329.6; 
var nF = 349.2;
var nF$ = 370.0; 
var nG = 392.0; 
var nG$ = 415.3;
var nA = 440.0; 
var nA$ = 466.2;
var nB = 493.9;

// Темп (не используется напрямую, но может быть полезен для расчётов позже)
var Tempo = 120;

// Массив мелодии: нота, длительность (4 = четверть ноты, 2 = половинная и т.п.)
var VoSadu = [
  nF, 4, nF, 4, nE, 4, nE, 4,
  nE, 4, nE, 4, nE, 4, nF, 4,
  nF, 4, nF, 4, nE, 4, nE, 4,
  nE, 2, nE, 2
];

// Создание виртуального устройства с кнопкой "Играть"
defineVirtualDevice("Music", {
  title: "Музыка",
  cells: {
    Play: {
      title: "Играть",
      type: "pushbutton",
      value: false,
    }
  }
});

// Правило воспроизведения мелодии
defineRule("PlayMusic", {
  whenChanged: "Music/Play",
  then: function (newValue, devName, cellName) {
    log("Pressed. Length = {}", VoSadu.length);
    var i = 0; // Индекс текущей ноты в массиве

    function playNextNote() {
      if (i >= VoSadu.length) {
        log("Finished playing melody");
        return; // Все ноты сыграны
      }

      var note = VoSadu[i];
      var duration = VoSadu[i + 1];
      var noteLength = 4000 / duration; // Вычисляем длительность ноты в миллисекундах

      log("Playing note", note, "for", noteLength, "ms");

      dev["buzzer/frequency"] = note;
      dev["buzzer/enabled"] = true;

      setTimeout(function () {
        dev["buzzer/enabled"] = false;

        // Пауза перед следующей нотой (можно изменить при необходимости)
        var pauseBetweenNotes = 50; // 50 мс

        i += 2; // Переходим к следующей паре нота-длительность
        setTimeout(playNextNote, pauseBetweenNotes);
      }, noteLength);
    }

    playNextNote(); // Запускаем первую ноту
  }
});