Покрытие сырого файла PCM в MP3 с помощью LAME возвращает искаженное аудио - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть сырые файлы PCM, сгенерированные из строки base64. Вот ссылка на ответ API, который возвращается. .

Затем я создаю файл PCM из этой строки, после чего преобразую его в MP3, используя библиотеку LAME.

Вот код, который относится к конвертации:

    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 и преобразовал ее в файл PCM с помощью онлайн-конвертера (Motobit). Затем я использовал очень изящный (и бесплатный) конвертер для Mac под названием XLD, чтобы протестировать эти преобразования без необходимости каждый раз компилировать приложение, чтобы посмотреть, смогу ли я выяснить, что происходит, и, возможно, я просто использовал неправильную комбинацию переменные для initEncoder.

Первое, что я заметил, было то, что мне пришлось выбрать опцию «Open raw PCM (bin + cue) ...», чтобы открыть файл pcm, загруженный с motobit.

Вот окно выбора. The selection window

Следующая часть головоломки, которая, кажется, является решающей, заключалась в том, что мне удалось только правильно преобразовать звук (без шума) при выборе «Little» в поле «Endian». Проблема в том, что в моем приложении я не могу узнать, как или даже могу ли я получить доступ и изменить это свойство в библиотеке LAME.

Для ясности я использую обертку отсюда: https://developer.samsung.com/technical-doc/view.do?v=T000000090

1 Ответ

0 голосов
/ 09 ноября 2018

Если вы приходите в отчаяние, вы всегда можете переключить порядок байтов самостоятельно:

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

... поскольку Base64.decode() возвращает байтовый массив, и я предполагаю, что вы используете 16-битный звук.

Я не смог найти initEncoder() документы самостоятельно.

...