play audio stream PCMBuffer, AVAudioPCMBuffer

1k Views Asked by At

My task is to receive an audio stream and play it. On the server side, the audio is encoded by pcmInt16 (16bit, 44100 sample rate, 2 channels)

I accept a stream of bytes and encode in AVAudioPCMBuffer and then pass it to the player in the playMusicFromBuffer function.


        while (inputStream!.hasBytesAvailable) {
            
            let length = inputStream!.read(&buffer, maxLength: buffer.count)

            if (length > 0) {
                

                print("\(#file) > \(#function) > \(length) bytes read")
                print(buffer)


                let audioBuffer = bytesToAudioBuffer16(buffer)
                playMusicFromBuffer(PCMBuffer: audioBuffer)
 
            }
        }

At first, for encoding in AVAudioPCMBuffer, I used the bytesToAudioBuffer method (the parameters do not match the server settings), however, the application starts and does not crash when converting, but still there is no sound.

    func bytesToAudioBuffer(_ buf: [UInt8]) -> AVAudioPCMBuffer {

        let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100.0, channels: 1, interleaved: true)
         let frameLength = UInt32(buf.count) / (fmt?.streamDescription.pointee.mBytesPerFrame)!

         let audioBuffer = AVAudioPCMBuffer(pcmFormat: fmt!, frameCapacity: frameLength)
         audioBuffer!.frameLength = frameLength

         let dstLeft = audioBuffer?.floatChannelData![0]

         buf.withUnsafeBufferPointer {
             let src = UnsafeRawPointer($0.baseAddress!).bindMemory(to: Float.self, capacity: Int(frameLength))
             dstLeft!.initialize(from: src, count: Int(frameLength))
         }
         print("Convert to AVAudioPCMBuffer")

         return audioBuffer!
     }
    
    func bytesToAudioBuffer16(_ buf: [UInt8]) -> AVAudioPCMBuffer {

        let fmt = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 44100.0, channels: 2, interleaved: true)
        let frameLength = UInt32(buf.count) / (fmt?.streamDescription.pointee.mBytesPerFrame)!

        let audioBuffer = AVAudioPCMBuffer(pcmFormat: fmt!, frameCapacity: frameLength)
        audioBuffer!.frameLength = frameLength

        let dstLeft = audioBuffer?.int16ChannelData![0]

        buf.withUnsafeBufferPointer {
            
            let src = UnsafeRawPointer($0.baseAddress!).bindMemory(to: Int16.self, capacity: Int(frameLength))
            dstLeft!.initialize(from: src, count: Int(frameLength))
            
        }
        print("Convert to AVAudioPCMBuffer")

        return audioBuffer!
    }
    
    var audioEngine: AVAudioEngine = AVAudioEngine()
    var audioFilePlayer: AVAudioPlayerNode = AVAudioPlayerNode()

    func playMusicFromBuffer(PCMBuffer: AVAudioPCMBuffer) {

        let mainMixer = audioEngine.mainMixerNode
        audioEngine.attach(audioFilePlayer)
        audioEngine.connect(audioFilePlayer, to:mainMixer, format: PCMBuffer.format)
        try? audioEngine.start()
        audioFilePlayer.play()
        audioFilePlayer.scheduleBuffer(PCMBuffer, at: nil, options:AVAudioPlayerNodeBufferOptions.loops)
    }

Next, I tried to fix this by changing the settings and writing the bytesToAudioBuffer16 function. But here when starting the application, when I convert the stream to AVAudioPCMBuffer and transfer it to the player, an error occurs: [reason __NSCFString * "[[busArray objectAtIndexedSubscript: (NSUInteger) element] setFormat: format error: & nsErr]: returned false, error Error Domain = NSOSStatusErrorDomain Code = -10868 \" (null) \ "" 0x0000600000d2e00.

The question is how to fix this situation. Do I need to fix bytesToAudioBuffer16 or playMusicFromBuffer. If so, how?

0

There are 0 best solutions below