Формула RMS-метра

  • Автор темы Автор темы MSerg
  • Дата начала Дата начала

MSerg

Well-Known Member
30 Ноя 2015
869
1.533
93
Наверное в теме с рипером больше всего программистов) спрошу тут))

Знакомому программисту требуется написать RMS-meter на языке C#. Но я ему ничем помочь не смог т.к. не знаю математику, по какой формуле работает подсчёт RMS-уровня. Друзья, коллеги, соратники!) подскажите, что из себя представляет формула RMS-метра?Как объяснить программисту, что именно надо закодить?

У него есть много всякого кода по пиковым индикаторам громкости - этого добра в C# очень много на GitHub и других ресурсах. Но превратить пиковый индикатор в RMS - тут знаний нахватает. Кто шарит?)

PS
Можем даж денежку заплатить за написание RMS-индикатор на C#
 

(извиняюсь за банальность ссылки, но, как бы, чего более желать…)
ну так то можно и в Гугл вбить «RMS» и результат запостить сюда. Только от этого ни горячо ни холодно. Там сотни разных формул с вольтами и ещё черт знает чем. Но формулы все разные. Надо что-то одно и конкретное. По какой именно формуле работает RMS индикатор в рипере? Кто знает?
 
Я просто искренне не могу понять суть вопроса. Ваш приятель не знает, как посчитать среднее квадратичное число? Это же школьная программа, какие сотни формул?

Берётся массив значений, суммируется, делится на количество элементов в массиве (то есть получаем среднее арифметическое значение), из него извлекается квадратный корень

В случае с аудиосигналом (тут меня, надеюсь поправят и дополнят, пишу без гугла) берут квазипиковые значения, время интеграции 300 мс (емнип). Если у него уже есть инструмент для измерения пиковых уровней — …
 
  • Like
Реакции: buncker и PianoIst
Тут единственный неизвестный параметр — окно интеграции. @fakeitback его назвал)

А всё остальное, в принципе sqrt(сумма квадратов пиков / количество пиков).
хмм, а при чем тут пики? RMS это же практически среднее давление за промежуток времени, если это будет низкочастотная составляющая, то она как-то не особо сравнивается с высокочастотной. При небольшой громкости низы вам могут стекла вынести напрочь волной. А хэты не сделают этого никогда ) Там не просто так все расчитывется, пики это просто пики )
Соответственно RMS это звуковое давление на единицу площади за единицу времени. Громкость и пики привязаны тут лишь косвенно.
 
Последнее редактирование:
@vip76, тогда это будет уже не RMS а LUFS.
А RMS это RootMeanSquare — взяли каждый сэмпл, возвели в квадрат, проссуммировали, разделили, получили RMS.

Вообще, можно держать под рукой библиотеку для Python librosa. Там много хорошо читаемых, понятных без перевода реализаций типичных для DSP вещей. Хотя я сейчас стал кое-какие вещи переписывать под себя.
 
  • Like
Реакции: fakeitback
@PianoIst, не буду спорить, честно не разбирался в этом вопросе, просто логически пытаюсь рассуждать из базовых знаний ) Да и этих стандартов, что черт ногу сломит )
 
взяли каждый сэмпл, возвели в квадрат, проссуммировали, разделили, получили RMS
А можете текстом эту механику просчитать? Например на 3х сэмплах? Типа...
Сэмпл1: -10дб
Сэмпл2: -3дб
Сэмпл3: -8,91дб

Какой путь пройдёт число от каждого сэмпла и какое будет результирующее число
 
vip76
Геометрический смысл RMS - площадь поверхности, которая ограничена волной
 
  • Like
Реакции: Long
Если сигнал дискретный, то тупо суммируем площадь всех прямоугольничков цифрового сигнала на определенном отрезке времени. Обычно 300мс. Всё!
 
  • Like
Реакции: MSerg и vip76
А можете текстом эту механику просчитать? Например на 3х сэмплах? Типа...
Сэмпл1: -10дб
Сэмпл2: -3дб
Сэмпл3: -8,91дб

Какой путь пройдёт число от каждого сэмпла и какое будет результирующее число

Лучше в значениях сэмплов (хотя наверное разницы нет, но сходу не могу точно сказать). Допустим значения 100, 30, 89, тогда RMS за окно в 3 сэмпла будет sqrt(100^2/3+30^2/3+89^2/3)≈79. Если с дБ нет разницы, то будет -7,9 дБ
 
  • Like
Реакции: fakeitback и MSerg
А квадраты в формуле для того, чтобы положительные и отрицательные значения не взаимовычитались при суммировании.
 
@MSerg,
Python:
from math import sqrt

peaks = [-10, -3, -8.91]


def RMS(peaks):
    return sqrt(sum(peak**2 for peak in peaks) / len(peaks))


print(RMS(peaks))


def RMS_step_by_step(peaks):
    print('got peaks:', peaks)
    sum_ = 0
    for peak in peaks:
        sum_ += peak**2
        print('peak is', peak, ', squared', peak**2, ', sum now is', sum_)
    print(f'sum / number of peaks ({len(peaks)})', sum_ / len(peaks))
    print('returning square root')
    return sqrt(sum_ / len(peaks))


print('--------------')
print('now step by step:')
print(RMS_step_by_step(peaks))
Код:
7.924394824422452
--------------
now step by step:
got peaks: [-10, -3, -8.91]
peak is -10 , squared 100 , sum now is 100
peak is -3 , squared 9 , sum now is 109
peak is -8.91 , squared 79.38810000000001 , sum now is 188.3881
sum / number of peaks (3) 62.796033333333334
returning square root
7.924394824422452
[Finished in 36ms]

P.S. Но @Цыхра прав в том, что обычно мы не считаем в ДБ, хотя я разницы не вижу, результат-то тоже в децибелах)
P.P.S. Квадраты нужны не для того, чтобы избавиться от негативного влияния отрицательных чисел (для этого было бы достаточно брать модуль). Квадраты нужны примерно для того же, для чего в теореме Пифагора. Но я в геометрии не силён) Если б не было квадратов — это было бы просто Mean. И оно было бы -7.3
 
Последнее редактирование:
  • Like
Реакции: MSerg
Во, теперь что-то проясняется. Тогда получается, что, если мы берём 300мс звука, и у нас, допустим, 48000hz... то... количество сэмплов, которые надо так просуммировать... 48000hz x 0.3sec = 14 400 сэмплов.

И тогда мы получаем обычную риперовскую RMS-индикацию?
 
  • Like
Реакции: PianoIst
если вы думаете что все так просто, то ответьте на вопросы:
- Как часто надо слать рмс в морду? по частоте монитора или реже? или чаще?
- надо ли собирать рмс каждый следующий семпл? копить и фильтровать?
- а если он меньше чем предыдущий - слать ли в гуй?
 
RMS некого переменного сигнала, это действующее значение напряжения. А действующее значение переменного напряжения, это значение постоянного напряжения, при котором в активной нагрузке будет выделяться эквивалентная мощность.

Мощность, мгновенное значение которой равно U^2/R - величина интегральная, поэтому и сумма, и квадратов. Таким образом, для напряжения произвольной формы мы считаем выделившуюся за период времени мощность и высчитываем, какое значение постоянного напряжения привело бы к такому же результату. Бинго.

Например, знаменитое розеточное 220В - это величина действующая и мощность в активной нагрузке будет выделяться точно такая же, если на нее подать 220В постоянного напряжения.
 
  • Like
Реакции: Alx_g и PianoIst
@basЫl, если исходить из программистской логики — можно вообще пойти от прерываний:
Хост сам решает, когда запросить у плагина GUI. Поэтому можно обновлять по факту запроса: сколько накопилось, столько и отдавать.
Для этого даже не нужны какие-то супер-пупер динамические массивы, т.к. мы всё равно складываем сумму по одному адресу.

Если же нам интересно конкретное окно (сглаживание) — то я бы делал так:
Сделал очередь по размеру окна, и скидывал туда все сэмплы подряд. А как хост запросит обновить картинку — интегрировал. Дёшево и сердито. Таким образом, у нас получается фиксированное сглаживание и автоматический подбор перекрытия окна (В ReaTune, допустим, количество перекрытий выбираешь явно).

Для «живого» метра нам не нужна идеальная точность. Для идеальной точности есть статический анализ. Пиковые значения (для «пробивных индикаторов»), если они нужны, можно интегрировать без перекрытия и отдавать по запросу, чтобы учесть все сэмплы и не грузить процессор лишний раз.
 
  • Like
Реакции: MSerg
Друзья, всем огромное спасибо! Благодаря Вашим подсказкам RMS-индикатор был закоден минут за 20 на базе другого пикового индикатора) всё отлично! Вопрос решён)
 
  • Like
Реакции: fakeitback
Если сигнал дискретный, то тупо суммируем площадь всех прямоугольничков цифрового сигнала на определенном отрезке времени

-- Вычисление определённого интеграла методом трапеций.
 
  • Like
Реакции: Цыхра

Сейчас просматривают