菜鸟教程小白 发表于 2022-12-11 20:23:36

ios - 将 AKAudioFile 拆分为由静音分隔的 block


                                            <p><p>给定一个由 <code>AKNodeRecorder</code> 创建的单个 <code>AKAudioFile</code>,该 <code>AKNodeRecorder</code> 包含一系列口语单词,<strong>每个单词至少相隔 1 秒</strong>,最终创建一系列文件且每个文件包含一个单词的最佳方法是什么?</p>

<p>我相信如果有办法以例如 100 毫秒的 block 迭代文件并测量每个 block 的平均幅度,则可以实现这一点。 “静音 block ”可能是低于任意小幅度的那些。在迭代时,如果我遇到一个非静音幅度的 block ,我可以获取这个“非静音” block 的开始时间戳来创建一个从这里开始并在下一个“静音” block 的开始时间结束的音频文件。 </p>

<p>无论是使用上述手动方法还是 AudioKit 更内置的处理技术,任何建议都将不胜感激。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我没有完整的解决方案,但我已经开始研究与此类似的东西。此功能可以作为您需要的起点。基本上你想将文件读入缓冲区然后分析缓冲区数据。此时,您可以将其分割成更小的缓冲区并将其写入文件。</p>

<pre><code>public class func guessBoundaries(url: URL, sensitivity: Double = 1) -&gt; ? {
    var out: = []

    guard let audioFile = try? AVAudioFile(forReading: url) else { return nil }
    let processingFormat = audioFile.processingFormat
    let frameCount = AVAudioFrameCount(audioFile.length)

    guard let pcmBuffer = AVAudioPCMBuffer(pcmFormat: processingFormat, frameCapacity: frameCount) else { return nil }
    audioFile.framePosition = 0

    do {
      audioFile.framePosition = 0
      try audioFile.read(into: pcmBuffer, frameCount: frameCount)

    } catch let err as NSError {
      AKLog(&#34;ERROR: Couldn&#39;t read data into buffer. \(err)&#34;)
      return nil
    }

    let channelCount = Int(pcmBuffer.format.channelCount)
    let bufferLength = 1024
    let inThreshold: Double = 0.001 / sensitivity
    let outThreshold: Double = 0.0001 * sensitivity
    let minSegmentDuration: Double = 1
    var counter = 0
    var thresholdCrossed = false
    var rmsBuffer = (repeating: 0, count: bufferLength)
    var lastTime: Double = 0

    AKLog(&#34;inThreshold&#34;, inThreshold, &#34;outThreshold&#34;, outThreshold)

    for i in 0 ..&lt; Int(pcmBuffer.frameLength) {
      // n is the channel
      for n in 0 ..&lt; channelCount {
            guard let sample: Float = pcmBuffer.floatChannelData? else { continue }

            if counter == rmsBuffer.count {
                let time: Double = Double(i) / processingFormat.sampleRate

                let avg = rmsBuffer.reduce(0, +) / rmsBuffer.count
                // AKLog(&#34;Average Value at frame \(i):&#34;, avg)

                if avg &gt; inThreshold &amp;&amp; !thresholdCrossed &amp;&amp; time - lastTime &gt; minSegmentDuration {
                  thresholdCrossed = true
                  out.append(time)
                  lastTime = time
                } else if avg &lt;= outThreshold &amp;&amp; thresholdCrossed &amp;&amp; time - lastTime &gt; minSegmentDuration {
                  thresholdCrossed = false
                  out.append(time)
                  lastTime = time
                }
                counter = 0
            }
            rmsBuffer = abs(sample)
            counter += 1
      }
    }

    rmsBuffer.removeAll()
    return out
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 将 AKAudioFile 拆分为由静音分隔的 block ,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/51432115/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/51432115/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 将 AKAudioFile 拆分为由静音分隔的 block