ios - 如何使用 Swift 采样器播放一个音调,然后在播放下一个音调之前暂停?

标签 ios swift avaudioplayer midi

我有代码可以获取字符串中的一系列字母并将它们解释为注释。然后代码将播放音符。问题是他们都在同一时间玩。如何将它们分别作为四分音符演奏,本质上是演奏一个音符,等待它结束,然后演奏下一个音符?

@IBAction func playButton(sender: AnyObject) {
    fractalEngine.output = "adgadefe"
    var notes = Array(fractalEngine.output.characters)

    var counter = 0
    while counter < notes.count {

            var note = notes[counter]
            if note == "a" {
                play(58)
            }
            else if note == "b" {
                play(59)
            }
            else if note == "c" {
                play(60)
            }
            else if note == "d" {
                play(61)
            }
            else if note == "e" {
                play(62)
            }
            else if note == "f" {
                play(63)
            }
            else {
                play(64)
            }

            counter += 1
    }


    //self.sampler.startNote(60, withVelocity: 64, onChannel: 0)
}

func play(note: UInt8) {
    sampler.startNote(note, withVelocity: 64, onChannel: 0)
}

func stop(note: UInt8) {
    sampler.stopNote(note, onChannel: 0)

}

这是启动采样器的代码:

func initAudio(){

     engine = AVAudioEngine()
     self.sampler = AVAudioUnitSampler()
     engine.attachNode(self.sampler)
     engine.connect(self.sampler, to: engine.outputNode, format: nil)

     guard let soundbank = NSBundle.mainBundle().URLForResource("gs_instruments", withExtension: "dls") else {

     print("Could not initalize soundbank.")
     return
     }

     let melodicBank:UInt8 = UInt8(kAUSampler_DefaultMelodicBankMSB)
     let gmHarpsichord:UInt8 = 6
     do {
     try engine.start()
     try self.sampler.loadSoundBankInstrumentAtURL(soundbank, program: gmHarpsichord, bankMSB: melodicBank, bankLSB: 0)

     }catch {
     print("An error occurred \(error)")
     return
     }

    /*
    self.musicSequence = createMusicSequence()
    createAVMIDIPlayer(self.musicSequence)
    createAVMIDIPlayerFromMIDIFIle()
    self.musicPlayer = createMusicPlayer(musicSequence)
    */

}

最佳答案

看来您需要依次延迟播放。这是一种实现(避免阻塞主线程)。

//global delay helper function
func delay(delay:Double, closure:()->()) {
  dispatch_after(
    dispatch_time(
      DISPATCH_TIME_NOW,
      Int64(delay * Double(NSEC_PER_SEC))
    ),
    dispatch_get_main_queue(), closure)
}

//inside your playButton
let delayConstant = 0.05 //customize as needed
for (noteNumber, note) in notes.enumerate() {
  delay(delayConstant * noteNumber) {
    play(note)
    //handle stopping
    delay(delayConstant) {stop(note)}
  }
}

它的作用是在逐渐增加的延迟后播放每个音符,然后在音符长度后停止播放,这被假定为延迟常数。

关于ios - 如何使用 Swift 采样器播放一个音调,然后在播放下一个音调之前暂停?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37756092/

相关文章:

swift - 即使有公差,AVPlayer Seek 也不准确Before : kCMTimeZero

ios - 如何在 swift 4 中动态创建控件并动态对齐?

ios - 从 map View 上长按触发推送 segue

ios - git 提交错误 : large file detected

ios - swift 中的 filterUsingPredicate 给出错误 "Void is not convertible to NSArray"

ios - 未登录 Game Center 时应用程序崩溃

ios - 当我尝试呈现 View 时收到此警告 "attempt to present ViewController whose view is not in the window hierarchy"

iphone - 如何在 "Ringer & Alert Volume"级别播放声音

iphone - tableview 和 UIButton 在同一 View 上

ios - 从 Xcode 6 重新构建应用程序时出现 OSStatus 错误 2003334207