PortAudio: воспроизведение нескольких сгенерированных звуков путем вызова функции

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

  • запустить метод, который будет воспроизводить один звук,
  • укажите частоту и продолжительность звука в качестве параметров этого метода,
  • воспроизводить несколько звуков (т. е. три звука одновременно, но вызывает три метода).

В файлах примеров это выглядит сложнее. Когда я хочу воспроизвести несколько синусоидальных волн, мне нужно объединить все эти волны, а затем передать эти данные в поток.

Может у кого-то есть решения по решению этой проблемы получше?


person Lizard_Paszczyk    schedule 10.12.2017    source источник
comment
Большинство аудиоустройств не поддерживают одновременное воспроизведение нескольких файлов, поэтому для этого вам придется создать простой микшер. Это довольно просто, если ваши файлы имеют одинаковую частоту дискретизации. Даже если вы не указали это, похоже, что вы хотите создать тон-генератор. Опять же, в Интернете есть много ресурсов, так что проверьте их. Не знакомо, поддерживает ли PortAudio что-либо из этого.   -  person dsp_user    schedule 10.12.2017
comment
Да, я хочу создать тон-генератор, который будет генерировать синусоидальную, квадратную, треугольную и пилообразную волну. Я не знаю, как создавать эти волны с частотой, определенной пользователем, и одновременно воспроизводить много звуков.   -  person Lizard_Paszczyk    schedule 10.12.2017
comment
что ты уже испробовал? Создать простое приложение тон-генератора несложно.   -  person dsp_user    schedule 10.12.2017
comment
У меня есть что-то вроде этого примера. Я уже провел некоторые исследования и знаю, как изменить частоту и несколько тонов, но все еще пытаюсь сделать это так, как я писал выше. (вот ссылка на пример генерации синусоиды: ссылка)   -  person Lizard_Paszczyk    schedule 10.12.2017
comment
Я не могу помочь вам с PortAudio, но я могу написать простую функцию C ++, которая генерирует синусоидальную волну и принимает в качестве параметров частоту и продолжительность. Таким образом, вы сможете понять больше, чем просто использовать библиотеку (хотя я не говорю, что с ее использованием что-то не так)   -  person dsp_user    schedule 10.12.2017
comment
Буду признателен, если вы это напишете. Каждая помощь полезна.   -  person Lizard_Paszczyk    schedule 10.12.2017


Ответы (2)


Я просто приведу вам простой пример (для sine wave), а затем вы сможете создавать другие типы волн, которые вам интересны. Необходимые входные параметры:

  • частота дискретизации (например, 8000, 16000 и т. д.)
  • амплитуда (фактические значения зависят от формата вывода, но лучше иметь значения в диапазоне 0-1 и преобразовывать их в любой формат, который вам нравится / нужен)
  • частота (выражается как часть частоты дискретизации)
  • продолжительность (в секундах)

Длина буфера для данных тона (выборок) определяется как tone duration в секундах, умноженное на sampling rate.

Фактический код для создания синусоиды может выглядеть примерно так:

//global variables
const float PI = 3.141593;
const unsigned samplingRate = 8000;
const float amp = 0.8;

float *GenerateTone(float frequency, unsigned duration, unsigned &bufferLen){

     const float freq = frequency/samplingRate; //(e.g 440 / 8000 = 0,055)

     bufferLen = samplingRate * duration;

     float *buffer = new float[bufferLen]

     for(int i = 0; i < bufferLen; i++ ){

        buffer[i] = amp * sin(2 * PI*freq  * ((float)i)/samplingRate);

        }
    return buffer;
}   

Вы можете вызвать эту функцию как

unsigned len;
float *pTone = GenerateTone(440, 1, len);//len is an out parameter
...
delete [] pTone; //deallocatone memory when you no longer need it

В C ++ вы также можете использовать std::vector для хранения образцов. Таким образом, вам не нужно беспокоиться о выделении / освобождении памяти.

std::vector<float> v; //make vector global  
const float PI = 3.141593;
const unsigned samplingRate = 8000;
const float amp = 0.8;

void GenerateTone(float frequency, unsigned duration){

  const amp = 0.8f;

  const float freq = frequency/samplingRate; 

  const unsigned len = samplingRate * duration; 
  for(int i = 0; i < len; i++ )
        v.push_back(amp * sin(2*PI*freq  * ((float)i)/sampleRate));

}

Вы также можете передать амплитуду в качестве параметра, но в приведенных выше примерах амплитуда жестко запрограммирована. Также см. (https://en.wikipedia.org/wiki/Triangle_wave, https://en.wikipedia.org/wiki/Square_wave)

person dsp_user    schedule 10.12.2017

Вышеупомянутая программа представляет собой быстрый способ создания звукового сигнала. Небольшая поправка: Вместо

const float freq = frequency/samplingRate; 

это должно быть: const float freq = frequency; // т.е. передать частоту прямо в sin ()

person hishatrughan    schedule 03.11.2020