如何解决将流式 u-law 转换为 PCM 听起来很金属
我有一个语音流应用,它通过网络套接字接收实时音频,编码为 G.711 u-law 8KHz 单声道,我想使用 AVAudioEngine
播放。
为此,我使用 AVAudioConverter
将音频样本转换为具有相同采样率和音频参数的 PCM (Float32)。
出于某种原因,我听到的声音是金属和回声。
这是我的代码:
class AudioEngine {
private var engine: AVAudioEngine!
// Audio player
private var playerNode: AVAudioPlayerNode!
private let playerFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32,sampleRate: 8000,channels: 1,interleaved: false)
// AudioConverter properties
private var inputConverter: AVAudioConverter? // audioIn (Player)
private lazy var inputDescriptor = AudioStreamBasicDescription(mSampleRate: 8000,mFormatID: kAudioFormatULaw,mFormatFlags: 0,mBytesPerPacket: 1,mFramesPerPacket: 1,mBytesPerFrame: 1,mChannelsPerFrame: 1,mBitsPerChannel: 8,mReserved: 0)
private var inputFormat: AVAudioFormat?
init() {
engine = AVAudioEngine()
setupPlayerFormats()
setupSession()
setupPlayer()
}
deinit {
stopStream()
}
func playStream() throws {
guard !engine.isRunning else {
print("engine is running")
return
}
try engine.start()
playerNode.play()
print("playing stream")
}
func stopStream() {
playerNode.stop()
engine.stop()
}
/// each byte of kAudioFormatULaw is converted to 4 bytes of pcmFormatFloat32
func convertAudio(data: Data) {
guard let sourceFormat = inputFormat,let targetFormat = playerFormat,let dataBuffer = data.makePCMBuffer(format: sourceFormat),let pcmBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat,frameCapacity: dataBuffer.frameLength) else {
fatalError("Unable to set audio player converter formats")
}
do {
try inputConverter?.convert(to: pcmBuffer,from: dataBuffer)
} catch let error as NSError {
print("audioIn (Player) Conversion error=\(error)")
}
let audioBufferSize = pcmBuffer.audiobufferlist.pointee.mBuffers.mDataByteSize
if audioBufferSize > 0 {
self.playerNode.scheduleBuffer(pcmBuffer,completionHandler: nil)
}
}
private extension AudioEngine {
func setupPlayerFormats() {
inputFormat = AVAudioFormat(streamDescription: &inputDescriptor)
guard let source = inputFormat,let output = playerFormat else {
fatalError("Unable to set audio player formats")
}
inputConverter = AVAudioConverter(from: source,to: output)
}
func setupSession() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(.playAndRecord,mode: .voiceChat)
try session.setActive(true,options: .notifyOthersOnDeactivation)
} catch let error as NSError {
fatalError("Unable to setup audio session with error=\(error)")
}
}
func setupPlayer() {
playerNode = AVAudioPlayerNode()
engine.attach(playerNode)
engine.connect(playerNode,to: engine.mainmixerNode,format: playerFormat)
}
}
每次我从 websocket 接收音频数据时都会调用 func convertAudio(data: Data)
。
我想知道我的音频转换代码是否不正确,或者是否有更好的解决方案来解决这个问题,希望得到任何建议。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。