SlideShare a Scribd company logo
1 of 30
Download to read offline
Mischief Maker
ENLIGHTEN
Observable
.fromPromise(navigator.requestMIDIAccess())
.map((midi: any) => Array.from(midi.inputs)) // convert from iterable
.map((devices: any) => devices.map(device => device[1])) // grab just the MIDIInput
.subscribe((devices: any) => this.devices = devices)
;
Connect to Devices
KNOW
private initMidiStream() {
const midiAccess$ = Observable.fromPromise(navigator.requestMIDIAccess());
const inputStream$ = midiAccess$.map((midi: any) => midi.inputs.values().next().value);
const messages$ = inputStream$
.filter(input => input !== undefined)
.flatMap(input => this.midiMessageAsObservable(input))
.map((message: any) => ({
status: message.data[0] & 0xf0,
data: [
message.data[1],
message.data[2],
],
}))
.subscribe(message => {
this.messages.unshift(message);
this.cd.detectChanges();
})
;
}
private midiMessageAsObservable(input) {
const source = new Subject();
input.onmidimessage = note => source.next(note);
return source.asObservable();
}
Capture Input
UNDERSTAND
const noteTransforms = {
48: 'C2', 49: 'C#2', 50: 'D2', 51: 'D#2', 52: 'E2', 53: 'F2',
54: 'F#2', 55: 'G2', 56: 'G#2', 57: 'A2', 58: 'A#2', 59: 'B2',
60: 'C3', 61: 'C#3', 62: 'D3', 63: 'D#3', 64: 'E3', 65: 'F3',
66: 'F#3', 67: 'G3', 68: 'G#3', 69: 'A3', 70: 'A#3', 71: 'B3'
};
const messages$ = inputStream$
.filter(input => input !== undefined)
.flatMap(input => this.midiMessageAsObservable(input))
.map((message: any) => {
const status = message.data[0] & 0xf0;
return {
status: status === 144 ? 'PRESSED' : 'RELEASED', // Good until its not ¯_(ツ)_/¯
name: noteTransforms[message.data[1]],
pressure: message.data[2]
}})
;
Convert Input
MANIFEST
private initSynth() {
this.fft = new Tone.Analyser('fft', 32);
this.waveform = new Tone.Analyser('waveform', 1024);
return new Tone.PolySynth(6, Tone.Synth, {
'oscillator': {
'type': 'fatsawtooth',
'count': 3,
'spread': 30
},
'envelope': {
'attack': 0.01,
'decay': 0.1,
'sustain': 0.5,
'release': 0.4,
'attackCurve': 'exponential'
},
})
.fan(this.fft, this.waveform)
.toMaster();
}
Initialize Tone.js Synth
private midiMessageReceived(message: any) {
let cmd = message.status >> 4;24 pt
let noteNumber = noteTransforms[message.data[0]];
let velocity = 0;
if (message.data.length > 1) {
velocity = message.data[1] / 120; // needs to be between 0 and 1 and sometimes it is over 100 ¯_(ツ)_/¯
}
// MIDI noteon with velocity=0 is the same as noteoff
if (cmd === 8 || ((cmd === 9) && (velocity === 0))) { // noteoff
this.noteOff(noteNumber);
} else if (cmd === 9) { // note on
this.noteOn(noteNumber, velocity);
}
}
noteOn(note, velocity) {
this.synth.triggerAttack(note, null, velocity);
}
noteOff(note) {
this.synth.triggerRelease(note);
}
Play Midi Note
PERCEIVE
constructor(
private cd: ChangeDetectorRef,
private sanitizer: DomSanitizer
) {
this.synth = this.initSynth();
this.audioRecorder = new Recorder(this.synth);
}
toggleRecording() {
if (this.isRecording) {
// stop recording
this.audioRecorder.stop();
this.audioRecorder.getBuffers(this.processBuffers.bind(this));
this.isRecording = false;
} else {
// start recording
if (!this.audioRecorder) {
return;
}
this.isRecording = true;
this.audioRecorder.clear();
this.audioRecorder.record();
}
}
New Recorder Instance
onBuffersProcessed(buffers) {
this.audioRecorder.exportWAV(this.onEncoded.bind(this));
}
onEncoded(blob) {
this.addBlob(blob);
this.setupDownload(blob, `myRecording${this.recIndex}.wav`);
this.recIndex++;
}
setupDownload(blob, filename) {
let url = (window.URL).createObjectURL(blob);
this.downloadLink = this.sanitizer.bypassSecurityTrustUrl(url);
this.downloadFile = filename || 'output.wav';
}
addBlob(blob) {
this.wavesurfer.loadBlob(blob);
}
Process Audio Buffers
REFLECT
export class TrackComponent implements OnInit, OnChanges {
@ViewChild('trackWave') trackWave;
@Input() blob;
@Input() playing;
waveSurfer = null;
ngOnInit() {
this.waveSurfer = WaveSurfer.create({
container: this.trackWave.nativeElement,
scrollParent: true,
waveColor: 'violet',
progressColor: 'purple'
});
// Loop
this.waveSurfer.on('finish', () => this.waveSurfer.playPause());
// Load
this.waveSurfer.loadBlob(this.blob);
}
ngOnChanges(changes: SimpleChanges) {
if (changes['playing']) {
if (!this.waveSurfer) { return; }
this.waveSurfer.playPause();
}
}
}
Encapsulate Track
EVOLVE
<!-- workspace.component.html -->
<app-track *ngFor="let blob of blobs" [blob]="blob" [playing]="isPlaying"></app-track>
// workspace.component.js
addBlob(blob) {
this.blobs = this.blobs.concat(blob);
}
togglePlaying() {
this.isPlaying = !this.isPlaying;
}
Multiple Tracks
REVIEW
First Verse
I'm so attracted to what I observe
Can't help reacting to the things I've heard
I never stress about the state of you
Because I'm first to know of anything you do
Chorus
It's all about, Angular
Baby you're ahead of the curve
You've got all the tools I prefer
I'mma let it out, ain't no doubt, all about that, Angular
Second Verse
I love the way you're way ahead of time
I say you're classy just to say you're fine
You're more than just a CLI to me
I think I might just love you universally
Chorus
It's all about, Angular
Baby you're ahead of the curve
You've got all the tools I prefer
I'mma let it out, ain't no doubt, all about that, Angular
Bridge
It's semantics but I know you're mine
Our romance is changing all the time
So progressive, I can catch you offline
Total package, you're one of a kind
SOLOS!
Chorus
It's all about, Angular
Baby you're ahead of the curve
You've got all the tools I prefer
I'mma let it out, ain't no doubt, all about that, Angular
ANGULAR!
https://github.com/onehungrymind/mischief-maker
WE❤YOU!
@simpulton
@rogertippingii
Thanks!

More Related Content

What's hot

Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察
Tsuyoshi Yamamoto
 
Hacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from PerlHacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from Perl
typester
 
Javascript & Ajax Basics
Javascript & Ajax BasicsJavascript & Ajax Basics
Javascript & Ajax Basics
Richard Paul
 

What's hot (20)

Non stop random2b
Non stop random2bNon stop random2b
Non stop random2b
 
Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察
 
YCAM Workshop Part 3
YCAM Workshop Part 3YCAM Workshop Part 3
YCAM Workshop Part 3
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
ZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 VersionZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 Version
 
Intro to Systems Orchestration with MCollective
Intro to Systems Orchestration with MCollectiveIntro to Systems Orchestration with MCollective
Intro to Systems Orchestration with MCollective
 
Clojure@Nuday
Clojure@NudayClojure@Nuday
Clojure@Nuday
 
clonehd01
clonehd01clonehd01
clonehd01
 
Hacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from PerlHacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from Perl
 
The Ring programming language version 1.5.1 book - Part 65 of 180
The Ring programming language version 1.5.1 book - Part 65 of 180The Ring programming language version 1.5.1 book - Part 65 of 180
The Ring programming language version 1.5.1 book - Part 65 of 180
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
Javascript & Ajax Basics
Javascript & Ajax BasicsJavascript & Ajax Basics
Javascript & Ajax Basics
 
システムコールトレーサーの動作原理と実装 (Writing system call tracer for Linux/x86)
システムコールトレーサーの動作原理と実装 (Writing system call tracer for Linux/x86)システムコールトレーサーの動作原理と実装 (Writing system call tracer for Linux/x86)
システムコールトレーサーの動作原理と実装 (Writing system call tracer for Linux/x86)
 
ZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made SimpleZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made Simple
 
The Ring programming language version 1.6 book - Part 71 of 189
The Ring programming language version 1.6 book - Part 71 of 189The Ring programming language version 1.6 book - Part 71 of 189
The Ring programming language version 1.6 book - Part 71 of 189
 
ZeroMQ Is The Answer
ZeroMQ Is The AnswerZeroMQ Is The Answer
ZeroMQ Is The Answer
 
Yg byev2e
Yg byev2eYg byev2e
Yg byev2e
 
Groovy
GroovyGroovy
Groovy
 
Node day 2014
Node day 2014Node day 2014
Node day 2014
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 

Similar to ng-conf 2017: Angular Mischief Maker Slides

in this assignment you are asked to write a simple driver program an.pdf
in this assignment you are asked to write a simple driver program an.pdfin this assignment you are asked to write a simple driver program an.pdf
in this assignment you are asked to write a simple driver program an.pdf
michardsonkhaicarr37
 
Java Programpublic class Fraction {   instance variablesin.pdf
Java Programpublic class Fraction {   instance variablesin.pdfJava Programpublic class Fraction {   instance variablesin.pdf
Java Programpublic class Fraction {   instance variablesin.pdf
aroramobiles1
 

Similar to ng-conf 2017: Angular Mischief Maker Slides (20)

Reactive programming with RxJS - ByteConf 2018
Reactive programming with RxJS - ByteConf 2018Reactive programming with RxJS - ByteConf 2018
Reactive programming with RxJS - ByteConf 2018
 
Pablo Magaz | ECMAScript 2018 y más allá | Codemotion Madrid 2018
Pablo Magaz | ECMAScript 2018 y más allá | Codemotion Madrid 2018Pablo Magaz | ECMAScript 2018 y más allá | Codemotion Madrid 2018
Pablo Magaz | ECMAScript 2018 y más allá | Codemotion Madrid 2018
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event Sourcing
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Designing and implementing embedded synthesizer UIs with JUCE (Geert Bevin, A...
Designing and implementing embedded synthesizer UIs with JUCE (Geert Bevin, A...Designing and implementing embedded synthesizer UIs with JUCE (Geert Bevin, A...
Designing and implementing embedded synthesizer UIs with JUCE (Geert Bevin, A...
 
Android For All The Things
Android For All The ThingsAndroid For All The Things
Android For All The Things
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
 
Hadoop
HadoopHadoop
Hadoop
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
 
in this assignment you are asked to write a simple driver program an.pdf
in this assignment you are asked to write a simple driver program an.pdfin this assignment you are asked to write a simple driver program an.pdf
in this assignment you are asked to write a simple driver program an.pdf
 
Why Sifu?
Why Sifu?Why Sifu?
Why Sifu?
 
Why Sifu
Why SifuWhy Sifu
Why Sifu
 
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
 
Solid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalySolid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon Italy
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみた
 
Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & Xamarin
 
Actor Based Asyncronous IO in Akka
Actor Based Asyncronous IO in AkkaActor Based Asyncronous IO in Akka
Actor Based Asyncronous IO in Akka
 
Greyhound - Powerful Pure Functional Kafka Library - Scala Love in the City
Greyhound - Powerful Pure Functional Kafka Library - Scala Love in the CityGreyhound - Powerful Pure Functional Kafka Library - Scala Love in the City
Greyhound - Powerful Pure Functional Kafka Library - Scala Love in the City
 
Java Programpublic class Fraction {   instance variablesin.pdf
Java Programpublic class Fraction {   instance variablesin.pdfJava Programpublic class Fraction {   instance variablesin.pdf
Java Programpublic class Fraction {   instance variablesin.pdf
 
Version Control with Puppet
Version Control with PuppetVersion Control with Puppet
Version Control with Puppet
 

More from Lukas Ruebbelke

More from Lukas Ruebbelke (12)

Components Are the New Thin Client
Components Are the New Thin ClientComponents Are the New Thin Client
Components Are the New Thin Client
 
Embrace the Angular 2 Ethos in Angular 1.x
Embrace the Angular 2 Ethos in Angular 1.xEmbrace the Angular 2 Ethos in Angular 1.x
Embrace the Angular 2 Ethos in Angular 1.x
 
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and FirebaseGo Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
 
Get that Corner Office with Angular 2 and Electron
Get that Corner Office with Angular 2 and ElectronGet that Corner Office with Angular 2 and Electron
Get that Corner Office with Angular 2 and Electron
 
The REAL Angular Keynote
The REAL Angular KeynoteThe REAL Angular Keynote
The REAL Angular Keynote
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015
 
Turn Your Designers Into Death Stars with Angular
Turn Your Designers Into Death Stars with AngularTurn Your Designers Into Death Stars with Angular
Turn Your Designers Into Death Stars with Angular
 
Badges? We don't need no stinkin' badges!
Badges? We don't need no stinkin' badges!Badges? We don't need no stinkin' badges!
Badges? We don't need no stinkin' badges!
 
ngAnimate crash course
ngAnimate crash coursengAnimate crash course
ngAnimate crash course
 
Ionic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SFIonic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SF
 
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJSngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
 
AngularJS Directives - DSL for your HTML
AngularJS Directives - DSL for your HTMLAngularJS Directives - DSL for your HTML
AngularJS Directives - DSL for your HTML
 

Recently uploaded

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Recently uploaded (20)

%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 

ng-conf 2017: Angular Mischief Maker Slides

  • 3. Observable .fromPromise(navigator.requestMIDIAccess()) .map((midi: any) => Array.from(midi.inputs)) // convert from iterable .map((devices: any) => devices.map(device => device[1])) // grab just the MIDIInput .subscribe((devices: any) => this.devices = devices) ; Connect to Devices
  • 5. private initMidiStream() { const midiAccess$ = Observable.fromPromise(navigator.requestMIDIAccess()); const inputStream$ = midiAccess$.map((midi: any) => midi.inputs.values().next().value); const messages$ = inputStream$ .filter(input => input !== undefined) .flatMap(input => this.midiMessageAsObservable(input)) .map((message: any) => ({ status: message.data[0] & 0xf0, data: [ message.data[1], message.data[2], ], })) .subscribe(message => { this.messages.unshift(message); this.cd.detectChanges(); }) ; } private midiMessageAsObservable(input) { const source = new Subject(); input.onmidimessage = note => source.next(note); return source.asObservable(); } Capture Input
  • 7. const noteTransforms = { 48: 'C2', 49: 'C#2', 50: 'D2', 51: 'D#2', 52: 'E2', 53: 'F2', 54: 'F#2', 55: 'G2', 56: 'G#2', 57: 'A2', 58: 'A#2', 59: 'B2', 60: 'C3', 61: 'C#3', 62: 'D3', 63: 'D#3', 64: 'E3', 65: 'F3', 66: 'F#3', 67: 'G3', 68: 'G#3', 69: 'A3', 70: 'A#3', 71: 'B3' }; const messages$ = inputStream$ .filter(input => input !== undefined) .flatMap(input => this.midiMessageAsObservable(input)) .map((message: any) => { const status = message.data[0] & 0xf0; return { status: status === 144 ? 'PRESSED' : 'RELEASED', // Good until its not ¯_(ツ)_/¯ name: noteTransforms[message.data[1]], pressure: message.data[2] }}) ; Convert Input
  • 9. private initSynth() { this.fft = new Tone.Analyser('fft', 32); this.waveform = new Tone.Analyser('waveform', 1024); return new Tone.PolySynth(6, Tone.Synth, { 'oscillator': { 'type': 'fatsawtooth', 'count': 3, 'spread': 30 }, 'envelope': { 'attack': 0.01, 'decay': 0.1, 'sustain': 0.5, 'release': 0.4, 'attackCurve': 'exponential' }, }) .fan(this.fft, this.waveform) .toMaster(); } Initialize Tone.js Synth
  • 10. private midiMessageReceived(message: any) { let cmd = message.status >> 4;24 pt let noteNumber = noteTransforms[message.data[0]]; let velocity = 0; if (message.data.length > 1) { velocity = message.data[1] / 120; // needs to be between 0 and 1 and sometimes it is over 100 ¯_(ツ)_/¯ } // MIDI noteon with velocity=0 is the same as noteoff if (cmd === 8 || ((cmd === 9) && (velocity === 0))) { // noteoff this.noteOff(noteNumber); } else if (cmd === 9) { // note on this.noteOn(noteNumber, velocity); } } noteOn(note, velocity) { this.synth.triggerAttack(note, null, velocity); } noteOff(note) { this.synth.triggerRelease(note); } Play Midi Note
  • 12. constructor( private cd: ChangeDetectorRef, private sanitizer: DomSanitizer ) { this.synth = this.initSynth(); this.audioRecorder = new Recorder(this.synth); } toggleRecording() { if (this.isRecording) { // stop recording this.audioRecorder.stop(); this.audioRecorder.getBuffers(this.processBuffers.bind(this)); this.isRecording = false; } else { // start recording if (!this.audioRecorder) { return; } this.isRecording = true; this.audioRecorder.clear(); this.audioRecorder.record(); } } New Recorder Instance
  • 13. onBuffersProcessed(buffers) { this.audioRecorder.exportWAV(this.onEncoded.bind(this)); } onEncoded(blob) { this.addBlob(blob); this.setupDownload(blob, `myRecording${this.recIndex}.wav`); this.recIndex++; } setupDownload(blob, filename) { let url = (window.URL).createObjectURL(blob); this.downloadLink = this.sanitizer.bypassSecurityTrustUrl(url); this.downloadFile = filename || 'output.wav'; } addBlob(blob) { this.wavesurfer.loadBlob(blob); } Process Audio Buffers
  • 15. export class TrackComponent implements OnInit, OnChanges { @ViewChild('trackWave') trackWave; @Input() blob; @Input() playing; waveSurfer = null; ngOnInit() { this.waveSurfer = WaveSurfer.create({ container: this.trackWave.nativeElement, scrollParent: true, waveColor: 'violet', progressColor: 'purple' }); // Loop this.waveSurfer.on('finish', () => this.waveSurfer.playPause()); // Load this.waveSurfer.loadBlob(this.blob); } ngOnChanges(changes: SimpleChanges) { if (changes['playing']) { if (!this.waveSurfer) { return; } this.waveSurfer.playPause(); } } } Encapsulate Track
  • 17. <!-- workspace.component.html --> <app-track *ngFor="let blob of blobs" [blob]="blob" [playing]="isPlaying"></app-track> // workspace.component.js addBlob(blob) { this.blobs = this.blobs.concat(blob); } togglePlaying() { this.isPlaying = !this.isPlaying; } Multiple Tracks
  • 19. First Verse I'm so attracted to what I observe Can't help reacting to the things I've heard I never stress about the state of you Because I'm first to know of anything you do
  • 20. Chorus It's all about, Angular Baby you're ahead of the curve You've got all the tools I prefer I'mma let it out, ain't no doubt, all about that, Angular
  • 21. Second Verse I love the way you're way ahead of time I say you're classy just to say you're fine You're more than just a CLI to me I think I might just love you universally
  • 22. Chorus It's all about, Angular Baby you're ahead of the curve You've got all the tools I prefer I'mma let it out, ain't no doubt, all about that, Angular
  • 23. Bridge It's semantics but I know you're mine Our romance is changing all the time So progressive, I can catch you offline Total package, you're one of a kind
  • 25. Chorus It's all about, Angular Baby you're ahead of the curve You've got all the tools I prefer I'mma let it out, ain't no doubt, all about that, Angular