ios - 通过流播放的音频出现抖动/断断续续

标签 ios swift stream avaudioplayer

我将简要介绍一下我的应用程序的所有元素:

我有一个将音频记录到 AVAudioPCMBuffer 的应用程序。然后将该缓冲区转换为 NSData,然后转换为 [UInt8]。然后通过 OutputStream 进行流式传输。在另一台设备上,使用 InputStream 接收此数据。然后它被转换为 NSData,并返回到 AVAudioPCMBuffer。然后播放该缓冲区。

问题是音频非常不稳定,您无法听清声音,只是音频会根据对方是否在说话而变大或变小。

<小时/>

调度缓冲区时:

self.peerAudioPlayer.scheduleBuffer(audioBuffer, completionHandler: nil)

我延迟了播放该音频几秒钟,然后再播放,希望这样可以使音频更清晰,但没有帮助。我最好的猜测是我正在创建的缓冲区以某种方式切断了一些音频。所以我将向您展示我的相关代码:

这是我录制音频的方法:

    localInput?.installTap(onBus: 1, bufferSize: 4096, format: localInputFormat) {
        (buffer, when) -> Void in

        let data = self.audioBufferToNSData(PCMBuffer: buffer)
        let output = self.outputStream!.write(data.bytes.assumingMemoryBound(to: UInt8.self), maxLength: data.length)
    }

audioBufferToNSData 只是将 AVAudioPCMBuffer 转换为 NSData 的方法,如下:

func audioBufferToNSData(PCMBuffer: AVAudioPCMBuffer) -> NSData {
    let channelCount = 1  // given PCMBuffer channel count is 1
    let channels = UnsafeBufferPointer(start: PCMBuffer.floatChannelData, count: channelCount)
    let data = NSData(bytes: channels[0], length:Int(PCMBuffer.frameCapacity * PCMBuffer.format.streamDescription.pointee.mBytesPerFrame))

    return data
}

我想知道问题是否出在上面的方法上。可能当我计算 NSData 对象的长度时,我可能会切断部分音频。

<小时/>

在接收端我有这个:

    case Stream.Event.hasBytesAvailable:
        DispatchQueue.global().async {
            var tempBuffer: [UInt8] = .init(repeating: 0, count: 17640)
            let length = self.inputStream!.read(&tempBuffer, maxLength: tempBuffer.count)

            self.testBufferCount += length
            self.testBuffer.append(contentsOf: tempBuffer)

            if (self.testBufferCount >= 17640) {

                let data = NSData.init(bytes: &self.testBuffer, length: self.testBufferCount)
                let audioBuffer = self.dataToPCMBuffer(data: data)

                self.peerAudioPlayer.scheduleBuffer(audioBuffer, completionHandler: nil)

                self.testBuffer.removeAll()
                self.testBufferCount = 0
            }
        }

我检查17640的原因是因为发送的数据正好是17640字节,所以我需要在播放之前获取所有这些数据。

此外,dataToPCMBuffer方法只是将NSData转换为AVAudioPCMBuffer以便可以播放。这是该方法:

func dataToPCMBuffer(data: NSData) -> AVAudioPCMBuffer {
    let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: false)  // given NSData audio format
    let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: UInt32(data.length) / audioFormat.streamDescription.pointee.mBytesPerFrame)
    audioBuffer.frameLength = audioBuffer.frameCapacity
    let channels = UnsafeBufferPointer(start: audioBuffer.floatChannelData, count: Int(audioBuffer.format.channelCount))
    data.getBytes(UnsafeMutableRawPointer(channels[0]) , length: data.length)
    return audioBuffer
}

提前谢谢您!

最佳答案

我认为在audioBufferToNSData中你应该使用frame​Length而不是frameCapacity。

let data = NSData(bytes: channels[0], length:Int(PCMBuffer.<strong>frame​Length</strong> * PCMBuffer.format.streamDescription.pointee.mBytesPerFrame))

PCMBuffer.frameCapacity -> 可以存储多少 PCMBuffer.frame​Length -> PCMBuffer.frameCapacity 有多少是实际有效数据

关于ios - 通过流播放的音频出现抖动/断断续续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43098349/

相关文章:

ios - 键值观察外观类上的静态 NSDictionary

android - 移动设备上网络应用程序的内存限制?

iOS 信用卡使用 paypal 定期付款

ios - 将手势识别器添加到由 PaintCode 创建的 BezierPath

c++ - 在 C++ 中使用继承类流

python - 在 Python 中创建流类

ios - 颜色在径向渐变中无法正常工作

ios - 使用 EventKit 在 Swift 中检查并(可能)从日历中删除事件

ios - swift 中 Base 64 的 RFC2045-MIME 变体

java - 返回 XML 文档 Jax-WS