2

I'm able to change the pitch and speed of my audio but I'm getting problem in saving the audio with changed pitch and speed

//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!!!");
}

// call the method on button tap

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

I'm changing the pitch using this function but how to save it with changed pitch .... please help...

Ian
  • 1,221
  • 1
  • 18
  • 30
Mitesh Varu
  • 246
  • 1
  • 14

1 Answers1

0

You can enable offline manual rendering mode in AVAudioEngine,In this mode, the engine’s input and output nodes are disconnected from the audio hardware and the rendering is driven by your app.

Prepare the Source Audio

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).")
}

Create and Configure the Audio Engine

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)

Enable Offline Manual Rendering Mode

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).")
}

Prepare the Output Destinations

// 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).")
}

Manually Render the Audio

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