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@33
|
6 declare let 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@33
|
46 timeline.timeContext.offset = 0.5 * timeline.timeContext.visibleDuration;
|
dev@18
|
47 timeline.createTrack(track, height, 'main');
|
dev@18
|
48
|
dev@18
|
49 // time axis
|
dev@18
|
50 const timeAxis = new wavesUI.helpers.TimeAxisLayer({
|
dev@18
|
51 height: height,
|
dev@18
|
52 color: 'gray'
|
dev@18
|
53 });
|
dev@18
|
54
|
dev@18
|
55 timeline.addLayer(timeAxis, 'main', 'default', true);
|
dev@20
|
56 return timeline;
|
dev@16
|
57 }
|
dev@16
|
58
|
dev@20
|
59 renderWaveform(buffer: AudioBuffer): void {
|
dev@20
|
60 const height: number = this.trackDiv.nativeElement.getBoundingClientRect().height;
|
dev@20
|
61 const timeline: Timeline = this.renderTimeline(buffer.duration);
|
dev@20
|
62 const waveformLayer = new wavesUI.helpers.WaveformLayer(buffer, {
|
dev@10
|
63 top: 10,
|
dev@20
|
64 height: height * 0.9,
|
dev@16
|
65 color: 'darkblue'
|
dev@16
|
66 });
|
dev@20
|
67 (timeline as any).addLayer(waveformLayer, 'main');
|
dev@31
|
68
|
dev@31
|
69 const cursorLayer = new wavesUI.helpers.CursorLayer({
|
dev@31
|
70 height: height
|
dev@31
|
71 });
|
dev@31
|
72 timeline.addLayer(cursorLayer, 'main');
|
dev@31
|
73 timeline.state = new wavesUI.states.CenteredZoomState(timeline);
|
dev@31
|
74 this.ngZone.runOutsideAngular(() => {
|
dev@31
|
75 // listen for time passing...
|
dev@31
|
76 // TODO this gets the fans going on large files... worth fixing? or waiting to write a better component?
|
dev@31
|
77 // or, can this be updated in a more efficient manner?
|
dev@31
|
78 const updateSeekingCursor = () => {
|
dev@31
|
79 cursorLayer.currentPosition = this.audioService.getCurrentTime();
|
dev@31
|
80 cursorLayer.update();
|
dev@34
|
81 if (timeline.timeContext.offset + this.audioService.getCurrentTime() >= timeline.timeContext.visibleDuration) {
|
dev@33
|
82 timeline.timeContext.offset -= timeline.timeContext.visibleDuration;
|
dev@34
|
83 timeline.tracks.update();
|
dev@34
|
84 }
|
dev@34
|
85 if (-this.audioService.getCurrentTime() > timeline.timeContext.offset) {
|
dev@33
|
86 timeline.timeContext.offset += timeline.timeContext.visibleDuration;
|
dev@34
|
87 timeline.tracks.update();
|
dev@34
|
88 }
|
dev@31
|
89 requestAnimationFrame(updateSeekingCursor);
|
dev@31
|
90 };
|
dev@31
|
91 updateSeekingCursor();
|
dev@31
|
92 });
|
dev@6
|
93 }
|
dev@16
|
94
|
dev@6
|
95 }
|