Skip to content

Commit

Permalink
Deprecated AKOfflineRenderNode in favor of AudioKit.renderToFile.
Browse files Browse the repository at this point in the history
  • Loading branch information
dave234 committed Nov 9, 2017
1 parent a0f6d44 commit 09aedf7
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 7 deletions.
76 changes: 69 additions & 7 deletions AudioKit/Common/Internals/AudioKit.swift
Expand Up @@ -17,13 +17,6 @@ import Dispatch

public typealias AKCallback = () -> Void

/// Adding connection between nodes with default format
extension AVAudioEngine {
open func connect(_ node1: AVAudioNode, to node2: AVAudioNode) {
connect(node1, to: node2, format: AudioKit.format)
}
}

/// Top level AudioKit managing class
@objc open class AudioKit: NSObject {

Expand Down Expand Up @@ -554,4 +547,73 @@ extension AudioKit {
engine.detach(node)
}
}

/// Render output to an AVAudioFile for a duration.
/// - Parameters
/// - audioFile: An file initialized for writing
/// - seconds: Duration to render
/// - prerender: A closure called before rendering starts, use this to start players, set initial parameters, etc...
///
@available(iOS 11, macOS 10.13, tvOS 11, *)
@objc open static func renderToFile(_ audioFile: AVAudioFile, seconds: Double, prerender: (() -> Void)? = nil) throws {
try engine.renderToFile(audioFile, seconds: seconds, prerender: prerender)
}

}


extension AVAudioEngine {

/// Adding connection between nodes with default format
open func connect(_ node1: AVAudioNode, to node2: AVAudioNode) {
connect(node1, to: node2, format: AudioKit.format)
}

/// Render output to an AVAudioFile for a duration.
/// - Parameters
/// - audioFile: An file initialized for writing
/// - seconds: Duration to render
/// - prerender: A closure called before rendering starts, use this to start players, set initial parameters, etc...
///
@available(iOS 11.0, macOS 10.13, *)
public func renderToFile(_ audioFile: AVAudioFile, seconds: Double, prerender: (() -> Void)? = nil) throws {
guard seconds >= 0 else {
throw NSError.init(domain: "AVAudioEngine ext", code: 1, userInfo: [NSLocalizedDescriptionKey:"Seconds needs to be a positive value"])
}
// Engine can't be running when switching to offline render mode.
if isRunning { stop() }
try enableManualRenderingMode(.offline, format: audioFile.processingFormat, maximumFrameCount: 4096)

// This resets the sampleTime of offline rendering to 0.
reset()

try start()

guard let buffer = AVAudioPCMBuffer(pcmFormat: manualRenderingFormat, frameCapacity: manualRenderingMaximumFrameCount) else {
throw NSError.init(domain: "AVAudioEngine ext", code: 1, userInfo: [NSLocalizedDescriptionKey:"Couldn't creat buffer in renderToFile"])
}

// This is for users to prepare the nodes for playing, i.e player.play()
prerender?()

// Render until file contains >= target samples
let targetSamples = AVAudioFramePosition(seconds * manualRenderingFormat.sampleRate)
while audioFile.framePosition < targetSamples {
let framesToRender = min(buffer.frameCapacity, AVAudioFrameCount( targetSamples - audioFile.framePosition))
let status = try renderOffline(framesToRender, to: buffer)
switch status {
case .success:
try audioFile.write(from: buffer)
case .cannotDoInCurrentContext:
print("renderToFile cannotDoInCurrentContext")
continue
case .error, .insufficientDataFromInputNode:
throw NSError.init(domain: "AVAudioEngine ext", code: 1, userInfo: [NSLocalizedDescriptionKey:"renderToFile render error"])
}
}

stop()
disableManualRenderingMode()

}
}
Expand Up @@ -9,6 +9,7 @@
#pragma once
#import "AKAudioUnit.h"

NS_DEPRECATED(10_10, 10_13, 8_0, 11_0)
@interface AKOfflineRenderAudioUnit : AKAudioUnit
@property BOOL internalRenderEnabled; // default = true;

Expand Down
Expand Up @@ -8,6 +8,9 @@

import Foundation

@available(iOS, obsoleted: 11)
@available(tvOS, obsoleted: 11)
@available(macOS, obsoleted: 10.13)
open class AKOfflineRenderNode: AKNode, AKComponent, AKInput {

public typealias AKAudioUnitType = AKOfflineRenderAudioUnit
Expand Down

0 comments on commit 09aedf7

Please sign in to comment.