【问题标题】:AudioKit - How to get Real Time floatChannelData from Microphone?AudioKit - 如何从麦克风获取实时 floatChannelData?
【发布时间】:2018-11-21 03:34:35
【问题描述】:

我是 Audiokit 的新手,我正在尝试对来自麦克风的输入音频进行一些实时数字信号处理。

我知道我想要的数据在 AKAudioFile 的 FloatChannelData 中,但是如果我想实时获取呢?我目前正在使用 AKMicrophone、AKFrequencyTracker、AKNodeOutputPlot、AKBooster,并且正在绘制跟踪器的幅度数据。但是,该数据与音频信号不同(如您所知,它是 RMS)。有什么方法可以从麦克风获取信号的浮点数据吗?甚至来自 AKNodeOutputPlot?我只需要读取权限。

AKSettings.audioInputEnabled = true
mic = AKMicrophone()
plot = AKNodeOutputPlot(mic, frame: audioInputPlot.bounds)
tracker = AKFrequencyTracker.init(mic)
silence = AKBooster(tracker,gain:0)
AudioKit.output = silence
AudioKit.start()

创建者推荐here

AKNodeOutputPlot 有效,它是一个短文件。你基本上只是点击节点并抓取数据。

如果有 plot (AKNodeOutputPlot)、mic(AKMicrophone) 的实例并且想要将这些值输出到标签,这将如何在我的 viewController 中工作?

【问题讨论】:

    标签: ios swift audiokit


    【解决方案1】:

    点击您想要从中获取数据的任何节点。我在上面的引用中使用了 AKNodeOutputPlot,因为它非常简单,只需使用该数据作为绘图的输入,但您可以获取数据并对其进行任何处理。在这段代码中(来自AKNodeOutputPlot):

    internal func setupNode(_ input: AKNode?) {
        if !isConnected {
            input?.avAudioNode.installTap(
                onBus: 0,
                bufferSize: bufferSize,
                format: nil) { [weak self] (buffer, _) in
    
                    guard let strongSelf = self else {
                        AKLog("Unable to create strong reference to self")
                        return
                    }
                    buffer.frameLength = strongSelf.bufferSize
                    let offset = Int(buffer.frameCapacity - buffer.frameLength)
                    if let tail = buffer.floatChannelData?[0] {
                        strongSelf.updateBuffer(&tail[offset], withBufferSize: strongSelf.bufferSize)
                    }
            }
        }
        isConnected = true
    }
    

    您可以实时获取缓冲区数据。在这里,我们只是将它发送到“updateBuffer”,在那里它会被绘制出来,但你会做其他事情而不是绘制。

    【讨论】:

    【解决方案2】:

    完成 Aurelius Prochazka 的回答:

    要记录流经节点的音频,您需要在其上附加一个水龙头。 Tap 只是一个闭包,每次缓冲区可用时都会调用它。

    这是一个示例代码,您可以在自己的类中重用:

    var mic = AKMicrophone()
    
    func initMicrophone() {
    
      // Facultative, allow to set the sampling rate of the microphone
      AKSettings.sampleRate = 44100
    
      // Link the microphone note to the output of AudioKit with a volume of 0.
      AudioKit.output = AKBooster(mic, gain:0)
    
      // Start AudioKit engine
      try! AudioKit.start()
    
      // Add a tap to the microphone
      mic?.avAudioNode.installTap(
          onBus: audioBus, bufferSize: 4096, format: nil // I choose a buffer size of 4096
      ) { [weak self] (buffer, _) in //self is now a weak reference, to prevent retain cycles
    
          // We try to create a strong reference to self, and name it strongSelf
          guard let strongSelf = self else {
            print("Recorder: Unable to create strong reference to self #1")
            return
          }
    
          // We look at the buffer if it contains data
          buffer.frameLength = strongSelf.bufferSize
          let offset = Int(buffer.frameCapacity - buffer.frameLength)
          if let tail = buffer.floatChannelData?[0] {
            // We convert the content of the buffer to a swift array
            let samples = Array(UnsafeBufferPointer(start: &tail[offset], count: 4096))
            strongSelf.myFunctionHandlingData(samples)
          }
      }
    
      func myFunctionhandlingData(data: [Float]) {
        // ...
      }
    

    如果您需要在不同线程之间对此数据进行交互,请小心使用DispatchQueue 或其他同步机制。 就我而言,我确实使用:

    DispatchQueue.main.async { [weak self]  in
      guard let strongSelf = self else {
        print("Recorder: Unable to create strong reference to self #2")
        return
      }
      strongSelf.myFunctionHandlingData(samples)
    }
    

    让我的函数在主线程中运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 1970-01-01
      • 1970-01-01
      • 2019-05-20
      • 2013-11-18
      • 1970-01-01
      相关资源
      最近更新 更多