swiftswift3unsafemutablepointeravaudiopcmbuffer

UnsafeMutablePointer<Float> to UnsafeMutablePointer<_>


I'm really going crazy with a stupid and apparently simple problem... I have to convert a Data to an AVAudioPCMBuffer.

Looking to this question it seems to be easy, but all has changed with Swift 3. This cursed language which is continuously changing (sorry for the outburst)!

I have this snippet of code

let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat!, frameCapacity: UInt32(data.count)/(audioFormat?.streamDescription.pointee.mBytesPerFrame)!)
audioBuffer.frameLength = audioBuffer.frameCapacity
let channels = UnsafeBufferPointer(start: audioBuffer.floatChannelData, count: Int(audioFormat!.channelCount))
data.copyBytes(to: UnsafeMutablePointer<Float>(channels[0]))

But this last line gives me this error:

Cannot convert value of type 'UnsafeMutablePointer<Float>' to expected 
argument type 'UnsafeMutablePointer<_>'

May someone has a solution to this?


Solution

  • Checking the API Reference of Data, you can find 3 overloads of copyBytes:

    func copyBytes(to: UnsafeMutablePointer<UInt8>, count: Int)

    func copyBytes(to: UnsafeMutablePointer<UInt8>, from: Range<Data.Index>)

    func copyBytes<DestinationType>(to: UnsafeMutableBufferPointer<DestinationType>, from: Range<Data.Index>?)

    None of them takes UnsafeMutablePointer<Float> as its to: argument.

    (And in your code, the type of channels[0] becomes UnsafeMutablePointer<Float>, passing it to an initializer of UnsafeMutablePointer<Float> is "do nothing".)

    If you want to call the third copyBytes, you need to create an UnsafeMutableBufferPointer<DestinationType>, and in your case DestinationType should be Float.

    _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: channels[0], count: Int(audioBuffer.frameLength)))
    

    (from: argument is optional in this copyBytes, and without putting _ =, Swift complains about not using the result.)

    If you want to use other overloads of copyBytes, you may need to convert UnsafeMutablePointer<Float> to UnsafeMutablePointer<UInt8>. You can find how to do that in some other articles in the SO. Please remember count: and from: (in the second) are not optional.