Конечно, вы можете, это не тривиально, чтобы это звучало "красиво".
Я не знаю, как это сделать в Linux, но если вы можете играть в буфер PCM, все, что вам нужно сделать, это заполнить его всем, что вы хотите.
Предположим, что ваш буфер настроен на воспроизведение в монофонических 16-битных сэмплах со знаком со скоростью 44100 сэмплов в секунду, поэтому создание чистого (синусоидального) звука формата A4 (440 Гц) так же просто
int16_t buffer[44100];
float frequency = 440.0f;
float sampling_ratio = 44100.0f;
float amplitude = 0.5f;
float t;
for (int i = 0; i < 44100; i++)
{
float theta = ((float)i / sampling_ratio) * PI;
buffer[i] = (int16_t)(sin(theta * frequency) * 32767.0f * amplitude);
}
Тем не менее, этот звук, вероятно, очень скучный для ваших интересов, поэтому вы должны сделать некоторые более сложные вещи. В целом, существует два типа синтеза звука: аддитивный и субтрактивный . Есть много других, но эти два, вероятно, самые простые. Сегодня я просто расскажу о аддитивном синтезе.
Для аддитивного синтеза вы делаете то же самое, что я делал там, но вместо того, чтобы использовать одну частоту с одной амплитудой, вы добавляете несколько волн вместе. Это похоже на одновременное нажатие нескольких клавиш на пианино. Таким образом, вы модифицируете свой код, чтобы он выглядел примерно так:
void add_sine_wave(int16_t* buffer, int buffer_length, float frequency, float sampling_ratio, float amplitude)
{
for (int i = 0; i < buffer_length; i++)
{
float theta = ((float)i / sampling_ratio) * M_PI;
// make sure to correct for overflows and underflows
buffer[i] += (int16_t)(sin(theta * frequency) * 32767.0f * amplitude);
}
}
и затем используйте это так:
int16_t buffer[44100];
memset(buffer, 0, sizeof(buffer));
// Create an A Major chord
add_sine_wave(buffer, 44100, 440.0f, 44100.0f, 0.5f);
add_sine_wave(buffer, 44100, 554.37f, 44100.0f, 0.5f);
add_sine_wave(buffer, 44100, 659.26f, 44100.0f, 0.5f);
Кстати, я получаю мои частоты из здесь (я использую равный темперамент , но есть много из других строев доступных).
Обратите внимание, что до сих пор я использовал только синусоидальные волны, но старые синтезаторы также поддерживают квадратные , треугольные и пильные волны, каждый со своими интересными звуковыми свойствами. Реализовать это довольно просто.
Другие вещи, которые вы можете сделать, чтобы увеличить разнообразие звуков, которые вы можете создать:
- Амплитудная модуляция : изменение амплитуды волны по всему буферу
- Частотная модуляция : изменение частоты волны в буфере
- Реверберация : повторение семпла путем изменения его формы и положения в буфере. Сама тема очень сложная.
- Обволакивание : изменение амплитуды образца для увеличения срока его службы
Дело в том, что сами методы не очень сложны, поэтому вам не нужна библиотека, чтобы абстрагировать их для вас. Он использует их для создания интересных звуков, что сложно.
Последнее замечание При экспериментировании со звуком, подобным этому, может быть действительно полезно сохранить ваши данные в файлы WAV, а затем визуализировать их в некотором программном обеспечении, таком как Audacity. Таким образом, вы можете видеть, что вы делаете более четко.