аудио — C ++ ASIO, доступ к буферам

У меня нет опыта в звуковом программировании, и C ++ является языком довольно низкого уровня, поэтому у меня есть небольшие проблемы с ним. Я работаю с ASIO SDK 2.3, скачанной с http://www.steinberg.net/en/company/developers.html.

Я пишу свой собственный хост на основе примера в SDK.

На данный момент мне удалось пройти весь образец, и похоже, что он работает. У меня есть внешняя звуковая карта, подключенная к моему ПК. Я успешно загрузил драйвер для этого устройства, настроил его, обработал обратные вызовы, преобразовал данные из аналоговых в цифровые и т. Д.

И часть, где я застрял сейчас:
Когда я играю какую-то дорожку через свое устройство, я вижу движущиеся полосы в микшере (программное обеспечение устройства). Таким образом, устройство подключено правильно. В своем коде я выбрал входы и выходы с именами баров, которые движутся в микшере. Я также использовал ASIOCreateBuffers () для создания буфера для каждого ввода / вывода.

  1. Теперь поправьте меня, если я ошибаюсь:
    Когда вызывается ASIOStart () и драйвер находится в рабочем состоянии, когда я подаю звуковой сигнал на внешнее устройство, я считаю, что буферы заполняются данными, верно?

  2. Я читаю документацию, но я немного растерялся — как я могу получить доступ к данным, отправляемым устройством в приложение, хранящимся в буферах INPUT? Или сигнал? Мне нужно это для анализа сигнала или, возможно, записи в будущем.

РЕДАКТИРОВАТЬ: Если я сделал это сложным, то в двух словах мой вопрос: как я могу получить доступ к данным входного потока из кода? Я не вижу никаких объектов / обратных вызовов, позволяющих мне делать это в документации.

0

Решение

Образец 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...
0

Другие решения

Большое спасибо. Ваш ответ очень помог, но поскольку я немного неопытен в C ++: P, я нахожу это немного проблематичным.

В общем, я написал свой собственный хост на основе hostsample. Я не реализовал структуру asioDriverInfo и пока не использовал общие переменные.

  1. Моя первая проблема была:

    char* buf = asioDriver.bufferInfos[i].buffers[index];
    

    как я получил ошибку, что я не могу привести (void *) к char *, но это, вероятно, решило проблему:

    char* buf = static_cast<char*>(bufferInfos[i].buffers[doubleBufferIndex]);
    
  2. Моя вторая проблема с преобразованием данных. Я проверил файл, который вы мне порекомендовали, но нашел немного чёрной магии. Сейчас я пытаюсь последовать вашему примеру и:

    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 подходит для моего ПК.

0