首页 > 解决方案 > 如何使用 AVFoundation 在 Mac OS swift 中将速度或时间信息发送到 AVAudioUnitMIDIInstrument

问题描述

我有一个 Mac OS 桌面应用程序,它将虚拟乐器插件作为 AVAudioUnitMIDIInstrument 托管。我的应用程序基本上是一个音乐音序器。我想触发使用鼓循环和/或琶音器的乐器。这需要向 AVAudioUnitMIDIInstrument 发送某种时间信息。我该怎么做呢?我的猜测是我需要发送一个 MidiMetaEvent,或者可能是常规的 MidiTimestamp 信息。我该怎么做呢?我在 AVAudioUnitMidiInstrument 上没有看到任何这样做的方法。以下是我看到的方法:

func sendController(UInt8, withValue: UInt8, onChannel: UInt8)
Send a MIDI controller event to the instrument.

func sendMIDIEvent(UInt8, data1: UInt8)
Sends a MIDI event which contains one data byte to the instrument.

func sendMIDIEvent(UInt8, data1: UInt8, data2: UInt8)
Sends a MIDI event which contains two data bytes to the instrument.

func sendMIDISysExEvent(Data)
Sends a MIDI System Exclusive event to the instrument.

func sendPitchBend(UInt16, onChannel: UInt8)
Sends a MIDI Pitch Bend event to the instrument.

func sendPressure(UInt8, onChannel: UInt8)
Sends a MIDI channel pressure event to the instrument.

func sendPressure(forKey: UInt8, withValue: UInt8, onChannel: UInt8)
Sends a MIDI Polyphonic key pressure event to the instrument.

func sendProgramChange(UInt8, bankMSB: UInt8, bankLSB: UInt8, onChannel: UInt8)
Sends MIDI Program Change and Bank Select events to the instrument.

func sendProgramChange(UInt8, onChannel: UInt8)
Sends MIDI Program Change and Bank Select events to the instrument.

func startNote(UInt8, withVelocity: UInt8, onChannel: UInt8)
Sends a MIDI Note On event to the instrument.

func stopNote(UInt8, onChannel: UInt8)
Sends a MIDI Note Off event to the instrument

标签: swiftmacosavfoundationmidi

解决方案


音频插件获取时间信息的方式是设置一个回调函数,该函数调用您的主机并检索诸如时间签名、速度和位置等信息。

导入 Foundation 导入 AVFoundation 导入 AudioToolbox 导入 CoreAudioKit

class AudioNodeFactory{
    class func instrument(description: AudioComponentDescription, context: AUHostMusicalContextBlock?) -> AVAudioUnitMIDIInstrument{
        let plugin = AVAudioUnitMIDIInstrument(audioComponentDescription: description)
        plugin.auAudioUnit.musicalContextBlock = context
        return plugin
    }
}

音乐上下文块看起来像这样:


func getMusicalContext(currentTempo : UnsafeMutablePointer<Double>?,
                        timeSignatureNumerator : UnsafeMutablePointer<Double>?,
                        timeSignatureDenominator : UnsafeMutablePointer<Int>?,
                        currentBeatPosition: UnsafeMutablePointer<Double>?,
                        sampleOffsetToNextBeat : UnsafeMutablePointer<Int>?,
                        currentMeasureDownbeatPosition: UnsafeMutablePointer<Double>?) -> Bool {
     if self.delegate == nil { return false }
     let context = self.delegate!.musicalContext
     currentTempo?.pointee = context.currentTempo
     timeSignatureNumerator?.pointee = context.timeSignatureNumerator
     timeSignatureDenominator?.pointee = context.timeSignatureDenominator
     currentBeatPosition?.pointee = context.currentBeatPosition
     sampleOffsetToNextBeat?.pointee = context.sampleOffsetToNextBeat
     currentMeasureDownbeatPosition?.pointee = context.currentMeasureDownbeatPosition
     return true
 }

推荐阅读