воспроизводить аудиопоток PCMBuffer, AVAudioPCMBuffer - PullRequest
1 голос
/ 21 июня 2020

Моя задача - получить аудиопоток и воспроизвести его. На стороне сервера звук кодируется pcmInt16 (16 бит, частота дискретизации 44100, 2 канала)

Я принимаю поток байтов и кодирую его в AVAudioPCMBuffer, а затем передаю его проигрывателю в функции playMusicFromBuffer.


        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)
 
            }
        }

Сначала для кодирования в AVAudioPCMBuffer я использовал метод bytesToAudioBuffer (параметры не совпадают с настройками сервера), однако приложение запускается и при конвертации не трескает sh, но все равно есть нет звука.

    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)
    }

Затем я попытался исправить это, изменив настройки и записав функцию bytesToAudioBuffer16. Но вот при запуске приложения, когда я конвертирую поток в AVAudioPCMBuffer и передаю его плееру, возникает ошибка: [reason __NSCFString * "[[busArray objectAtIndexedSubscript: (NSUInteger) element] setFormat: format error: & nsErr]: returned false, error Error Domain = NSOSStatusErrorDomain Code = -10868 \" (null) \ "" 0x0000600000d2e00.

Вопрос в том, как исправить эту ситуацию. Мне нужно исправить bytesToAudioBuffer16 или playMusicFromBuffer. Если да, то как?

...