Цитирование одного периода не обязательно является хорошей идеей - цикл может не укладываться в точное количество образцов, чтобы вы могли получить нежелательный разрыв в конце каждого цикла или, что еще хуже, слышимая частота может закончиться вверх немного.
Тем не менее, математика не трудно:
float sample_rate = 44100;
float samples_per_cycle = sample_rate/frequency;
int samples_to_produce = ....
for (int i = 0; i < samples_to_produce; ++i) {
sample[i] = Math.floor(32767.0 * Math.sin(2 * Math.PI * i/samples_per_cycle));
}
Чтобы увидеть, что я имел в виду выше о частоте, возьмите стандартную настройку высоты тона 440 Гц.
Строго это необходимо 100.227 образцы, но выше код будет производить 100. Так что если вы повторите ваши 100 образцов снова и снова вы будете играть на самом деле образец раз в секунду, так что ваш шаг будет выключен на 1 Гц.
Чтобы избежать проблемы, вам действительно нужно вычислить несколько периодов формы сигнала, хотя я не знаю, что многим необходимо обмануть ухо, чтобы услышать правильный шаг.
В идеале было бы столько, сколько необходимо, что:
i/samples_per_cycle
представляет собой целое число, так что последний образец (технически один после последнего образца) заканчивается ровно на границе цикла , I думаю,, если ваши входные частоты - все целые числа, тогда производительность одной секунды точно будет работать.
Согласен. Кроме того, поскольку настройка, как правило, выражается в «центах» (сотые доли полутона), возможно, вы можете настроить свою частоту в пределах ± 0,5 цента, чтобы получить некоторое разумное целое число выборок для целого числа циклов. –