├── README.md ├── r2.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── phil_busby.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── phil_busby.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── Debug.xcscheme │ ├── Release.xcscheme │ └── xcschememanagement.plist └── r2 ├── AppDelegate.swift ├── Assets.xcassets ├── AppIcon.appiconset │ ├── Contents.json │ └── r2x1024.png └── Contents.json ├── Base.lproj └── Main.storyboard ├── EventMonitor.swift ├── Info.plist ├── MidiPlayer.swift ├── SinePlayer.swift ├── Tone.swift └── gs_instruments.dls /README.md: -------------------------------------------------------------------------------- 1 | # R2 2 | This is a program that turns your keystrokes into music. It can be installed with the command 3 | 4 | brew cask install philihp/casket/r2 5 | -------------------------------------------------------------------------------- /r2.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2E6186EC1EC7D32500E999AF /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E6186EB1EC7D32500E999AF /* EventMonitor.swift */; }; 11 | 2E6186EE1EC7E57800E999AF /* SinePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E6186ED1EC7E57800E999AF /* SinePlayer.swift */; }; 12 | 2E6186F01EC8006400E999AF /* Tone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E6186EF1EC8006400E999AF /* Tone.swift */; }; 13 | 2E6186F21EC9276500E999AF /* MidiPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E6186F11EC9276500E999AF /* MidiPlayer.swift */; }; 14 | 2E6186F41EC9294C00E999AF /* gs_instruments.dls in Resources */ = {isa = PBXBuildFile; fileRef = 2E6186F31EC9294600E999AF /* gs_instruments.dls */; }; 15 | 2E66ED211EC7D0FB00FECB44 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E66ED201EC7D0FB00FECB44 /* AppDelegate.swift */; }; 16 | 2E66ED251EC7D0FB00FECB44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2E66ED241EC7D0FB00FECB44 /* Assets.xcassets */; }; 17 | 2E66ED281EC7D0FB00FECB44 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2E66ED261EC7D0FB00FECB44 /* Main.storyboard */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 2E6186EB1EC7D32500E999AF /* EventMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = ""; }; 22 | 2E6186ED1EC7E57800E999AF /* SinePlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SinePlayer.swift; sourceTree = ""; }; 23 | 2E6186EF1EC8006400E999AF /* Tone.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tone.swift; sourceTree = ""; }; 24 | 2E6186F11EC9276500E999AF /* MidiPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MidiPlayer.swift; sourceTree = ""; }; 25 | 2E6186F31EC9294600E999AF /* gs_instruments.dls */ = {isa = PBXFileReference; lastKnownFileType = file; path = gs_instruments.dls; sourceTree = ""; }; 26 | 2E66ED1D1EC7D0FB00FECB44 /* R2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = R2.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 2E66ED201EC7D0FB00FECB44 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 28 | 2E66ED241EC7D0FB00FECB44 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | 2E66ED271EC7D0FB00FECB44 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 2E66ED291EC7D0FB00FECB44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 2E66ED1A1EC7D0FB00FECB44 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 2E66ED141EC7D0FB00FECB44 = { 45 | isa = PBXGroup; 46 | children = ( 47 | 2E66ED1F1EC7D0FB00FECB44 /* r2 */, 48 | 2E66ED1E1EC7D0FB00FECB44 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 2E66ED1E1EC7D0FB00FECB44 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 2E66ED1D1EC7D0FB00FECB44 /* R2.app */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 2E66ED1F1EC7D0FB00FECB44 /* r2 */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 2E6186F31EC9294600E999AF /* gs_instruments.dls */, 64 | 2E66ED201EC7D0FB00FECB44 /* AppDelegate.swift */, 65 | 2E66ED241EC7D0FB00FECB44 /* Assets.xcassets */, 66 | 2E66ED261EC7D0FB00FECB44 /* Main.storyboard */, 67 | 2E66ED291EC7D0FB00FECB44 /* Info.plist */, 68 | 2E6186EB1EC7D32500E999AF /* EventMonitor.swift */, 69 | 2E6186ED1EC7E57800E999AF /* SinePlayer.swift */, 70 | 2E6186EF1EC8006400E999AF /* Tone.swift */, 71 | 2E6186F11EC9276500E999AF /* MidiPlayer.swift */, 72 | ); 73 | path = r2; 74 | sourceTree = ""; 75 | }; 76 | /* End PBXGroup section */ 77 | 78 | /* Begin PBXNativeTarget section */ 79 | 2E66ED1C1EC7D0FB00FECB44 /* R2 */ = { 80 | isa = PBXNativeTarget; 81 | buildConfigurationList = 2E66ED2C1EC7D0FB00FECB44 /* Build configuration list for PBXNativeTarget "R2" */; 82 | buildPhases = ( 83 | 2E66ED191EC7D0FB00FECB44 /* Sources */, 84 | 2E66ED1A1EC7D0FB00FECB44 /* Frameworks */, 85 | 2E66ED1B1EC7D0FB00FECB44 /* Resources */, 86 | ); 87 | buildRules = ( 88 | ); 89 | dependencies = ( 90 | ); 91 | name = R2; 92 | productName = r2; 93 | productReference = 2E66ED1D1EC7D0FB00FECB44 /* R2.app */; 94 | productType = "com.apple.product-type.application"; 95 | }; 96 | /* End PBXNativeTarget section */ 97 | 98 | /* Begin PBXProject section */ 99 | 2E66ED151EC7D0FB00FECB44 /* Project object */ = { 100 | isa = PBXProject; 101 | attributes = { 102 | LastSwiftUpdateCheck = 0830; 103 | LastUpgradeCheck = 0830; 104 | ORGANIZATIONNAME = "Philihp Busby"; 105 | TargetAttributes = { 106 | 2E66ED1C1EC7D0FB00FECB44 = { 107 | CreatedOnToolsVersion = 8.3.2; 108 | ProvisioningStyle = Automatic; 109 | }; 110 | }; 111 | }; 112 | buildConfigurationList = 2E66ED181EC7D0FB00FECB44 /* Build configuration list for PBXProject "r2" */; 113 | compatibilityVersion = "Xcode 8.0"; 114 | developmentRegion = English; 115 | hasScannedForEncodings = 0; 116 | knownRegions = ( 117 | en, 118 | Base, 119 | ); 120 | mainGroup = 2E66ED141EC7D0FB00FECB44; 121 | productRefGroup = 2E66ED1E1EC7D0FB00FECB44 /* Products */; 122 | projectDirPath = ""; 123 | projectRoot = ""; 124 | targets = ( 125 | 2E66ED1C1EC7D0FB00FECB44 /* R2 */, 126 | ); 127 | }; 128 | /* End PBXProject section */ 129 | 130 | /* Begin PBXResourcesBuildPhase section */ 131 | 2E66ED1B1EC7D0FB00FECB44 /* Resources */ = { 132 | isa = PBXResourcesBuildPhase; 133 | buildActionMask = 2147483647; 134 | files = ( 135 | 2E66ED251EC7D0FB00FECB44 /* Assets.xcassets in Resources */, 136 | 2E6186F41EC9294C00E999AF /* gs_instruments.dls in Resources */, 137 | 2E66ED281EC7D0FB00FECB44 /* Main.storyboard in Resources */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXSourcesBuildPhase section */ 144 | 2E66ED191EC7D0FB00FECB44 /* Sources */ = { 145 | isa = PBXSourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 2E6186EC1EC7D32500E999AF /* EventMonitor.swift in Sources */, 149 | 2E6186F01EC8006400E999AF /* Tone.swift in Sources */, 150 | 2E6186F21EC9276500E999AF /* MidiPlayer.swift in Sources */, 151 | 2E66ED211EC7D0FB00FECB44 /* AppDelegate.swift in Sources */, 152 | 2E6186EE1EC7E57800E999AF /* SinePlayer.swift in Sources */, 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | }; 156 | /* End PBXSourcesBuildPhase section */ 157 | 158 | /* Begin PBXVariantGroup section */ 159 | 2E66ED261EC7D0FB00FECB44 /* Main.storyboard */ = { 160 | isa = PBXVariantGroup; 161 | children = ( 162 | 2E66ED271EC7D0FB00FECB44 /* Base */, 163 | ); 164 | name = Main.storyboard; 165 | sourceTree = ""; 166 | }; 167 | /* End PBXVariantGroup section */ 168 | 169 | /* Begin XCBuildConfiguration section */ 170 | 2E66ED2A1EC7D0FB00FECB44 /* Debug */ = { 171 | isa = XCBuildConfiguration; 172 | buildSettings = { 173 | ALWAYS_SEARCH_USER_PATHS = NO; 174 | CLANG_ANALYZER_NONNULL = YES; 175 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 176 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 177 | CLANG_CXX_LIBRARY = "libc++"; 178 | CLANG_ENABLE_MODULES = YES; 179 | CLANG_ENABLE_OBJC_ARC = YES; 180 | CLANG_WARN_BOOL_CONVERSION = YES; 181 | CLANG_WARN_CONSTANT_CONVERSION = YES; 182 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 183 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 184 | CLANG_WARN_EMPTY_BODY = YES; 185 | CLANG_WARN_ENUM_CONVERSION = YES; 186 | CLANG_WARN_INFINITE_RECURSION = YES; 187 | CLANG_WARN_INT_CONVERSION = YES; 188 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 189 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 190 | CLANG_WARN_UNREACHABLE_CODE = YES; 191 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 192 | CODE_SIGN_IDENTITY = "-"; 193 | COPY_PHASE_STRIP = NO; 194 | DEBUG_INFORMATION_FORMAT = dwarf; 195 | ENABLE_STRICT_OBJC_MSGSEND = YES; 196 | ENABLE_TESTABILITY = YES; 197 | GCC_C_LANGUAGE_STANDARD = gnu99; 198 | GCC_DYNAMIC_NO_PIC = NO; 199 | GCC_NO_COMMON_BLOCKS = YES; 200 | GCC_OPTIMIZATION_LEVEL = 0; 201 | GCC_PREPROCESSOR_DEFINITIONS = ( 202 | "DEBUG=1", 203 | "$(inherited)", 204 | ); 205 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 206 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 207 | GCC_WARN_UNDECLARED_SELECTOR = YES; 208 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 209 | GCC_WARN_UNUSED_FUNCTION = YES; 210 | GCC_WARN_UNUSED_VARIABLE = YES; 211 | MACOSX_DEPLOYMENT_TARGET = 10.12; 212 | MTL_ENABLE_DEBUG_INFO = YES; 213 | ONLY_ACTIVE_ARCH = YES; 214 | SDKROOT = macosx; 215 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 216 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 217 | }; 218 | name = Debug; 219 | }; 220 | 2E66ED2B1EC7D0FB00FECB44 /* Release */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | ALWAYS_SEARCH_USER_PATHS = NO; 224 | CLANG_ANALYZER_NONNULL = YES; 225 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 226 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 227 | CLANG_CXX_LIBRARY = "libc++"; 228 | CLANG_ENABLE_MODULES = YES; 229 | CLANG_ENABLE_OBJC_ARC = YES; 230 | CLANG_WARN_BOOL_CONVERSION = YES; 231 | CLANG_WARN_CONSTANT_CONVERSION = YES; 232 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 233 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 234 | CLANG_WARN_EMPTY_BODY = YES; 235 | CLANG_WARN_ENUM_CONVERSION = YES; 236 | CLANG_WARN_INFINITE_RECURSION = YES; 237 | CLANG_WARN_INT_CONVERSION = YES; 238 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 239 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 240 | CLANG_WARN_UNREACHABLE_CODE = YES; 241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 242 | CODE_SIGN_IDENTITY = "-"; 243 | COPY_PHASE_STRIP = NO; 244 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 245 | ENABLE_NS_ASSERTIONS = NO; 246 | ENABLE_STRICT_OBJC_MSGSEND = YES; 247 | GCC_C_LANGUAGE_STANDARD = gnu99; 248 | GCC_NO_COMMON_BLOCKS = YES; 249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 251 | GCC_WARN_UNDECLARED_SELECTOR = YES; 252 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 253 | GCC_WARN_UNUSED_FUNCTION = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | MACOSX_DEPLOYMENT_TARGET = 10.12; 256 | MTL_ENABLE_DEBUG_INFO = NO; 257 | SDKROOT = macosx; 258 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 259 | }; 260 | name = Release; 261 | }; 262 | 2E66ED2D1EC7D0FB00FECB44 /* Debug */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 266 | CODE_SIGN_IDENTITY = "Mac Developer"; 267 | COMBINE_HIDPI_IMAGES = YES; 268 | DEVELOPMENT_TEAM = EZSQLEUL4D; 269 | INFOPLIST_FILE = r2/Info.plist; 270 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 271 | PRODUCT_BUNDLE_IDENTIFIER = com.philihp.r2; 272 | PRODUCT_NAME = "$(TARGET_NAME)"; 273 | PROVISIONING_PROFILE_SPECIFIER = ""; 274 | SWIFT_VERSION = 3.0; 275 | }; 276 | name = Debug; 277 | }; 278 | 2E66ED2E1EC7D0FB00FECB44 /* Release */ = { 279 | isa = XCBuildConfiguration; 280 | buildSettings = { 281 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 282 | CODE_SIGN_IDENTITY = "Mac Developer"; 283 | COMBINE_HIDPI_IMAGES = YES; 284 | DEVELOPMENT_TEAM = EZSQLEUL4D; 285 | INFOPLIST_FILE = r2/Info.plist; 286 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 287 | PRODUCT_BUNDLE_IDENTIFIER = com.philihp.r2; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | PROVISIONING_PROFILE_SPECIFIER = ""; 290 | SWIFT_VERSION = 3.0; 291 | }; 292 | name = Release; 293 | }; 294 | /* End XCBuildConfiguration section */ 295 | 296 | /* Begin XCConfigurationList section */ 297 | 2E66ED181EC7D0FB00FECB44 /* Build configuration list for PBXProject "r2" */ = { 298 | isa = XCConfigurationList; 299 | buildConfigurations = ( 300 | 2E66ED2A1EC7D0FB00FECB44 /* Debug */, 301 | 2E66ED2B1EC7D0FB00FECB44 /* Release */, 302 | ); 303 | defaultConfigurationIsVisible = 0; 304 | defaultConfigurationName = Release; 305 | }; 306 | 2E66ED2C1EC7D0FB00FECB44 /* Build configuration list for PBXNativeTarget "R2" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 2E66ED2D1EC7D0FB00FECB44 /* Debug */, 310 | 2E66ED2E1EC7D0FB00FECB44 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | /* End XCConfigurationList section */ 316 | }; 317 | rootObject = 2E66ED151EC7D0FB00FECB44 /* Project object */; 318 | } 319 | -------------------------------------------------------------------------------- /r2.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /r2.xcodeproj/project.xcworkspace/xcuserdata/phil_busby.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philihp/R2/fcb320989929e82ffa85f548621e5e38180e9882/r2.xcodeproj/project.xcworkspace/xcuserdata/phil_busby.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /r2.xcodeproj/project.xcworkspace/xcuserdata/phil_busby.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /r2.xcodeproj/xcuserdata/phil_busby.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /r2.xcodeproj/xcuserdata/phil_busby.xcuserdatad/xcschemes/Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /r2.xcodeproj/xcuserdata/phil_busby.xcuserdatad/xcschemes/Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /r2.xcodeproj/xcuserdata/phil_busby.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Debug.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | Release.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 2E66ED1C1EC7D0FB00FECB44 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /r2/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // r2 4 | // 5 | // Created by Philihp Busby on 2017-05-13. 6 | // Copyright © 2017 Philihp Busby. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import AppKit 11 | 12 | @NSApplicationMain 13 | class AppDelegate: NSObject, NSApplicationDelegate { 14 | 15 | var monitor: EventMonitor? 16 | let sinePlayer = SinePlayer() 17 | let midiPlayer = MidiPlayer() 18 | 19 | func applicationDidFinishLaunching(_ aNotification: Notification) { 20 | trust() 21 | monitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown, .keyDown, .keyUp]) { (event) in 22 | 23 | // using the sine player, you get annoying little pops at the end and beginning of all of the samples. 24 | //self.sinePlayer.tone = Tone.rand().rawValue 25 | //let tone = UInt8(arc4random_uniform(128)) 26 | 27 | //let chord: [UInt8] = [0, 2, 4, 5, 7, 9, 11] 28 | //let randomIndex = Int(arc4random_uniform(UInt32(chord.count))) 29 | let note = UInt8(arc4random_uniform(20) + 60) 30 | let time = Int(arc4random_uniform(2)+1) 31 | 32 | self.midiPlayer.sampler.startNote(note, withVelocity: 127, onChannel: 0) 33 | Timer.scheduledTimer(withTimeInterval: Double(time) / 8, repeats: false) { timer in 34 | self.midiPlayer.sampler.stopNote(note, onChannel: 0) 35 | } 36 | } 37 | monitor?.start() 38 | } 39 | 40 | func applicationWillTerminate(_ aNotification: Notification) { 41 | monitor = nil 42 | } 43 | 44 | func trust() { 45 | let trusted = kAXTrustedCheckOptionPrompt.takeUnretainedValue() as NSString 46 | let privOptions = [trusted: true] 47 | AXIsProcessTrustedWithOptions(privOptions as CFDictionary?) 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /r2/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "size" : "512x512", 50 | "idiom" : "mac", 51 | "filename" : "r2x1024.png", 52 | "scale" : "2x" 53 | } 54 | ], 55 | "info" : { 56 | "version" : 1, 57 | "author" : "xcode" 58 | } 59 | } -------------------------------------------------------------------------------- /r2/Assets.xcassets/AppIcon.appiconset/r2x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philihp/R2/fcb320989929e82ffa85f548621e5e38180e9882/r2/Assets.xcassets/AppIcon.appiconset/r2x1024.png -------------------------------------------------------------------------------- /r2/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | }, 6 | "properties" : { 7 | "compression-type" : "lossless" 8 | } 9 | } -------------------------------------------------------------------------------- /r2/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /r2/EventMonitor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EventMonitor.swift 3 | // r2 4 | // 5 | // Created by Philihp Busby on 2017-05-13. 6 | // Copyright © 2017 Philihp Busby. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AppKit 11 | 12 | public class EventMonitor { 13 | private var monitor: Any? 14 | private let mask: NSEventMask 15 | public typealias EventHandler = (NSEvent?) -> () 16 | private let handler: EventHandler 17 | 18 | public init(mask: NSEventMask, handler: @escaping EventHandler) { 19 | self.mask = mask 20 | self.handler = handler 21 | } 22 | 23 | deinit { 24 | stop() 25 | } 26 | 27 | public func start() { 28 | monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) 29 | } 30 | 31 | public func stop() { 32 | if let monitor = monitor { 33 | NSEvent.removeMonitor(monitor) 34 | self.monitor = nil 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /r2/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | R2 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSApplicationCategoryType 24 | public.app-category.entertainment 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2017 Philihp Busby. All rights reserved. 29 | NSMainStoryboardFile 30 | Main 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /r2/MidiPlayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MidiPlayer.swift 3 | // http://stackoverflow.com/questions/33920157/playing-a-single-midi-note-from-gs-instruments-in-ios-swift 4 | // 5 | // Created by Philihp Busby on 2017-05-14. 6 | // Copyright © 2017 Philihp Busby. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AVFoundation 11 | 12 | class MidiPlayer { 13 | 14 | public let engine = AVAudioEngine() 15 | public let sampler = AVAudioUnitSampler() 16 | 17 | init() { 18 | 19 | engine.attach(self.sampler) 20 | engine.connect(self.sampler, to: engine.outputNode, format: nil) 21 | 22 | guard let soundbank = Bundle.main.url(forResource: "gs_instruments", withExtension: "dls") else { 23 | print("Could not initalize soundbank.") 24 | return 25 | } 26 | 27 | let patch:UInt8 = 81 28 | let bank:UInt8 = UInt8(kAUSampler_DefaultBankLSB)//UInt8(kAUSampler_DefaultMelodicBankMSB)// 29 | do { 30 | 31 | try engine.start() 32 | try self.sampler.loadSoundBankInstrument(at: soundbank, program: patch, bankMSB: bank, bankLSB: 0) 33 | 34 | } catch { 35 | print("An error occurred \(error)") 36 | return 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /r2/SinePlayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SinePlayer.swift 3 | // from: http://www.tmroyal.com/playing-sounds-in-swift-audioengine.html 4 | // 5 | 6 | import AVFoundation 7 | 8 | class SinePlayer { 9 | // store persistent objects 10 | var engine: AVAudioEngine 11 | var player: AVAudioPlayerNode 12 | 13 | public var tone: Float = 441.0 { 14 | didSet { 15 | print(tone) 16 | player.scheduleBuffer(makeBuffer(note: tone), at: nil, options: .interruptsAtLoop, completionHandler: nil) 17 | } 18 | } 19 | 20 | init() { 21 | // initialize objects 22 | engine = AVAudioEngine() 23 | player = AVAudioPlayerNode() 24 | 25 | // setup audio engine 26 | engine.attach(player) 27 | engine.connect(player, to: engine.mainMixerNode, format: player.outputFormat(forBus: 0)) 28 | 29 | do { 30 | try engine.start() 31 | player.play() 32 | } 33 | catch _ {} 34 | } 35 | 36 | func makeBuffer(note: Float) -> AVAudioPCMBuffer { 37 | let buffer = AVAudioPCMBuffer(pcmFormat: player.outputFormat(forBus: 0), frameCapacity: 2000) 38 | buffer.frameLength = 2000 39 | // generate sine wave 40 | let sr:Float = Float(engine.mainMixerNode.outputFormat(forBus: 0).sampleRate) 41 | let n_channels = engine.mainMixerNode.outputFormat(forBus: 0).channelCount 42 | 43 | var i = 0 44 | while(i < Int(buffer.frameLength)) { 45 | let val = sinf(tone * Float(i) * 2 * Float(Double.pi)/sr) 46 | if let fcd = buffer.floatChannelData { 47 | fcd.pointee[i] = val * 0.5 48 | } 49 | i += Int(n_channels) 50 | } 51 | return buffer 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /r2/Tone.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tone.swift 3 | // http://www.phy.mtu.edu/~suits/notefreqs.html 4 | // 5 | // Created by Philihp Busby on 2017-05-13. 6 | // Copyright © 2017 Philihp Busby. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum Tone: Float { 12 | case C0 = 16.35 13 | case C0sh = 17.32 14 | case D0 = 18.35 15 | case D0sh = 19.45 16 | case E0 = 20.60 17 | case F0 = 21.83 18 | case F0sh = 23.12 19 | case G0 = 24.50 20 | case G0sh = 25.96 21 | case A0 = 27.50 22 | case A0sh = 29.14 23 | case B0 = 30.87 24 | case C1 = 32.70 25 | case C1sh = 34.65 26 | case D1 = 36.71 27 | case D1sh = 38.89 28 | case E1 = 41.20 29 | case F1 = 43.65 30 | case F1sh = 46.25 31 | case G1 = 49.00 32 | case G1sh = 51.91 33 | case A1 = 55.00 34 | case A1sh = 58.27 35 | case B1 = 61.74 36 | case C2 = 65.41 37 | case C2sh = 69.30 38 | case D2 = 73.42 39 | case D2sh = 77.78 40 | case E2 = 82.41 41 | case F2 = 87.31 42 | case F2sh = 92.50 43 | case G2 = 98.00 44 | case G2sh = 103.83 45 | case A2 = 110.00 46 | case A2sh = 116.54 47 | case B2 = 123.47 48 | case C3 = 130.81 49 | case C3sh = 138.59 50 | case D3 = 146.83 51 | case D3sh = 155.56 52 | case E3 = 164.81 53 | case F3 = 174.61 54 | case F3sh = 185.00 55 | case G3 = 196.00 56 | case G3sh = 207.65 57 | case A3 = 220.00 58 | case A3sh = 233.08 59 | case B3 = 246.94 60 | case C4 = 261.63 61 | case C4sh = 277.18 62 | case D4 = 293.66 63 | case D4sh = 311.13 64 | case E4 = 329.63 65 | case F4 = 349.23 66 | case F4sh = 369.99 67 | case G4 = 392.00 68 | case G4sh = 415.30 69 | case A4 = 440.00 70 | case A4sh = 466.16 71 | case B4 = 493.88 72 | case C5 = 523.25 73 | case C5sh = 554.37 74 | case D5 = 587.33 75 | case D5sh = 622.25 76 | case E5 = 659.25 77 | case F5 = 698.46 78 | case F5sh = 739.99 79 | case G5 = 783.99 80 | case G5sh = 830.61 81 | case A5 = 880.00 82 | case A5sh = 932.33 83 | case B5 = 987.77 84 | case C6 = 1046.50 85 | case C6sh = 1108.73 86 | case D6 = 1174.66 87 | case D6sh = 1244.51 88 | case E6 = 1318.51 89 | case F6 = 1396.91 90 | case F6sh = 1479.98 91 | case G6 = 1567.98 92 | case G6sh = 1661.22 93 | case A6 = 1760.00 94 | case A6sh = 1864.66 95 | case B6 = 1975.53 96 | case C7 = 2093.00 97 | case C7sh = 2217.46 98 | case D7 = 2349.32 99 | case D7sh = 2489.02 100 | case E7 = 2637.02 101 | case F7 = 2793.83 102 | case F7sh = 2959.96 103 | case G7 = 3135.96 104 | case G7sh = 3322.44 105 | case A7 = 3520.00 106 | case A7sh = 3729.31 107 | case B7 = 3951.07 108 | case C8 = 4186.01 109 | case C8sh = 4434.92 110 | case D8 = 4698.63 111 | case D8sh = 4978.03 112 | case E8 = 5274.04 113 | case F8 = 5587.65 114 | case F8sh = 5919.91 115 | case G8 = 6271.93 116 | case G8sh = 6644.88 117 | case A8 = 7040.00 118 | case A8sh = 7458.62 119 | case B8 = 7902.13 120 | 121 | public static func rand() -> Tone { 122 | let tones:[Tone] = 123 | [ 124 | // .C0, .C0sh, .D0, .D0sh, .E0, .F0, .F0sh, .G0, .G0sh, .A0, .A0sh, .B0, 125 | // .C1, .C1sh, .D1, .D1sh, .E1, .F1, .F1sh, .G1, .G1sh, .A1, .A1sh, .B1, 126 | // .C2, .C2sh, .D2, .D2sh, .E2, .F2, .F2sh, .G2, .G2sh, .A2, .A2sh, .B2, 127 | .C3, .C3sh, .D3, .D3sh, .E3, .F3, .F3sh, .G3, .G3sh, .A3, .A3sh, .B3, 128 | .C4, .C4sh, .D4, .D4sh, .E4, .F4, .F4sh, .G4, .G4sh, .A4, .A4sh, .B4, 129 | .C5, .C5sh, .D5, .D5sh, .E5, .F5, .F5sh, .G5, .G5sh, .A5, .A5sh, .B5 130 | // .C6, .C6sh, .D6, .D6sh, .E6, .F6, .F6sh, .G6, .G6sh, .A6, .A6sh, .B6, 131 | // .C7, .C7sh, .D7, .D7sh, .E7, .F7, .F7sh, .G7, .G7sh, .A7, .A7sh, .B7, 132 | // .C8, .C8sh, .D8, .D8sh, .E8, .F8, .F8sh, .G8, .G8sh, .A8, .A8sh, .B8 133 | ] 134 | let randomIndex = Int(arc4random_uniform(UInt32(tones.count))) 135 | return tones[randomIndex] 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /r2/gs_instruments.dls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philihp/R2/fcb320989929e82ffa85f548621e5e38180e9882/r2/gs_instruments.dls --------------------------------------------------------------------------------