# HG changeset patch # User Lucas Thompson # Date 1480957054 0 # Node ID 933c64ebcd138f977df72ee142979fa61f38a9ca # Parent 88052122ec019fbc27756cf2a333f7ab73558679 Some extraction logic in place. diff -r 88052122ec01 -r 933c64ebcd13 src/app/app.component.html --- a/src/app/app.component.html Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/app.component.html Mon Dec 05 16:57:34 2016 +0000 @@ -22,7 +22,7 @@ - + diff -r 88052122ec01 -r 933c64ebcd13 src/app/app.component.ts --- a/src/app/app.component.ts Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/app.component.ts Mon Dec 05 16:57:34 2016 +0000 @@ -1,5 +1,7 @@ import {Component} from '@angular/core'; import {AudioPlayerService} from "./services/audio-player/audio-player.service"; +import {FeatureExtractionService} from "./services/feature-extraction/feature-extraction.service"; +import {ExtractorOutputInfo} from "./feature-extraction-menu/feature-extraction-menu.component"; @Component({ selector: 'app-root', @@ -9,7 +11,8 @@ export class AppComponent { audioBuffer: AudioBuffer; // TODO consider revising - constructor(private audioService: AudioPlayerService) {} + constructor(private audioService: AudioPlayerService, + private piperService: FeatureExtractionService) {} onFileOpened(file: File) { const reader: FileReader = new FileReader(); @@ -25,4 +28,17 @@ }; reader.readAsArrayBuffer(file); } + + extractFeatures(outputInfo: ExtractorOutputInfo) { + this.piperService.process({ + audioData: [...Array(this.audioBuffer.numberOfChannels).keys()] + .map(i => this.audioBuffer.getChannelData(i)), + audioFormat: { + sampleRate: this.audioBuffer.sampleRate, + channelCount: this.audioBuffer.numberOfChannels + }, + key: outputInfo.extractorKey, + outputId: outputInfo.outputId + }).then(data => console.log(data)).catch(err => console.error(err)); + } } diff -r 88052122ec01 -r 933c64ebcd13 src/app/feature-extraction-menu/feature-extraction-menu.component.html --- a/src/app/feature-extraction-menu/feature-extraction-menu.component.html Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/feature-extraction-menu/feature-extraction-menu.component.html Mon Dec 05 16:57:34 2016 +0000 @@ -1,9 +1,11 @@ - -

- +

diff -r 88052122ec01 -r 933c64ebcd13 src/app/feature-extraction-menu/feature-extraction-menu.component.ts --- a/src/app/feature-extraction-menu/feature-extraction-menu.component.ts Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/feature-extraction-menu/feature-extraction-menu.component.ts Mon Dec 05 16:57:34 2016 +0000 @@ -1,8 +1,10 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, Output, EventEmitter} from '@angular/core'; import {FeatureExtractionService} from "../services/feature-extraction/feature-extraction.service"; -interface ExtractorInfo { - key: string; +export interface ExtractorOutputInfo { + extractorKey: string; + combinedKey: string; + outputId: string; name: string; } @@ -13,29 +15,42 @@ }) export class FeatureExtractionMenuComponent implements OnInit { - extractors: ExtractorInfo[]; + @Output() requestOutput: EventEmitter; + + private extractorsMap: Map; + extractors: Iterable; constructor(private piperService: FeatureExtractionService) { + this.extractorsMap = new Map(); this.extractors = []; + this.requestOutput = new EventEmitter(); } ngOnInit() { this.piperService.list().then(available => { const maxCharacterLimit = 50; available.available.forEach(staticData => { - if (staticData.basicOutputInfo.length > 1) - staticData.basicOutputInfo.forEach(output => this.extractors.push({ - key: `${staticData.key}:${output.identifier}`, - name: `${staticData.basic.name}: ${output.name}`.substr(0, maxCharacterLimit) + '...' - }) - ); - else - this.extractors.push({ - key: staticData.key, - name: staticData.basic.name.substr(0, maxCharacterLimit) + '...' + const isSingleOutputExtractor = staticData.basicOutputInfo.length === 1; + staticData.basicOutputInfo.forEach(output => { + const combinedKey = `${staticData.key}:${output.identifier}`; + this.extractorsMap.set(combinedKey, { + extractorKey: staticData.key, + combinedKey: combinedKey, + name: ( + isSingleOutputExtractor + ? staticData.basic.name + : `${staticData.basic.name}: ${output.name}` + ).substr(0, maxCharacterLimit) + '...', + outputId: output.identifier }); + }); }); + this.extractors = [...this.extractorsMap.values()]; }); } + extract(combinedKey: string): void { + this.requestOutput.emit(this.extractorsMap.get(combinedKey)); + } + } diff -r 88052122ec01 -r 933c64ebcd13 src/app/playback-control/playback-control.component.ts --- a/src/app/playback-control/playback-control.component.ts Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/playback-control/playback-control.component.ts Mon Dec 05 16:57:34 2016 +0000 @@ -13,9 +13,7 @@ private featureExtractionService: FeatureExtractionService) { } - ngOnInit() { - this.featureExtractionService.testMessageStream(); - } + ngOnInit() {} emitPlayPause() { this.audioService.togglePlaying(); diff -r 88052122ec01 -r 933c64ebcd13 src/app/services/feature-extraction/FeatureExtractionWorker.ts --- a/src/app/services/feature-extraction/FeatureExtractionWorker.ts Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/services/feature-extraction/FeatureExtractionWorker.ts Mon Dec 05 16:57:34 2016 +0000 @@ -23,16 +23,20 @@ constructor(workerScope: WorkerGlobalScope) { this.workerScope = workerScope; - let counter = 0; - setInterval(() => this.workerScope.postMessage(counter++), 1000); this.piperClient = new PiperSimpleClient(new EmscriptenProxy(VampExamplePlugins())); this.workerScope.onmessage = (ev: MessageEvent) => { + const sendResponse = (result) => this.workerScope.postMessage({ + method: ev.data.method, + result: result + }); switch (ev.data.method) { case 'list': - this.piperClient.list({}).then(this.workerScope.postMessage); + this.piperClient.list({}).then(sendResponse); + break; + case 'process': + this.piperClient.process(ev.data.params).then(sendResponse); } }; } - } diff -r 88052122ec01 -r 933c64ebcd13 src/app/services/feature-extraction/feature-extraction.service.ts --- a/src/app/services/feature-extraction/feature-extraction.service.ts Mon Dec 05 11:59:22 2016 +0000 +++ b/src/app/services/feature-extraction/feature-extraction.service.ts Mon Dec 05 16:57:34 2016 +0000 @@ -1,6 +1,20 @@ -import { Injectable } from '@angular/core'; -import {ListResponse} from "piper"; +import {Injectable} from '@angular/core'; +import { + ListResponse, ProcessResponse, ProcessRequest, + ListRequest +} from "piper"; +import {SimpleRequest} from "piper/HigherLevelUtilities"; +import {FeatureList} from "piper/Feature"; +interface RequestMessage { + method: string; + params: RequestType; +} + +interface ResponseMessage { + method: string; + result: ResponseType; +} @Injectable() export class FeatureExtractionService { @@ -12,24 +26,31 @@ this.worker = new Worker('bootstrap-feature-extraction-worker.js'); } - testMessageStream() { - this.worker.addEventListener('message', ev => console.log(ev.data)); - this.worker.postMessage('anything'); + list(): Promise { + return this.request( + {method: 'list', params: {}}, + (ev: MessageEvent) => ev.data.result.available !== undefined + ).then(msg => msg.result); } - list(): Promise { - return this.request({method: 'list'}, (ev: MessageEvent) => ev.data.available !== undefined); + process(request: SimpleRequest): Promise { + return this.request( + {method: 'process', params: request}, + (ev: MessageEvent) => ev.data.method === 'process' + ); } - private request(request: Req, predicate: (ev: MessageEvent) => boolean): Promise { + private request(request: RequestMessage, + predicate: (ev: MessageEvent) => boolean) + : Promise> { return new Promise(res => { - const listener = (ev: MessageEvent ) => { + const listener = (ev: MessageEvent) => { this.worker.removeEventListener('message', listener); if (predicate(ev)) res(ev.data); }; this.worker.addEventListener('message', listener); this.worker.postMessage(request); - }); + }).catch(err => console.error(err)); } }