-
Notifications
You must be signed in to change notification settings - Fork 2
Алгоритм вычисления пауз
Для вычисления пауз производится следующая калибровка: перед началом записи выступления выводится обратный отсчёт, во время которого пользователь молчит, а приложение определяет "уровень тишины".
- для определения громкости и тишины/речи одного фрагмента записи: массив целых чисел типа
Short
, полученный в результате вызова методаread()
у экземпляраAudioRecord
- для определения уровней громкости всей записи: отсортированный по возрастанию список громкостей всех фрагментов записи
- для определения громкости: число типа
Double
, равное громкости фрагмента - для определения уровней громкости всей записи: тройка чисел типа
Double
, соответствующих минимальной, максимальной и средней громкостям
Перед началом записи происходит пятисекундный обратный отсчёт, во время которого пользователь молчит. При этом происходит запись аудио (т.е. естественного шума помещения) в буфер. Вычисляются уровни громкости записи. Рассчитывается т.н. "уровень тишины" как:
(avgLevel
— средний уровень громкости, maxLevel
— максимальный уровень громкости)
Метод read()
класса AudioRecord
записывает целые числа в массив типа ShortArray
. Проходим по этому массиву и вычисляем amplitude
— среднее квадратическое всех значений . Громкость фрагмента вычисляется как
.
Но нам удобнее не брать квадратный корень для среднего квадратического, поэтому мы считаем среднее арифметическое суммы квадратов и умножаем не на 20, а на 10.
Псевдокод:
v = 0.0
for (i in 0 to buffer.length)
v += audioBuffer[i] * audioBuffer[i]
amplitude = v / buffer.length
return if (amplitude > 0) 10 * log10(amplitude) else 0.0
Заводим два счётчика: счётчик фрагментов, являющихся тишиной, и общих счётчик фрагментов.
Полученное значение громкости фрагмента сравнивается с уровнем тишины (выше описано, как он вычисляется). Если оно ниже уровня тишины, фрагмент считается тишиной, иначе речью. Увеличиваем общий счётчик и, если надо, счётчик фрагментов, являющихся тишиной.
Объём пауз вычисляется по формуле:
Псевдокод вычисления объёма пауз:
totalFragmentsCounter = 0
silentFragmentsCounter = 0
while (recording)
record.read()
volume = calculateVolume(record)
volumeLevelsList.add(volume)
if (volume < silenceLevel)
silentFragmentsCounter++
totalFragmentsCounter++
silencePercentage = silentFragmentsCounter / totalFragmentsCounter
volumeLevelsList
сортируется и используется для определения минимального, максимального и среднего уровней громкости фрагмента.
Аналогичным образом считается информация по каждому слайду (заводятся счётчики silentFragmentsCounterOnSlide
и totalFragmentsCounterOnSlide
, обнуляющиеся при переходе к следующему слайду).
Для каждого слайда выводятся: суммарная доля пауз, средняя длина паузы, количество пауз с длиной выше средней.
Определение суммарной доли пауз на слайде:
Используется булево поле isPause
. Если считается, что сейчас (анализ ведётся по ходу записи) не пауза, и был прочитан фрагмент тишины, начинаем считать, что сейчас пауза, и записываем время начала паузы. Если сейчас пауза и был прочитан фрагмент речи, то начинаем считать, что сейчас не пауза, и сохраняем время, в течение которого длилась пауза. Сохранённые длины пауз используются для вычисления средней длины паузы и определения количества пауз с длиной выше средней.
while (recording)
...
if (fragmentVolume < silenceLevel)
if (not isPause)
isPause = true
pauseStartTime = currentTime
silentFragmentsCounterOnSlide++
else if (isPause)
pausesPerSlide.add(currentTime - pauseStartTime) // list of pause lengths
isPause = false