Добрый день!
Сразу скажу — что-то внятное «сыграть» на встроенном бузере, к сожалению, не получится.
Тоже в своё время пытался воспроизвести имперский марш, но в итоге пришёл к выводу, что лучше подключить внешнюю звуковую карту и нормальные колонки на случай ЧП.
У вас получилось так, что потоки частот идут параллельно и не формируют нормальную мелодию.
Чтобы всё звучало более правильно, нужно:
- отключать бузер после каждой ноты,
- переключать частоту,
- и только потом включать звук для новой ноты.
Примерно так это должно выглядеть для корректного воспроизведения мелодии.
// Определение частот нот
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(); // Запускаем первую ноту
}
});