Write Int16 Into AVAudioPCMBuffer swift

1.8k Views Asked by At

I have a Data object in swift that is an array of Int16 objects. For some reason using ".pcmFormatInt16" did not work for the format of my AVAudioPCMBuffer and yielded no sound, or a memory error. Eventually, I was able to get white noise/static to play from the speakers by converting the Int16 to a float and putting that onto both channels of my AVAudioPCMBuffer. I have a feeling that I am getting close to the answer, because whenever I speak into the microphone I hear a different frequency of static. I think the issue is that I am not converting the converted Int16 into the buffer floatChannelData.

Here is my code:

 for ch in 0..<2 {
  for i in 0..<audio.count {

       var val = Float( Int16(audio[i]) ) / Float(Int16.max)

       if( val > 1 ){
          val = 1;
       }
       if( val < -1 ){
          val = -1;
       }


       self.buffer.floatChannelData![ch][i+self.bufferCount] = val
       self.bufferCount+=1
     }
  }
  self.audioFilePlayer.scheduleBuffer(self.buffer, at:nil, options: .interruptsAtLoop, completionHandler: {
                print("played sum")
                 self.bufferCount=0
  })
1

There are 1 best solutions below

3
On

a typical multi-channel PCM buffer has the channels interleaving on a per sample basis although, not being familiar with swift audio, I find it refreshing to see here channels given a dimension on the buffer datastructure

... a flag goes up when I see your guard checks clamping val > 1 set to val = 1 etc. ... elsewhere that is not needed as those boundary checks are moot as the data nicely falls into place as is

... my guess is your input audio[] is signed int 16 because of your val > 1 and val < -1 ? if true then dividing by max int float is wrong as you would be loosing half your dynamic range ...

I suggest you look closely at your

var val = Float( Int16(audio[i]) ) / Float(Int16.max)

lets examine range of your ints in audio[]

2^16 == 65536 // if unsigned then values range from 0 to (2^16 - 1) which is 0 to 65535

2^15 == 32768 // if signed then values would range from -32768 to (2^15 - 1) which is -32768 to 32767

Please tell is whether input buffer audio[] is signed or not ... sometimes its helpful to identify the max_seen and min_seen values of your input data ... do this and tell us the value of max and min of your input audio[]

Now lets focus on your desired output buffer self.buffer.floatChannelData ... since you are saying its 16 bit float ... what is the valid range here ? -1 < valid_value < 1 ?

We can continue once you tell us answers to these basic questions