Сравнение звука с микрофона с сохраненным аудиофайлом и определение его положенияAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Сравнение звука с микрофона с сохраненным аудиофайлом и определение его положения

Сообщение Anonymous »

У меня есть сохраненный аудиофайл. Формат файла может быть любым, если это имеет значение. Затем у меня записывается звук с микрофона устройства. Допустим, это просто какая-то песня.
Теперь мне нужно найти момент в аудиофайле, который в данный момент записывается через микрофон.
Я полностью понимаю, что простое сравнение явно не вариант, поскольку звук с микрофона далеко не идентичен аудиофайлу. Я пробовал найти наиболее подходящую часть аудиофайла, используя пики формы сигнала, но это работает не очень хорошо.
Вот как я пытался:

Код: Выделить всё

//record waveform peaks from the microphone
suspend fun getWaveformPeakFromMic(): List {
val sampleRate = 44100
val bufferSize = 882 // 200ms buffer size for more frequent peaks

val duration = calculateBufferDuration(bufferSize, sampleRate)
Log.d("WaveformPeaks", "Buffer duration: $duration")
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
) != PackageManager.PERMISSION_GRANTED
) {
return emptyList()
}
val audioRecord = AudioRecord(
MediaRecorder.AudioSource.MIC,
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize
)

val waveformPeaks = mutableListOf()
val buffer = ShortArray(bufferSize)

audioRecord.startRecording()
lifecycleScope.launch {
delay(5000)
Log.d("WaveformPeaks", "Stopping audio recording")
audioRecord.stop()
audioRecord.release()
}

var read = audioRecord.read(buffer, 0, buffer.size)
while (read > 0) {
val peak = buffer.maxOf { abs(it.toInt()) }
waveformPeaks.add(peak)
read = audioRecord.read(buffer, 0, buffer.size)
}
Log.d("WaveformPeaks", "WaveformPeaks size: ${waveformPeaks.size}")

return waveformPeaks
}

//get waveform peaks from the audio file
fun getWaveformPeaksFromPCM(filePath: String, ): List {
val bufferSize = 882 // 200ms buffer size for more frequent peaks
val waveformPeaks = mutableListOf()
val byteArray  = readFileFromAssets(this, filePath)
val shortBuffer = ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer()
val buffer = ShortArray(bufferSize)

while (shortBuffer.hasRemaining()) {
val length = minOf(buffer.size, shortBuffer.remaining())
shortBuffer.get(buffer, 0, length)
val peak = buffer.take(length).maxOf { abs(it.toInt()) }
waveformPeaks.add(peak)
}

Log.d("WaveformPeaks", "WaveformPeaks size: ${waveformPeaks.size}")

return waveformPeaks
}
Аудиофайл в настоящее время представляет собой необработанный звук PCM (который я сделал из mp3 с помощью FFMpeg)
И вот как я пытался найти совпадение время:

Код: Выделить всё

fun findIndex(full:IntArray, part:IntArray) {

val (bestMatchIndex, likenessCoefficient) = findBestMatch(full, part)
if (bestMatchIndex != -1) {
Log.d("FindMic", "Matching subarray found at position ${bestMatchIndex * 0.02}, likeness coefficient: $likenessCoefficient")
} else {
Log.d("FindMic", "Matching subarray not found")
}
}

fun findBestMatch(full: IntArray, part: IntArray): Pair {
var bestMatchIndex = -1
var bestMatchDistance = Double.POSITIVE_INFINITY

for (i in 0..(full.size - part.size)) {
val subArray = full.sliceArray(i until (i + part.size))
val distance = dtwDistance(subArray, part)
if (distance <  bestMatchDistance) {
bestMatchDistance = distance
bestMatchIndex = i
}
}
val likenessCoefficient = 1 / (1 + bestMatchDistance) // Example coefficient calculation
return Pair(bestMatchIndex, likenessCoefficient)
}

fun dtwDistance(seq1: IntArray, seq2: IntArray): Double {
val n = seq1.size
val m = seq2.size
val dtw = Array(n + 1) { DoubleArray(m + 1) { Double.POSITIVE_INFINITY } }
dtw[0][0] = 0.0

for (i in 1..n) {
for (j in 1..m) {
val cost = Math.abs(seq1[i - 1] - seq2[j - 1]).toDouble()
dtw[i][j] = cost + minOf(dtw[i - 1][j], dtw[i][j - 1], dtw[i - 1][j - 1])
}
}
return dtw[n][m]
}
Поэтому в настоящее время это просто не работает - он показывает совершенно случайные позиции как наиболее подходящие, а коэффициент сходства равен 2,4996687938848104E-6
И наконец, вопрос: как мне правильно найти момент времени, воспроизводимый через микрофон? Я открыт для любых способов, включая сторонние библиотеки, внешние сервисы, даже платные, предложения по реализации этого на бэкэнде и т. д.

Подробнее здесь: https://stackoverflow.com/questions/790 ... its-positi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»