이 코드는 AudioKit, STKAudioKit, SwiftUI를 활용하여 구현된 셰이커(Shaker) 기반 메트로놈 데모 앱입니다. 사용자는 템포, 박자, 음색, 벨로시티 등을 조절할 수 있으며, 시각적인 피드백도 함께 제공합니다.
아래는 구조를 전체적으로 설명한 뒤, 구성 요소별로 자세하게 해석해드립니다.
🧭 전체 개요
STKView: 사용자 인터페이스를 담당하는 SwiftUI 뷰
ShakerConductor: AudioKit 엔진을 설정하고 Sequencer 및 Shaker를 관리하는 오디오 컨트롤러
SynthesisToolkitView.swift는 STKAudioKit 기반의 샘플 기반 악기인 Shaker를 사용한 오디오 타이머/메트로놈 구현입니다.
🎼 오디오 구성 (ShakerConductor)
1
| class ShakerConductor: ObservableObject, HasAudioEngine
|
구성 요소:
| 속성 |
설명 |
shaker |
STKAudioKit의 셰이커 악기 |
callbackInstrument |
비트 타이밍마다 호출되는 콜백 악기 |
reverb |
셰이커에 적용할 리버브 |
sequencer |
시퀀서 – 박자 및 타이밍 제어 |
data |
사용자 설정 상태 (isPlaying, tempo, currentBeat 등) |
핵심 동작:
data가 바뀔 때마다 didSet에서 시퀀서 재시작 + 템포 반영 + 시퀀스 갱신
updateSequences()에서 박자에 따라 셰이커 노트 시퀀스를 생성
1
| track.sequence.add(...) // 각 박에 음표 추가
|
callbackInstrument는 UI 업데이트용으로 박마다 콜백을 호출
🧱 SwiftUI 레이아웃 구성 (STKView)
🌐 Orientation-aware Layout
1
| let isLandscape = geometry.size.width > geometry.size.height
|
- 화면 비율을 기준으로 가로/세로 모드를 판별
- 각 모드에 맞는 HStack/VStack 레이아웃을 다르게 설정
- “Start”/”Stop” 토글 버튼
GeometryReader를 통해 버튼을 가운데에 배치
1
| .position(x: geometry.size.width / 2, y: geometry.size.height / 2)
|
🎚 TempoSliderArea
1
| Slider(value: $conductor.data.tempo, in: 60.0...240.0)
|
- 60~240 BPM 범위 내에서 템포 조절 가능
- 텍스트로 현재 템포 표시
🎵 BeatSelectArea
-
두 개의 Stepper UI:
- Downbeat (첫 박자에 나올 음색)
- Other beats (나머지 박자의 음색)
1
| conductor.data.downbeatNoteNumber += 1
|
- MIDI 노트 번호를 기반으로
ShakerType과 매핑된 음색을 설정함
🔊 VelocityArea
1
| Slider(value: $conductor.data.beatNoteVelocity, in: 0...127)
|
🧮 BeatCounterArea
- 현재 박자 수(
timeSignatureTop)만큼 버튼이 생성
- 현재 박자는
data.currentBeat와 비교해 색상 강조
- 마지막 “+” 버튼을 눌러 박자 수 증가 가능
1
| GeoCircleButton(...) { conductor.data.timeSignatureTop += 1 }
|
1
2
| GeometryReader { geometry in
let fontSize = size * 0.5
|
- 원형 버튼 안에 텍스트가 동적으로 크기 조절됨
.aspectRatio(1, .fit)로 정사각형 → 원 형태 유지
🔬 updateSequences()
1
| track.sequence.add(noteNumber: data.downbeatNoteNumber, ...)
|
- 첫 번째 트랙에 메트로놈 셰이커 노트를 추가
- 두 번째 트랙(콜백 트랙)은
beat마다 CallbackInstrument 콜백 호출
currentBeat 값을 실시간으로 업데이트하여 UI와 동기화
📈 FFTView
1
| FFTView(conductor.reverb)
|
AudioKitUI의 실시간 주파수 스펙트럼 뷰
reverb로 출력된 오디오를 시각화
🧪 Preview
1
2
3
| #Preview {
STKView()
}
|
- Xcode canvas에서 실시간 인터랙션 테스트 가능
✅ 요약
| 구성 요소 |
역할 |
ShakerConductor |
오디오 엔진, 시퀀서, 셰이커 구성 |
STKView |
SwiftUI 기반 UI |
.onAppear/.onDisappear |
오디오 엔진 시작/종료 |
updateSequences() |
박자에 따라 음 시퀀스 자동 구성 |
GeoCircleButton |
박자 표시용 원형 버튼 (터치 가능) |
CallbackInstrument |
시퀀서와 UI를 연결하는 핵심 콜백 |
FFTView |
실시간 시각화 |