I had the type-alias for the AVAudioNodeCompletionHandler all wrong. Not sure where I got that definition from, but my newness to the terminology of the error report put me off the scent. Xcode was quite clearly saying what the problem was:
Taking out atTime and options brings the function down to the simpler case of:
func scheduleBuffer(_
buffer: AVAudioPCMBuffer!,completionHandler
completionHandler: AVAudioNodeCompletionHandler!)What the error message is saying (when I finally understood it) was that the completion handler Tuple - e.g. parameter types were not correct - the correct one is () and I had used (AVAudioPCMBuffer!, AVAudioTime!). It helped reading about closures to understand this, although that wasn't the cause of the problem. It does help understanding the syntax and concepts of Swift in a good deal more detail though.
The type alias of AVAudioNodeCompletionHandler is far much simpler, and for completeness is described below:
typealias AVAudioNodeCompletionHandler = @objc_block () -> Void
Putting this into the code (again in a Playground this is too slow), you get something like this:
fun handler() -> Void
{
// do some audio work
}
player.scheduleBuffer(buffer,atTime:nil, options:nil, completionHandler: handler)
player.scheduleBuffer(buffer,atTime:nil, options:nil,
completionHandler: { () -> Void in
// do some audio work
})
//
// main.swift
// Audio
//
// Created by hondrou on 11/09/2014.
// Copyright (c) 2014 hondrou. All rights reserved.
//
import Foundation
import AVFoundation
let twopi:Float = 2.0 * 3.14159
var freq:Float = 440.00
var sampleRate:Float = 44100.00
var engine = AVAudioEngine()
var player:AVAudioPlayerNode = AVAudioPlayerNode()
var mixer = engine.mainMixerNode
var length = 4000
var buffer = AVAudioPCMBuffer(PCMFormat: player.outputFormatForBus(0),frameCapacity:AVAudioFrameCount(length))
buffer.frameLength = AVAudioFrameCount(length)
engine.attachNode(player)
engine.connect(player,to:mixer,format:mixer.outputFormatForBus(0))
var error:NSErrorPointer = nil
engine.startAndReturnError(error)
var j:Int=0;
func handler() -> Void
{
for (var i=0; i<length; i++)
{
var val:Float = 5.0 * sin(Float(j)*twopi*freq/sampleRate)
buffer.floatChannelData.memory[i] = val
j++
}
player.scheduleBuffer(buffer,atTime:nil,options:.InterruptsAtLoop,completionHandler:handler)
}
handler()
player.play()
while (true)
{
NSThread.sleepForTimeInterval(2)
freq += 10
}
Hmph.... more still to get sorted
Now, just in case you wondered (I did) where I cooked up the handler function parameters, it was all down to mixing up two function type aliases that I'd been looking at. The previous incorrect handler function for the completionHandler below:
Is completely the proper type of function if you are installing an audio node tap block:
typealias AVAudioNodeTapBlock = (AVAudioPCMBuffer!, AVAudioTime!) -> Void
Which I'd also been thinking about at the time (and we will most likely be coming to next in our investigations).
For completeness, this is used in the AudioNode function installTapOnBus below:
func installTapOnBus(_
bufferSize
format
block
Now, just in case you wondered (I did) where I cooked up the handler function parameters, it was all down to mixing up two function type aliases that I'd been looking at. The previous incorrect handler function for the completionHandler below:
func handler(buffer:AVAudioPCMBuffer!,time:AVAudioTime!) -> Void
{
}
typealias AVAudioNodeTapBlock = (AVAudioPCMBuffer!, AVAudioTime!) -> Void
For completeness, this is used in the AudioNode function installTapOnBus below:
func installTapOnBus(_
bus: AVAudioNodeBus,bufferSize
bufferSize: AVAudioFrameCount,format
format: AVAudioFormat!,block
tapBlock: AVAudioNodeTapBlock!)