annotate src/app/visualisations/notes/notes.component.ts @ 389:29b817e49a22
Introduce interface VerticallyBounded, which describes a component with a vertical range and the ability to render a scale on itself. VerticallyBoundedWavesComponent partially implements this interface, in that it adds a ScaleLayer to itself - derived instances provide the means of obtaining the scale.
author |
Lucas Thompson <dev@lucas.im> |
date |
Thu, 01 Jun 2017 10:04:41 +0100 |
parents |
afe2fa4a3215 |
children |
26ca17e67364 |
rev |
line source |
dev@380
|
1 /**
|
dev@380
|
2 * Created by lucast on 31/05/2017.
|
dev@380
|
3 */
|
dev@380
|
4 import {WavesComponent} from '../waves-base.component';
|
dev@380
|
5 import {
|
dev@380
|
6 ChangeDetectionStrategy,
|
dev@380
|
7 Component,
|
dev@380
|
8 Input,
|
dev@380
|
9 } from '@angular/core';
|
dev@380
|
10 import {Note} from '../FeatureUtilities';
|
dev@380
|
11 import Waves from 'waves-ui-piper';
|
dev@380
|
12
|
dev@380
|
13 @Component({
|
dev@380
|
14 selector: 'ugly-notes',
|
dev@380
|
15 templateUrl: '../waves-template.html',
|
dev@380
|
16 styleUrls: ['../waves-template.css'],
|
dev@380
|
17 changeDetection: ChangeDetectionStrategy.OnPush
|
dev@380
|
18 })
|
dev@383
|
19 export class NotesComponent extends WavesComponent<Note[]> {
|
dev@380
|
20
|
dev@380
|
21 @Input() set notes(notes: Note[]) {
|
dev@383
|
22 this.feature = notes;
|
dev@380
|
23 }
|
dev@380
|
24
|
dev@383
|
25 protected get featureLayers(): Layer[] {
|
dev@383
|
26 return [
|
dev@380
|
27 new Waves.helpers.PianoRollLayer(
|
dev@383
|
28 this.feature,
|
dev@380
|
29 {
|
dev@380
|
30 height: this.height,
|
dev@380
|
31 color: this.colour,
|
dev@383
|
32 yDomain: findVerticalRange(this.feature)
|
dev@380
|
33 }
|
dev@383
|
34 )
|
dev@383
|
35 ];
|
dev@380
|
36 }
|
dev@380
|
37 }
|
dev@380
|
38
|
dev@380
|
39 // TODO there might be scope to create a generic utility function like this
|
dev@380
|
40 function findVerticalRange(notes: Note[]): [number, number] {
|
dev@380
|
41 let [min, max] = notes.reduce((acc, note) => {
|
dev@380
|
42 const [min, max] = acc;
|
dev@380
|
43 return [Math.min (min, note.pitch), Math.max (max, note.pitch)];
|
dev@380
|
44 }, [Infinity, -Infinity]);
|
dev@380
|
45 if (min === Infinity || min < 0 || max < 0) {
|
dev@380
|
46 min = 0;
|
dev@380
|
47 max = 127;
|
dev@380
|
48 }
|
dev@380
|
49 // round min and max to octave boundaries (starting at C as in MIDI)
|
dev@380
|
50 return [
|
dev@380
|
51 12 * Math.floor(min / 12),
|
dev@380
|
52 12 * Math.ceil(max / 12)
|
dev@380
|
53 ];
|
dev@380
|
54 }
|