dev@10
|
1 import {
|
dev@31
|
2 Component, OnInit, ViewChild, ElementRef, Input, AfterViewInit, NgZone
|
dev@10
|
3 } from '@angular/core';
|
dev@31
|
4 import {AudioPlayerService} from "../services/audio-player.service";
|
dev@8
|
5
|
dev@16
|
6 declare var wavesUI: any; // TODO non-global app scope import
|
dev@20
|
7 type Timeline = any; // TODO what type actually is it.. start a .d.ts for waves-ui?
|
dev@6
|
8
|
dev@6
|
9 @Component({
|
dev@6
|
10 selector: 'app-waveform',
|
dev@6
|
11 templateUrl: './waveform.component.html',
|
dev@6
|
12 styleUrls: ['./waveform.component.css']
|
dev@6
|
13 })
|
dev@20
|
14 export class WaveformComponent implements OnInit, AfterViewInit {
|
dev@20
|
15
|
dev@8
|
16 @ViewChild('track') trackDiv: ElementRef;
|
dev@6
|
17
|
dev@16
|
18 private _audioBuffer: AudioBuffer = undefined;
|
dev@16
|
19
|
dev@16
|
20 @Input()
|
dev@16
|
21 set audioBuffer(buffer: AudioBuffer) {
|
dev@16
|
22 this._audioBuffer = buffer || undefined;
|
dev@20
|
23 if (this.audioBuffer)
|
dev@20
|
24 this.renderWaveform(this.audioBuffer);
|
dev@16
|
25 }
|
dev@16
|
26
|
dev@16
|
27 get audioBuffer(): AudioBuffer {
|
dev@16
|
28 return this._audioBuffer;
|
dev@16
|
29 }
|
dev@16
|
30
|
dev@31
|
31 constructor(private audioService: AudioPlayerService,
|
dev@31
|
32 public ngZone: NgZone) {}
|
dev@10
|
33 ngOnInit() {}
|
dev@10
|
34
|
dev@10
|
35 ngAfterViewInit(): void {
|
dev@20
|
36 this.renderTimeline();
|
dev@20
|
37 }
|
dev@20
|
38
|
dev@20
|
39 renderTimeline(duration: number = 1.0): Timeline {
|
dev@18
|
40 const track: HTMLElement = this.trackDiv.nativeElement;
|
dev@20
|
41 track.innerHTML = "";
|
dev@18
|
42 const height: number = track.getBoundingClientRect().height;
|
dev@18
|
43 const width: number = track.getBoundingClientRect().width;
|
dev@18
|
44 const pixelsPerSecond = width / duration;
|
dev@18
|
45 const timeline = new wavesUI.core.Timeline(pixelsPerSecond, width);
|
dev@18
|
46 timeline.createTrack(track, height, 'main');
|
dev@18
|
47
|
dev@18
|
48 // time axis
|
dev@18
|
49 const timeAxis = new wavesUI.helpers.TimeAxisLayer({
|
dev@18
|
50 height: height,
|
dev@18
|
51 color: 'gray'
|
dev@18
|
52 });
|
dev@18
|
53
|
dev@18
|
54 timeline.addLayer(timeAxis, 'main', 'default', true);
|
dev@20
|
55 return timeline;
|
dev@16
|
56 }
|
dev@16
|
57
|
dev@20
|
58 renderWaveform(buffer: AudioBuffer): void {
|
dev@20
|
59 const height: number = this.trackDiv.nativeElement.getBoundingClientRect().height;
|
dev@20
|
60 const timeline: Timeline = this.renderTimeline(buffer.duration);
|
dev@20
|
61 const waveformLayer = new wavesUI.helpers.WaveformLayer(buffer, {
|
dev@10
|
62 top: 10,
|
dev@20
|
63 height: height * 0.9,
|
dev@16
|
64 color: 'darkblue'
|
dev@16
|
65 });
|
dev@20
|
66 (timeline as any).addLayer(waveformLayer, 'main');
|
dev@31
|
67
|
dev@31
|
68 const cursorLayer = new wavesUI.helpers.CursorLayer({
|
dev@31
|
69 height: height
|
dev@31
|
70 });
|
dev@31
|
71 timeline.addLayer(cursorLayer, 'main');
|
dev@31
|
72 timeline.state = new wavesUI.states.CenteredZoomState(timeline);
|
dev@31
|
73 this.ngZone.runOutsideAngular(() => {
|
dev@31
|
74 // listen for time passing...
|
dev@31
|
75 // TODO this gets the fans going on large files... worth fixing? or waiting to write a better component?
|
dev@31
|
76 // or, can this be updated in a more efficient manner?
|
dev@31
|
77 const updateSeekingCursor = () => {
|
dev@31
|
78 cursorLayer.currentPosition = this.audioService.getCurrentTime();
|
dev@31
|
79 cursorLayer.update();
|
dev@31
|
80 requestAnimationFrame(updateSeekingCursor);
|
dev@31
|
81 };
|
dev@31
|
82 updateSeekingCursor();
|
dev@31
|
83 });
|
dev@6
|
84 }
|
dev@16
|
85
|
dev@6
|
86 }
|