ScheduledAudioFileRegion cannot be constructed because it has no accessible initializers

I have the feeling that this is very basic and I'm missing out on something but I cannot figure out what so here goes.


I have this method for creating a ScheduledAudioFileRegion for me:


    private func scheduledAudioFileRegion(startFrame: Int64, loopCount: UInt32, framesToPlay: UInt32) -> ScheduledAudioFileRegion {
        var audioFileRegion: ScheduledAudioFileRegion = ScheduledAudioFileRegion()
        audioFileRegion.mTimeStamp.mFlags = UInt32(kAudioTimeStampSampleTimeValid)
        audioFileRegion.mTimeStamp.mSampleTime = 0
        audioFileRegion.mCompletionProc = nil
        audioFileRegion.mCompletionProcUserData = nil
        audioFileRegion.mAudioFile = audioFile
        audioFileRegion.mLoopCount = loopCount
        audioFileRegion.mStartFrame = startFrame
        audioFileRegion.mFramesToPlay = framesToPlay
        return audioFileRegion
    }


Which works in Swift 1.2 and Xcode 6.4


However, after converting to Swift 2.0 the method looks like this


    private func scheduledAudioFileRegion(startFrame: Int64, loopCount: UInt32, framesToPlay: UInt32) -> ScheduledAudioFileRegion {
        var audioFileRegion: ScheduledAudioFileRegion = ScheduledAudioFileRegion()
        audioFileRegion.mTimeStamp.mFlags = AudioTimeStampFlags.SampleTimeValid
        audioFileRegion.mTimeStamp.mSampleTime = 0
        audioFileRegion.mCompletionProc = nil
        audioFileRegion.mCompletionProcUserData = nil
        audioFileRegion.mAudioFile = audioFile
        audioFileRegion.mLoopCount = loopCount
        audioFileRegion.mStartFrame = startFrame
        audioFileRegion.mFramesToPlay = framesToPlay
        return audioFileRegion
    }


And there is an error in this line:


var audioFileRegion: ScheduledAudioFileRegion = ScheduledAudioFileRegion()


'ScheduledAudioFileRegion' cannot be constructed because it has no accessible initializers.


If I look in AudioUnitProperties I can see ScheduledAudioFileRegion declared like this:


public struct ScheduledAudioFileRegion {
    public var mTimeStamp: AudioTimeStamp
    public var mCompletionProc: ScheduledAudioFileRegionCompletionProc?
    public var mCompletionProcUserData: UnsafeMutablePointer<Void>
    public var mAudioFile: COpaquePointer
    public var mLoopCount: UInt32
    public var mStartFrame: Int64
    public var mFramesToPlay: UInt32
}


Which doesn't look suspicious to me.


I would assume that I could then initialize a ScheduledAudioFileRegion with the default init method like so:


        var audioTimeStamp = AudioTimeStamp()
        audioTimeStamp.mFlags = AudioTimeStampFlags.SampleTimeValid
        audioTimeStamp.mSampleTime = 0
     
        return ScheduledAudioFileRegion(mTimeStamp: audioTimeStamp,
            mCompletionProc: nil,
            mCompletionProcUserData: nil,
            mAudioFile: audioFile,
            mLoopCount: loopCount,
            mStartFrame: startFrame,
            mFramesToPlay: framesToPlay)


But...same error.


The funny thing is that the ScheduledAudioSlice struct, which - as far as I can see - is declared similarly works fine. Xcode autocompletes the initilizer for it perfectly, which it doesn't for the ScheduledAudioFileRegion.


This is probably really simple and a result of the Swift 2.0 migration, but I can not figure out where the problem is, so...please...kind people of the internet, help me out :-)

You should definitely file a bug about this. Even if there is some rationale behind it (which is eluding me as well you), it’s obviously getting in the way of your adoption of Swift 2 and thus should be improved.

Please post your bug number, just for the record.

You can work around this using unsafe goo. Here’s something I cooked up (although I’m hardly an expert in Swift unsafe goo so, folks, please chime in if I’m doing something dumb).

func makeScheduledAudioFileRegion() -> ScheduledAudioFileRegion {
    let tmp = UnsafeMutablePointer<ScheduledAudioFileRegion>.alloc(1)
    memset(tmp, 0, sizeof(ScheduledAudioFileRegion))
    return tmp.move()
}

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for your reply. I didn't see it until now because I was busy creating a playground and filing a bug report 🙂


I managed to find a different workaround this morning (nothing like a good nights sleep when you're stuck).


If I create a complete copy of the ScheduledAudioFileRegion struct with a different name like so

public struct PatchedScheduledAudioFileRegion {
    public var mTimeStamp: AudioTimeStamp
    public var mCompletionProc: ScheduledAudioFileRegionCompletionProc?
    public var mCompletionProcUserData: UnsafeMutablePointer<Void>
    public var mAudioFile: COpaquePointer
    public var mLoopCount: UInt32
    public var mStartFrame: Int64
    public var mFramesToPlay: UInt32
}


I can then use that struct, complete with code completion and all:


    private func scheduledAudioFileRegion(startFrame: Int64, loopCount: UInt32, framesToPlay: UInt32) -> PatchedScheduledAudioFileRegion {
        var audioTimeStamp = AudioTimeStamp()
        audioTimeStamp.mFlags = AudioTimeStampFlags.SampleTimeValid
        audioTimeStamp.mSampleTime = 0

        let myScheduledAudioFileRegion = PatchedScheduledAudioFileRegion(mTimeStamp: audioTimeStamp, mCompletionProc: nil, mCompletionProcUserData: nil, mAudioFile: audioFile, mLoopCount: loopCount, mStartFrame: startFrame, mFramesToPlay: framesToPlay)
     
        return myScheduledAudioFileRegion
    }


This works and can be used with AudioUnitSetProperty


A bug report (number: 22536082) has been created.

I'm just a beginner programmer trying to learn audio programming but here's my take on it. Apparently the initializers are missing so I made an extension and added my own initializer:


public extension ScheduledAudioFileRegion {
    public init () {
        self.mTimeStamp = AudioTimeStamp()
        self.mCompletionProc = nil
        self.mCompletionProcUserData = nil
        self.mAudioFile = AudioFileID()
        self.mLoopCount = 0
        self.mStartFrame = 0
        self.mFramesToPlay = 0
    }
}


And after that I was able to carry on this way:


    var region = ScheduledAudioFileRegion()
    region.mTimeStamp.mFlags = AudioTimeStampFlags.SampleTimeValid
    region.mTimeStamp.mSampleTime = 0
    region.mCompletionProc = nil
    region.mCompletionProcUserData = nil
    region.mAudioFile = player.memory.inputFile
    region.mLoopCount = 1
    region.mStartFrame = 0
    region.mFramesToPlay = UInt32(nPackets) * player.memory.inputFormat.mFramesPerPacket
   
    error = AudioUnitSetProperty(
        player.memory.fileAU,
        kAudioUnitProperty_ScheduledFileRegion,
        kAudioUnitScope_Global,
        0,
        &region,
        UInt32(sizeofValue(region)))

"I'm just a beginner programmer trying to learn audio programming"


Glad to see that I'm not the only one 🙂


Thank you for your reply, it worked perfect and it is prettier than my struct definition fix.


I've extended on your init method, and "my" init method looks like this


public extension ScheduledAudioFileRegion {
    init(mTimeStamp: AudioTimeStamp, mCompletionProc: ScheduledAudioFileRegionCompletionProc?, mCompletionProcUserData: UnsafeMutablePointer<Void>, mAudioFile: COpaquePointer, mLoopCount: UInt32, mStartFrame: Int64, mFramesToPlay: UInt32) {
        self.mTimeStamp = mTimeStamp
        self.mCompletionProc = mCompletionProc
        self.mCompletionProcUserData = mCompletionProcUserData
        self.mAudioFile = mAudioFile
        self.mLoopCount = mLoopCount
        self.mStartFrame = mStartFrame
        self.mFramesToPlay = mFramesToPlay
    }
}


And I can then use it in this convenience method


    private func scheduledAudioFileRegion(startFrame: Int64, loopCount: UInt32, framesToPlay: UInt32) -> ScheduledAudioFileRegion {
        var audioTimeStamp = AudioTimeStamp()
        audioTimeStamp.mFlags = AudioTimeStampFlags.SampleTimeValid
        audioTimeStamp.mSampleTime = 0
      
        let scheduledAudioFileRegion = ScheduledAudioFileRegion(mTimeStamp: audioTimeStamp, mCompletionProc: nil, mCompletionProcUserData: nil, mAudioFile: audioFile, mLoopCount: loopCount, mStartFrame: startFrame, mFramesToPlay: framesToPlay)
      
        return scheduledAudioFileRegion
    }


Perfect!


Once again thanks.

ScheduledAudioFileRegion cannot be constructed because it has no accessible initializers
 
 
Q