Saturday, May 13, 2017

Mac Technique: External keyboard configuration for Home and End keys

To configure the [Home] and [End] keys of an external USB keyboard to move the cursor to the front or the end of line in Xcode, try:

1. create the following path:

~/Library/KeyBindings/

2. Create a file called DefaultKeyBinding.dict in this directory with:

{
    "\UF729" = moveToBeginningOfParagraph:; // home
    "\UF72B" = moveToEndOfParagraph:; // end
    "$\UF729" = moveToBeginningOfParagraphAndModifySelection:; // shift-home
    "$\UF72B" = moveToEndOfParagraphAndModifySelection:; // shift-end
}

With this solution, holding a [Shift] key and [Home]/[End] makes a selection for the characters to the beginning or end of the line.

References:

Remap “Home” and “End” to beginning and end of line
Mac OS X and Home / End keys

Sunday, May 7, 2017

Modified Version of AudioKit's Microphone Analysis Example without using the Storyboard

The code below is modified from AudioKit's Microphone Analysis example. The UI components are written programmatically without using the storyboard. The code is developed with Xcode 8.3.2 (Swift 3.1) and iOS 10.

1. Use CocoaPods to include the AudioKit framework by add this line to the Podfile:

pod 'AudioKit'

*************** Updated October 4, 2020 for AudioKit 4 *****************
Type this terminal command:

pod install



*************************** Update 2020 End *****************************

2. Enable the microphone by adding NSMicrophoneUsageDescription and a request string such as "This app needs microphone access." to Info.plist.

Your Info.plist should be like this:


When app is run at the first time, this message should be displayed:



Without this modification, you'll see error like this:


This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSMicrophoneUsageDescription key with a string value explaining to the user how the app uses this data.

3. Modify ViewController.swift as below

import UIKit
import AudioKit

class ViewController: UIViewController {
    
    var labelFrequencyValue : UILabel!
    var labelAmplitudeValue : UILabel!
    var labelSharpValue : UILabel!
    var labelFlatValue : UILabel!
    let mic = AKMicrophone()
    var tracker : AKFrequencyTracker!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let labelSing = UILabel(frame: CGRect(x: 0, y: 28, width: view.frame.width, height: 50))
        labelSing.text = "Sing into the Microphone"
        labelSing.textAlignment = .center
        labelSing.font = UIFont.systemFont(ofSize: 24, weight: UIFontWeightBold) //System Font Bold
        labelSing.textColor = UIColor.white
        labelSing.backgroundColor = UIColor(red: 2/255, green: 181/255, blue: 31/255, alpha: 1.0)
        view.addSubview(labelSing)
        
        let labelFrequency = UILabel(frame: CGRect(x: 16, y: 86, width: 85.5, height: 20.5))
        labelFrequency.text = "Frequency:"
        view.addSubview(labelFrequency)
        
        labelFrequencyValue = UILabel(frame: CGRect(x: view.frame.width-70, y: 86, width: 50, height: 20.5))
        labelFrequencyValue.text = "0"
        labelFrequencyValue.textAlignment = .right
        view.addSubview(labelFrequencyValue)
        
        let labelAmplitude = UILabel(frame: CGRect(x: 16, y: 114.5, width: 85.5, height: 20.5))
        labelAmplitude.text = "Amplitude:"
        view.addSubview(labelAmplitude)
        
        labelAmplitudeValue = UILabel(frame: CGRect(x: view.frame.width-70, y: 114.5, width: 50, height: 20.5))
        labelAmplitudeValue.text = "0"
        labelAmplitudeValue.textAlignment = .right
        view.addSubview(labelAmplitudeValue)
        
        let labelSharp = UILabel(frame: CGRect(x: 16, y: 142, width: 111.5, height: 20.5))
        labelSharp.text = "Note (Sharps):"
        view.addSubview(labelSharp)
        
        labelSharpValue = UILabel(frame: CGRect(x: view.frame.width-70, y: 142, width: 50, height: 20.5))
        labelSharpValue.text = "C4"
        labelSharpValue.textAlignment = .right
        view.addSubview(labelSharpValue)
        
        let labelFlat = UILabel(frame: CGRect(x: 16, y: 170.5, width: 94, height: 20.5))
        labelFlat.text = "Note (Flats):"
        view.addSubview(labelFlat)
        
        labelFlatValue = UILabel(frame: CGRect(x: view.frame.width-70, y: 170.5, width: 50, height: 20.5))
        labelFlatValue.text = "F4"
        labelFlatValue.textAlignment = .right
        view.addSubview(labelFlatValue)
        
        let labelPlot = UILabel(frame: CGRect(x: 0, y: 199, width: view.frame.width, height: 21.5))
        labelPlot.text = "Audio Input Plot"
        labelPlot.textAlignment = .center
        view.addSubview(labelPlot)
        

        tracker = AKFrequencyTracker.init(mic)
        let silence = AKBooster(tracker, gain: 0)
        AudioKit.output = silence
        AudioKit.start()
        
        setupPlot()
        
        Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateUI), userInfo: nil, repeats: true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func setupPlot() {
        let audioInputPlot = EZAudioPlot(frame: CGRect(x: 0, y: view.center.y, width: view.frame.width, height: 200))
        
        let plot = AKNodeOutputPlot(mic, frame: audioInputPlot.bounds)
        plot.plotType = .rolling
        plot.shouldFill = true
        plot.shouldMirror = true
        plot.color = UIColor.blue
        audioInputPlot.addSubview(plot)
        view.addSubview(audioInputPlot)
    }
    
    func updateUI() {
        
        let noteFrequencies = [16.35,17.32,18.35,19.45,20.6,21.83,23.12,24.5,25.96,27.5,29.14,30.87]
        let noteNamesWithSharps = ["C", "C♯","D","D♯","E","F","F♯","G","G♯","A","A♯","B"]
        let noteNamesWithFlats = ["C", "D♭","D","E♭","E","F","G♭","G","A♭","A","B♭","B"]
        
        if tracker.amplitude > 0.1 {
            labelFrequencyValue.text = String(format: "%0.1f", tracker.frequency)
        
            var frequency = Float(tracker.frequency)
            while (frequency > Float(noteFrequencies[noteFrequencies.count-1])){
                frequency = frequency / 2.0
            }
            while (frequency < Float(noteFrequencies[0])) {
                frequency = frequency * 2.0
            }
            
            var minDistance : Float = 10000.0
            var index = 0
            
            for i in 0..<noteFrequencies.count {
                let distance = fabsf(Float(noteFrequencies[i]) - frequency)
                if (distance < minDistance) {
                    index = i
                    minDistance = distance
                }
            }
            let octave = Int(log2f(Float(tracker.frequency) / frequency))
            labelSharpValue.text = "\(noteNamesWithSharps[index])\(octave)"
            labelFlatValue.text = "\(noteNamesWithFlats[index])\(octave)"
        }
        labelAmplitudeValue.text = String(format: "%0.2f", tracker.amplitude)
    }

}

4. Result:



Related Information

AudioKit
Beethoven (Pitch Detection)




Monday, May 1, 2017

UIButton - Update button label when pressed

This post shows how to change the text/title of a button every time the button is pressed.
The code below is written in Swift 3.1 with Xcode 8.3.2 and tested with iOS 10.3.1.

Code:

import UIKit

class ViewController: UIViewController {
    
    var count : Int = 1
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
        button.center = view.center
        button.setTitle("Press", for: UIControlState.normal)
        button.setTitleColor(UIColor.blue, for: UIControlState.normal)
        button.setTitleColor(UIColor.cyan, for: UIControlState.highlighted)
        button.addTarget(self, action: #selector(buttonPressed(sender:)), for: UIControlEvents.touchUpInside)
        view.addSubview(button)
    }
    
    func buttonPressed(sender: UIButton) {
        sender.setTitle("Pressed \(count)", for: UIControlState.normal)
        count = count+1
        print("button pressed!!")
    }
}

Reference:

UIButton - Selector Warning (Update with Swift 3.1)

Sunday, March 12, 2017

Mac Technique: Hotkey to enable Mac's dictionary

To look up a word in Mac's dictionary, highlight the word and press the hotkey:
啟動Mac內建字典的快捷鍵:

[control] + [command ⌘] + [D]

To add a new Traditional Chinese-English dictionary for users in Taiwan or Hong Kong, refer to this:

「教學」Mac 內建字典安裝繁體英漢辭典

Monday, January 30, 2017

Mac Technique: Save Photos from iPhone in a Mac folder with correct date and time information in

While directly dragging photos from a Mac's Photos app to a Finder folder, the date and time that the photos were taken cannot be preserved. Here is the solution to keep the correct date and time of photos:

1. Import photos from an iPhone using the Photos app on a Mac.

2. Select photos and select File -> Export -> Export Unmodified Original For ## Items...


3. Select the folder to export the files.

Tuesday, January 17, 2017

Mac Technique: Steps to Create a Bootable macOS Installer on a USB drive

This post shows how to create a bootable USB drive for macOS Sierra installation. The USB drive was created with a MacBook Pro running OS X 10.8.5 (Mountain Lion), which was installed on a clean SSD by holding down the option key during the first boot after swapping the Mac's hard drive with the SSD.

The steps to create the bootable macOS USB installer are as below:

The original OS X version is Mountain Lion 10.8.5.

Go to the Mac's App Store and get the latest macOS.

Quit the macOS installer.

The installer may be found in the Applications folder of Finder:
Application\Install macOS Sierra

Open the terminal and type this command:

sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/MyUSB/ --applicationpath /Applications/Install\ macOS\ Sierra.app/

For other paths for USB drive or  Sierra.app or for installing other OS X versions, refer to Apple's official document: Create a bootable installer for macOS.


Now the USB drive has been successfully formatted as a bootable macOS installer.

Reference:

Create a bootable installer for macOS