swift - 如何使用 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
解决方案
音频插件获取时间信息的方式是设置一个回调函数,该函数调用您的主机并检索诸如时间签名、速度和位置等信息。
导入 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
}
推荐阅读
- javascript - 如何将字符串从视图传递到mvc中的控制器
- python - make virtualenv with specific python version(MACOS)
- python - 如何使用 Flask Python 制作 API
- sql - 查询中的 Microsoft Access 日期比较不起作用
- perl - 在不调用 perl.exe 的情况下无法在 cmd 中执行 perl 脚本
- c# - sqlite 增量数据每 5 分钟备份一次
- angular - Angular 7 Cdk:使用 CdkPortal 没有实例
- amazon-web-services - 跨可用区的 EBS 容错
- sql - 如果我想从存储过程执行可执行文件,除了使用 xp_cmdshell 之外,还有其他方法吗?
- java - 有没有办法在不使用 list index 的情况下捕获 List 元素 xpath 。在 java 中使用 selenium