У меня почти ничего не известно об обработке сигналов, и в настоящее время я пытаюсь реализовать в Swift функцию, которая запускает событие при увеличении уровень звукового давления (например, когда человек кричит).
Я подключаюсь к входному узлу AVAudioEngine с помощью такого обратного вызова:
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat){
(buffer : AVAudioPCMBuffer?, when : AVAudioTime) in
let arraySize = Int(buffer.frameLength)
let samples = Array(UnsafeBufferPointer(start: buffer.floatChannelData![0], count:arraySize))
//do something with samples
let volume = 20 * log10(floatArray.reduce(0){ $0 + $1} / Float(arraySize))
if(!volume.isNaN){
print("this is the current volume: \(volume)")
}
}
После преобразования его в массив с плавающей запятой я попытался получить приблизительную оценку уровня звукового давления, вычислив среднее значение.
Но это дает мне значения, которые сильно колеблются, даже когда iPad просто находится в тихой комнате:
this is the current volume: -123.971
this is the current volume: -119.698
this is the current volume: -147.053
this is the current volume: -119.749
this is the current volume: -118.815
this is the current volume: -123.26
this is the current volume: -118.953
this is the current volume: -117.273
this is the current volume: -116.869
this is the current volume: -110.633
this is the current volume: -130.988
this is the current volume: -119.475
this is the current volume: -116.422
this is the current volume: -158.268
this is the current volume: -118.933
Это значение действительно значительно увеличивается, если я хлопаю в ладоши в микрофон.
Итак, я могу сделать что-то вроде первого вычисления среднего значения этих объемов на этапе подготовки и сравнения, есть ли значительное увеличение разницы на этапе запуска события:
if(!volume.isNaN){
if(isInThePreparingPhase){
print("this is the current volume: \(volume)")
volumeSum += volume
volumeCount += 1
}else if(isInTheEventTriggeringPhase){
if(volume > meanVolume){
//triggers an event
}
}
}
где средний объем вычисляется во время перехода от фазы подготовки к фазе инициирующего события: meanVolume = volumeSum / Float(volumeCount)
....
Однако, если я включаю громкую музыку помимо микрофона, значительного увеличения не будет. И в редких случаях volume
больше meanVolume
, даже когда окружающая среда не имеет значительного увеличения громкости (слышимого человеческими ушами).
Итак, как правильно извлечь уровень звукового давления из AVAudioPCMBuffer?
Википедия дает такую формулу
где p - среднеквадратичное звуковое давление, а p0 - эталонное звуковое давление.
Но я понятия не имею, что представляют собой значения с плавающей запятой в AVAudioPCMBuffer.floatChannelData
. На странице Apple только говорится
Аудиосэмплы буфера как значения с плавающей запятой.
Как мне с ними работать?
floatArray
? вот ...let volume = 20 * log10(floatArray.reduce(0){ $0 + $1} / Float(arraySize)) ....
- person MikeMaus   schedule 19.06.2021