<commit_before>//
//  Sampler.swift
//  R9MIDISequencer
//
//  Created by <NAME> on 2016/01/29.
//  Copyright © 2016年 <NAME>. All rights reserved.
//

import AVFoundation
import CoreMIDI

@available(iOS 9.0, *)
@available(OSX 10.11, *)
open class Sampler {
    
    // Sampler's volume
    public var volume: Float {
        get {
            return samplerNode.masterGain
        }
        set(value) {
            samplerNode.masterGain = value
        }
    }

    public var audioEngine = AVAudioEngine()
    let samplerNode = AVAudioUnitSampler()
    let channelNumberForDrum: UInt8 = 10
    
    let channelNumber: UInt8
    
    /// MIDI Client Reference
    var midiClient = MIDIClientRef()
    var midiOutPort = MIDIPortRef()
    
    // ドラムの場合はチャンネル10を指定すること
    public init(channelNumber: UInt8) {
        self.channelNumber = channelNumber
        
        audioEngine.attach(samplerNode)
        audioEngine.connect(samplerNode,
            to: audioEngine.mainMixerNode,
            format: samplerNode.outputFormat(forBus: 0))

        var result = OSStatus(noErr)
        result = MIDIClientCreateWithBlock("MIDI Client" as CFString, &midiClient, MIDINotifyBlock)
        if result != OSStatus(noErr) {
            print("error creating client : \(result)")
        }
        result = MIDIOutputPortCreate(midiClient, "Midi Output" as CFString, &midiOutPort);
        if result != OSStatus(noErr) {
            print("error creating output port : \(result)")
        }
        
        let center = NotificationCenter.default
        center.addObserver(forName: NSNotification.Name.AVAudioEngineConfigurationChange, object: nil, queue: OperationQueue.main) { [weak self] (notification: Notification) in
            guard let localSelf = self else { return }
            if !localSelf.audioEngine.isRunning {
                localSelf.startAudioEngine()
            }
        }
        
        startAudioEngine()
    }
    
    public convenience init() {
        self.init(channelNumber: 0)
    }
    
    deinit {
        MIDIPortDispose(midiOutPort)
        MIDIClientDispose(midiClient)
        audioEngine.stop()
    }
    
    public func startAudioEngine() {
        audioEngine.prepare()
        do {
            try audioEngine.start()
        } catch {
    
        }
    }
    
    // If your bank has only one instrument, it seems likely that it is at program 0.
    public func loadSoundBankInstrument(at bankURL: URL, program: UInt8, bankMSB: UInt8, bankLSB: UInt8) {
        do {
            try samplerNode.loadSoundBankInstrument(at: bankURL, program: program, bankMSB: bankMSB, bankLSB: bankLSB)
        } catch {
            print("error load SoundBank")
        }
    }
    
    public func loadMelodicBankInstrument(at bankURL: URL) {
        let msb = UInt8(kAUSampler_DefaultMelodicBankMSB)
        let lsb = UInt8(kAUSampler_DefaultBankLSB)
        loadSoundBankInstrument(at: bankURL, program: 0, bankMSB: msb, bankLSB: lsb)
    }
    
    public func loadPercussionBankInstrument(at bankURL: URL) {
        let msb = UInt8(kAUSampler_DefaultPercussionBankMSB)
        let lsb = UInt8(kAUSampler_DefaultBankLSB)
        loadSoundBankInstrument(at: bankURL, program: 0, bankMSB: msb, bankLSB: lsb)
    }
    
    public func loadAudioFiles(audioFiles: [URL]) {
        do {
            try samplerNode.loadAudioFiles(at: audioFiles)
        } catch {
            print("error load SoundBank")
        }
    }
    
    public func sendProgramChange(_ program: UInt8, bankMSB: UInt8, bankLSB: UInt8) {
        samplerNode.sendProgramChange(program, bankMSB: bankMSB, bankLSB: bankLSB, onChannel: channelNumber)
    }
    
    public func turnOnSustain() {
        samplerNode.sendController(64, withValue: 127, onChannel: channelNumber)
        
        let controllerCommand: UInt8 = UInt8(0xB0) + channelNumber
        let message: [UInt8] = [controllerCommand, 64, UInt8(127)]
        sendMessage(message)
    }
    
    public func turnOffSustain() {
        samplerNode.sendController(64, withValue: 0, onChannel: channelNumber)
        
        let controllerCommand: UInt8 = UInt8(0xB0) + channelNumber
        let message: [UInt8] = [controllerCommand, 64, UInt8(0)]
        sendMessage(message)
    }<commit_msg>Fix error handling on sampler.<commit_after>//
//  Sampler.swift
//  R9MIDISequencer
//
//  Created by <NAME> on 2016/01/29.
//  Copyright © 2016年 <NAME>. All rights reserved.
//

import AVFoundation
import CoreMIDI

@available(iOS 9.0, *)
@available(OSX 10.11, *)
open class Sampler {
    
    // Sampler's volume
    public var volume: Float {
        get {
            return samplerNode.masterGain
        }
        set(value) {
            samplerNode.masterGain = value
        }
    }

    public var audioEngine = AVAudioEngine()
    let samplerNode = AVAudioUnitSampler()
    let channelNumberForDrum: UInt8 = 10
    
    let channelNumber: UInt8
    
    /// MIDI Client Reference
    var midiClient = MIDIClientRef()
    var midiOutPort = MIDIPortRef()
    
    // ドラムの場合はチャンネル10を指定すること
    public init(channelNumber: UInt8) {
        self.channelNumber = channelNumber
        
        audioEngine.attach(samplerNode)
        audioEngine.connect(samplerNode,
            to: audioEngine.mainMixerNode,
            format: samplerNode.outputFormat(forBus: 0))

        var result = OSStatus(noErr)
        result = MIDIClientCreateWithBlock("MIDI Client" as CFString, &midiClient, MIDINotifyBlock)
        if result != OSStatus(noErr) {
            print("error creating client : \(result)")
        }
        result = MIDIOutputPortCreate(midiClient, "Midi Output" as CFString, &midiOutPort);
        if result != OSStatus(noErr) {
            print("error creating output port : \(result)")
        }
        
        let center = NotificationCenter.default
        center.addObserver(forName: NSNotification.Name.AVAudioEngineConfigurationChange, object: nil, queue: OperationQueue.main) { [weak self] (notification: Notification) in
            guard let localSelf = self else { return }
            if !localSelf.audioEngine.isRunning {
                localSelf.startAudioEngine()
            }
        }
        
        startAudioEngine()
    }
    
    public convenience init() {
        self.init(channelNumber: 0)
    }
    
    deinit {
        MIDIPortDispose(midiOutPort)
        MIDIClientDispose(midiClient)
        audioEngine.stop()
    }
    
    public func startAudioEngine() {
        audioEngine.prepare()
        do {
            try audioEngine.start()
        } catch {
    
        }
    }
    
    // If your bank has only one instrument, it seems likely that it is at program 0.
    public func loadSoundBankInstrument(at bankURL: URL, program: UInt8, bankMSB: UInt8, bankLSB: UInt8) throws { try samplerNode.loadSoundBankInstrument(at: bankURL, program: program, bankMSB: bankMSB, bankLSB: bankLSB)
    }
    
    public func loadMelodicBankInstrument(at bankURL: URL) {
        let msb = UInt8(kAUSampler_DefaultMelodicBankMSB)
        let lsb = UInt8(kAUSampler_DefaultBankLSB)
        do {
            try loadSoundBankInstrument(at: bankURL, program: 0, bankMSB: msb, bankLSB: lsb)
        } catch {
            print("error load SoundBank")
        }
    }
    
    public func loadPercussionBankInstrument(at bankURL: URL) {
        let msb = UInt8(kAUSampler_DefaultPercussionBankMSB)
        let lsb = UInt8(kAUSampler_DefaultBankLSB)
        do {
            try loadSoundBankInstrument(at: bankURL, program: 0, bankMSB: msb, bankLSB: lsb)
        } catch {
            // If percussion bank loaded to error. It tries to load the melodic bank.
            loadMelodicBankInstrument(at: bankURL)
        }
    }
    
    public func loadAudioFiles(audioFiles: [URL]) {
        do {
            try samplerNode.loadAudioFiles(at: audioFiles)
        } catch {
            print("error load sound files")
        }
    }
    
    public func sendProgramChange(_ program: UInt8, bankMSB: UInt8, bankLSB: UInt8) {
        samplerNode.sendProgramChange(program, bankMSB: bankMSB, bankLSB: bankLSB, onChannel: channelNumber)
    }
    
    public func turnOnSustain() {
        samplerNode.sendController(64, withValue: 127, onChannel: channelNumber)
        
        let controllerCommand: UInt8 = UInt8(0xB0) + channelNumber
        let message: [UInt8] = [controllerCommand, 64, UInt8(127)]
        sendMessage(message)
    }
    
    public func turnOffSustain() {
        samplerNode.sendController(64, withValue: 0, onChannel: channelNumber)
        
        let controllerCommand: UInt8 = UInt8(0xB0) + channelNumber
        let message: [UInt8] = [controllerCommand, 64, UInt8(0)]
        sendMessage(message)
    }
{'fraction_non_alphanumeric': 0.08755443502177401, 'fraction_numerical': 0.01581480632592253, 'mean_word_length': 2.3462423312883436, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '7470439', 'n_tokens_mistral': 2777, 'n_tokens_neox': 2666, 'n_words': 613}