将原始 PCM 文件转换为带有 LAME returns 失真音频的 MP3

Coverting raw PCM file to MP3 with LAME returns distorted audio

我有从 base64 字符串生成的原始 PCM 文件。 Here is the link to the API response that returns in.

然后我从该字符串创建一个 PCM 文件,然后使用 LAME 库将其转换为 MP3。

这是处理转换的代码:

    companion object {
  init {
      System.loadLibrary("mp3lame")
  }
  }


private external fun initEncoder(numChannels: Int, sampleRate: Int, bitRate: Int, mode: Int, quality: Int)
private external fun destroyEncoder()
private external fun encodeFile(sourcePath: String, targetPath: String): Int
val NUM_CHANNELS = 1
val SAMPLE_RATE = 16000
val BITRATE = 128
val MODE = 3
val QUALITY = 0

fun createAudioFromBase64AndGetPath(inputBase64: String, outputFileName: String) {
    initEncoder(NUM_CHANNELS, SAMPLE_RATE, BITRATE, MODE, QUALITY)

    val path: String = "newFile.wav"

    try {
        val decoded = Base64.decode(inputBase64, Base64.NO_WRAP)
        try {
            val fileRaw = File(Environment.getExternalStorageDirectory().toString() + "/$outputFileName.pcm")
            val fileEncoded = File(Environment.getExternalStorageDirectory().toString() + "/$outputFileName.mp3")


                val os = FileOutputStream(fileRaw, true)
                os.write(decoded)
                os.close()

            val result = encodeFile(fileRaw!!.absolutePath, fileEncoded!!.absolutePath)
            if (result == 0) {
                Log.d ("encoded to ", fileEncoded!!.name)
            }
            destroyEncoder()

        } catch (e: Exception) {
            Log.e ("decode ", "first catch", e)
            e.printStackTrace()
        }

    } catch (e: Exception) {
        e.printStackTrace()
        Log.d ("decode ", "2nd catch", e)
    }
}

音频听起来像 this.

我尝试浏览 C 库文件,这些文件解释了 initEncoder 的不同变量选项的含义,我已经摆弄过但没有任何变化。

为了尝试解决此问题而不拖延每次编译应用程序,我采用了 base64 字符串并使用在线转换器 (Motobit) 将其转换为 PCM 文件。然后,我为 mac 使用了一个非常漂亮(且免费)的转换器,称为 XLD 来测试这些转换,而不必每次都编译该应用程序,看看我是否能弄清楚发生了什么,如果我只是在使用initEncoder 的变量组合错误。

我注意到的第一件事是我必须 select 'Open raw PCM (bin+cue)...' 选项才能打开从 motobit 下载的 pcm 文件。

这里是select离子window。

下一个谜题,似乎是关键部分,是我只能在 selecting "Little" 时正确转换音频(没有噪音)字节序框。问题是,回到我的应用程序,我无法找出如何或是否可以访问和更改 LAME 库中的 属性。

为清楚起见,我使用此处的包装器:https://developer.samsung.com/technical-doc/view.do?v=T000000090

如果你绝望了,你可以随时自己切换字节顺序:

for (i in decoded.indices step 2)
{
    val swap = decoded[i]
    decoded[i] = decoded[i + 1]
    decoded[i + 1] = swap
}

...因为 Base64.decode() returns 一个字节数组,我假设您使用的是 16 位音频。

我自己找不到 initEncoder() 文档。