Post

AudioKit: MIDISampler+AppleSequencer를 이용한 미디 멀티트랙 재생 중 트랙 중간에 프로그램 체인지가 있는 경우 대응 방법

AudioKit: MIDISampler+AppleSequencer를 이용한 미디 멀티트랙 재생 중 트랙 중간에 프로그램 체인지가 있는 경우 대응 방법

문제 상황 요약

코드

1
2
3
4
5
track 2: [
  ProgramChange(channel: 2, number: 57) // 시작 시
  ProgramChange(channel: 2, number: 60) // 64초쯤
  ProgramChange(channel: 2, number: 57) // 120초쯤 복귀
]
  • 표준 MIDI에서는 이런 식으로 Program Change 메시지를 트랙 내에 삽입하여 동일 채널에 악기 전환을 수행
  • AudioKit의 기본 Sequencer 처리 방식에서는 이를 자동 인식하거나 대응하지 않음

로그

1
2
3
4
5
track 2: [
  AudioKit.MIDIProgramChangeEvent(time: 0.0, channel: 2, number: 57),
  AudioKit.MIDIProgramChangeEvent(time: 64.0, channel: 2, number: 60),
  AudioKit.MIDIProgramChangeEvent(time: 119.98697916666667, channel: 2, number: 57)
]

track 2처럼 트랙 중간에 Program Change 메시지로 악기가 바뀌는 경우, AudioKit의 AppleSequencerMIDISampler 조합만으로는 정확한 사운드 전환을 구현하기 어렵습니다.

기본적으로 track.setMIDIOutput(sampler.midiIn)으로 연결된 MIDISampler트랙 전체를 하나의 악기로만 재생합니다. 중간에 악기를 바꾸는 기능은 직접 처리해주지 않으면 반영되지 않습니다.

해결 방향

(1) Program Change 이벤트를 파싱해서

  • 시점별로 악기(프리셋) 변경 정보를 추출

(2) 해당 채널의 MIDI 이벤트를 악기 구간별로 나눠서

  • 구간별 MIDISampler를 생성하거나
  • 하나의 Sampler에 프리셋을 실시간으로 변경 요청 (단, 대부분의 MIDISampler는 실행 중 preset 변경을 안정적으로 지원하지 않음)

실현 가능한 접근 방법

방법 A: 트랙을 구간별로 분할하여 각각 sampler에 할당

1개 트랙을 Program Change 기준으로 여러 개로 나누고, 구간마다 MIDISampler와 연결 → Mixer에 병합

단점:

  • 구현 복잡도 있음
  • MIDI 이벤트 재구성이 필요

방법 B: ProgramChange 메시지 수신 시 sampler의 preset을 변경

1
2
3
4
5
if case let .programChange(channel, number) = event {
  if channel == 2 {
    try? sampler.loadSoundFont("CT8MGM", preset: number, bank: 0)
  }
}
  • MIDI 이벤트를 수신하는 커스텀 MIDIListener 구현 필요
  • 실행 중 preset을 바꾸면 버퍼 끊김이나 글리치 발생 가능

실행 중 preset 변경은 대부분 권장되지 않음

권장 방식 (현실적 대안)

트랙 중간에 Program Change가 있는 경우:

  1. MIDI 파일을 외부에서 미리 분할하거나
  2. DAW에서 동일 채널에 Program Change를 쓰지 않도록 재구성
  3. 또는 AudioKit으로 다룰 경우, 중간 ProgramChange를 무시하고 시작 preset만 사용

요약

상황 설명
트랙에 ProgramChange가 여러 개 있음 MIDI 채널의 악기가 재생 중에 바뀜
AudioKit AppleSequencer 한 트랙당 하나의 sampler만 연결됨
실시간 preset 변경 가능은 하지만 glitch 발생 가능
현실적인 방법 ProgramChange 기준으로 트랙을 사전 분할 또는 첫 preset만 사용
This post is licensed under CC BY 4.0 by the author.