Передискретизация звука в Android с 48 кГц до 44,1 кГц и наоборот — чистая Java или OpenSL ES?

#android #audio #android-mediacodec

#Android #Аудио #android-mediacodec

Вопрос:

Мне удалось объединить звуковые дорожки видеофайлов с помощью MediaCodec. С этим проблем нет, если количество каналов и частота дискретизации обеих звуковых дорожек одинаковы.

(по какой-то причине OMX.SEC.aac.dec всегда выводится 2-канальный звук 44100 Гц, если исходная дорожка имеет частоту 22050 Гц, и выводит 2-канальный звук 48000 Гц, если исходная дорожка равна 24000 Гц.)

Проблема возникает, когда я пытаюсь добавить звуковую дорожку 24000 Гц после звуковой дорожки 22050 Гц. Предполагая, что я хочу вывести звуковую дорожку 22050 Гц, состоящую из обеих указанных дорожек, мне придется передискретизировать 24000 Гц.

Я пробовал это:

 private byte[] minorDownsamplingFrom48kTo44k(byte[] origByteArray)
{
    int origLength = origByteArray.length;
    int moddedLength = origLength * 147/160;
    int delta = origLength - moddedLength;
    byte[] resultByteArray = new byte[moddedLength];
    int arrayIndex = 0;
    for(int i = 0; i < origLength; i =11)
    {
        for(int j = i; j < i 10; j  )
        {
            resultByteArray[arrayIndex] = origByteArray[j];
            arrayIndex  ;
        }
    }
    return resultByteArray;
}
 

Он возвращает массив байтов из 3700 с чем-то байтов и правильный звук после кодирования… за очень громким скремблированным звуком.

Мои вопросы:

  1. Как мне правильно уменьшить дискретизацию звуковой дорожки, не оставляя таких артефактов? Должен ли я использовать средние значения?
  2. Должен ли я использовать передискретизатор, реализованный с использованием OpenSL ES, чтобы ускорить и / или улучшить процесс?

Комментарии:

1. Ваши данные, вероятно, 16 бит, и особенно, если это два канала, вы не можете просто пропустить байты из данных. Также, если вы хотите сделать это правильно, вы должны отфильтровать конечный результат, чтобы убедиться, что нет артефактов сглаживания или чего-либо еще. Но я думаю, что первая часть является основной проблемой. Копирование 40 байт и пропуск 4 могут это исправить.

2. 16 бит и повышенная дискретизация (источник имел частоту дискретизации 22050 Гц, а выходной сигнал декодера составлял 44100 Гц), по-видимому. В любом случае, как мне применить этот фильтр на основе выборки к выборке в Java?

3. Копирование 40 байт и пропуск 4 работает, но звук в конечном выходном видео замедляет воспроизведение всего видео.

4. Не могли бы вы посоветовать, как реализовать повторную выборку с использованием OpenSL?

Ответ №1:

Основная проблема заключается в том, что вы просто пропускаете байты, когда должны пропускать сэмплы.

Каждая выборка составляет 16 бит, то есть два байта. Если звук стерео, на выборку приходится четыре байта. Вы всегда должны пропускать столько байтов, иначе ваши сэмплы будут полностью перепутаны.

Используя то же соотношение (10/11), вы можете использовать 40/44, чтобы всегда пропускать полный четырехбайтовый сэмпл и сохранять правильные сэмплы.

Что касается того, почему результирующее видео воспроизводится с другой скоростью, это нечто совершенно другое.