使用LAME将原始PCM文件覆盖到MP3会返回失真的音频

时间:2018-11-08 12:42:21

标签: android kotlin mp3 pcm lame

我有从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的变量。

我注意到的第一件事是我必须选择“打开原始PCM(bin + cue)...”选项,以便打开从motobit下载的pcm文件。

这是选择窗口。 The selection window

难题的下一部分似乎是至关重要的部分,那就是在Endian框中选择“小”时,我只能正确转换音频(没有噪音)。问题是,回到我的应用程序后,我无法找到如何甚至是否可以访问和更改LAME库中的此属性。

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

1 个答案:

答案 0 :(得分:1)

如果您感到绝望,可以随时切换自己的字节序:

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

...由于Base64.decode()返回一个字节数组,因此我假设您使用的是16位音频。

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