Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Musical Phantoms
Search
TJ Usiyan
September 16, 2016
Programming
0
67
Musical Phantoms
Slides from my NSSpain 2016 talk
TJ Usiyan
September 16, 2016
Tweet
Share
More Decks by TJ Usiyan
See All by TJ Usiyan
Property-Based Testing with SwiftCheck
griotspeak
1
5.5k
Speaking in Types
griotspeak
0
28
Other Decks in Programming
See All in Programming
VSCodeでのDatabricks開発もお勧めしたい/I would also recommend Databricks development with VSCode.
kazumain
0
240
Java 22 Overview
kishida
1
170
Elm Form Validation
bkuhlmann
0
510
1BRC--Nerd Sniping the Java Community
gunnarmorling
0
300
コードレビューで学ぶ!Kotlinオブジェクト指向デザインパターン
akkie76
2
180
PostmanでAPIの動作確認が楽になった話
h455h1
0
130
ONE WEDGE_company_guide
1wedge_one
0
380
1인 개발자로 행복하게 살기 - GDG 송도 헬로월드 2024
benjaminkim
1
5.6k
puregoの活用例
aethiopicuschan
0
220
Designing for tomorrow's programming workflows
honnibal
PRO
2
110
GitHub Actionsで泣かないためにやっておきたい設定 / Recommended GHA settings to avoid crying
pinkumohikan
3
490
チーム力を高めるスクラム実践法:カンバン公開と課題攻略について - ニフティのスクラムトーク Vol. 2 - NIFTY Tech Talk #18
niftycorp
PRO
1
110
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
27
6.3k
Raft: Consensus for Rubyists
vanstee
132
6.2k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
12
1.5k
A designer walks into a library…
pauljervisheath
199
23k
Facilitating Awesome Meetings
lara
41
5.6k
The Mythical Team-Month
searls
215
42k
Code Review Best Practice
trishagee
54
15k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
658
120k
VelocityConf: Rendering Performance Case Studies
addyosmani
320
23k
Music & Morning Musume
bryan
41
5.6k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
1
3.4k
How GitHub Uses GitHub to Build GitHub
holman
468
290k
Transcript
Musical Phantoms © TJ Usiyan, 2016 1
Caveats 4 Details omitted 4 More Signals, Less Types 4
This is all exploratory © TJ Usiyan, 2016 2
This is All Exploratory 4 Problems of Interest 4 Semantics
4 Sample Rate 4 Infinite Sequences 4 User Input © TJ Usiyan, 2016 3
This is All Exploratory 1. Make it work 2. Make
it fast 3. Make it pretty © TJ Usiyan, 2016 4
This is All Exploratory 1. Make it work 2. Make
it pretty 3. Could it be prettier? 4. Make it prettier 5. Make it fast © TJ Usiyan, 2016 5
Stay Calm and Let It Wash Over You © TJ
Usiyan, 2016 6
The Plan 4 Math 4 Audio 4 Types 4 Phantom
Types © TJ Usiyan, 2016 7
Unit Circle1 1 from: Wikipedia, LucasVB Circle_cos_sin © TJ Usiyan,
2016 8
© TJ Usiyan, 2016 9
© TJ Usiyan, 2016 10
Hertz.swift typealias Samples = Int typealias Seconds = Double ///
Cycles (or periods) per second typealias Hertz = Double © TJ Usiyan, 2016 11
SampleRateType.swift public protocol SampleRateType { static var hertz: Hertz {
get } init() } © TJ Usiyan, 2016 12
SampleRateType.swift extension SampleRateType { var frameDuration: Seconds { return 1.0
/ Self.value } func convert(samples: Samples) -> Seconds { return frameDuration * Double(samples) } func convertToSamples(seconds: Seconds) -> Samples { return Int(Self.value * seconds) } } © TJ Usiyan, 2016 13
public struct SampleRate_44100 : SampleRateType { public static let hertz:
Hertz = 44100.0 public init() {} } public struct SampleRate_50 : SampleRateType { public static let hertz: Hertz = 50.0 public init() { } } public struct SampleRate_100 : SampleRateType { public static let hertz: Hertz = 100.0 public init() { } } public struct SampleRate_500 : SampleRateType { public static let hertz: Hertz = 500.0 public init() { } } public struct SampleRate_1000 : SampleRateType { public static let hertz: Hertz = 1000.0 public init() { } } © TJ Usiyan, 2016 14
Signals © TJ Usiyan, 2016 15
public protocol SignalType : Sequence { associatedtype SampleRate : SampleRateType
associatedtype Iterator : SignalGeneratorType } public protocol SignalGeneratorType : IteratorProtocol { associatedtype SampleRate : SampleRateType } © TJ Usiyan, 2016 16
Constant Return an unchanging value © TJ Usiyan, 2016 17
Constant.swift public struct Constant<T, SR : SampleRateType> { public let
value:T public init(value:T) { self.value = value } } © TJ Usiyan, 2016 18
Constant.swift extension Constant : SignalType { public typealias SampleRate =
SR public typealias Iterator = ConstantGenerator<T, SR> public func makeIterator() -> Iterator { return Iterator(signal: self) } } © TJ Usiyan, 2016 19
Constant.swift public struct ConstantGenerator<T, SR : SampleRateType> { fileprivate let
value:T fileprivate init(value:T) { self.value = value } fileprivate init(signal:Constant<T, SR>) { self.init(value: signal.value) } } © TJ Usiyan, 2016 20
SR? © TJ Usiyan, 2016 21
Oscillators © TJ Usiyan, 2016 22
Oscillators Sine(x) © TJ Usiyan, 2016 23
TimeSignal.swift struct TimeSignal<SR : SampleRateType> { init() { } }
© TJ Usiyan, 2016 24
TimeSignal.swift extension TimeSignal : SignalType { typealias SampleRate = SR
typealias Iterator = TimeSignalGenerator<SR> func makeIterator() -> Iterator { return Iterator(index: 0) } } © TJ Usiyan, 2016 25
TimeSignal.swift public struct TimeSignalGenerator<SR : SampleRateType> { fileprivate var index:Index
internal init(index:Index) { self.index = index } } © TJ Usiyan, 2016 26
TimeSignal.swift extension TimeSignalGenerator : SignalGeneratorType { public typealias SampleRate =
SR public typealias Element = (frame:Int, seconds:Double) public typealias Index = Int public mutating func next() -> Element? { let value = (frame:index, seconds:Double(index) / SR.hertz) index += 1 return value } } © TJ Usiyan, 2016 27
TimeSignal.swift extension TimeSignal : SignalType { typealias SampleRate = SR
typealias Iterator = TimeSignalGenerator<SR> func makeIterator() -> Iterator { return Iterator(index: 0) } } © TJ Usiyan, 2016 28
Oscillators are Continuous Functions of Time struct ContinuousTimeFunction<OutputType, SR :
SampleRateType> { let function:(_ time:Double) -> OutputType init(function:@escaping (_ time:Double) -> OutputType) { self.function = function } } © TJ Usiyan, 2016 29
Continuous Functions of Time public struct ContinuousTimeFunctionGenerator<OutputType, SR : SampleRateType>
{ public typealias Index = Int public typealias Function = (_ time:Double) -> OutputType fileprivate var clock:TimeSignal<SR>.Iterator fileprivate let function:Function public init(index:Index, function:@escaping Function) { self.clock = TimeSignalGenerator<SR>(index:index) self.function = function } fileprivate init(clock:TimeSignalGenerator<SR>, function:@escaping Function) { self.clock = clock self.function = function } } © TJ Usiyan, 2016 30
Sine let contFnSin: ContinuousTimeDoubleSignal = { let frequency: Hertz =
2 let period: Second = twoPi let initialPhase: Double = 0 let fn = { sample in return sin(initialPhase + sample * frequency * period) } return ContinuousTimeFunction(function: fn) }() © TJ Usiyan, 2016 31
Phase class Phase<SR : SampleRateType> { var value: Seconds {
didSet { if value >= period { value = value.truncatingRemainder(dividingBy: period) } } } let period: Seconds init(value: Seconds, period: Seconds) { self.value = fabs(value).truncatingRemainder(dividingBy: period) self.period = period } } © TJ Usiyan, 2016 32
Playground © TJ Usiyan, 2016 33
Drawbacks 4 Lock in to sample rate 4 Limitations with
generics 4 Inference. So much inference. © TJ Usiyan, 2016 34
© TJ Usiyan, 2016 35
© TJ Usiyan, 2016 36
© TJ Usiyan, 2016 37
© TJ Usiyan, 2016 38
© TJ Usiyan, 2016 39
Based on "Audio Processing and Sound Synthesis in Haskell" by
Eric Cheng and Paul Hudak © TJ Usiyan, 2016 40
Thank you Questions @griotspeak © TJ Usiyan, 2016 41