comparison src/app/waveform/waveform.component.ts @ 341:684619d3fad5

Allow interacting with highlight layer regardless of whether playback / seeking is supported. Also remove cursor layer when component seeking disabled.
author Lucas Thompson <dev@lucas.im>
date Fri, 19 May 2017 16:18:34 +0100
parents 097d93b11445
children b5f2ee789fb3
comparison
equal deleted inserted replaced
338:2b374217d8a0 341:684619d3fad5
155 if (isPlaying) { 155 if (isPlaying) {
156 this.animate(); 156 this.animate();
157 } 157 }
158 }); 158 });
159 } else { 159 } else {
160 if (this.cursorLayer && this.waveTrack) {
161 this.waveTrack.remove(this.cursorLayer);
162 }
160 if (this.playingStateSubscription) { 163 if (this.playingStateSubscription) {
161 this.playingStateSubscription.unsubscribe(); 164 this.playingStateSubscription.unsubscribe();
162 } 165 }
163 if (this.seekedSubscription) { 166 if (this.seekedSubscription) {
164 this.seekedSubscription.unsubscribe(); 167 this.seekedSubscription.unsubscribe();
195 private onAudioDataSubscription: Subscription; 198 private onAudioDataSubscription: Subscription;
196 private zoomOnMouseDown: number; 199 private zoomOnMouseDown: number;
197 private offsetOnMouseDown: number; 200 private offsetOnMouseDown: number;
198 private hasShot: boolean; 201 private hasShot: boolean;
199 private isLoading: boolean; 202 private isLoading: boolean;
203 private waveTrack: Track;
200 204
201 private static changeColour(layer: Layer, colour: string): void { 205 private static changeColour(layer: Layer, colour: string): void {
202 const butcherShapes = (shape) => { 206 const butcherShapes = (shape) => {
203 shape.install({color: () => colour}); 207 shape.install({color: () => colour});
204 shape.params.color = colour; 208 shape.params.color = colour;
253 this.timeline.visibleWidth = width; 257 this.timeline.visibleWidth = width;
254 } 258 }
255 } else { 259 } else {
256 this.timeline = new wavesUI.core.Timeline(pixelsPerSecond, width); 260 this.timeline = new wavesUI.core.Timeline(pixelsPerSecond, width);
257 } 261 }
258 const waveTrack = this.timeline.createTrack( 262 this.waveTrack = this.timeline.createTrack(
259 track, 263 track,
260 height, 264 height,
261 `wave-${this.trackIdPrefix}` 265 `wave-${this.trackIdPrefix}`
262 ); 266 );
263 if (isInitialRender && hasExistingTimeline) { 267 if (isInitialRender && hasExistingTimeline) {
264 // time axis 268 // time axis
265 const timeAxis = new wavesUI.helpers.TimeAxisLayer({ 269 const timeAxis = new wavesUI.helpers.TimeAxisLayer({
266 height: height, 270 height: height,
267 color: '#b0b0b0' 271 color: '#b0b0b0'
268 }); 272 });
269 this.addLayer(timeAxis, waveTrack, this.timeline.timeContext, true); 273 this.addLayer(timeAxis, this.waveTrack, this.timeline.timeContext, true);
270 this.cursorLayer = new wavesUI.helpers.CursorLayer({ 274 this.cursorLayer = new wavesUI.helpers.CursorLayer({
271 height: height, 275 height: height,
272 color: '#c33c54' 276 color: '#c33c54'
273 }); 277 });
274 this.addLayer(this.cursorLayer, waveTrack, this.timeline.timeContext); 278 this.addLayer(
279 this.cursorLayer,
280 this.waveTrack,
281 this.timeline.timeContext
282 );
275 } 283 }
276 if ('ontouchstart' in window) { 284 if ('ontouchstart' in window) {
277 interface Point { 285 interface Point {
278 x: number; 286 x: number;
279 y: number; 287 y: number;
540 } 548 }
541 } 549 }
542 } 550 }
543 551
544 renderWaveform(buffer: AudioBuffer): void { 552 renderWaveform(buffer: AudioBuffer): void {
545 // const height: number = this.trackDiv.nativeElement.getBoundingClientRect().height / 2; 553 const height = this.trackDiv.nativeElement.getBoundingClientRect().height;
546 const height: number = this.trackDiv.nativeElement.getBoundingClientRect().height;
547 const waveTrack = this.timeline.getTrackById(`wave-${this.trackIdPrefix}`);
548 if (this.timeline) { 554 if (this.timeline) {
549 // resize 555 // resize
550 const width = this.trackDiv.nativeElement.getBoundingClientRect().width; 556 const width = this.trackDiv.nativeElement.getBoundingClientRect().width;
551 557
552 this.clearTimeline(); 558 this.clearTimeline();
553 559
554 this.timeline.visibleWidth = width; 560 this.timeline.visibleWidth = width;
555 this.timeline.pixelsPerSecond = width / buffer.duration; 561 this.timeline.pixelsPerSecond = width / buffer.duration;
556 waveTrack.height = height; 562 this.waveTrack.height = height;
557 } else { 563 } else {
558 this.renderTimeline(buffer.duration); 564 this.renderTimeline(buffer.duration);
559 } 565 }
560 this.timeline.timeContext.offset = 0.5 * this.timeline.timeContext.visibleDuration; 566 this.timeline.timeContext.offset = 0.5 * this.timeline.timeContext.visibleDuration;
561 567
562 // time axis 568 // time axis
563 const timeAxis = new wavesUI.helpers.TimeAxisLayer({ 569 const timeAxis = new wavesUI.helpers.TimeAxisLayer({
564 height: height, 570 height: height,
565 color: '#b0b0b0' 571 color: '#b0b0b0'
566 }); 572 });
567 this.addLayer(timeAxis, waveTrack, this.timeline.timeContext, true); 573 this.addLayer(timeAxis, this.waveTrack, this.timeline.timeContext, true);
568 574
569 const nchannels = buffer.numberOfChannels; 575 const nchannels = buffer.numberOfChannels;
570 const totalWaveHeight = height * 0.9; 576 const totalWaveHeight = height * 0.9;
571 const waveHeight = totalWaveHeight / nchannels; 577 const waveHeight = totalWaveHeight / nchannels;
572 578
576 top: (height - totalWaveHeight) / 2 + waveHeight * ch, 582 top: (height - totalWaveHeight) / 2 + waveHeight * ch,
577 height: waveHeight, 583 height: waveHeight,
578 color: '#0868ac', 584 color: '#0868ac',
579 channel: ch 585 channel: ch
580 }); 586 });
581 this.addLayer(waveformLayer, waveTrack, this.timeline.timeContext); 587 this.addLayer(waveformLayer, this.waveTrack, this.timeline.timeContext);
582 } 588 }
583 589
584 this.cursorLayer = new wavesUI.helpers.CursorLayer({ 590 this.cursorLayer = new wavesUI.helpers.CursorLayer({
585 height: height, 591 height: height,
586 color: '#c33c54' 592 color: '#c33c54'
587 }); 593 });
588 this.addLayer(this.cursorLayer, waveTrack, this.timeline.timeContext); 594 this.addLayer(this.cursorLayer, this.waveTrack, this.timeline.timeContext);
589 this.timeline.state = new wavesUI.states.CenteredZoomState(this.timeline); 595 this.timeline.state = new wavesUI.states.CenteredZoomState(this.timeline);
590 waveTrack.render(); 596 this.waveTrack.render();
591 waveTrack.update(); 597 this.waveTrack.update();
592 598
593 this.isLoading = false; 599 this.isLoading = false;
594 this.ref.markForCheck(); 600 this.ref.markForCheck();
595 this.animate(); 601 this.animate();
596 } 602 }
639 min = 0; 645 min = 0;
640 max = 1; 646 max = 1;
641 } 647 }
642 648
643 const height = this.trackDiv.nativeElement.getBoundingClientRect().height; 649 const height = this.trackDiv.nativeElement.getBoundingClientRect().height;
644 const waveTrack = this.timeline.getTrackById(`wave-${this.trackIdPrefix}`);
645 650
646 // Now add a line layer for each vector feature 651 // Now add a line layer for each vector feature
647 const lineLayers = features.map(feature => { 652 const lineLayers = features.map(feature => {
648 653
649 let duration = 0; 654 let duration = 0;
667 height: height, 672 height: height,
668 yDomain: [ min, max ] 673 yDomain: [ min, max ]
669 }); 674 });
670 this.addLayer( 675 this.addLayer(
671 lineLayer, 676 lineLayer,
672 waveTrack, 677 this.waveTrack,
673 this.timeline.timeContext 678 this.timeline.timeContext
674 ); 679 );
675 680
676 // Set start and duration so that the highlight layer can use 681 // Set start and duration so that the highlight layer can use
677 // them to determine which line to draw values from 682 // them to determine which line to draw values from
689 height: height, 694 height: height,
690 yDomain: [ min, max ] 695 yDomain: [ min, max ]
691 }); 696 });
692 this.addLayer( 697 this.addLayer(
693 scaleLayer, 698 scaleLayer,
694 waveTrack, 699 this.waveTrack,
695 this.timeline.timeContext 700 this.timeline.timeContext
696 ); 701 );
697 702
698 // And a single highlight layer which uses all of the line layers 703 // And a single highlight layer which uses all of the line layers
699 // as its source material 704 // as its source material
705 yDomain: [ min, max ], 710 yDomain: [ min, max ],
706 unit 711 unit
707 }); 712 });
708 this.addLayer( 713 this.addLayer(
709 this.highlightLayer, 714 this.highlightLayer,
710 waveTrack, 715 this.waveTrack,
711 this.timeline.timeContext 716 this.timeline.timeContext
712 ); 717 );
713 } 718 }
714 719
715 // TODO refactor - this doesn't belong here 720 // TODO refactor - this doesn't belong here
728 return; 733 return;
729 } 734 }
730 const features: FeatureCollection = (extracted.features as FeatureCollection); 735 const features: FeatureCollection = (extracted.features as FeatureCollection);
731 const outputDescriptor = extracted.outputDescriptor; 736 const outputDescriptor = extracted.outputDescriptor;
732 const height = this.trackDiv.nativeElement.getBoundingClientRect().height; 737 const height = this.trackDiv.nativeElement.getBoundingClientRect().height;
733 const waveTrack = this.timeline.getTrackById(`wave-${this.trackIdPrefix}`);
734 738
735 let unit = ''; 739 let unit = '';
736 if (outputDescriptor.configured.hasOwnProperty('unit')) { 740 if (outputDescriptor.configured.hasOwnProperty('unit')) {
737 unit = outputDescriptor.configured.unit; 741 unit = outputDescriptor.configured.unit;
738 } 742 }
776 labelPosition: 'bottom', 780 labelPosition: 'bottom',
777 shadeSegments: true 781 shadeSegments: true
778 }); 782 });
779 this.addLayer( 783 this.addLayer(
780 featureLayer, 784 featureLayer,
781 waveTrack, 785 this.waveTrack,
782 this.timeline.timeContext 786 this.timeline.timeContext
783 ); 787 );
784 break; 788 break;
785 case 'regions': 789 case 'regions':
786 this.renderRegions( 790 this.renderRegions(
787 featureData, 791 featureData,
788 outputDescriptor, 792 outputDescriptor,
789 waveTrack, 793 this.waveTrack,
790 height, 794 height,
791 colour 795 colour
792 ); 796 );
793 break; 797 break;
794 case 'notes': 798 case 'notes':
808 notes, 812 notes,
809 {height: height, color: colour, yDomain: [min, max] } 813 {height: height, color: colour, yDomain: [min, max] }
810 ); 814 );
811 this.addLayer( 815 this.addLayer(
812 pianoRollLayer, 816 pianoRollLayer,
813 waveTrack, 817 this.waveTrack,
814 this.timeline.timeContext 818 this.timeline.timeContext
815 ); 819 );
816 break; 820 break;
817 } 821 }
818 } catch (e) { 822 } catch (e) {
847 normalise: 'none', 851 normalise: 'none',
848 mapper: this.iceMapper() 852 mapper: this.iceMapper()
849 }); 853 });
850 this.addLayer( 854 this.addLayer(
851 matrixLayer, 855 matrixLayer,
852 waveTrack, 856 this.waveTrack,
853 this.timeline.timeContext 857 this.timeline.timeContext
854 ); 858 );
855 break; 859 break;
856 } 860 }
857 default: 861 default:
876 const updateSeekingCursor = () => { 880 const updateSeekingCursor = () => {
877 const currentTime = this.audioService.getCurrentTime(); 881 const currentTime = this.audioService.getCurrentTime();
878 this.cursorLayer.currentPosition = currentTime; 882 this.cursorLayer.currentPosition = currentTime;
879 this.cursorLayer.update(); 883 this.cursorLayer.update();
880 884
881 if (typeof(this.highlightLayer) !== 'undefined') { 885 if (this.highlightLayer) {
882 this.highlightLayer.currentPosition = currentTime; 886 this.highlightLayer.currentPosition = currentTime;
883 this.highlightLayer.update(); 887 this.highlightLayer.update();
884 } 888 }
885 889
886 const currentOffset = this.timeline.timeContext.offset; 890 const currentOffset = this.timeline.timeContext.offset;
1047 } 1051 }
1048 1052
1049 seek(x: number): void { 1053 seek(x: number): void {
1050 if (this.timeline) { 1054 if (this.timeline) {
1051 const timeContext: any = this.timeline.timeContext; 1055 const timeContext: any = this.timeline.timeContext;
1056 const timeX = timeContext.timeToPixel.invert(x) - timeContext.offset;
1052 if (this.isSeeking) { 1057 if (this.isSeeking) {
1053 this.audioService.seekTo( 1058 this.audioService.seekTo(timeX);
1054 timeContext.timeToPixel.invert(x) - timeContext.offset 1059 } else {
1055 ); 1060 if (this.highlightLayer) {
1061 this.highlightLayer.currentPosition = timeX;
1062 this.highlightLayer.update();
1063 }
1056 } 1064 }
1057 } 1065 }
1058 } 1066 }
1059 } 1067 }
1060 1068