MacOS 控制台应用程序可在不降低质量的情况下减慢或加快语音
MacOSX Console Application to slow or speedup speech without losing quality
我有一个仅包含语音的 .mp3 文件,我想在保持相同清晰度的同时调整速度(更慢或更快)。没有花栗鼠!然后将修改后的文件写入磁盘。为了做到这一点,我正在尝试使用 AVAudioEngine 框架,但我是该框架的完整 N00B。我发现的所有示例都适用于修改音乐或录制语音然后播放。我只想转换为不同的速度并让它吐出修改后的文件。到目前为止,这是我能弄清楚的所有内容,我在代码的注释中记录了我的困惑。
import Foundation
import AVFoundation
import AVKit
print("Change Voice Speed")
let engine = AVAudioEngine()
let speedControl = AVAudioUnitVarispeed()
let originalFile = URL(fileURLWithPath: "/Users/User/Desktop/speech.mp3")
do {
// What do I do with the input file ?
let file = try AVAudioFile(forReading: originalFile)
} catch let error as NSError {
print("There's an error: \(error)")
}
speedControl.rate += 0.1
engine.attach(speedControl)
// Do I need to attach a AVAudioRecorder and record here ?
print("Write New File")
let outputFile = URL(fileURLWithPath: "/Users/User/Desktop/modifiedSpeech.mp3")
// Don't know what settings to put for a .mp3 file are. Also not
// sure if this actually writes the file to disk
do {
try AVAudioFile(forWriting: outputFile, settings: <#T##[String : Any]#>)
} catch let error as NSError {
print("There's an error: \(error)")
}
这是概念验证代码,可加速立体声 M4A 文件并将其另存为 WAVE 文件。错误处理最少,也没有尝试处理不同的频道布局,但希望它能帮助您入门:
let engine = AVAudioEngine()
// Use AVAudioUnitTimePitch to avoid pitch shifts
let timePitch = AVAudioUnitTimePitch()
let player = AVAudioPlayerNode()
engine.attach(timePitch)
engine.attach(player)
engine.connect(player, to:timePitch, format: nil)
engine.connect(timePitch, to:engine.mainMixerNode, format: nil)
// Speed up the file 1.5x
timePitch.rate = 1.5
// Run the engine in manual rendering mode using chunks of 512 frames
let renderSize: AVAudioFrameCount = 512
let renderFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 44100.0, channels: 2, interleaved: true)!
let renderBuffer = AVAudioPCMBuffer(pcmFormat: renderFormat, frameCapacity: renderSize)!
try! engine.enableManualRenderingMode(.offline, format: renderFormat, maximumFrameCount: renderBuffer.frameCapacity)
try! engine.start()
player.play()
// The render format is also the output format
let output = try! AVAudioFile(forWriting: URL(fileURLWithPath: "/tmp/foo.wav"), settings: renderFormat.settings, commonFormat: renderFormat.commonFormat, interleaved: renderFormat.isInterleaved)
let file = try! AVAudioFile(forReading: URL(fileURLWithPath: "/tmp/test.m4a"))
// Read using a buffer sized to produce `renderSize` frames of output
let readSize = AVAudioFrameCount(Float(renderSize) * timePitch.rate)
let readBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: readSize)!
// Process the file
while true {
do {
// Processing is finished if all frames have been read
if file.framePosition == file.length {
break
}
try file.read(into: readBuffer)
player.scheduleBuffer(readBuffer, completionHandler: nil)
let result = try engine.renderOffline(renderBuffer.frameCapacity, to: renderBuffer)
// Try to avoid adding silence
let expectedFrames = AVAudioFrameCount(Float(readBuffer.frameLength) / timePitch.rate)
if expectedFrames < renderBuffer.frameLength {
renderBuffer.frameLength = expectedFrames
}
// Write the adjusted-rate audio
try output.write(from: renderBuffer)
if result != .success {
break
}
}
catch {
break
}
}
player.stop()
engine.stop()
我有一个仅包含语音的 .mp3 文件,我想在保持相同清晰度的同时调整速度(更慢或更快)。没有花栗鼠!然后将修改后的文件写入磁盘。为了做到这一点,我正在尝试使用 AVAudioEngine 框架,但我是该框架的完整 N00B。我发现的所有示例都适用于修改音乐或录制语音然后播放。我只想转换为不同的速度并让它吐出修改后的文件。到目前为止,这是我能弄清楚的所有内容,我在代码的注释中记录了我的困惑。
import Foundation
import AVFoundation
import AVKit
print("Change Voice Speed")
let engine = AVAudioEngine()
let speedControl = AVAudioUnitVarispeed()
let originalFile = URL(fileURLWithPath: "/Users/User/Desktop/speech.mp3")
do {
// What do I do with the input file ?
let file = try AVAudioFile(forReading: originalFile)
} catch let error as NSError {
print("There's an error: \(error)")
}
speedControl.rate += 0.1
engine.attach(speedControl)
// Do I need to attach a AVAudioRecorder and record here ?
print("Write New File")
let outputFile = URL(fileURLWithPath: "/Users/User/Desktop/modifiedSpeech.mp3")
// Don't know what settings to put for a .mp3 file are. Also not
// sure if this actually writes the file to disk
do {
try AVAudioFile(forWriting: outputFile, settings: <#T##[String : Any]#>)
} catch let error as NSError {
print("There's an error: \(error)")
}
这是概念验证代码,可加速立体声 M4A 文件并将其另存为 WAVE 文件。错误处理最少,也没有尝试处理不同的频道布局,但希望它能帮助您入门:
let engine = AVAudioEngine()
// Use AVAudioUnitTimePitch to avoid pitch shifts
let timePitch = AVAudioUnitTimePitch()
let player = AVAudioPlayerNode()
engine.attach(timePitch)
engine.attach(player)
engine.connect(player, to:timePitch, format: nil)
engine.connect(timePitch, to:engine.mainMixerNode, format: nil)
// Speed up the file 1.5x
timePitch.rate = 1.5
// Run the engine in manual rendering mode using chunks of 512 frames
let renderSize: AVAudioFrameCount = 512
let renderFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 44100.0, channels: 2, interleaved: true)!
let renderBuffer = AVAudioPCMBuffer(pcmFormat: renderFormat, frameCapacity: renderSize)!
try! engine.enableManualRenderingMode(.offline, format: renderFormat, maximumFrameCount: renderBuffer.frameCapacity)
try! engine.start()
player.play()
// The render format is also the output format
let output = try! AVAudioFile(forWriting: URL(fileURLWithPath: "/tmp/foo.wav"), settings: renderFormat.settings, commonFormat: renderFormat.commonFormat, interleaved: renderFormat.isInterleaved)
let file = try! AVAudioFile(forReading: URL(fileURLWithPath: "/tmp/test.m4a"))
// Read using a buffer sized to produce `renderSize` frames of output
let readSize = AVAudioFrameCount(Float(renderSize) * timePitch.rate)
let readBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: readSize)!
// Process the file
while true {
do {
// Processing is finished if all frames have been read
if file.framePosition == file.length {
break
}
try file.read(into: readBuffer)
player.scheduleBuffer(readBuffer, completionHandler: nil)
let result = try engine.renderOffline(renderBuffer.frameCapacity, to: renderBuffer)
// Try to avoid adding silence
let expectedFrames = AVAudioFrameCount(Float(readBuffer.frameLength) / timePitch.rate)
if expectedFrames < renderBuffer.frameLength {
renderBuffer.frameLength = expectedFrames
}
// Write the adjusted-rate audio
try output.write(from: renderBuffer)
if result != .success {
break
}
}
catch {
break
}
}
player.stop()
engine.stop()