Простой Babymonitor с Bass.DLL
Я пытаюсь запрограммировать простой Babymonitor для Windows (для личного использования). Присмотр за ребенком должен просто определять уровень дБ микрофона и срабатывать при определенной громкости.
После некоторых исследований я нашел библиотеку Bass.dll и наткнулся на ее функцию. BASS_ChannelGetLevel
, что замечательно, но, похоже, имеет ограничения и не соответствует моим потребностям (пиковое значение равно значению DWORD).
В примерах я нашел жизненный пример, который "почти" мне нужен. В примере используются BASS_ChannelGetData
, но я не совсем знаю, как обрабатывать возвращенный массив...
Я хочу, чтобы все было как можно проще: определите громкость микрофона как дБ или любое другое значение (например, значение 0-MAXINT).
Как это можно сделать с помощью библиотеки Bass.dll?
2 ответа
BASS_ChannelGetLevel
возвращает значение, ограниченное до 0 дБ (в этом случае возвращаемое значение равно 32768). Если вы отрегулируете уровень источника (более низкий уровень микрофона в настройках звуковой карты), то он будет работать нормально.
Другой способ, если вы хотите получить значение без ограничения, это использовать BASS_ChannelGetLevelEx
Функция вместо этого: она возвращает уровни с плавающей запятой, где 1 - максимальное (0 дБ) значение, которое соответствует 32767 BASS_ChannelGetLevel, но оно может превышать 1, чтобы обнаружить уровни звука выше 0 дБ, что вам может понадобиться.
Я также предлагаю вам некоторое время контролировать уровень звука: срабатывать только в том случае, если определенный уровень существует как минимум в течение 2-3 секунд (таким образом вы исключите ложные срабатывания).
Вот как вы получаете уровень БД с помощью дескриптора входного потока (streamHandle):
var peak = (double)Bass.BASS_ChannelGetLevel(streamHandle);
var decibels = 20 * Math.Log10(peak / Int32.MaxValue);
Кроме того, вы можете использовать следующее, чтобы получить среднеквадратичное значение. Чтобы получить среднеквадратичное значение, вы должны передать длину выборки в BASS_ChannelGetLevel
, Я использую здесь 20 миллисекунд, но вы можете поиграть со значением, чтобы увидеть, что лучше всего подходит для ваших нужд.
var decibels = 0m;
var channelCount = 2; //Assuming two channels
var sampleLengthMS = 20f;
var rmsLevels = new float[channelCount];
var rmsObtained = Bass.BASS_ChannelGetLevel(streamHandle, rmsLevels, sampleLengthMS / 1000f, BASSLevel.BASS_LEVEL_RMS);
if (rmsObtained)
decibels = 20*Math.Log10(rmsLevels[0]); //using first channel (index 0) but you can get both if needed.
else
Console.WriteLine(Bass.BASS_ErrorGetCode());
Надеюсь это поможет.