// Copyright AudioKit. All Rights Reserved. Revision History at http://github.com/AudioKit/AudioKit/
// This file was auto-autogenerated by scripts and templates at http://github.com/AudioKit/AudioKitDevTools/

import AVFoundation
import CAudioKit

/// This will digitally degrade a signal.
public class BitCrusher: Node, AudioUnitContainer, Tappable, Toggleable {

    /// Unique four-letter identifier "btcr"
    public static let ComponentDescription = AudioComponentDescription(effect: "btcr")

    /// Internal type of audio unit for this node
    public typealias AudioUnitType = InternalAU

    /// Internal audio unit
    public private(set) var internalAU: AudioUnitType?

    // MARK: - Parameters

    /// Specification details for bitDepth
    public static let bitDepthDef = NodeParameterDef(
        identifier: "bitDepth",
        name: "Bit Depth",
        address: akGetParameterAddress("BitCrusherParameterBitDepth"),
        range: 1 ... 24,
        unit: .generic,
        flags: .default)

    /// The bit depth of signal output. Typically in range (1-24). Non-integer values are OK.
    @Parameter public var bitDepth: AUValue

    /// Specification details for sampleRate
    public static let sampleRateDef = NodeParameterDef(
        identifier: "sampleRate",
        name: "Sample Rate (Hz)",
        address: akGetParameterAddress("BitCrusherParameterSampleRate"),
        range: 0.0 ... 20_000.0,
        unit: .hertz,
        flags: .default)

    /// The sample rate of signal output.
    @Parameter public var sampleRate: AUValue

    // MARK: - Audio Unit

    /// Internal Audio Unit for BitCrusher
    public class InternalAU: AudioUnitBase {
        /// Get an array of the parameter definitions
        /// - Returns: Array of parameter definitions
        public override func getParameterDefs() -> [NodeParameterDef] {
            [BitCrusher.bitDepthDef,
             BitCrusher.sampleRateDef]
        }

        /// Create the DSP Refence for this node
        /// - Returns: DSP Reference
        public override func createDSP() -> DSPRef {
            akCreateDSP("BitCrusherDSP")
        }
    }

    // MARK: - Initialization

    /// Initialize this bitcrusher node
    ///
    /// - Parameters:
    ///   - input: Input node to process
    ///   - bitDepth: The bit depth of signal output. Typically in range (1-24). Non-integer values are OK.
    ///   - sampleRate: The sample rate of signal output.
    ///
    public init(
        _ input: Node,
        bitDepth: AUValue = 8,
        sampleRate: AUValue = 10_000
        ) {
        super.init(avAudioNode: AVAudioNode())

        instantiateAudioUnit { avAudioUnit in
            self.avAudioUnit = avAudioUnit
            self.avAudioNode = avAudioUnit

            guard let audioUnit = avAudioUnit.auAudioUnit as? AudioUnitType else {
                fatalError("Couldn't create audio unit")
            }
            self.internalAU = audioUnit

            self.bitDepth = bitDepth
            self.sampleRate = sampleRate
        }
        connections.append(input)
    }
}
