Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Musical Phantoms
Search
TJ Usiyan
September 16, 2016
Programming
0
82
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
34
Other Decks in Programming
See All in Programming
C-Shared Buildで突破するAI Agent バックテストの壁
po3rin
0
390
re:Invent 2025 のイケてるサービスを紹介する
maroon1st
0
130
実はマルチモーダルだった。ブラウザの組み込みAI🧠でWebの未来を感じてみよう #jsfes #gemini
n0bisuke2
3
1.2k
大規模Cloud Native環境におけるFalcoの運用
owlinux1000
0
130
Deno Tunnel を使ってみた話
kamekyame
0
110
GISエンジニアから見たLINKSデータ
nokonoko1203
0
140
Findy AI+の開発、運用におけるMCP活用事例
starfish719
0
1.2k
開発に寄りそう自動テストの実現
goyoki
2
1.1k
Cell-Based Architecture
larchanjo
0
130
ELYZA_Findy AI Engineering Summit登壇資料_AIコーディング時代に「ちゃんと」やること_toB LLMプロダクト開発舞台裏_20251216
elyza
1
250
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
160
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
250
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Building Adaptive Systems
keathley
44
2.9k
Stop Working from a Prison Cell
hatefulcrawdad
273
21k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Making Projects Easy
brettharned
120
6.5k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
The Pragmatic Product Professional
lauravandoore
37
7.1k
Mobile First: as difficult as doing things right
swwweet
225
10k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
21k
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