Post

AudioKit의 PolyphonicSTK+MIDIKit

AudioKit의 PolyphonicSTK+MIDIKit

Polyphonic STK + MIDIKit

이 코드는 AudioKit과 MIDIKit을 함께 사용하여, 가상 또는 외부 MIDI 장치로부터 들어오는 MIDI 이벤트를 수신하고, RhodesPianoKey(SoundpipeAudioKit) 기반으로 폴리포닉 연주를 가능하게 하는 구조입니다.


MIDIKit 관련 설명

MIDIManager 생성

1
2
3
4
5
let midiManager = MIDIManager(
  clientName: "CookbookAppMIDIManager",
  model: "CookbookApp",
  manufacturer: "BGSMM"
)
  • MIDIKit의 핵심 객체
  • CoreMIDI 클라이언트를 만들고, 포트와 연결을 관리함
  • iOS/macOS의 MIDI 시스템과 연동됨

MIDI 연결 설정: MIDIConnect()

1. MIDI 서비스 시작

1
try midiManager.start()
  • MIDI 시스템 접근을 시작하며, 장치 탐색 및 연결 가능 상태로 전환

2. 입력 연결 설정

1
2
3
4
5
6
try midiManager.addInputConnection(
  to: .allOutputs,
  tag: "Listener",
  filter: .owned(),
  receiver: .events { ... }
)
  • .allOutputs: 연결 가능한 모든 외부 출력 포트를 수신 대상으로 설정
  • filter: .owned(): 본 앱이 만든 가상 포트는 수신 대상에서 제외
  • receiver: .events: 이벤트 수신 핸들러

이벤트 수신 핸들러

1
2
3
4
5
6
7
receiver: .events { [weak self] events, timeStamp, source in
  Task { @MainActor in
    for event in events {
      self?.received(midiEvent: event)
    }
  }
}
  • 비동기 클로저이며 백그라운드 스레드에서 호출됨
  • Task { @MainActor in ... }으로 UI 안전하게 업데이트
  • selfweak으로 캡처하여 메모리 누수 방지

@Sendable 제한을 피하기 위해 DispatchQueue.main.async 대신 Task { @MainActor } 사용


수신된 MIDI 이벤트 처리

1
private func received(midiEvent: MIDIEvent) { ... }
  • MIDI 이벤트 타입별로 분기 처리
타입 처리 내용
.noteOn 음을 재생 + NotificationCenter로 노트 정보 전달
.noteOff 해당 음을 멈춤 + NotificationCenter로 노트 정보 전달
.cc 콘트롤 체인지 정보 콘솔 출력
.programChange 프로그램 체인지 이벤트 출력
기타 무시

NotificationCenter.default.post(...)는 외부 UI에 키보드 상태 전파에 사용됨


AudioKit 관련 (간단 요약)

  • RhodesPianoKey → 기본 오실레이터
  • AmplitudeEnvelope으로 각각 음의 게이트 제어
  • 최대 11음까지 동시에 연주 가능
  • .noteOn, .noteOffenvs[i].openGate() / closeGate() 처리
  • 출력은 Mixer(envs)engine.output

🧪 동작 요약

  1. 앱 실행 → MIDIManager 시작
  2. 가상포트 혹은 실제 MIDI 키보드에서 노트를 누름
  3. .noteOn 수신 → noteOn(pitch:) 호출
  4. RhodesPianoKey 연주 시작
  5. .noteOff 수신 → noteOff(pitch:) → 게이트 닫힘

사용 예

  • 외부 MIDI 장치, 가상 MIDI 장치, DAW 등에서 이 앱으로 노트 전송 가능
  • SwiftUI UI에서 MIDIKItKeyboard로 직접 연주도 가능
  • 모든 이벤트는 콘솔과 UI에 실시간 반영됨

This post is licensed under CC BY 4.0 by the author.