Покрытие сырого файла PCM в MP3 с помощью LAME возвращает искаженное аудио

137
14

У меня есть сырые файлы 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)
}
}

Звук выходит звучащим так .

Я пробовал перемещаться по файлам библиотеки 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

спросил(а) 2021-01-27T18:51:37+03:00 8 месяцев, 3 недели назад
1
Решение
65

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

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

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

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

ответил(а) 2021-01-27T18:51:37+03:00 8 месяцев, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема