Reputation: 392
I am using AVAudioEngine to monitor microphone input. After the AudioEngine stops I would like to save the audio received into an AVAudioFile for future use.
This is my current implementation, and the file does contain data. It is a wav file, but it is not a playable audio file. I am thinking there may be something wrong in my formatting, here is my approach.
private enum Setting {
static let formatID = Int(kAudioFormatLinearPCM)
static let sampleRate = 16000
static let numberOfChannels = 1
static let encoderQuality = AVAudioQuality.min.rawValue
}
private let settings: [String: Any] =
[AVFormatIDKey: Setting.formatID,
AVSampleRateKey: Setting.sampleRate,
AVLinearPCMIsFloatKey: true,
AVNumberOfChannelsKey: Setting.numberOfChannels,
AVEncoderAudioQualityKey: Setting.encoderQuality]
func record() {
let mixer = AVAudioMixerNode()
audioEngine.attach(mixer)
let format = AVAudioFormat(settings: settings)
audioEngine.connect(audioEngine.inputNode, to: mixer, format: audioEngine.inputNode.inputFormat(forBus: 0))
audioEngine.connect(mixer, to: audioEngine.outputNode, format: format)
guard let destinationURL = FileManager.default.whs_generateWAVFile() else { return }
do {
file = try AVAudioFile(forWriting: destinationURL, settings: mixer.outputFormat(forBus: 0).settings, commonFormat: .pcmFormatFloat32, interleaved: true)
mixer.installTap(onBus: 0, bufferSize: 1024, format: mixer.outputFormat(forBus: 0)) { (buffer, time) in
do { try self.file?.write(from: buffer); print("Wrote \(buffer)") } catch { print("Error: \(error)") }
}
audioEngine.prepare()
do { try audioEngine.start() } catch { print("Big error: \(RecordingError.audioEngineStart.description)"); return }
} catch {
print("Big Error: \(RecordingError.audioEngineStart.description), \(error)")
}
}
Upvotes: 2
Views: 1504
Reputation: 1484
It's because you haven't closed the AVAudioFile you're recording to. Set file to nil when stopping the engine and the wav file will be playable.
Upvotes: 2