Я строю приложение для обнаружения шага в реальном времени в Kotlin/Android с использованием Tarsosdsp. Приложение захватывает аудио вход, обнаруживает фундаментальную частоту с использованием алгоритма FFT_YIN, и отображает результат на вертикальном виде с фортепиано, который позволяет вам визуально отслеживать высоту со временем. Правильно соответствует значениям шага с их вертикальным положением (ось Y) в ролике на фортепиано. Предыдущий уровень. Эти падения происходят только после выпуска, а не во время устойчивых нот, и, по-видимому, возникают в рамках обнаружения высоты тона TarsosDSP, а не на моем собственном графике или математике. Tarsosdsp. Таким образом, в моей логике DrawPitchGraph () нет ошибки. Наиболее стабильным до сих пор является FFT_YIN. < /P>
< /li>
Изменение скорости дискретизации и размер буфера не помогли: < /p>
< /li>
< /ul>
samprere = 22050, buffersize = 1024, Onlappors = 0. Выпустить. https://i.sstatic.net/ot5yk1oa.png - ошибочное падение происходит здесь
[Печать экрана для 21:55] [3] https://i.static.net/2l5bfcm6.png - идет к следующему воспроизведению после быстрого возвращения к 1 -й позиции
woe to the note note return to 1st
pitchinhz: 54.94872 (hz) < /p>
y = 1599.3716 < /p>
3nцин. Hz) < /p>
y = 1035.145 < /p>
Мне нужно упомянуть, что то, что я играл с пианино с первого до третьего изображения, составляет всего две ноты. Во -первых, A3, это правильно показывает на первом изображении. Я буквально выпустил заметку на милисекунду перед вторым изображением в 20:70. Следующей нотой, которую я играл почти мгновенно, была G3 (в 21:30 APROX), которое правильно показывает на 3 -м изображении. Падение и возвращение к первой позиции Y происходит между обеими примечаниями, где в основном не было звука, потому что я нахожусь в очень молчаливой среде.
Я проверял в одиночку в одиночестве с моим приложением, а Tarsos не обнаруживает их, так что устранение возможностей фонового шума по большей части. /> Настройка обнаружения высоты тона. Эта настройка вложена в слушатель моего Playpausebutton и выполняется при нажатии на «Play» и останавливается, когда «приостановил»: < /li>
< /ol>
Код: Выделить всё
val sampleRate = 22050
val bufferSize = 1024
val overlap = 0
val audioRecord = AudioRecord(
MediaRecorder.AudioSource.MIC,
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize
)
val tarsosFormat = TarsosDSPAudioFormat(
sampleRate.toFloat(),
16, // bitsPerSample
1, // channels
true, // signed
false // bigEndian
)
val inputStream = AndroidAudioInputStream(audioRecord, tarsosFormat)
dispatcher = AudioDispatcher(inputStream, bufferSize, overlap)
val pdh = PitchDetectionHandler { result, _ ->
val pitchInHz = result.pitch
if (pitchInHz > 0) {
val note = NoteConverter.hzToNote(pitchInHz)
runOnUiThread {
findViewById(R.id.textView1).text = note
}
} else {
runOnUiThread {
findViewById(R.id.textView1).text = "No note detected"
}
}
pianoRollView.pitchInHz2 = pitchInHz
pianoRollView.invalidate()
}
val p: AudioProcessor = PitchProcessor(
PitchProcessor.PitchEstimationAlgorithm.FFT_YIN,
22050f,
1024,
pdh
)
dispatcher?.addAudioProcessor(p)
Thread(dispatcher, "Audio Dispatcher").start()
< /code>
My Drawpitchgraph () и Dlawtrace (). Нарисуйте текущий и предыдущий шаг, обнаруженный (называемый в моем основном ondraw ()) внутри класса Pianorollview (): < /li>
< /ol>
private fun drawPitchGraph(canvas: Canvas) {
if (baseKeyHeight == 0f || listOfNotes.isEmpty()) return
val a4Index = listOfNotes.indexOf("A4")
val yRef = baseKeyHeight * (totalKeys - 1 - a4Index) + baseKeyHeight / 2f
val y: Float? = if (pitchInHz2 > 0.0) {
val semitoneOffset = log2(pitchInHz2 / 440.0) * 12
yRef - baseKeyHeight * semitoneOffset.toFloat()
} else {
null
}
currentYValue = y
if (y != null) {
canvas.drawCircle(width * 0.7f, y, 8f, pitchPaint)
}
}
fun drawTrace(canvas: Canvas) {
currentYValue?.let { y ->
tracePoints.add(TracePoint(width.toFloat() * 0.7f, y))
} ?: tracePoints.add(null)
for (i in tracePoints.indices) {
tracePoints[i]?.let {
tracePoints[i] = it.copy(x = it.x - 2f)
}
}
for (i in 0 until tracePoints.size - 1) {
val p1 = tracePoints[i]
val p2 = tracePoints[i + 1]
if (p1 != null && p2 != null) {
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, pastPitchPaint)
}
}
tracePoints.lastOrNull()?.let {
canvas.drawCircle(it.x, it.y, 8f, pastPitchPaint)
}
invalidate()
}
Это ожидаемое поведение от FFT_yin или аналогичных алгоритмов? Существуют ли больше алгоритмов одобрения для отслеживания высоты тона или я могу повторно конфигурировать FFT_YIN для более надежных результатов? или значения среднеквадратичных значений, или есть лучший подход? Я мог бы даже загрузить видео, если это необходимо. Я также открыт для обходных путей - даже если это означает предварительную обработку или стабилизацию значений шага перед рисунком.
Заранее спасибо за вашу помощь!
Подробнее здесь: https://stackoverflow.com/questions/797 ... te-release