comparison src/app/waveform/waveform.component.ts @ 64:270f59ef3b83

Incorporate recent piper changes and use output descriptor for some basic feature discrimination to render appropriate layers.
author Lucas Thompson <dev@lucas.im>
date Mon, 12 Dec 2016 00:41:37 +0000
parents dc07ec243491
children 1b8dec9f6fe6
comparison
equal deleted inserted replaced
63:dc07ec243491 64:270f59ef3b83
3 OnDestroy 3 OnDestroy
4 } from '@angular/core'; 4 } from '@angular/core';
5 import {AudioPlayerService} from "../services/audio-player/audio-player.service"; 5 import {AudioPlayerService} from "../services/audio-player/audio-player.service";
6 import wavesUI from 'waves-ui'; 6 import wavesUI from 'waves-ui';
7 import { 7 import {
8 FeatureExtractionService, 8 FeatureExtractionService
9 Extracted
10 } from "../services/feature-extraction/feature-extraction.service"; 9 } from "../services/feature-extraction/feature-extraction.service";
11 import {Subscription} from "rxjs"; 10 import {Subscription} from "rxjs";
12 import { 11 import {
13 FeatureCollection, 12 FeatureCollection,
14 FixedSpacedFeatures 13 FixedSpacedFeatures, SimpleResponse
15 } from "piper/HigherLevelUtilities"; 14 } from "piper/HigherLevelUtilities";
16 import {toSeconds} from "piper"; 15 import {toSeconds} from "piper";
16 import {FeatureList} from "piper/Feature";
17 17
18 type Timeline = any; // TODO what type actually is it.. start a .d.ts for waves-ui? 18 type Timeline = any; // TODO what type actually is it.. start a .d.ts for waves-ui?
19 type Layer = any; 19 type Layer = any;
20 type Track = any; 20 type Track = any;
21 type DisposableIndex = number; 21 type DisposableIndex = number;
161 mainTrack.update(); 161 mainTrack.update();
162 this.animate(); 162 this.animate();
163 } 163 }
164 164
165 // TODO refactor - this doesn't belong here 165 // TODO refactor - this doesn't belong here
166 private renderFeatures(extracted: Extracted, colour: Colour): void { 166 private renderFeatures(extracted: SimpleResponse, colour: Colour): void {
167 if (!extracted.hasOwnProperty('shape') || !extracted.hasOwnProperty('data')) return; 167 if (!extracted.hasOwnProperty('features') || !extracted.hasOwnProperty('outputDescriptor')) return;
168 const features: FeatureCollection = (extracted as FeatureCollection); 168 if (!extracted.features.hasOwnProperty('shape') || !extracted.features.hasOwnProperty('data')) return;
169 const features: FeatureCollection = (extracted.features as FeatureCollection);
170 const outputDescriptor = extracted.outputDescriptor;
171 const height = this.trackDiv.nativeElement.getBoundingClientRect().height;
172 const mainTrack = this.timeline.getTrackById('main');
173
174 // TODO refactor all of this
169 switch (features.shape) { 175 switch (features.shape) {
170 case 'vector': 176 case 'vector': {
171 const stepDuration = (features as FixedSpacedFeatures).stepDuration; 177 const stepDuration = (features as FixedSpacedFeatures).stepDuration;
172 const featureData = (features.data as Float32Array); 178 const featureData = (features.data as Float32Array);
173 const normalisationFactor = 1.0 / 179 const normalisationFactor = 1.0 /
174 featureData.reduce( 180 featureData.reduce(
175 (currentMax, feature) => Math.max(currentMax, feature), 181 (currentMax, feature) => Math.max(currentMax, feature),
181 cy: feature * normalisationFactor 187 cy: feature * normalisationFactor
182 }; 188 };
183 }); 189 });
184 let breakpointLayer = new wavesUI.helpers.BreakpointLayer(plotData, { 190 let breakpointLayer = new wavesUI.helpers.BreakpointLayer(plotData, {
185 color: colour, 191 color: colour,
186 height: this.trackDiv.nativeElement.getBoundingClientRect().height 192 height: height
187 }); 193 });
188 this.colouredLayers.set(this.addLayer( 194 this.colouredLayers.set(this.addLayer(
189 breakpointLayer, 195 breakpointLayer,
190 this.timeline.getTrackById('main'), 196 mainTrack,
191 this.timeline.timeContext 197 this.timeline.timeContext
192 ), colour); 198 ), colour);
193 break; 199 break;
200 }
201 case 'list': {
202 const featureData = (features.data as FeatureList);
203 // TODO look at output descriptor instead of directly inspecting features
204 const hasDuration = outputDescriptor.configured.hasDuration;
205 const isMarker = !hasDuration
206 && outputDescriptor.configured.binCount === 0
207 && featureData[0].featureValues == null;
208 const isRegion = hasDuration
209 && featureData[0].timestamp != null;
210
211 // TODO refactor, this is incomprehensible
212 if (isMarker) {
213 const plotData = featureData.map(feature => {
214 return {x: toSeconds(feature.timestamp)}
215 });
216 let markerLayer = new wavesUI.helpers.MarkerLayer(plotData, {
217 height: height,
218 color: colour,
219 });
220 this.colouredLayers.set(this.addLayer(
221 markerLayer,
222 mainTrack,
223 this.timeline.timeContext
224 ), colour);
225 } else if (isRegion) {
226 const isBarRegion = featureData[0].featureValues.length === 1;
227 const getSegmentArgs = () => {
228 if (isBarRegion) {
229 const min = featureData.reduce((min, feature) =>
230 Math.min(min, feature.featureValues[0]),
231 Infinity
232 );
233
234 const max = featureData.reduce((max, feature) =>
235 Math.max(max, feature.featureValues[0]),
236 -Infinity
237 );
238
239 return [
240 featureData.map(feature => {
241 return {
242 x: toSeconds(feature.timestamp),
243 y: feature.featureValues[0],
244 width: toSeconds(feature.duration),
245 height: 0.05 * max,
246 color: colour,
247 opacity: 0.8
248 }
249 }),
250 {yDomain: [min, max + 0.05 * max], height: height} as any
251 ]
252 } else {
253 return [featureData.map(feature => {
254 return {
255 x: toSeconds(feature.timestamp),
256 width: toSeconds(feature.duration),
257 color: colour,
258 opacity: 0.8
259 }
260 }), {height: height}];
261 }
262 };
263
264 let segmentLayer = new wavesUI.helpers.SegmentLayer(
265 ...getSegmentArgs()
266 );
267 this.colouredLayers.set(this.addLayer(
268 segmentLayer,
269 mainTrack,
270 this.timeline.timeContext
271 ), colour);
272 }
273
274 break;
275 }
194 } 276 }
195 277
196 this.timeline.tracks.update(); 278 this.timeline.tracks.update();
197 } 279 }
198 280