如何使用改变的音高和速度保存音频iOS?

时间:2016-08-20 09:33:37

标签: objective-c audio audio-recording avaudioengine pitch-shifting

我能够改变音频的音高和速度,但是我在改变音高和速度的过程中遇到了问题

//this is method which set the pitch  
[self.audioEngine connect:audioPlayerNode
                       to:timePitchEffect
                   format:nil];
[self.audioEngine connect:timePitchEffect
                       to:self.audioEngine.outputNode
                   format:nil];

[audioPlayerNode scheduleFile:self.audioFile
                       atTime:nil
            completionHandler:nil];
[self.audioEngine startAndReturnError:&audioEngineError];
NSLog(@"%@",self.audioFile.url);
if (audioEngineError) {
    NSLog(@"%@",@"whats this!!!");
}

//按下按钮点击方法

[self playAudioWithEffect:EAudioEffectPitch effectValue:@-500.0];

我正在使用此功能更改音高,但如何使用更改的音高保存音量....请帮助......

1 个答案:

答案 0 :(得分:-1)

您可以在AVAudioEngine中启用离线手动渲染模式,在这种模式下,引擎的输入和输出节点与音频硬件断开连接,并且渲染由您的应用程序驱动。

准备源音频

let sourceFile: AVAudioFile
let format: AVAudioFormat
do {
    let sourceFileURL = Bundle.main.url(forResource: "YOUR_AUDIO_NAME", withExtension: "caf")!
    sourceFile = try AVAudioFile(forReading: sourceFileURL)
    format = sourceFile.processingFormat
} catch {
    fatalError("Unable to load the source audio file: \(error.localizedDescription).")
}

创建和配置音频引擎

let engine = AVAudioEngine()
let player = AVAudioPlayerNode()
let reverb = AVAudioUnitReverb()

engine.attach(player)
engine.attach(reverb)

// Set the desired reverb parameters.
reverb.loadFactoryPreset(.mediumHall)
reverb.wetDryMix = 50

// Connect the nodes.
engine.connect(player, to: reverb, format: format)
engine.connect(reverb, to: engine.mainMixerNode, format: format)

// Schedule the source file.
player.scheduleFile(sourceFile, at: nil)

启用离线手动渲染模式

do {
    // The maximum number of frames the engine renders in any single render call.
    let maxFrames: AVAudioFrameCount = 4096
    try engine.enableManualRenderingMode(.offline, format: format,
                                         maximumFrameCount: maxFrames)
} catch {
    fatalError("Enabling manual rendering mode failed: \(error).")
}
//start the engine
do {
    try engine.start()
    player.play()
} catch {
    fatalError("Unable to start audio engine: \(error).")
}

准备输出目标

// The output buffer to which the engine renders the processed data.
let buffer = AVAudioPCMBuffer(pcmFormat: engine.manualRenderingFormat,
                              frameCapacity: engine.manualRenderingMaximumFrameCount)!

let outputFile: AVAudioFile
do {
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let outputURL = documentsURL.appendingPathComponent("Rhythm-processed.caf")
    outputFile = try AVAudioFile(forWriting: outputURL, settings: sourceFile.fileFormat.settings)
} catch {
    fatalError("Unable to open output audio file: \(error).")
}

手动渲染音频

while engine.manualRenderingSampleTime < sourceFile.length {
    do {
        let frameCount = sourceFile.length - engine.manualRenderingSampleTime
        let framesToRender = min(AVAudioFrameCount(frameCount), buffer.frameCapacity)
        
        let status = try engine.renderOffline(framesToRender, to: buffer)
        
        switch status {
            
        case .success:
            // The data rendered successfully. Write it to the output file.
            try outputFile.write(from: buffer)
            
        case .insufficientDataFromInputNode:
            // Applicable only when using the input node as one of the sources.
            break
            
        case .cannotDoInCurrentContext:
            // The engine couldn't render in the current render call.
            // Retry in the next iteration.
            break
            
        case .error:
            // An error occurred while rendering the audio.
            fatalError("The manual rendering failed.")
        }
    } catch {
        fatalError("The manual rendering failed: \(error).")
    }
}

// Stop the player node and engine.
player.stop()
engine.stop()

The reference link