Skip to content

Commit

Permalink
Add reverb and distortion controls
Browse files Browse the repository at this point in the history
  • Loading branch information
vadymmarkov committed Jan 28, 2019
1 parent b003873 commit 0bfab32
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 189 deletions.
34 changes: 25 additions & 9 deletions Piano.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

/* Begin PBXBuildFile section */
CF20864721FA43EF007BECDC /* PianoEffectControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF20864621FA43EF007BECDC /* PianoEffectControl.swift */; };
CF20864921FA56EA007BECDC /* UIView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF20864821FA56EA007BECDC /* UIView+Layout.swift */; };
CF20864921FA56EA007BECDC /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF20864821FA56EA007BECDC /* UIView+Extensions.swift */; };
CF4A051F21FA85EE000BB7DA /* PianoSliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF4A051E21FA85EE000BB7DA /* PianoSliderView.swift */; };
CF4A052121FA86D3000BB7DA /* PianoEffectIndicatorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF4A052021FA86D3000BB7DA /* PianoEffectIndicatorsView.swift */; };
CF4A052321FB141B000BB7DA /* PianoEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF4A052221FB141B000BB7DA /* PianoEffectView.swift */; };
CFB13DAE21FF268500F8D126 /* CGFloat+Spacing.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFB13DAD21FF268500F8D126 /* CGFloat+Spacing.swift */; };
DAF51E5321AE02E300C1AAEC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF51E5221AE02E300C1AAEC /* AppDelegate.swift */; };
DAF51E5821AE02E300C1AAEC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAF51E5621AE02E300C1AAEC /* Main.storyboard */; };
DAF51E5A21AE02E400C1AAEC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAF51E5921AE02E400C1AAEC /* Assets.xcassets */; };
Expand All @@ -25,9 +27,11 @@

/* Begin PBXFileReference section */
CF20864621FA43EF007BECDC /* PianoEffectControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PianoEffectControl.swift; sourceTree = "<group>"; };
CF20864821FA56EA007BECDC /* UIView+Layout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Layout.swift"; sourceTree = "<group>"; };
CF20864821FA56EA007BECDC /* UIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = "<group>"; };
CF4A051E21FA85EE000BB7DA /* PianoSliderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PianoSliderView.swift; sourceTree = "<group>"; };
CF4A052021FA86D3000BB7DA /* PianoEffectIndicatorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PianoEffectIndicatorsView.swift; sourceTree = "<group>"; };
CF4A052221FB141B000BB7DA /* PianoEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PianoEffectView.swift; sourceTree = "<group>"; };
CFB13DAD21FF268500F8D126 /* CGFloat+Spacing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGFloat+Spacing.swift"; sourceTree = "<group>"; };
DAF51E4F21AE02E300C1AAEC /* Piano.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Piano.app; sourceTree = BUILT_PRODUCTS_DIR; };
DAF51E5221AE02E300C1AAEC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
DAF51E5721AE02E300C1AAEC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
Expand Down Expand Up @@ -59,12 +63,22 @@
isa = PBXGroup;
children = (
CF20864621FA43EF007BECDC /* PianoEffectControl.swift */,
CF4A051E21FA85EE000BB7DA /* PianoSliderView.swift */,
CF4A052021FA86D3000BB7DA /* PianoEffectIndicatorsView.swift */,
CF4A052221FB141B000BB7DA /* PianoEffectView.swift */,
CF4A051E21FA85EE000BB7DA /* PianoSliderView.swift */,
);
path = EffectControl;
sourceTree = "<group>";
};
CFB13DAC21FF25CC00F8D126 /* Keyboard */ = {
isa = PBXGroup;
children = (
DAF51E6B21AE034800C1AAEC /* PianoKeyView.swift */,
DAF51E6C21AE034800C1AAEC /* PianoView.swift */,
);
path = Keyboard;
sourceTree = "<group>";
};
DAF51E4621AE02E300C1AAEC = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -125,9 +139,8 @@
DAF51E6A21AE034800C1AAEC /* Views */ = {
isa = PBXGroup;
children = (
CFB13DAC21FF25CC00F8D126 /* Keyboard */,
CF4A051D21FA85D9000BB7DA /* EffectControl */,
DAF51E6B21AE034800C1AAEC /* PianoKeyView.swift */,
DAF51E6C21AE034800C1AAEC /* PianoView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand All @@ -138,7 +151,8 @@
DAF51E7221AE054600C1AAEC /* UIColor+RGB.swift */,
DAF51E7821AE099500C1AAEC /* AVAudioSession+Swift.h */,
DAF51E7921AE099500C1AAEC /* AVAudioSession+Swift.m */,
CF20864821FA56EA007BECDC /* UIView+Layout.swift */,
CF20864821FA56EA007BECDC /* UIView+Extensions.swift */,
CFB13DAD21FF268500F8D126 /* CGFloat+Spacing.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -220,10 +234,12 @@
CF20864721FA43EF007BECDC /* PianoEffectControl.swift in Sources */,
DAF51E6D21AE034800C1AAEC /* ViewController.swift in Sources */,
CF4A051F21FA85EE000BB7DA /* PianoSliderView.swift in Sources */,
CFB13DAE21FF268500F8D126 /* CGFloat+Spacing.swift in Sources */,
DAF51E7321AE054600C1AAEC /* UIColor+RGB.swift in Sources */,
DAF51E6F21AE034800C1AAEC /* PianoKeyView.swift in Sources */,
CF20864921FA56EA007BECDC /* UIView+Layout.swift in Sources */,
CF20864921FA56EA007BECDC /* UIView+Extensions.swift in Sources */,
DAF51E7A21AE099500C1AAEC /* AVAudioSession+Swift.m in Sources */,
CF4A052321FB141B000BB7DA /* PianoEffectView.swift in Sources */,
DAF51E7021AE034800C1AAEC /* PianoView.swift in Sources */,
DAF51E5321AE02E300C1AAEC /* AppDelegate.swift in Sources */,
);
Expand Down Expand Up @@ -375,7 +391,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 2KM44359R3;
INFOPLIST_FILE = Piano/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -397,7 +413,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 2KM44359R3;
INFOPLIST_FILE = Piano/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
25 changes: 25 additions & 0 deletions Piano/Sources/Extensions/CGFloat+Spacing.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Copyright © FINN.no AS, Inc. All rights reserved.
//

import Foundation

public extension CGFloat {
/// Separation of 2 points.
static let verySmallSpacing: CGFloat = 2

/// Separation of 4 points.
static let smallSpacing: CGFloat = 4

/// Separation of 8 points.
static let mediumSpacing: CGFloat = 8

/// Separation of 16 points.
static let mediumLargeSpacing: CGFloat = 16

/// Separation of 32 points.
static let largeSpacing: CGFloat = 32

/// Separation of 64 points.
static let veryLargeSpacing: CGFloat = 64
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ extension UIView {

return constraints
}

convenience init(withAutoLayout autoLayout: Bool) {
self.init()
translatesAutoresizingMaskIntoConstraints = !autoLayout
}
}
117 changes: 52 additions & 65 deletions Piano/Sources/Piano/ViewController.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
//
// ViewController.swift
// Piano
//
// Created by Vadym Markov on 27/11/2018.
// Copyright © 2018 FINN.no. All rights reserved.
// Copyright © 2018 FINN AS. All rights reserved.
//

import UIKit
Expand All @@ -14,7 +10,6 @@ final class ViewController: UIViewController {
let octave: UInt8 = 5
let root: UInt8 = octave * 12
let numberOfNotesInOctave: UInt8 = 12

return (0..<numberOfNotesInOctave).map({ root + $0 })
}()

Expand All @@ -24,12 +19,12 @@ final class ViewController: UIViewController {
let audioEngine = AVAudioEngine()

audioEngine.attach(reverb)
audioEngine.attach(delay)
audioEngine.attach(distortion)
audioEngine.attach(sampler)

audioEngine.connect(sampler, to: reverb, format: nil)
audioEngine.connect(reverb, to: delay, format: nil)
audioEngine.connect(delay, to: audioEngine.mainMixerNode, format: nil)
audioEngine.connect(reverb, to: distortion, format: nil)
audioEngine.connect(distortion, to: audioEngine.mainMixerNode, format: nil)

return audioEngine
}()
Expand All @@ -41,37 +36,36 @@ final class ViewController: UIViewController {
return reverb
}()

private lazy var delay: AVAudioUnitDistortion = {
let delay = AVAudioUnitDistortion()
delay.loadFactoryPreset(.multiBrokenSpeaker)
delay.wetDryMix = 0
return delay
private lazy var distortion: AVAudioUnitDistortion = {
let distortion = AVAudioUnitDistortion()
distortion.loadFactoryPreset(.multiBrokenSpeaker)
distortion.wetDryMix = 0
return distortion
}()

private lazy var pianoView: PianoView = {
let pianoView = PianoView()
pianoView.translatesAutoresizingMaskIntoConstraints = false
// MARK: - Views

private lazy var pianoView: PianoKeyboardView = {
let pianoView = PianoKeyboardView(withAutoLayout: true)
pianoView.dataSource = self
pianoView.delegate = self
return pianoView
}()

private lazy var reverbControl: PianoEffectControl = {
let control = PianoEffectControl()
control.delegate = self
control.translatesAutoresizingMaskIntoConstraints = false
control.sliderColor = UIColor(r: 50, g: 162, b: 255)
control.titleLabel.text = "reverb"
return control
private lazy var reverbView: PianoEffectView = {
let view = PianoEffectView(withAutoLayout: true)
view.titleLabel.text = "reverb"
view.control.sliderColor = UIColor(r: 50, g: 162, b: 255)
view.control.delegate = self
return view
}()

private lazy var delayControl: PianoEffectControl = {
let control = PianoEffectControl()
control.delegate = self
control.translatesAutoresizingMaskIntoConstraints = false
control.sliderColor = UIColor(r: 255, g: 75, b: 0)
control.titleLabel.text = "delay"
return control
private lazy var distortionView: PianoEffectView = {
let view = PianoEffectView(withAutoLayout: true)
view.titleLabel.text = "distortion"
view.control.sliderColor = UIColor(r: 255, g: 75, b: 0)
view.control.delegate = self
return view
}()

// MARK: - Lifecycle
Expand All @@ -88,36 +82,28 @@ final class ViewController: UIViewController {
private func setup() {
view.backgroundColor = UIColor(r: 216, g: 219, b: 227)

view.addSubview(reverbView)
view.addSubview(distortionView)
view.addSubview(pianoView)
view.addSubview(reverbControl)
view.addSubview(delayControl)

let isPad = UIDevice.current.userInterfaceIdiom == .pad
let widthMultiplier: CGFloat = isPad ? 0.6 : 0.9
let heightMultiplier: CGFloat = isPad ? 0.5 : 0.63
let yConstraint: NSLayoutConstraint

if isPad {
yConstraint = pianoView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
} else {
yConstraint = pianoView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -5)
}
let reverbYAnchor = isPad
? reverbView.bottomAnchor.constraint(equalTo: view.centerYAnchor, constant: -.veryLargeSpacing)
: reverbView.topAnchor.constraint(equalTo: view.topAnchor, constant: .mediumLargeSpacing)
let pianoTopConstant: CGFloat = isPad ? .veryLargeSpacing : .mediumLargeSpacing

NSLayoutConstraint.activate([
yConstraint,
reverbYAnchor,
reverbView.trailingAnchor.constraint(equalTo: pianoView.centerXAnchor),

distortionView.topAnchor.constraint(equalTo: reverbView.topAnchor),
distortionView.leadingAnchor.constraint(equalTo: reverbView.trailingAnchor, constant: 55),
distortionView.heightAnchor.constraint(equalTo: reverbView.heightAnchor),

pianoView.topAnchor.constraint(equalTo: reverbView.bottomAnchor, constant: pianoTopConstant),
pianoView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
pianoView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: widthMultiplier),
pianoView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: heightMultiplier),

reverbControl.bottomAnchor.constraint(equalTo: pianoView.topAnchor, constant: -25),
reverbControl.trailingAnchor.constraint(equalTo: pianoView.centerXAnchor),
reverbControl.widthAnchor.constraint(equalToConstant: 100),
reverbControl.heightAnchor.constraint(equalTo: reverbControl.widthAnchor),

delayControl.bottomAnchor.constraint(equalTo: reverbControl.bottomAnchor),
delayControl.leadingAnchor.constraint(equalTo: reverbControl.trailingAnchor, constant: 55),
delayControl.widthAnchor.constraint(equalTo: reverbControl.widthAnchor),
delayControl.heightAnchor.constraint(equalTo: delayControl.widthAnchor)
pianoView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),
pianoView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -.mediumSpacing)
])

pianoView.reloadData()
Expand Down Expand Up @@ -155,23 +141,23 @@ final class ViewController: UIViewController {
}
}

// MARK: - PianoViewDataSource
// MARK: - PianoKeyboardViewDataSource

extension ViewController: PianoViewDataSource {
func pianoViewNumberOfKeyViews(_ pianoView: PianoView) -> Int {
extension ViewController: PianoKeyboardViewDataSource {
func pianoKeyboardViewNumberOfKeyViews(_ pianoView: PianoKeyboardView) -> Int {
return notes.count
}
}

// MARK: - PianoViewDelegate
// MARK: - PianoKeyboardViewDelegates

extension ViewController: PianoViewDelegate {
func pianoView(_ pianoView: PianoView, didSelectKeyViewAt index: Int) {
extension ViewController: PianoKeyboardViewDelegate {
func pianoKeyboardView(_ pianoView: PianoKeyboardView, didSelectKeyViewAt index: Int) {
let note = notes[index]
sampler.startNote(note, withVelocity: 120, onChannel: 0)
}

func pianoView(_ pianoView: PianoView, didDeselectKeyViewAt index: Int) {
func pianoKeyboardView(_ pianoView: PianoKeyboardView, didDeselectKeyViewAt index: Int) {
let note = notes[index]
sampler.stopNote(note, onChannel: 0)
}
Expand All @@ -181,10 +167,11 @@ extension ViewController: PianoViewDelegate {

extension ViewController: PianoEffectControlDelegate {
func pianoEffectControl(_ control: PianoEffectControl, didChangeValue value: Float) {
if control == reverbControl {
if control == reverbView.control {
reverb.wetDryMix = value * 100
} else if control == delayControl {
delay.wetDryMix = value * 100
} else if control == distortionView.control {
distortion.wetDryMix = value * 100
}
}
}

Loading

0 comments on commit 0bfab32

Please sign in to comment.