2013-04-02 6 views
2

В настоящее время я использую libsndfile в сочетании с PortAudio V19, чтобы читать аудиоданные из файла и воспроизводить их обратно. (Обратите внимание, что я делаю это на малине Pi, работающем на Raspbian.) Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно динамически контролировать громкость воспроизведения в реальном времени для каждого воспроизводимого таким образом звука. Я попытался использовать системные вызовы для управления глобальным объемом воспроизведения через alsamixer, что было бы приемлемым решением в моем случае использования, но задержка слишком высока, чтобы это работало.Управление громкостью звука в реальном времени

То, что я ищу это одна из двух вещей:

  • библиотека, которая может обрабатывать изменения громкости звука в режиме реального времени, либо путем воздействия на сырье аудио данных, полученных с помощью libsndfile, или путем установки глобальный объем воспроизведения с минимальной задержкой (субмиллисекунда). Библиотека должна быть бесплатной (безвозмездно) и использоваться на Raspbian; лицензирование не вызывает беспокойства.

  • Математические преобразования, которые необходимо применять к аудиоданным, полученным с помощью файла libsndfile, для изменения уровня громкости данных, предпочтительно, когда целевой объем находится в диапазоне [0.0f, 1.0f], с 0.0f - тихий, а 1.0f - исходный том из файла.

Я попытался разобраться во всем полезном (свободном) материале по этой теме и не смог найти что-либо, что помогает. Любая помощь очень ценится!

ответ

3

Вы можете манипулировать амплитудой аудиопотока PCM, применяя множитель к каждому образцу. Вы можете сделать это непосредственно перед передачей каждого буфера (набора образцов) в PortAudio. Это так же просто:

float buffer[SAMPLES_PER_BUFFER]; 
const float volumeMultiplier = 0.2f; 
for(int i = 0; i < SAMPLES_PER_BUFFER; ++i) 
{ 
    buffer[i] *= volumeMultiplier; 
} 

Однако уловка в том, как вы рассчитываете свой множитель. Как правило, вы не заметите значительного изменения уровня сигнала, пока не снизите общий уровень сигнала в половине volumeMultiplier = 0.5f. Как вам известно, человеческое ухо не воспринимает изменения в уровне громкости линейно, но логарифмически. Следующие ссылки могут помочь объяснить эту концепцию:

Используя эту информацию, можно изменить код, приведенный выше, как, например:

float buffer[SAMPLES_PER_BUFFER]; 
//volume in dB 0db = unity gain, no attenuation, full amplitude signal 
//   -20db = 10x attenuation, significantly more quiet 
float volumeLevelDb = -6.f; //cut amplitude in half; same as 0.5 above 
const float VOLUME_REFERENCE = 1.f; 
const float volumeMultiplier = (VOLUME_REFERENCE * pow(10, (volumeLevelDb/20.f); 
for(int i = 0; i < SAMPLES_PER_BUFFER; ++i) 
{ 
    buffer[i] *= volumeMultiplier; 
} 

Для ваши цели могут быть не важны, но если у ou должны были присоединить значение volumeLevelDb или volumeMultiplier к пользовательскому интерфейсу, подобному виджету ползунка, разница будет очевидна.

Вы можете применить этот алгоритм к любому типу данных.

Смежные вопросы