Estoy trabajando para agregar una función a una aplicación existente, para tomar la entrada de audio del micrófono del dispositivo, convertirla al dominio de frecuencia a través de una FFT y enviarla a un modelo coreML. Estoy usando un AVCaptureDevice estándar:
guard let microphone = AVCaptureDevice.default(.builtInMicrophone, for: .audio, position: .unspecified), let microphoneInput = try? AVCaptureDeviceInput(device: microphone) else { fatalError("Can't create microphone.") } El problema es que necesito que se defina una frecuencia de muestreo personalizada para el micrófono. Siguiendo la documentación de Apple, setPreferredSampleRate (enlace) debería poder hacerlo en un rango entre 8000-48000 Hz. Sin embargo, independientemente del valor que elija, la frecuencia de muestreo no cambiará y no arrojará ningún error:
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)Producción:
Microphone sample rate: 48000.0 Microphone sample rate: 48000.0¿Cómo podría definir la frecuencia de muestreo para dispositivos iOS?
Siguiendo la sugerencia de usar AVAudioConverter para volver a muestrear la entrada del micrófono, cuál es la forma más eficiente de hacerlo, considerando que estoy usando AVCaptureAudioDataOutputSampleBufferDelegate y el método captureOutput correspondiente para recopilar la entrada de audio sin procesar del micrófono:
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) } }