Программирование мелодий с использованием системного динамика — это занятие, которое позволяет лучше понять основные концепции работы с частотами звуков и временными интервалами. В этой статье мы рассмотрим, как можно создать и проиграть мелодию на языке программирования D, используя системный динамик.
Основные концепции
Частоты нот
Музыкальные ноты имеют определенные частоты, измеряемые в Герцах (Гц). Например, нота «A4» (ля первой октавы) имеет частоту 440 Гц. Для создания мелодий важно знать частоты основных нот. Вот несколько частот для основных нот:
- C4 (до первой октавы) — 261.63 Гц
- D4 (ре первой октавы) — 293.66 Гц
- E4 (ми первой октавы) — 329.63 цГ
- F4 (фа первой октавы) — 349.23 Гц
- G4 (соль первой октавы) — 392.00 Гц
- A4 (ля первой октавы) — 440.00 Гц
- B4 (си первой октавы) — 493.88 Гц
Структура данных для хранения частот
Для удобства работы с нотами и их частотами м можем использовать ассоциативный массив (словарь), где ключами будут названия нот, а значениями — их частоты. Это позволит нам легко обращаться к частотам нот по их именма.
Пример кода
Давайте рассмотрим пример кода на языке D, который создает мелодию и проигрывает её с использованием системного динамика.
import core.stdc.stdio : printf;
import core.thread : Thread;
import std.datetime : Duration, msecs;
import std.string : format;
import std.array : Appender;
enum Note : string
{
C4 = "C4",
D4 = "D4",
E4 = "E4",
F4 = "F4",
G4 = "G4",
A4 = "A4",
B4 = "B4",
C5 = "C5"
}
immutable double[string] noteFrequencies = [
Note.C4 : 261.63,
Note.D4 : 293.66,
Note.E4 : 329.63,
Note.F4 : 349.23,
Note.G4 : 392.00,
Note.A4 : 440.00,
Note.B4 : 493.88,
Note.C5 : 523.25
];
struct NoteDuration
{
string note;
Duration duration;
}
void playTone(double frequency, Duration duration)
{
int durationMs = cast(int)duration.total!"msecs";
printf("Playing frequency: %.2f Hz for %d ms\n", frequency, durationMs);
// Здесь следует добавить код для генерации звука через системный динамик
Thread.sleep(duration); // Временно используем задержку
}
void playMelody(NoteDuration[] melody)
{
foreach (noteDuration; melody)
{
double frequency = noteFrequencies[noteDuration.note];
playTone(frequency, noteDuration.duration);
}
}
void main()
{
NoteDuration[] melody = [
NoteDuration(Note.C4, 500.msecs),
NoteDuration(Note.D4, 500.msecs),
NoteDuration(Note.E4, 500.msecs),
NoteDuration(Note.F4, 500.msecs),
NoteDuration(Note.G4, 500.msecs),
NoteDuration(Note.A4, 500.msecs),
NoteDuration(Note.B4, 500.msecs),
NoteDuration(Note.C5, 500.msecs)
];
playMelody(melody);
}
Пояснение кода
- Импорт библиотек: Мы импортируем необходимые модули, такие как
core.stdc.stdio
для вывода на экран,core.thread
для задержки выполнения,std.datetime
для работы с временными интервалами, иstd.string
для форматирования строк. - Перечисление онт: Создаем перечисление
Note
, содержащее ноты, которые мы бдем использовать. - Ассоциативный массив частот нот: Создаем immutable ассоциативный массив
noteFrequencies
, в котором ключами являются ноты, а значениями — их частоты. - Структура NoteDuration: Определяем структуру
NoteDuration
, которая хранит ноту и её продолжительность. - Функция playTone: Эта функция принимает частоту и продолжительность, проигывая тон с заданной частотой в течение указанного времени. В данной реализации звуковой сигнал не генерируется, вместо этого выводится сообщение и используется задержка.
- Функция playMelody: Принимает массив нот с продолжительностями и последовательно проигрывает их, вызывая
playTone
. - Функция main: Создает массив нот и их продолжительностей, а затем вызывает
playMelody
для проигрывания мелодии.
Автор статьи:
Обновлено:
Добавить комментарий