当前位置: 首页 > 面试题库 >

尝试通过多点连接将音频从麦克风流传输到另一部电话

逄兴昌
2023-03-14
问题内容

我正在尝试通过Apples Multipeer
Connectivity框架将音频从麦克风流式传输到另一个iPhone。为了进行音频捕获和回放,我使用了AVAudioEngine。

我通过在输入上安装一个抽头来从麦克风接收数据,由此我得到了AVAudioPCMBuffer,然后将其转换为UInt8数组,然后将其流式传输到另一部电话。

但是,当我将数组转换回AVAudioPCMBuffer时,我得到了EXC_BAD_ACCESS异常,编译器指向将字节数组再次转换为AVAudioPCMBuffer的方法。

这是我要处理,转换和流式处理输入内容的代码:

input.installTap(onBus: 0, bufferSize: 2048, format: input.inputFormat(forBus: 0), block: {
                (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in

                let audioBuffer = self.typetobinary(buffer)
                stream.write(audioBuffer, maxLength: audioBuffer.count)
            })

我对将数据转换两种功能:

func binarytotype <T> (_ value: [UInt8], _: T.Type) -> T {
    return value.withUnsafeBufferPointer {
        UnsafeRawPointer($0.baseAddress!).load(as: T.self)
    }

}

func typetobinary<T>(_ value: T) -> [UInt8] {
    var data = [UInt8](repeating: 0, count: MemoryLayout<T>.size)
    data.withUnsafeMutableBufferPointer {
        UnsafeMutableRawPointer($0.baseAddress!).storeBytes(of: value, as: T.self)
    }
    return data
}

在接收端:

func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
    if streamName == "voice" {

        stream.schedule(in: RunLoop.current, forMode: .defaultRunLoopMode)
        stream.open()

        var bytes = [UInt8](repeating: 0, count: 8)
        stream.read(&bytes, maxLength: bytes.count)

        let audioBuffer = self.binarytotype(bytes, AVAudioPCMBuffer.self) //Here is where the app crashes

        do {
            try engine.start()

            audioPlayer.scheduleBuffer(audioBuffer, completionHandler: nil)
            audioPlayer.play()
       }catch let error {
            print(error.localizedDescription)

        }
    }
}

问题是,我可以在来回传输字节数组(在同一部电话中)之前来回转换字节数组并从中播放声音,但不能在接收端创建AVAudioPCMBuffer。有谁知道为什么转换无法在接收端进行?这是正确的方法吗?

任何帮助,对此的想法/投入将不胜感激。


问题答案:

您的AVAudioPCMBuffer序列化/反序列化是错误的。

Swift3的投放方式已发生很大变化,并且似乎需要比Swift2更多的复制。

您可以在[UInt8]和之间进行转换AVAudioPCMBuffer

注意 :此代码假定单浮点数据为44.1kHz。
您可能要更改它。

func copyAudioBufferBytes(_ audioBuffer: AVAudioPCMBuffer) -> [UInt8] {
    let srcLeft = audioBuffer.floatChannelData![0]
    let bytesPerFrame = audioBuffer.format.streamDescription.pointee.mBytesPerFrame
    let numBytes = Int(bytesPerFrame * audioBuffer.frameLength)

    // initialize bytes to 0 (how to avoid?)
    var audioByteArray = [UInt8](repeating: 0, count: numBytes)

    // copy data from buffer
    srcLeft.withMemoryRebound(to: UInt8.self, capacity: numBytes) { srcByteData in
        audioByteArray.withUnsafeMutableBufferPointer {
            $0.baseAddress!.initialize(from: srcByteData, count: numBytes)
        }
    }

    return audioByteArray
}

func bytesToAudioBuffer(_ buf: [UInt8]) -> AVAudioPCMBuffer {
    // format assumption! make this part of your protocol?
    let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, 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]
    // for stereo
    // let dstRight = audioBuffer.floatChannelData![1]

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

    return audioBuffer
}


 类似资料:
  • 我正在尝试获取传入的麦克风音频并将其流式传输到另一部iPhone。基本上是一个电话,但通过蓝牙。我有音频通过进入: 然后我尝试使用来自这里的-StreamReader from@martin-r 使用: 然后使用以下方法将数据发送到另一台设备: 我将行转换为NSData,然后使用dispatch_after 0.5秒不断运行,我通过蓝牙将其发送到另一台设备。 它似乎不起作用,我不认为这是一种实用的

  • 我正在尝试创建一个麦克风应用程序,在会议中用作观众的真正麦克风。我们将把Android设备连接到Wi-Fi局域网,任何人都可以从他们的应用程序中触发麦克风,向他人讲话。数据将进入局域网内的服务器Java程序,并从那里进入扬声器。 我不知道该怎么做。有人能帮我吗???提前谢谢

  • 问题内容: 我正在寻找一种将文件中的音频数据馈送到麦克风的方法,因此,当第三方应用程序(例如 arecord 或Chromium的“按语音搜索”功能)使用麦克风进行音频输入时,它们会从文件中接收音频数据代替。 这是我的情况 :我编写的一个应用程序记录了来自麦克风的音频数据(使用ALSA)并将其保存到文件(audioFile0.raw)中。在将来的某个未知时间点,某些未知的第三方应用程序(例如,我没

  • 有没有办法通过耳机传送麦克风输入,同时通过智能手机扬声器使用音频输出? 我已经看了几个小时了,我看到这在iOS上显然是不可能的,但是Android呢... 我用的是三星Galaxy S4。 这是我的代码的一部分,即使耳机已插入,也可以通过扬声器路由音频输出: 但当我试图通过耳机的麦克风控制我的应用程序时,什么都没有。所以我试着用智能手机的那一个,它显然起作用了。 它看起来不像其他AudioMana

  • 伙计们,我现在正在做一个项目,当你和一个Android设备通话时,它会将音频输出发送到另一个通过wifi相互连接的Android设备上。 我发现这个链接有助于通过WiFi在Android手机之间传输语音,但我的代码问题是,我甚至无法运行该应用程序。谁能告诉我这个问题吗?我应该在舱单上注明什么样的任务?谢谢

  • 根据官方文件 Android 10 (API level 29)和更高版本采用了一种优先级方案,可以在应用程序运行时在它们之间切换输入音频流。在大多数情况下,如果一个新的应用程序获得了音频输入,以前捕获的应用程序会继续运行,但会收到静音。在某些情况下,系统可以继续向两个应用程序发送音频。下面解释了各种共享场景。 除某些特殊情况外,应用程序之间不共享音频。 但是我看到许多应用程序共享音频输入,而没有