annotate src/app/Session.ts @ 460:ccce2c09502e

Manually cherry-pick various refactoring efforts from feature/basic-session-loading
author Lucas Thompson <dev@lucas.im>
date Fri, 30 Jun 2017 10:41:30 +0100
parents
children 2624bb55dbf6
rev   line source
dev@460 1 /**
dev@460 2 * Created by lucast on 08/06/2017.
dev@460 3 */
dev@460 4 import {
dev@460 5 Item,
dev@460 6 RootAudioItem
dev@460 7 } from './analysis-item/AnalysisItem';
dev@460 8
dev@460 9 export const exampleSession: SerialisedNotebook = {
dev@460 10 root: {
dev@460 11 id: '1',
dev@460 12 hasSharedTimeline: true,
dev@460 13 title: 'Drum Loop',
dev@460 14 description: 'Remotely hosted audio file',
dev@460 15 uri: 'https://piper-audio.github.io/waves-ui-piper/examples/assets/drum-loop.wav'
dev@460 16 },
dev@460 17 analyses: [
dev@460 18 {
dev@460 19 id: '2',
dev@460 20 hasSharedTimeline: true,
dev@460 21 extractorKey: 'vamp-example-plugins:amplitudefollower',
dev@460 22 outputId: 'amplitude',
dev@460 23 title: 'Amplitude',
dev@460 24 description: 'amplitude'
dev@460 25 },
dev@460 26 {
dev@460 27 id: '3',
dev@460 28 hasSharedTimeline: true,
dev@460 29 extractorKey: 'vamp-example-plugins:powerspectrum',
dev@460 30 outputId: 'powerspectrum',
dev@460 31 title: 'Simple Power Spectrum',
dev@460 32 description: 'powerspectrum'
dev@460 33 },
dev@460 34
dev@460 35 ]
dev@460 36 };
dev@460 37
dev@460 38 export interface SerialisedAnalysisItem extends Item {
dev@460 39 extractorKey: string;
dev@460 40 outputId: string;
dev@460 41 }
dev@460 42
dev@460 43 export interface SerialisedNotebook {
dev@460 44 root: RootAudioItem;
dev@460 45 analyses: SerialisedAnalysisItem[];
dev@460 46 }
dev@460 47
dev@460 48 export type ResourceRetriever = (url: string) => Promise<Blob>;
dev@460 49
dev@460 50 export const downloadResource: ResourceRetriever = async (url) => {
dev@460 51 const response = await fetch(url);
dev@460 52 const mimeType = response.headers.get('content-type');
dev@460 53 // Safari's fetch.blob implementation doesn't populate the type property
dev@460 54 // causing the audio player to fail due to an unsupported type.
dev@460 55 // Manually create a blob from an array buffer and the content type in
dev@460 56 // the response object
dev@460 57 const arrayBufferToBlob = async () => {
dev@460 58 const arrayBuffer = await response.arrayBuffer();
dev@460 59 return new Blob([arrayBuffer], {type: mimeType});
dev@460 60 };
dev@460 61 return mimeType ? arrayBufferToBlob() : response.blob();
dev@460 62 };
dev@460 63
dev@460 64 export class PersistentStack<T> {
dev@460 65 private stack: T[];
dev@460 66 private history: T[][];
dev@460 67
dev@460 68 constructor() {
dev@460 69 this.stack = [];
dev@460 70 this.history = [];
dev@460 71 }
dev@460 72
dev@460 73 shift(): T {
dev@460 74 this.history.push([...this.stack]);
dev@460 75 const item = this.stack[0];
dev@460 76 this.stack = this.stack.slice(1);
dev@460 77 return item;
dev@460 78 }
dev@460 79
dev@460 80 unshift(item: T): number {
dev@460 81 this.history.push([...this.stack]);
dev@460 82 this.stack = [item, ...this.stack];
dev@460 83 return this.stack.length;
dev@460 84 }
dev@460 85
dev@460 86 findIndex(predicate: (value: T,
dev@460 87 index: number,
dev@460 88 array: T[]) => boolean): number {
dev@460 89 return this.stack.findIndex(predicate);
dev@460 90 }
dev@460 91
dev@460 92 filter(predicate: (value: T, index: number, array: T[]) => boolean): T[] {
dev@460 93 return this.stack.filter(predicate);
dev@460 94 }
dev@460 95
dev@460 96 get(index: number): T {
dev@460 97 return this.stack[index];
dev@460 98 }
dev@460 99
dev@460 100 set(index: number, value: T) {
dev@460 101 this.history.push([...this.stack]);
dev@460 102 this.stack = [
dev@460 103 ...this.stack.slice(0, index),
dev@460 104 value,
dev@460 105 ...this.stack.slice(index + 1)
dev@460 106 ];
dev@460 107 }
dev@460 108
dev@460 109 map<U>(transform: (value: T, index: number, array: T[]) => U): U[] {
dev@460 110 return this.stack.map(transform);
dev@460 111 }
dev@460 112
dev@460 113 reduce<U>(reducer: (previousValue: U,
dev@460 114 currentValue: T,
dev@460 115 currentIndex: number,
dev@460 116 array: T[]) => U,
dev@460 117 initialValue: U): U {
dev@460 118 return this.stack.reduce(reducer, initialValue);
dev@460 119 }
dev@460 120
dev@460 121 remove(...indices: number[]) {
dev@460 122 this.history.push([...this.stack]);
dev@460 123 this.stack = this.stack.reduce((acc, item, i) => {
dev@460 124 if (!indices.includes(i)) {
dev@460 125 acc.push(item);
dev@460 126 }
dev@460 127 return acc;
dev@460 128 }, [] as T[]);
dev@460 129 }
dev@460 130
dev@460 131 toIterable(): Iterable<T> {
dev@460 132 return this.stack;
dev@460 133 }
dev@460 134 }