This script reads /tmp/input.wav
and writes the copy of input as /tmp/output.wav
.
$ swift main.swift
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<Int16> = inputInt16ChannelData[channel] | |
let p2: UnsafeMutablePointer<Int16> = 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") |