I am attempting to document some audio, then instantly convert it to AAC and play it again. I maintain getting this error:
Recording stopped: file:///var/cell/Containers/Information/Software/941BE30D-569E-4780-8F0D-71964E9C5561/Paperwork/recording.caf
Audio file period: 3.4771882086167802 seconds
Audio buffer learn efficiently
AVAEInternal.h:130 [AUInterface.mm:539:SetFormat: ([[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr])] returned false, error Error Area=NSOSStatusErrorDomain Code=-10865 "(null)"
*** Terminating app as a consequence of uncaught exception 'com.apple.coreaudio.avfaudio', purpose: '[[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr]: returned false, error Error Area=NSOSStatusErrorDomain Code=-10865 "(null)"'
*** First throw name stack:
(0x19f280f20 0x197112018 0x19f37f66c 0x1b8df8198 0x1b8efc2a4 0x1b8efc640 0x1b8e5a744 0x1b8ed408c 0x1028e15b8 0x1028ddaa8 0x1a4947924 0x1a4061bc0 0x1a406653c 0x1a4064b20 0x1a4064a6c 0x1a4644114 0x1a384888c 0x1a32b34e8 0x1a32b5bec 0x1a32b34e8 0x1a32b07d0 0x1a32afe48 0x1a4a8ebd8 0x1a488bbb8 0x1a488a1b8 0x1a488a344 0x1a1600af4 0x1a150f560 0x1a1603b40 0x1a17ba680 0x1a17b9944 0x1a163a9e0 0x1a163c1d4 0x1a1644ecc 0x1a153784c 0x1a153576c 0x1a15353b0 0x1a1536254 0x19f253834 0x19f2537c8 0x19f251298 0x19f250484 0x19f24fcd8 0x1e41001a8 0x1a188890c 0x1a193c9d0 0x1a3440148 0x1a33ec714 0x1a33f84d0 0x1028dc500 0x1028dc5b0 0x1c2901e4c)
libc++abi: terminating as a consequence of uncaught exception of sort NSException
That is the logic of the recording/conversion move:
class AudioRecorder: ObservableObject {
@Revealed var isRecording = false
@Revealed var audioFileURL: URL?
non-public var audioRecorder: AVAudioRecorder?
func startRecording() {
let fileName = "recording.caf"
let filePath = getDocumentsDirectory().appendingPathComponent(fileName)
let settings = [
AVFormatIDKey: Int(kAudioFormatAppleIMA4),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
] as [String : Any]
do {
audioRecorder = attempt AVAudioRecorder(url: filePath, settings: settings)
audioRecorder?.document()
isRecording = true
print("Recording began: (filePath)")
} catch {
print("Failed to start out recording: (error.localizedDescription)")
}
}
func stopRecording() {
audioRecorder?.cease()
audioRecorder = nil // Make sure the audio recorder is correctly deallocated
audioFileURL = getDocumentsDirectory().appendingPathComponent("recording.caf")
isRecording = false
print("Recording stopped: (audioFileURL?.absoluteString ?? "No file URL")")
}
func convertToAAC() {
guard let audioFileURL = audioFileURL else {
print("No audio file to transform")
return
}
do {
let file = attempt AVAudioFile(forReading: audioFileURL)
let period = Double(file.size) / file.fileFormat.sampleRate
print("Audio file period: (period) seconds")
if period == 0.0 {
print("Audio file has zero period, skipping conversion.")
return
}
if let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: AVAudioFrameCount(file.size)), buffer.frameCapacity != 0 {
attempt file.learn(into: buffer)
print("Audio buffer learn efficiently")
let outputFileName = "transformed.m4a"
let outputFilePath = getDocumentsDirectory().appendingPathComponent(outputFileName)
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
] as [String : Any]
let outputFile = attempt AVAudioFile(forWriting: outputFilePath, settings: settings)
let audioEngine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
audioEngine.connect(playerNode)
// Use the primary mixer node's output format
let mixerFormat = audioEngine.mainMixerNode.outputFormat(forBus: 0)
audioEngine.join(playerNode, to: audioEngine.mainMixerNode, format: buffer.format)
audioEngine.put together()
attempt audioEngine.begin()
playerNode.scheduleBuffer(buffer, at: nil) {
DispatchQueue.fundamental.async {
print("Conversion to AAC accomplished: (outputFilePath)")
playerNode.cease()
audioEngine.cease()
}
}
playerNode.play()
audioEngine.mainMixerNode.installTap(onBus: 0, bufferSize: 1024, format: mixerFormat) { (buffer, time) in
do {
attempt outputFile.write(from: buffer)
} catch {
print("Error writing buffer to file: (error.localizedDescription)")
}
}
} else {
print("Did not create audio buffer or buffer body capability is zero")
}
} catch {
print("Error changing audio file: (error.localizedDescription)")
}
}
non-public func getDocumentsDirectory() -> URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
}
}