메트로놈 Simple Metronome 17
메트로놈 Simple Metronome 바로가기 ↗
이 글은 메트로놈 Simple Metronome 시리즈의 17번째 기록입니다. (총 18개)
오늘 한 일
- 재생 시작 때 첫 박 소리가 작게 들리던 문제 해결 — 안 들리는 예열음으로 오디오 경로를 미리 깨움
- 예열 때문에 어긋난 소리-인디케이터 정렬을 지연 보정으로 맞춤
- 매우 느린 BPM(1)에서 앱이 꺼지던 것 수정
- v1.20 출시
막힌 부분
첫 박만 작게 들리는 원인 — 오디오 경로 콜드스타트
재생을 시작하면 첫 박만 작게 들렸다(둘째 박부터는 정상). 첫 박과 둘째 박은 소리 크기(gain)가 똑같은데 첫 박만 작으니, 소리 데이터가 아니라 버퍼 맨 앞이라는 위치가 문제였다.
원인은 앱 밖에 있었다. 무음 상태에서 재생이 시작되면 기기 스피커·앰프가 pop을 막으려고 서서히 켜지는데(램프업), 그 램프가 끝나기 전에 나온 첫 클릭이 눌린 것이다. 한 번 데워지면 그 뒤론 정상이라 첫 박에만 나타났다.
- 해결: 트랙 맨 앞에 안 들리는 저레벨 노이즈(~150ms, 페이드아웃)를 프리롤해 경로를 미리 깨운다. 큰 부분은 아직 차가운 앰프에 눌려 안 들리고, 데워질 무렵엔 0이라 첫 박 직전엔 조용하다.
예열을 붙이니 소리와 인디케이터가 어긋남
인디케이터는 오디오 재생 위치의 주기 알림으로 켜진다. 그런데 이 알림은 “재생 시작(프레임 0)” 기준으로 뜨고, 실제 클릭은 프리롤만큼 뒤로 밀린다. 그래서 소리는 둘째 박인데 불은 첫 박에 뜨는 어긋남이 생겼다.
알림이 클릭보다 딱 “프리롤 + 리드”만큼 이르다는 걸 이용해, 점등을 그만큼 지연시켜 소리와 맞췄다.
// 클릭은 프리롤+리드만큼 늦게 난다 → 점등을 그만큼 미뤄 소리와 일치
val offsetMs = (warmFrames + leadFrames).toLong() * 1000L / sampleRate
// 주기 알림에서 박 번호를 구해:
mainHandler.postDelayed({
if (token == playToken) { tickIndex = idx; tickListener?.invoke(idx) }
}, offsetMs)
- 해결: 클릭 0은 주기 알림이 없어 재생 시작 + offset 뒤 직접 점등, 나머지는 알림마다 offset 지연 점등.
왜 예열을 “같은 트랙 프리롤”로 넣었나
예열 방식을 두 갈래 먼저 봤지만 이 기기에서 안 됐다.
- 별도 예열 트랙: 첫 박은 잡혔으나 재생 때마다 두 번째 오디오 트랙을 만드는 게 간헐 크래시.
- 재생 헤드를 flush로 되돌리는 방식: 예열이 다 나올 때까지 기다리는 로직이 안 끝나 재생이 아예 안 됨.
그래서 예열을 메트로놈 트랙 맨 앞 프리롤로 합치고(트랙 하나), 정렬은 위의 지연 보정으로 처리했다. 별도 트랙도 flush도 안 쓴다.
느린 BPM에서 앱이 꺼짐 — 버퍼 크기
BPM 1이면 한 마디가 240초라 한 마디 패턴 버퍼가 ~23MB가 된다. 그 크기를 그대로 오디오 트랙 버퍼로 요청하니 트랙 생성이 실패해 앱이 꺼졌다. 스트리밍 재생은 데이터를 계속 이어 쓰는 방식이라 버퍼가 한 마디를 통째로 담을 필요가 없다.
- 해결: 트랙 버퍼를 최대 ~4초로 캡. 정상 BPM엔 영향 없고, 아주 느린 BPM에서만 합리적 크기로 제한된다.
다음에 할 일
- 워밍업이 다른 기기·헤드폰에서도 첫 박을 살리는지 확인 (콜드스타트는 기기마다 다름)
Series: 메트로놈 Simple Metronome
1 | 메트로놈 Simple Metronome 2 | 메트로놈 Simple Metronome ― 처음 만든 앱, Google Play 출시기 3 | 메트로놈 Simple Metronome ― ver 1.9 4 | 메트로놈 Simple Metronome ― ver 1.10 5 | 메트로놈 Simple Metronome 4 6 | 메트로놈 Simple Metronome 5 7 | 메트로놈 Simple Metronome 6 8 | 메트로놈 Simple Metronome 7 9 | 메트로놈 Simple Metronome 8 10 | 메트로놈 Simple Metronome 9 11 | 메트로놈 Simple Metronome 10 12 | 메트로놈 Simple Metronome 11 13 | 메트로놈 Simple Metronome 12 14 | 메트로놈 Simple Metronome 13 15 | 메트로놈 Simple Metronome 14 16 | 메트로놈 Simple Metronome 15 17 | 메트로놈 Simple Metronome 17 읽는 중 18 | 메트로놈 Simple Metronome 16