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
79
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
32
Other Decks in Programming
See All in Programming
kiroとCodexで最高のSpec駆動開発を!!数時間で web3ネイティブなミニゲームを作ってみたよ!
mashharuki
0
710
「ちょっと古いから」って避けてた技術書、今だからこそ読もう
mottyzzz
11
6.9k
テーブル定義書の構造化抽出して、生成AIでDWH分析を試してみた / devio2025tokyo
kasacchiful
0
190
Le côté obscur des IA génératives
pascallemerrer
0
150
AI Agent 時代的開發者生存指南
eddie
3
1.9k
Serena MCPのすすめ
wadakatu
4
1k
Leading Effective Engineering Teams in the AI Era
addyosmani
7
470
デミカツ切り抜きで面倒くさいことはPythonにやらせよう
aokswork3
0
250
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
160
Flutterで分数(Fraction)を表示する方法
koukimiura
0
130
技術的負債の正体を知って向き合う
irof
0
190
Claude Agent SDK を使ってみよう
hyshu
0
1.2k
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
Agile that works and the tools we love
rasmusluckow
331
21k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.6k
BBQ
matthewcrist
89
9.8k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Gamification - CAS2011
davidbonilla
81
5.5k
Reflections from 52 weeks, 52 projects
jeffersonlam
353
21k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
How to Ace a Technical Interview
jacobian
280
24k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.7k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.7k
Into the Great Unknown - MozCon
thekraken
40
2.1k
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