如何更改 iPhone 的麦克风采样率
我正在努力向现有应用程序添加一项功能,以从设备麦克风获取音频输入,通过 FFT 将其转换为频域并将其发送到 coreML 模型。我正在使用标准 AVCaptureDevice:
guard let microphone = AVCaptureDevice.default(.builtInMicrophone,
for: .audio,
position: .unspecified),
let microphoneInput = try? AVCaptureDeviceInput(device: microphone) else {
fatalError("Can't create microphone.")
}
问题是,我需要为麦克风定义自定义采样率。按照 Apple 的文档,setPreferredSampleRate
(link) 应该能够在 8000-48000 Hz 范围内做到这一点。然而,无论我选择哪个值,采样率都不会改变,也不会抛出错误:
print("Microphone sample rate: ", AVAudioSession.sharedInstance().sampleRate)
do { var flag = try AVAudioSession.sharedInstance().setPreferredSampleRate(20000) }
catch { print("Unable to set microphone sampling rate!") }
print("Microphone sample rate: ", AVAudioSession.sharedInstance().sampleRate)
输出:
Microphone sample rate: 48000.0
Microphone sample rate: 48000.0
How can I Define the Sample Rate for iOS devices?
编辑:
遵循使用<的建议code>AVAudioConverter 来重新采样麦克风输入,考虑到我正在使用 AVCaptureAudioDataOutputSampleBufferDelegate
和相应的,最有效的方法是什么?从麦克风收集原始音频输入的 captureOutput
方法:
extension AudioSpectrogram: AVCaptureAudioDataOutputSampleBufferDelegate {
public func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
var audioBufferList = AudioBufferList()
var blockBuffer: CMBlockBuffer?
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
sampleBuffer,
bufferListSizeNeededOut: nil,
bufferListOut: &audioBufferList,
bufferListSize: MemoryLayout.stride(ofValue: audioBufferList),
blockBufferAllocator: nil,
blockBufferMemoryAllocator: nil,
flags: kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
blockBufferOut: &blockBuffer)
guard let data = audioBufferList.mBuffers.mData else {
return
}
if self.rawAudioData.count < self.sampleCount * 2 {
let actualSampleCount = CMSampleBufferGetNumSamples(sampleBuffer)
let ptr = data.bindMemory(to: Int16.self, capacity: actualSampleCount)
let buf = UnsafeBufferPointer(start: ptr, count: actualSampleCount)
rawAudioData.append(contentsOf: Array(buf))
}
while self.rawAudioData.count >= self.sampleCount {
let dataToProcess = Array(self.rawAudioData[0 ..< self.sampleCount])
self.rawAudioData.removeFirst(self.hopCount)
self.processData(values: dataToProcess)
}
}
I'm working on adding a feature to an existing app, to take audio input from the device microphone, convert it to frequency domain via an FFT and sends it to a coreML model. I'm using a standard AVCaptureDevice
:
guard let microphone = AVCaptureDevice.default(.builtInMicrophone,
for: .audio,
position: .unspecified),
let microphoneInput = try? AVCaptureDeviceInput(device: microphone) else {
fatalError("Can't create microphone.")
}
The issue is, I require a custom sample rate to be defined for the microphone. Following Apple's documentation, setPreferredSampleRate
(link) should be able to do that in a range between 8000-48000 Hz. However no matter which value I choose, the sample rate won't change, and no error is thrown:
print("Microphone sample rate: ", AVAudioSession.sharedInstance().sampleRate)
do { var flag = try AVAudioSession.sharedInstance().setPreferredSampleRate(20000) }
catch { print("Unable to set microphone sampling rate!") }
print("Microphone sample rate: ", AVAudioSession.sharedInstance().sampleRate)
Output:
Microphone sample rate: 48000.0
Microphone sample rate: 48000.0
How could I define the sampling rate for iOS devices?
EDIT:
Following the suggestion of using AVAudioConverter
to resample microphone input, what's the most efficient way of doing this, considering I'm using AVCaptureAudioDataOutputSampleBufferDelegate
and the corresponding captureOutput
method to collect raw audio input from the microphone:
extension AudioSpectrogram: AVCaptureAudioDataOutputSampleBufferDelegate {
public func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
var audioBufferList = AudioBufferList()
var blockBuffer: CMBlockBuffer?
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
sampleBuffer,
bufferListSizeNeededOut: nil,
bufferListOut: &audioBufferList,
bufferListSize: MemoryLayout.stride(ofValue: audioBufferList),
blockBufferAllocator: nil,
blockBufferMemoryAllocator: nil,
flags: kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
blockBufferOut: &blockBuffer)
guard let data = audioBufferList.mBuffers.mData else {
return
}
if self.rawAudioData.count < self.sampleCount * 2 {
let actualSampleCount = CMSampleBufferGetNumSamples(sampleBuffer)
let ptr = data.bindMemory(to: Int16.self, capacity: actualSampleCount)
let buf = UnsafeBufferPointer(start: ptr, count: actualSampleCount)
rawAudioData.append(contentsOf: Array(buf))
}
while self.rawAudioData.count >= self.sampleCount {
let dataToProcess = Array(self.rawAudioData[0 ..< self.sampleCount])
self.rawAudioData.removeFirst(self.hopCount)
self.processData(values: dataToProcess)
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论