Java алгоритм для нормализации звука
Я пытаюсь нормализовать аудиофайл речи.
В частности, где аудиофайл содержит пики в объеме, яЯ пытаюсь выровнять его, чтобы тихие участки были громче, а пики тише.
Я очень мало знаю о звуковых манипуляциях, помимо того, что ямы научились работать над этой задачей. Кроме того, моя математика смущающе слаба.
Мы провели некоторое исследование, и на сайте Xuggle приведен пример, показывающий уменьшение объема с помощью следующего кода: (полная версия здесь)
@Override
public void onAudioSamples(IAudioSamplesEvent event)
{
// get the raw audio byes and adjust it's value
ShortBuffer buffer = event.getAudioSamples().getByteBuffer().asShortBuffer();
for (int i = 0; i < buffer.limit(); ++i)
buffer.put(i, (short)(buffer.get(i) * mVolume));
super.onAudioSamples(event);
}
Здесь они модифицируют байты вgetAudioSamples()
константой.mVolume
Основываясь на этом подходе, япопытка нормализации изменяет байты вgetAudioSamples()
к нормированному значению, учитывая максимум / мин в файле. (Подробности смотрите ниже). У меня есть простой фильтр, чтобы уйтитишина» один (то есть, что-нибудь ниже значения) .I '
обнаружив, что выходной файлочень шумно (т. е. качество серьезно ухудшается). Я предполагаю, что ошибка либо в моём алгоритме нормализации, либо в способе манипулирования байтами. Однако я'Я не уверен, куда идти дальше.
Вот'это сокращенная версия того, что ям в настоящее время занимаюсь.
Шаг 1: Найти пики в файле:Читает полный аудиофайл и находит это самое высокое и самое низкое значенияbuffer.get()
для всех AudioSamples
@Override
public void onAudioSamples(IAudioSamplesEvent event) {
IAudioSamples audioSamples = event.getAudioSamples();
ShortBuffer buffer =
audioSamples.getByteBuffer().asShortBuffer();
short min = Short.MAX_VALUE;
short max = Short.MIN_VALUE;
for (int i = 0; i < buffer.limit(); ++i) {
short value = buffer.get(i);
min = (short) Math.min(min, value);
max = (short) Math.max(max, value);
}
// assign of min/max ommitted for brevity.
super.onAudioSamples(event);
}
Шаг 2: нормализуйте все значения:В цикле, подобном шагу 1, замените буфер нормализованными значениями, вызвав:
buffer.put(i, normalize(buffer.get(i));
public short normalize(short value) {
if (isBackgroundNoise(value))
return value;
short rawMin = // min from step1
short rawMax = // max from step1
short targetRangeMin = 1000;
short targetRangeMax = 8000;
int abs = Math.abs(value);
double a = (abs - rawMin) * (targetRangeMax - targetRangeMin);
double b = (rawMax - rawMin);
double result = targetRangeMin + ( a/b );
// Copy the sign of value to result.
result = Math.copySign(result,value);
return (short) result;
}
Вопросы:Это правильный подход для попытки нормализовать аудиофайл?Моя математика вnormalize()
действует?Почему это может привести к шуму файла, когда подобный подход в демонстрационном коде нет? "Я