import AVFoundation func readPCMBuffer(url: URL) -> AVAudioPCMBuffer? { guard let input = try? AVAudioFile(forReading: url, commonFormat: .pcmFormatInt16, interleaved: false) else { return nil } guard let buffer = AVAudioPCMBuffer(pcmFormat: input.processingFormat, frameCapacity: AVAudioFrameCount(input.length)) else { return nil } do { try input.read(into: buffer) } catch { return nil } return buffer } func writePCMBuffer(url: URL, buffer: AVAudioPCMBuffer) throws { let settings: [String: Any] = [ AVFormatIDKey: buffer.format.settings[AVFormatIDKey] ?? kAudioFormatLinearPCM, AVNumberOfChannelsKey: buffer.format.settings[AVNumberOfChannelsKey] ?? 2, AVSampleRateKey: buffer.format.settings[AVSampleRateKey] ?? 44100, AVLinearPCMBitDepthKey: buffer.format.settings[AVLinearPCMBitDepthKey] ?? 16 ] do { let output = try AVAudioFile(forWriting: url, settings: settings, commonFormat: .pcmFormatInt16, interleaved: false) try output.write(from: buffer) } catch { throw error } } func copyPCMBuffer(from inputPath: String, to outputPath: String) { guard let inputBuffer = readPCMBuffer(url: URL(string: inputPath)!) else { fatalError("failed to read \(inputPath)") } guard let outputBuffer = AVAudioPCMBuffer(pcmFormat: inputBuffer.format, frameCapacity: inputBuffer.frameLength) else { fatalError("failed to create a buffer for writing") } guard let inputInt16ChannelData = inputBuffer.int16ChannelData else { fatalError("failed to obtain underlying input buffer") } guard let outputInt16ChannelData = outputBuffer.int16ChannelData else { fatalError("failed to obtain underlying output buffer") } for channel in 0 ..< Int(inputBuffer.format.channelCount) { let p1: UnsafeMutablePointer = inputInt16ChannelData[channel] let p2: UnsafeMutablePointer = outputInt16ChannelData[channel] for i in 0 ..< Int(inputBuffer.frameLength) { p2[i] = p1[i] } } outputBuffer.frameLength = inputBuffer.frameLength do { try writePCMBuffer(url: URL(string: outputPath)!, buffer: outputBuffer) } catch { fatalError("failed to write \(outputPath)") } } copyPCMBuffer(from: "file:///tmp/input.wav", to: "file:///tmp/output.wav")