text rendering service and chord detection
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
export const KEYS = [
|
||||
'C', 'C#', 'Db', 'D', 'D#', 'Eb', 'E', 'F', 'F#', 'Gb', 'G', 'G#', 'Ab', 'A', 'A#', 'B', 'H',
|
||||
'c', 'c#', 'db', 'd', 'd#', 'eb', 'e', 'f', 'f#', 'gb', 'g', 'g#', 'ab', 'a', 'a#', 'b', 'h'
|
||||
'C#', 'C', 'Db', 'D#', 'D', 'Eb', 'E', 'F#', 'F', 'Gb', 'G#', 'G', 'Ab', 'A#', 'A', 'B', 'H',
|
||||
'c#', 'c', 'db', 'd#', 'd', 'eb', 'e', 'f#', 'f', 'gb', 'g#', 'g', 'ab', 'a#', 'a', 'b', 'h'
|
||||
];
|
||||
export const KEYS_REGEX = new RegExp('(' + KEYS.reduce((a, b) => a + '|' + b) + ')', 'gm');
|
||||
export const KEYS_MAJOR_FLAT = [
|
||||
'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'H',
|
||||
];
|
||||
|
||||
@@ -12,6 +12,6 @@ export class SongDataService {
|
||||
|
||||
public list$ = (): Observable<Song[]> => this.dbService.col$('songs');
|
||||
public read$ = (songId: string): Observable<Song | undefined> => this.dbService.doc$('songs/' + songId);
|
||||
public update = async (songId: string, data: any): Promise<void> => await this.dbService.doc(songId).update(data);
|
||||
public update = async (songId: string, data: any): Promise<void> => await this.dbService.doc('songs/' + songId).update(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Text Line 1-2
|
||||
Text Line 2-2
|
||||
|
||||
Refrain
|
||||
c# cb c7 cmaj7 c/e
|
||||
c c# db c7 cmaj7 c/e
|
||||
and the chorus
|
||||
|
||||
Bridge
|
||||
@@ -69,6 +69,17 @@ Cool bridge without any chords
|
||||
expect(sections[1].lines[2].type).toBe(LineType.chord);
|
||||
expect(sections[1].lines[2].text).toBe(' a d e f g a h c b');
|
||||
expect(sections[2].lines[0].type).toBe(LineType.chord);
|
||||
expect(sections[2].lines[0].text).toBe('c# cb c7 cmaj7 c/e');
|
||||
expect(sections[2].lines[0].text).toBe('c c# db c7 cmaj7 c/e');
|
||||
|
||||
// c c# db c7 cmaj7 c/e
|
||||
console.log(sections[2].lines[0].chords);
|
||||
expect(sections[2].lines[0].chords).toEqual([
|
||||
{chord: 'c', length: 2, position: 0},
|
||||
{chord: 'c#', length: 3, position: 2},
|
||||
{chord: 'db', length: 3, position: 5},
|
||||
{chord: 'c', length: 2, position: 8, add: '7'},
|
||||
{chord: 'c', length: 5, position: 13, add: 'maj7'},
|
||||
{chord: 'c', length: 3, position: 22, slashChord: 'e'},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,9 +11,18 @@ export enum LineType {
|
||||
text,
|
||||
}
|
||||
|
||||
export interface Chord {
|
||||
chord: string;
|
||||
length: number;
|
||||
position: number;
|
||||
slashChord?: string;
|
||||
add?: string;
|
||||
}
|
||||
|
||||
export interface Line {
|
||||
type: LineType;
|
||||
text: string;
|
||||
chords?: Chord[]
|
||||
}
|
||||
|
||||
export interface Section {
|
||||
@@ -27,8 +36,8 @@ export interface Section {
|
||||
})
|
||||
export class TextRenderingService {
|
||||
|
||||
|
||||
private regexSection = /(Strophe|Refrain|Bridge)/;
|
||||
private regexChords = /\b([CDEFGAHBcdefgahb](#|##|b|bb|sus|maj|maj7|min|aug|\d+|\/[CDEFGAHBcdefgahb])?\b)/;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
@@ -47,9 +56,13 @@ export class TextRenderingService {
|
||||
}
|
||||
|
||||
private getLineOfLineText(text: string): Line {
|
||||
const matches = !!text.match(this.regexChords);
|
||||
const type = matches ? LineType.chord : LineType.text;
|
||||
return {type, text}
|
||||
const regex = /\b(C#|C|Db|D#|D|Eb|E|F#|F|Gb|G#|G|Ab|A#|A|B|H|c#|c|db|d#|d|eb|e|f#|f|gb|g#|g|ab|a#|a|b|h)(\/(C#|C|Db|D#|D|Eb|E|F#|F|Gb|G#|G|Ab|A#|A|B|H|c#|c|db|d#|d|eb|e|f#|f|gb|g#|g|ab|a#|a|b|h))?(\d+|maj7)?.?\b/mg;
|
||||
|
||||
const match = text.match(regex);
|
||||
const hasMatches = !!match;
|
||||
const type = hasMatches ? LineType.chord : LineType.text;
|
||||
|
||||
return {type, text, chords: hasMatches ? this.readChords(text) : undefined}
|
||||
}
|
||||
|
||||
private getSectionTypeOfLine(line: string): SectionType {
|
||||
@@ -64,4 +77,24 @@ export class TextRenderingService {
|
||||
}
|
||||
}
|
||||
|
||||
private readChords(chordLine: string): Chord[] {
|
||||
let match;
|
||||
const chords: Chord[] = [];
|
||||
|
||||
const regex = /\b(C#|C|Db|D#|D|Eb|E|F#|F|Gb|G#|G|Ab|A#|A|B|H|c#|c|db|d#|d|eb|e|f#|f|gb|g#|g|ab|a#|a|b|h)(\/(C#|C|Db|D#|D|Eb|E|F#|F|Gb|G#|G|Ab|A#|A|B|H|c#|c|db|d#|d|eb|e|f#|f|gb|g#|g|ab|a#|a|b|h))?(\d+|maj7)?.?\b/mg;
|
||||
|
||||
while ((match = regex.exec(chordLine)) !== null) {
|
||||
const chord: Chord = {
|
||||
chord: match[1],
|
||||
length: match[0].length,
|
||||
position: regex.lastIndex - match[0].length,
|
||||
};
|
||||
if (match[3]) chord.slashChord = match[3];
|
||||
if (match[4]) chord.add = match[4];
|
||||
|
||||
chords.push(chord);
|
||||
}
|
||||
return chords;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
background: #fffe;
|
||||
overflow: hidden;
|
||||
width: 800px;
|
||||
transition: 3s all ease-in-out;
|
||||
@media screen and (max-width: 860px) {
|
||||
width: 100vw;
|
||||
border-radius: 0px;
|
||||
|
||||
Reference in New Issue
Block a user