1

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?

Community
  • 1
  • 1
Massimo
  • 3,436
  • 4
  • 40
  • 68

1 Answers1

2

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.

OOPer
  • 47,149
  • 6
  • 107
  • 142
  • It works correctly, but at the end I had to manually perform the copy, because I received a [UInt8] and needed to transform it into a [Float32]... thanks! – Massimo Dec 01 '16 at 13:20
  • @Massimo Can you show how you manually did the copy and converted [UInt8] to [Float32]? – hungrxyz Jan 30 '17 at 00:44
  • @zzzel For my problem I had a Data containing n/2 samples (2 bytes for sample) and I had to transform each sample (2 bytes) in one float (between -1.0 and 1.0). If your problem is the same, this is my code (samples is a `Data`object): `for i in 0.. – Massimo Jan 30 '17 at 08:27
  • @Massimo how did you figure this out? how did you knew it was [UInt8]?curious – masaldana2 Feb 25 '18 at 19:41