如何在 VexFlow 中渲染配乐?
How to render a soundtrack in VexFlow?
使用Tone.js
,我可以演奏这首旋律:
const textMeasures = ['rest/4 B4/16 A4/16 G#4/16 A4/16',
'C5/8 rest/8 D5/16 C5/16 B4/16 C5/16',
'E5/8 rest/8 F5/16 E5/16 D#5/16 E5/16',
'B5/16 A5/16 G#5/16 A5/16 B5/16 A5/16 G#5/16 A5/16',
'C6/4 A5/8 C6/8',
'B5/8 A5/8 G5/8 A5/8',
'B5/8 A5/8 G5/8 A5/8',
'B5/8 A5/8 G5/8 F#5/8',
'E5/4'];
现在,我想使用 VexFlow
在一些五线谱上呈现这些音符。
请记住,移动设备上的显示应该没问题,并且配乐上可能有多个声音。
现在我创建了一个方法让每个小节都有一个五线谱:
private renderSoundtrackVexflow(name: string, soundtrack: Soundtrack) {
const context = this.renderVexflowContext(name, VEXFLOW_WIDTH, VEXFLOW_HEIGHT);
context.setFont('Arial', 10, '').setBackgroundFillStyle('#eed'); // TODO Hard coded values
if (soundtrack.hasTracks()) {
let staveIndex: number = 0;
const voices: Array<vexflow.Flow.Voice> = new Array<vexflow.Flow.Voice>();
for (const track of soundtrack.tracks) {
if (track.hasMeasures()) {
for (const measure of track.measures) {
if (measure.hasNotes()) {
const stave = new this.VF.Stave(0, staveIndex * (VEXFLOW_STAVE_HEIGHT + VEXFLOW_STAVE_MARGIN), VEXFLOW_WIDTH);
staveIndex++;
stave.setContext(context);
stave.addClef(VEXFLOW_CLEF);
stave.addTimeSignature(this.renderTimeSignature(measure));
stave.draw();
const notes = new Array<vexflow.Flow.StaveNote>();
const voice = new this.VF.Voice();
voice.setStrict(false);
voice.setContext(context);
voice.setStave(stave);
for (const placedNote of measure.placedNotes) {
const note: Note = placedNote.note;
notes.push(new this.VF.StaveNote({ keys: [ this.renderAbc(note) ], duration: this.renderDuration(note) }));
}
voice.addTickables(notes);
voices.push(voice);
}
}
const formatter = new this.VF.Formatter();
formatter.joinVoices(voices).format(voices, VEXFLOW_WIDTH);
for (const voice of voices) {
voice.draw();
console.log('Min voice width: ' + formatter.getMinTotalWidth(voice));
}
}
}
}
}
但是在页面上,音符在五线谱上显示了一点,但是在五线谱之间显示了一些音符。
这个问题有点老了,但万一你还需要一个解决方案...
问题是所有音符的词干都朝上。要解决此问题,请将 auto_stem: true
和 clef: "treble"
添加到传递给 VF.StaveNote()
的选项列表中,请参阅 VexFlow: Stem Direction 了解更多信息。这是创建注释的更正行:
notes.push(new this.VF.StaveNote({
keys: [ this.renderAbc(note) ],
duration: this.renderDuration(note),
auto_stem: true,
clef: "treble"
}));
使用Tone.js
,我可以演奏这首旋律:
const textMeasures = ['rest/4 B4/16 A4/16 G#4/16 A4/16',
'C5/8 rest/8 D5/16 C5/16 B4/16 C5/16',
'E5/8 rest/8 F5/16 E5/16 D#5/16 E5/16',
'B5/16 A5/16 G#5/16 A5/16 B5/16 A5/16 G#5/16 A5/16',
'C6/4 A5/8 C6/8',
'B5/8 A5/8 G5/8 A5/8',
'B5/8 A5/8 G5/8 A5/8',
'B5/8 A5/8 G5/8 F#5/8',
'E5/4'];
现在,我想使用 VexFlow
在一些五线谱上呈现这些音符。
请记住,移动设备上的显示应该没问题,并且配乐上可能有多个声音。
现在我创建了一个方法让每个小节都有一个五线谱:
private renderSoundtrackVexflow(name: string, soundtrack: Soundtrack) {
const context = this.renderVexflowContext(name, VEXFLOW_WIDTH, VEXFLOW_HEIGHT);
context.setFont('Arial', 10, '').setBackgroundFillStyle('#eed'); // TODO Hard coded values
if (soundtrack.hasTracks()) {
let staveIndex: number = 0;
const voices: Array<vexflow.Flow.Voice> = new Array<vexflow.Flow.Voice>();
for (const track of soundtrack.tracks) {
if (track.hasMeasures()) {
for (const measure of track.measures) {
if (measure.hasNotes()) {
const stave = new this.VF.Stave(0, staveIndex * (VEXFLOW_STAVE_HEIGHT + VEXFLOW_STAVE_MARGIN), VEXFLOW_WIDTH);
staveIndex++;
stave.setContext(context);
stave.addClef(VEXFLOW_CLEF);
stave.addTimeSignature(this.renderTimeSignature(measure));
stave.draw();
const notes = new Array<vexflow.Flow.StaveNote>();
const voice = new this.VF.Voice();
voice.setStrict(false);
voice.setContext(context);
voice.setStave(stave);
for (const placedNote of measure.placedNotes) {
const note: Note = placedNote.note;
notes.push(new this.VF.StaveNote({ keys: [ this.renderAbc(note) ], duration: this.renderDuration(note) }));
}
voice.addTickables(notes);
voices.push(voice);
}
}
const formatter = new this.VF.Formatter();
formatter.joinVoices(voices).format(voices, VEXFLOW_WIDTH);
for (const voice of voices) {
voice.draw();
console.log('Min voice width: ' + formatter.getMinTotalWidth(voice));
}
}
}
}
}
但是在页面上,音符在五线谱上显示了一点,但是在五线谱之间显示了一些音符。
这个问题有点老了,但万一你还需要一个解决方案...
问题是所有音符的词干都朝上。要解决此问题,请将 auto_stem: true
和 clef: "treble"
添加到传递给 VF.StaveNote()
的选项列表中,请参阅 VexFlow: Stem Direction 了解更多信息。这是创建注释的更正行:
notes.push(new this.VF.StaveNote({
keys: [ this.renderAbc(note) ],
duration: this.renderDuration(note),
auto_stem: true,
clef: "treble"
}));