<commit_before>//
//  AKMIDINode.swift
//  AudioKit
//
//  Created by <NAME>, revision history on Github.
//  Copyright © 2016 AudioKit. All rights reserved.
//

import AVFoundation
import CoreAudio

/// A version of AKInstrument specifically targeted to instruments that
/// should be triggerable via MIDI or sequenced with the sequencer.
public class AKMIDINode: AKNode, AKMIDIListener {
    
    // MARK: - Properties
    
    /// MIDI Input
    public var midiIn = MIDIEndpointRef()
    
    /// Name of the instrument
    public var name = "AKMIDIInstrument"
    
    internal var internalNode: AKPolyphonicNode
    
    // MARK: - Initialization
    
    /// Initialize the MIDI node
    ///
    /// - parameter node: A polyphonic node that will be triggered via MIDI
    ///
    public init(node: AKPolyphonicNode) {
        internalNode = node
        super.init()
        avAudioNode = internalNode.avAudioNode
    }


    /// Enable MIDI input from a given MIDI client
    /// This is not in the init function because it must be called AFTER you start audiokit
    ///
    /// - parameter midiClient: A refernce to the midi client
    /// - parameter name: Name to connect with
    ///
    public func enableMIDI(midiClient: MIDIClientRef, name: String) {
        var result: OSStatus
        result = MIDIDestinationCreateWithBlock(midiClient, name, &midiIn, MyMIDIReadBlock)
        CheckError(result)
    }
    
    // MARK: - Handling MIDI Data
    
    // Send MIDI data to the audio unit
    func handleMIDI(data1: UInt32, data2: UInt32, data3: UInt32) {
        let status = data1 >> 4
        let channel = data1 & 0xF
        if(Int(status) == AKMIDIStatus.NoteOn.rawValue && data3 > 0) {
            start(note: Int(data2), withVelocity: Int(data3), onChannel: Int(channel))
        } else if Int(status) == AKMIDIStatus.NoteOn.rawValue && data3 == 0 {
            stop(note: Int(data2), onChannel: Int(channel))
        }
    }
    
    /// Handle MIDI commands that come in externally
    ///
    /// - parameter note: MIDI Note number
    /// - parameter velocity: MIDI velocity
    /// - parameter channel: MIDI channel
    ///
    public func receivedMIDINoteOn(note: Int, velocity: Int, channel: Int) {
        if velocity > 0 {
            internalNode.play(note: note, velocity: velocity)
        } else {
            internalNode.stop(note: note)
        }
    }
    // MARK: - MIDI Note Start/Stop
    
    /// Start a note
    public func start(note note: Int, withVelocity velocity: Int, onChannel channel: Int) {
        print("Start: Override in subclass")
    }
    
    /// Stop a note
    public func stop(note note: Int, onChannel channel: Int) {
        print("Stop: Override in subclass")
    }
    
    private func MyMIDIReadBlock(<commit_msg>Made AKMIDINote correctly inmplement AKMIDIListener (fixes MollyBChimes example)<commit_after>//
//  AKMIDINode.swift
//  AudioKit
//
//  Created by <NAME>, revision history on Github.
//  Copyright © 2016 AudioKit. All rights reserved.
//

import AVFoundation
import CoreAudio

/// A version of AKInstrument specifically targeted to instruments that
/// should be triggerable via MIDI or sequenced with the sequencer.
public class AKMIDINode: AKNode, AKMIDIListener {
    
    // MARK: - Properties
    
    /// MIDI Input
    public var midiIn = MIDIEndpointRef()
    
    /// Name of the instrument
    public var name = "AKMIDIInstrument"
    
    internal var internalNode: AKPolyphonicNode
    
    // MARK: - Initialization
    
    /// Initialize the MIDI node
    ///
    /// - parameter node: A polyphonic node that will be triggered via MIDI
    ///
    public init(node: AKPolyphonicNode) {
        internalNode = node
        super.init()
        avAudioNode = internalNode.avAudioNode
    }


    /// Enable MIDI input from a given MIDI client
    /// This is not in the init function because it must be called AFTER you start audiokit
    ///
    /// - parameter midiClient: A refernce to the midi client
    /// - parameter name: Name to connect with
    ///
    public func enableMIDI(midiClient: MIDIClientRef, name: String) {
        var result: OSStatus
        result = MIDIDestinationCreateWithBlock(midiClient, name, &midiIn, MyMIDIReadBlock)
        CheckError(result)
    }
    
    // MARK: - Handling MIDI Data
    
    // Send MIDI data to the audio unit
    func handleMIDI(data1: UInt32, data2: UInt32, data3: UInt32) {
        let status = data1 >> 4
        let channel = data1 & 0xF
        if(Int(status) == AKMIDIStatus.NoteOn.rawValue && data3 > 0) {
            internalNode.play(note: Int(data2), velocity: Int(data3))
        } else if Int(status) == AKMIDIStatus.NoteOn.rawValue && data3 == 0 {
            internalNode.stop(note: Int(data2))
        } else if Int(status) == AKMIDIStatus.NoteOff.rawValue {
            internalNode.stop(note: Int(data2))
        }
    }
    
    /// Handle MIDI commands that come in externally
    ///
    /// - parameter note: MIDI Note number
    /// - parameter velocity: MIDI velocity
    /// - parameter channel: MIDI channel
    ///
    public func receivedMIDINoteOn(note: Int, velocity: Int, channel: Int) {
        if velocity > 0 {
            internalNode.play(note: note, velocity: velocity)
        } else {
            internalNode.stop(note: note)
        }
    }
    
    private func MyMIDIReadBlock(
{'fraction_non_alphanumeric': 0.0965042766827817, 'fraction_numerical': 0.009483079211602826, 'mean_word_length': 2.2306306306306305, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4638521', 'n_tokens_mistral': 1679, 'n_tokens_neox': 1578, 'n_words': 505}