Midi 音乐音高转换不适用于 Swift 中的 iOS

如何解决Midi 音乐音高转换不适用于 Swift 中的 iOS

我有一个键盘的简单应用程序来播放音符。我的问题是我试图添加一个滑块来弯曲音符音高,但音高没有移动。没有错误或任何错误,音符继续播放,音高没有任何变化。

我知道还有其他类似的问题,我已经阅读了所有我能找到的内容,我实施的内容是基于该研究,但它不起作用。

请帮我找出我做错了什么,或者给我指明更好的方向。

在我的工作代码中,我使用的是 AudioToolBox。我创建并打开一个新的 AUGraph。我向图中添加一个 kAudioUnitSubType_RemoteIO 和一个 kAudioUnitSubType_MIdisynth 节点。我把它全部连接起来,我可以弹奏音符。

为了添加弯音,我创建了一个 kAudioUnitSubType_NewTimePitch AUNode 并将其连接在合成器和输出节点之间。然后我从效果节点获取音高 AudioUnit,当我的滑块值更改时,我尝试使用带有 kNewTimePitchParam_Pitch 的 AudioUnitSetParameter 更改音高。一切仍然有效,但是当我播放一个音符并拖动滑块时,音符的音高没有任何变化。我的滑块值在 -1000 和 +1000 之间变化,我看到打印出来的值,所以我知道正在调用 pitchBend 函数

这是我的相关代码。这段代码,除了我试图添加的音高效果部分,是从我在这里找到的内容中大量复制的: https://rollout.io/blog/building-a-midi-music-app-for-ios-in-swift/

import Foundation
import AudioToolBox

class AudioSynth
{
  var audioGraph:     AUGraph?
  var synthNode       = AUNode()
  var effectNode      = AUNode()
  var outputNode      = AUNode()
  var synthUnit:      AudioUnit?
  var effectUnit:      AudioUnit?
  var patch           = UInt32(0)
  
  func initAudio() {
    checkerror(osstatus: NewAUGraph(&audioGraph))
    createOutputNode(audioGraph: audioGraph!,outputNode: &outputNode)
    createSynthNode()
    createEffectNode()
    checkerror(osstatus: AUGraphOpen(audioGraph!))

    // get the synth unit
    checkerror(osstatus: AUGraphNodeInfo(audioGraph!,synthNode,nil,&synthUnit))
    checkerror(osstatus: AUGraphNodeInfo(audioGraph!,effectNode,&effectUnit))
    
    let synthOutputElement: AudioUnitElement = 0
    let effectOutputElement: AudioUnitElement = 0
    let IoUnitInputElement: AudioUnitElement = 0

    checkerror(osstatus:
      AUGraphConnectNodeInput(audioGraph!,synthOutputElement,effectOutputElement))
    checkerror(osstatus:
      AUGraphConnectNodeInput(audioGraph!,effectOutputElement,outputNode,IoUnitInputElement))

    checkerror(osstatus: AUGraphInitialize(audioGraph!))
    checkerror(osstatus: AUGraphStart(audioGraph!))
    loadSoundFont()
    loadPatch(patchNo: 0)
    
  }
  
  // Mark: - Audio Init Utility Methods
  func createOutputNode(audioGraph: AUGraph,outputNode: UnsafeMutablePointer<AUNode>) {
    var cd = AudioComponentDescription(
      componentType: OSType(kAudioUnitType_Output),componentSubType: OSType(kAudioUnitSubType_RemoteIO),componentManufacturer: OSType(kAudioUnitManufacturer_Apple),componentFlags: 0,componentFlagsMask: 0)
    checkerror(osstatus: AUGraphAddNode(audioGraph,&cd,outputNode))
  }
  
  func createSynthNode() {
    var cd = AudioComponentDescription(
      componentType: OSType(kAudioUnitType_MusicDevice),componentSubType: OSType(kAudioUnitSubType_MIdisynth),componentFlagsMask: 0)
    checkerror(osstatus: AUGraphAddNode(audioGraph!,&synthNode))
  }
  
    func createEffectNode() {
     var cd = AudioComponentDescription(
        componentType: OSType(kAudioUnitType_Effect),componentSubType: OSType(kAudioUnitSubType_NewTimePitch),componentFlagsMask: 0)
      checkerror(osstatus: AUGraphAddNode(audioGraph!,&effectNode))
    }
    
    func pitchBend(pitchBend: Double) {
        print("Bend pitch by " + String(pitchBend))
        checkerror(osstatus: AudioUnitSetParameter(effectUnit!,AudioUnitPropertyID(kNewTimePitchParam_Pitch),AudioUnitScope(kAudioUnitScope_Global),AudioUnitParameterValue(pitchBend),0))

    }
    
    func playNoteOn(channel: Int,note: UInt32,midiveLocity: Int) {
      let noteCommand = UInt32(0x90 | channel)
      checkerror(osstatus: MusicDeviceMIDIEvent(synthUnit!,noteCommand,note,UInt32(midiveLocity),0))
    }
    
    func playNoteOff(channel: Int,midiveLocity: Int) {
      let noteCommand = UInt32(0x80 | channel)
      checkerror(osstatus: MusicDeviceMIDIEvent(synthUnit!,0))
    }


    
  // In the simulator this takes a long time,so we
  //  call it in a background thread in the controller
  func loadSoundFont() {
    var bankURL = Bundle.main.url(forResource: "FluidR3_GM",withExtension: "sf2")
    checkerror(osstatus: AudioUnitSetProperty(synthUnit!,AudioUnitPropertyID(kMusicDeviceProperty_SoundBankURL),&bankURL,UInt32(MemoryLayout<URL>.size)))
  }
  
  func loadPatch(patchNo: Int) {
    let channel = UInt32(0)
    var enabled = UInt32(1)
    var disabled = UInt32(0)
    patch = UInt32(patchNo)
    
    checkerror(osstatus: AudioUnitSetProperty(
      synthUnit!,AudioUnitPropertyID(kAUMIdisynthProperty_EnablePreload),&enabled,UInt32(MemoryLayout<UInt32>.size)))
    
    let programChangeCommand = UInt32(0xC0 | channel)
    checkerror(osstatus: MusicDeviceMIDIEvent(self.synthUnit!,programChangeCommand,patch,0))
    
    checkerror(osstatus: AudioUnitSetProperty(
      synthUnit!,&disabled,UInt32(MemoryLayout<UInt32>.size)))
    
    // the prevIoUs programChangeCommand just triggered a preload
    // this one actually changes to the new voice
    checkerror(osstatus: MusicDeviceMIDIEvent(synthUnit!,0))
  }
  
  func checkerror(osstatus: Osstatus) {
    if osstatus != noErr {
      print(SoundError.GetErrorMessage(osstatus))
    }
  }
}

谢谢。任何帮助是appriciated。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?