오늘의 공부는?!/Android
[Android] 녹음기 만들기 with 코틀린(4) - 오디오 시각화(Custom Drawing)
꼬물쥰
2022. 2. 25. 14:39
커스텀뷰를 정의해서 녹음된 음성을 시각화하였다. 음폭에 따라 drawLine을 이용해 그려준다.
커스텀 뷰에는 Canvas로 무엇을 그릴지 Paint로 어떻게 그릴지 설정해준다. ( custom drawing )
//Paint 생성(음성시각화)
private val amplitudePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = context.getColor(R.color.purple_500)
strokeWidth = LINE_WIDTH
strokeCap = Paint.Cap.ROUND
}
paint객체를 정의해주고 아래에서 라인을 그려준다.
onSizeChanged를 오버라이드 해서 그릴 라인의 사이즈가 변경되는 경우 너비와 높이를 가져와 재설정할 수 있다.
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
drawingWidth = w
drawingHeight = h
}
onDraw
실제 paint 객체를 사용하여 원하는 라인을 그린다. 진폭에 대한 배열을 이용해 하나씩 그려준다.
이때, 우측부터 그리기 위해서 우측 좌표를 가지고 있다가 하나씩 그리면서 LINE_SPACE만큼 빼주면서 그린다.
뷰영역에서 넘어가는 경우에는 return을 해서 더이상 그리지 않는다.
재생할 때는 뒤에서부터 보여줘야하기 때문에 takeLast를 사용하였다.
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?: return
val centerY = drawingHeight / 2f
var offsetX = drawingWidth.toFloat()
drawingAmplitudes
.let{ amplitudes ->
if(isReplaying){
amplitudes.takeLast(replayingPosition)
} else{
amplitudes
}
}
.forEach { amplitude ->
val lineLength = amplitude / MAX_AMPLITUDE * drawingHeight * 0.8F
offsetX -= LINE_SPACE
if(offsetX <0) return@forEach
canvas.drawLine(
offsetX,
centerY - lineLength / 2F,
offsetX,
centerY + lineLength / 2F,
amplitudePaint
)
}
}
녹음을 시작하면 오디오 시각화를 실시간으로 하기위해 runnable 객체를 post해서 일정 인터벌 당 계속해서 호출하도록 설정하였다. 진폭값을 실시간으로 가져와서 현재 리스트의 가장 앞에 붙여서 순차적으로 그려질 수 있도록 하였다.
이때 리스트가 변경되면 invalidate()를 호출하여 뷰를 갱신해주어야 한다.
//Runnable : 반복해서 자신을 실행시키도록 요청(interface)
private val visualizeRepeatAction: Runnable = object : Runnable{
override fun run() {
if(!isReplaying) {
val currentAmplitude = onRequestCurrentAmplitude?.invoke() ?: 0
drawingAmplitudes = listOf(currentAmplitude) + drawingAmplitudes
}else{
replayingPosition++
}
invalidate()
handler?.postDelayed(this, ACTION_INTERVAL)
}
}