给定一个由 AKNodeRecorder 创建的单个 AKAudioFile ,该 AKNodeRecorder 包含一系列口语单词,每个单词至少相隔 1 秒,最终创建一系列文件且每个文件包含一个单词的最佳方法是什么?
我相信如果有办法以例如 100 毫秒的 block 迭代文件并测量每个 block 的平均幅度,则可以实现这一点。 “静音 block ”可能是低于任意小幅度的那些。在迭代时,如果我遇到一个非静音幅度的 block ,我可以获取这个“非静音” block 的开始时间戳来创建一个从这里开始并在下一个“静音” block 的开始时间结束的音频文件。
无论是使用上述手动方法还是 AudioKit 更内置的处理技术,任何建议都将不胜感激。
Best Answer-推荐答案 strong>
我没有完整的解决方案,但我已经开始研究与此类似的东西。此功能可以作为您需要的起点。基本上你想将文件读入缓冲区然后分析缓冲区数据。此时,您可以将其分割成更小的缓冲区并将其写入文件。
public class func guessBoundaries(url: URL, sensitivity: Double = 1) -> [Double]? {
var out: [Double] = []
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("ERROR: Couldn't read data into buffer. \(err)")
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 = [Float](repeating: 0, count: bufferLength)
var lastTime: Double = 0
AKLog("inThreshold", inThreshold, "outThreshold", outThreshold)
for i in 0 ..< Int(pcmBuffer.frameLength) {
// n is the channel
for n in 0 ..< channelCount {
guard let sample: Float = pcmBuffer.floatChannelData?[n][i] else { continue }
if counter == rmsBuffer.count {
let time: Double = Double(i) / processingFormat.sampleRate
let avg = rmsBuffer.reduce(0, +) / rmsBuffer.count
// AKLog("Average Value at frame \(i):", avg)
if avg > inThreshold && !thresholdCrossed && time - lastTime > minSegmentDuration {
thresholdCrossed = true
out.append(time)
lastTime = time
} else if avg <= outThreshold && thresholdCrossed && time - lastTime > minSegmentDuration {
thresholdCrossed = false
out.append(time)
lastTime = time
}
counter = 0
}
rmsBuffer[counter] = abs(sample)
counter += 1
}
}
rmsBuffer.removeAll()
return out
}
关于ios - 将 AKAudioFile 拆分为由静音分隔的 block ,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/51432115/
|