将 Android 中的音频从 48kHz 重采样到 44.1kHz,反之亦然 - 纯 Java 或 OpenSL ES?

Resampling audio in Android from 48kHz to 44.1kHz and vice versa - pure Java, or OpenSL ES?

我已经成功地使用 MediaCodec 加入了视频文件的音轨。如果两个音轨的通道数和采样率相同,那么这样做就没有问题。

(出于某种原因,如果原始音轨为 22050 Hz,OMX.SEC.aac.dec 始终输出 44100 Hz 2 声道音频,如果原始音轨为 24000 Hz,则输出 48000 Hz 2 声道音频。)

当我尝试在 22050 Hz 音轨之后附加 24000 Hz 音轨时出现问题。假设我想输出一个由上述两个音轨组成的 22050 Hz 音轨,我将不得不对 24000 Hz 音轨进行重新采样。

我试过这个:

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;
}

它 returns 一个 3700 左右字节的字节数组和编码后的正确音频...在非常响亮的加扰声音后面。

我的问题:

  1. 如何在不留下此类伪像的情况下正确地对音轨进行下采样?我应该使用平均值吗?
  2. 我是否应该使用使用 OpenSL ES 实现的重采样器来使过程更快 and/or 更好?

主要问题是当您应该跳过 samples.

时,您只是跳过 bytes

每个样本都是 16 位,所以两个字节。如果音频是立体声,则每个样本有四个字节。您必须始终跳过那么多字节,否则您的样本将完全混淆。

使用相同的比率 (10/11),您可以使用 40/44 始终跳过完整的四字节样本并保持样本正确。

至于为什么生成的视频以不同的速度播放,那是完全不同的事情。