Циклирование одного периода не обязательно является хорошей идеей - цикл может не вписываться в точное число выборок, поэтому вы можете получить нежелательную прерывистость в конце каждого цикла или, что еще хуже, слышимая частота может закончиться немного выключен.
Тем не менее, математика не сложно:
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 сэмплов снова и снова, вы фактически будете воспроизводить сэмпл 441 раз в секунду, так что ваша высота будет на 1 Гц.
Чтобы избежать этой проблемы, вам действительно нужно рассчитать несколько периодов формы волны, хотя я не знаю, сколько нужно, чтобы обмануть слух, чтобы услышать правильную высоту.
В идеале это было бы столько, сколько нужно, чтобы:
i / samples_per_cycle
- это целое число, так что последняя выборка (технически после последней выборки) заканчивается точно на границе цикла. Я думаю , если все ваши входные частоты являются целыми числами, то получение значения одной секунды точно будет работать.