Я новичок, когда дело доходит до обработки аудио сигнала.
В настоящее время я подключил к компьютеру устройство, которое отправляет мне аудиоданные с микрофона / дорожки воспроизведения. Я уже создал хост-приложение с использованием Steinberg ASIO SDK 2.3, которое подключается к устройству и при повторном обратном вызове возвращает необработанные данные. Сигнал 24 бит, и частоту можно выбирать как угодно, скажем, 44100 Гц, 2-канальный, одноканальный. Я преобразовал этот сигнал также удвоить <-1.0, 1.0> потому что я делаю некоторую обработку сигнала на нем.
То, что я хотел бы сделать сейчас, это добавить функциональность записи на мой хост. Например, при нажатии кнопки входящие данные непрерывно преобразуются в файл WAV, а когда я нажимаю другую кнопку, они останавливаются и сохраняются.
Я уже читал о файлах WAV, форматах файлов, форматах битового потока (RIFF) и каким-то образом имею общее представление о том, как выглядит файл WAV. Я также проверил множество веток форума, веток stackoverflow или постов с кодами и везде, где я нахожу что-то, связанное с темой, но я не могу понять, как я могу вести постоянную запись в реальном времени. Я обнаружил много кода о преобразовании массива данных в WAV после внесения в него изменений. Я хотел бы сделать текущее преобразование и сделать добавление / расширение WAV-файла, пока я не скажу ему остановиться.
Например, могу ли я как-то изменить это?
#include <fstream>
template <typename T>
void write(std::ofstream& stream, const T& t) {
stream.write((const char*)&t, sizeof(T));
}
template <typename T>
void writeFormat(std::ofstream& stream) {
write<short>(stream, 1);
}
template <>
void writeFormat<float>(std::ofstream& stream) {
write<short>(stream, 3);
}
template <typename SampleType>
void writeWAVData(
char const* outFile,
SampleType* buf,
size_t bufSize,
int sampleRate,
short channels)
{
std::ofstream stream(outFile, std::ios::binary);
stream.write("RIFF", 4);
write<int>(stream, 36 + bufSize);
stream.write("WAVE", 4);
stream.write("fmt ", 4);
write<int>(stream, 16);
writeFormat<SampleType>(stream); // Format
write<short>(stream, channels); // Channels
write<int>(stream, sampleRate); // Sample Rate
write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate
write<short>(stream, channels * sizeof(SampleType)); // Frame size
write<short>(stream, 8 * sizeof(SampleType)); // Bits per sample
stream.write("data", 4);
stream.write((const char*)&bufSize, 4);
stream.write((const char*)buf, bufSize);
}
И в обратном вызове как-то:
writeWAVData("mySound.wav", mySampleBuffer, mySampleBufferSize, 44100, 1);
Я благодарен за любую подсказку / ссылку / предложение / форму помощи.
Разница между вашим вариантом использования и кодом, который вы видели в сети, заключается в том, что в вашем случае использования вы не знаете заранее, как долго будет заканчиваться файл, поскольку вы не знаете, когда пользователь будет нажмите кнопку остановки.
Способ справиться с этим — начать с записи заголовка WAV как обычно, но пока не беспокойтесь о значениях, которые вы пишете для полей, зависящих от размера файла (т. Е. После «RIFF» и после » данные»). Вы можете оставить эти поля на ноль пока.
Затем запишите аудиосэмплы по мере их получения, то есть добавьте их в конец файла.
Наконец, после того, как пользователь нажал «Стоп» и вы собираетесь закрыть файл, вам нужно будет вернуться назад и перезаписать эти два поля заголовка правильными значениями. Вы можете сделать это сейчас, потому что на данный момент вы знаете, сколько байтов аудиоданных вы записали в файл. После того, как вы это сделаете, файл должен быть правильно сформирован и использоваться. Вы можете использовать, например, ofstream :: seekp (fieldOffset, ios_base :: beg) вернуться к соответствующим смещениям в верхней части файла для полей, которые нужно изменить.