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
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
AIエージェント、”どう作るか”で差は出るか? / AI Agents: Does the "How" Make a Difference?
rkaga
4
2k
なるべく楽してバックエンドに型をつけたい!(楽とは言ってない)
hibiki_cube
0
140
Amazon Bedrockを活用したRAGの品質管理パイプライン構築
tosuri13
5
750
AI Schema Enrichment for your Oracle AI Database
thatjeffsmith
0
310
Raku Raku Notion 20260128
hareyakayuruyaka
0
330
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.6k
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
7
3.9k
Honoを使ったリモートMCPサーバでAIツールとの連携を加速させる!
tosuri13
1
180
Smart Handoff/Pickup ガイド - Claude Code セッション管理
yukiigarashi
0
140
Oxlint JS plugins
kazupon
1
970
要求定義・仕様記述・設計・検証の手引き - 理論から学ぶ明確で統一された成果物定義
orgachem
PRO
1
150
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
1
130
Featured
See All Featured
WCS-LA-2024
lcolladotor
0
450
Darren the Foodie - Storyboard
khoart
PRO
2
2.4k
How GitHub (no longer) Works
holman
316
140k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
KATA
mclloyd
PRO
34
15k
The Power of CSS Pseudo Elements
geoffreycrofte
80
6.2k
Why Our Code Smells
bkeepers
PRO
340
58k
Design in an AI World
tapps
0
140
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.4k
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