У меня нет опыта в звуковом программировании, и C ++ является языком довольно низкого уровня, поэтому у меня есть небольшие проблемы с ним. Я работаю с ASIO SDK 2.3, скачанной с http://www.steinberg.net/en/company/developers.html.
Я пишу свой собственный хост на основе примера в SDK.
На данный момент мне удалось пройти весь образец, и похоже, что он работает. У меня есть внешняя звуковая карта, подключенная к моему ПК. Я успешно загрузил драйвер для этого устройства, настроил его, обработал обратные вызовы, преобразовал данные из аналоговых в цифровые и т. Д.
И часть, где я застрял сейчас:
Когда я играю какую-то дорожку через свое устройство, я вижу движущиеся полосы в микшере (программное обеспечение устройства). Таким образом, устройство подключено правильно. В своем коде я выбрал входы и выходы с именами баров, которые движутся в микшере. Я также использовал ASIOCreateBuffers () для создания буфера для каждого ввода / вывода.
Теперь поправьте меня, если я ошибаюсь:
Когда вызывается ASIOStart () и драйвер находится в рабочем состоянии, когда я подаю звуковой сигнал на внешнее устройство, я считаю, что буферы заполняются данными, верно?
Я читаю документацию, но я немного растерялся — как я могу получить доступ к данным, отправляемым устройством в приложение, хранящимся в буферах INPUT? Или сигнал? Мне нужно это для анализа сигнала или, возможно, записи в будущем.
РЕДАКТИРОВАТЬ: Если я сделал это сложным, то в двух словах мой вопрос: как я могу получить доступ к данным входного потока из кода? Я не вижу никаких объектов / обратных вызовов, позволяющих мне делать это в документации.
Образец hosts в ASIO SDK довольно близок к тому, что вам нужно. в bufferSwitchTimeInfo
обратный вызов есть такой код:
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
int ch = asioDriverInfo.bufferInfos[i].channelNum;
if (asioDriverInfo.bufferInfos[i].isInput == ASIOTrue)
{
char* buf = asioDriver.bufferInfos[i].buffers[index];
....
Внутри этого блока if asioDriver.bufferInfos[i].buffers[index]
указатель на необработанные аудиоданные (index
является параметром метода).
Формат буфера зависит от драйвера и может быть обнаружен путем тестирования asioDriverInfo.channelInfos[i].type
, Типы форматов: сначала 32-битный int LSB, сначала 32-битный int MSB и т. Д. Вы можете найти список значений в ASIOSampleType
перечислить в asio.h
, На этом этапе вы захотите преобразовать сэмплы в какой-то общий формат для кода обработки сигналов в нисходящем направлении. Если вы занимаетесь обработкой сигналов, вы, вероятно, захотите преобразовать в double
, Файл host\asioconvertsample.cpp
даст вам некоторое представление о том, что участвует в преобразовании. Наиболее распространенный формат, с которым вы столкнетесь, это, вероятно, INT32 MSB. Вот как вы можете преобразовать его в удвоение.
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
int ch = asioDriverInfo.bufferInfos[i].channelNum;
if (asioDriverInfo.bufferInfos[i].isInput == ASIOTrue)
{
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOInt32LSB:
{
double* pDoubleBuf = new double[_bufferSize];
for (int i = 0 ; i < _bufferSize ; ++i)
{
pDoubleBuf[i] = *(int*)asioDriverInfo.bufferInfos.buffers[index] / (double)0x7fffffff;
}
// now pDoubleBuf contains one channels worth of samples in the range of -1.0 to 1.0.
break;
}
// and so on...
Большое спасибо. Ваш ответ очень помог, но поскольку я немного неопытен в C ++: P, я нахожу это немного проблематичным.
В общем, я написал свой собственный хост на основе hostsample. Я не реализовал структуру asioDriverInfo и пока не использовал общие переменные.
Моя первая проблема была:
char* buf = asioDriver.bufferInfos[i].buffers[index];
как я получил ошибку, что я не могу привести (void *) к char *, но это, вероятно, решило проблему:
char* buf = static_cast<char*>(bufferInfos[i].buffers[doubleBufferIndex]);
Моя вторая проблема с преобразованием данных. Я проверил файл, который вы мне порекомендовали, но нашел немного чёрной магии. Сейчас я пытаюсь последовать вашему примеру и:
for (int i = 0; i < inputBuffers + outputBuffers; i++)
{
if (bufferInfos[i].isInput)
{
switch (channelInfos[i].type)
{
case ASIOSTInt32LSB:
{
double* pDoubleBuf = new double[buffSize];
for (int j = 0 ; j < buffSize ; ++j)
{
pDoubleBuf[j] = bufferInfos[i].buffers[doubleBufferIndex] / (double)0x7fffffff;
}
break;
}
}
}
Я получаю ошибку там:
pDoubleBuf[j] = bufferInfos[i].buffers[doubleBufferIndex] / (double)0x7fffffff;
который:
error C2296: '/' : illegal, left operand has type 'void *'
Чего я не понимаю, так это того, что в вашем примере нет таблицы: asioDriverInfo.bufferInfos.buffers [index] после bufferInfos, и даже если я исправлю это … к какому типу я должен привести его, чтобы он работал. п
PS. Я уверен, что тип данных ASIOSTInt32LSB подходит для моего ПК.