[英]Split AKAudioFile into chunks separated by silence
給定一個AKAudioFile
已經從創建AKNodeRecorder
包含一系列的口語單詞, 每個單詞是由至少1秒鍾分離 ,是什么,最終創造出了一系列包含一個字每一個文件的文件的最好的方法?
我相信,如果有一種方法可以迭代文件(例如100 ms的塊)並測量每個塊的平均幅度,則可以實現此目的。 “靜音塊”可能是低於任意小幅度的那些。 進行迭代時,如果遇到一個具有非靜默振幅的塊,則可以獲取此“非靜默”塊的開始時間戳,以創建一個從此處開始並在下一個“靜默”塊的開始時間結束的音頻文件。
無論是使用上述手動方法還是AudioKit內置的處理技術,任何建議都將不勝感激。
我沒有完整的解決方案,但是我已經開始從事與此類似的工作。 此功能可以作為您所需的起點。 基本上,您希望將文件讀入緩沖區,然后分析緩沖區數據。 那時,您可以將其切成較小的緩沖區,然后將其寫入文件。
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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.