Skip to content

Commit

Permalink
#986 MIDIからの表示
Browse files Browse the repository at this point in the history
  • Loading branch information
Romot committed Jan 5, 2023
1 parent 53da199 commit 749b48a
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 63 deletions.
46 changes: 46 additions & 0 deletions src/components/Sing/ScoreNote.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<div class="score-note">
<div
class="score-note-bar"
v-bind:style="{
left: `${position}px`,
bottom: `${(midi + 1) * 24}px`,
width: `${duration}px`,
height: '24px',
zIndex: 100,
}"
/>
</div>
</template>

<script lang="ts">
import { defineComponent, computed } from "vue";
import { useStore } from "@/store";
export default defineComponent({
name: "SingScoreNote",
props: {
position: { type: Number, required: true },
duration: { type: Number, required: true },
midi: { type: Number, required: true },
lyric: { type: String, required: false },
},
setup(props) {
const store = useStore();
return null;
},
});
</script>

<style scoped lang="scss">
@use '@/styles/variables' as vars;
@use '@/styles/colors' as colors;
.score-note-bar {
background: #ddd;
border: 1px solid #555;
position: relative;
}
</style>
125 changes: 76 additions & 49 deletions src/components/Sing/ScoreSequencer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,55 @@
<div class="score-sequencer">
<div class="sequencer-keys">
<div
v-for="key in displayKeys"
:key="key.midi"
:class="`sequencer-key sequencer-key-${key.color} ${
key.pitch === 'C' ? 'sequencer-key-octave' : ''
} ${key.pitch === 'F' || key.pitch === 'D' ? 'sequencer-key-f' : ''}`"
:id="`sequencer-key-${key.midi}`"
:title="key.name"
v-for="y in gridY"
:key="y.midi"
:class="`sequencer-key ${y.color} ${y.pitch === 'C' ? 'key-c' : ''} ${
y.pitch === 'F' ? 'key-f' : ''
}`"
:id="`sequencer-key-${y.midi}`"
:title="y.name"
>
{{ key.pitch === "C" ? key.name : "" }}
{{ y.pitch === "C" ? y.name : "" }}
</div>
</div>
<div class="sequencer-grid-y">
<div class="sequencer-grids">
<div
v-for="key in displayKeys"
:key="key.midi"
:class="`sequencer-y sequencer-y-${key.color} ${
key.pitch === 'C' ? 'sequencer-y-octave' : ''
} ${key.pitch === 'F' ? 'sequencer-y-f' : ''}`"
:id="`sequencer-y-${key.midi}`"
/>
</div>
<div
v-for="(note, index) in notes"
:key="index"
v-bind:style="{
background: '#ddd',
position: 'relative',
left: `${note.position}px`,
bottom: `${(note.midi + 1) * 24}px`,
width: `${note.duration}px`,
height: '24px',
zIndex: 100,
}"
>
{{ note.midi }}
v-for="x in gridX"
:key="x"
:class="`sequencer-row`"
:id="`sequencer-row-${x}`"
>
<div
v-for="y in gridY"
:key="y.midi"
:class="`sequencer-cell ${y.color} ${
y.pitch === 'C' ? 'key-c' : ''
} ${y.pitch === 'F' ? 'key-f' : ''}`"
:id="`sequencer-cell-${x}-${y.midi}`"
/>
</div>
<div
v-for="(note, index) in notes"
:key="index"
v-bind:style="{
background: '#ddd',
position: 'absolute',
border: '1px solid #333',
left: `${note.position}px`,
bottom: `${(note.midi + 1) * 24}px`,
width: `${note.duration}px`,
height: '24px',
zIndex: 10,
}"
>
{{ note.midi }}
</div>
</div>
<div class="sequencer-grid-x" />
</div>
</template>

<script lang="ts">
import { defineComponent, computed } from "vue";
import { defineComponent, computed, ref } from "vue";
import { useStore } from "@/store";
import { midiKeys } from "@/helpers/singHelper";
Expand All @@ -52,12 +59,25 @@ export default defineComponent({
setup() {
const store = useStore();
const displayKeys = midiKeys.reverse();
const gridY = midiKeys;
const gridX = computed(() => {
const resolution = store.state.score?.resolution || 480;
// NOTE: 最低幅: 仮
const minDuration = resolution * 4 * 16;
const lastNote = store.state.score?.notes.slice(-1)[0];
const totalDuration = lastNote
? Math.min(lastNote.position + lastNote.duration, minDuration)
: minDuration;
// NOTE: グリッド幅1/16: 設定できるようにする必要あり
const gridDuration = resolution / 4;
return [...Array(Math.ceil(totalDuration / gridDuration)).keys()];
});
const notes = computed(() => store.state.score?.notes);
const timeSignatures = computed(() => store.state.score?.timeSignatures);
return {
displayKeys,
timeSignatures,
gridY,
gridX,
notes,
};
},
Expand All @@ -72,19 +92,18 @@ export default defineComponent({
display: block;
overflow: auto;
margin-left: 0;
padding-left: 64px;
padding-left: 0;
position: relative;
height: 100%;
width: auto;
}
.sequencer-keys {
background: white;
border-right: 1px solid #ccc;
position: absolute;
top: 0;
position: sticky;
left: 0;
width: 64px;
z-index: 10;
z-index: 100;
}
.sequencer-key {
Expand All @@ -102,11 +121,11 @@ export default defineComponent({
border-bottom: 1px solid solid #ccc;
}
&.sequencer-key-white {
&.white {
background: white;
}
&.sequencer-key-black {
&.black {
background: #555;
&:before {
Expand All @@ -131,30 +150,38 @@ export default defineComponent({
}
}
&.sequencer-key-octave {
&.key-c {
border-bottom: 1px solid #ccc;
}
&.sequencer-key-f {
&.key-f {
border-bottom: 1px solid #ddd;
}
}
.sequencer-grid-y {
min-width: 100%;
position: relative;
.sequencer-grids {
display: flex;
position: absolute;
top: 0;
left: 64px;
}
.sequencer-row {
border-right: 1px solid #ddd;
flex-shrink: 0;
width: 120px;
}
.sequencer-y {
.sequencer-cell {
border-bottom: 1px solid #ddd;
flex-shrink: 0;
height: 24px;
&.sequencer-y-black {
&.black {
background: #f2f2f2;
}
&.sequencer-y-octave {
&.key-c {
border-bottom: 1px solid #ccc;
}
}
Expand Down
28 changes: 15 additions & 13 deletions src/helpers/singHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,21 @@ export function getKeyColorFromMidi(midi: number): string {
return mapWhiteKeys.includes(pitch) ? "white" : "black";
}

export const midiKeys = [...Array(128)].map((_, midi) => {
const pitch = getPitchFromMidi(midi);
const octave = getOctaveFromMidi(midi);
const name = `${pitch}${octave}`;
const color = getKeyColorFromMidi(midi);
return {
midi,
pitch,
octave,
name,
color,
};
});
export const midiKeys = [...Array(128)]
.map((_, midi) => {
const pitch = getPitchFromMidi(midi);
const octave = getOctaveFromMidi(midi);
const name = `${pitch}${octave}`;
const color = getKeyColorFromMidi(midi);
return {
midi,
pitch,
octave,
name,
color,
};
})
.reverse();

export function getDisplayKey(midi: number): object {
return midiKeys[midi];
Expand Down
18 changes: 17 additions & 1 deletion src/store/singing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,23 @@ import { Midi } from "@tonejs/midi";
export const singingStoreState: SingingStoreState = {
engineId: undefined,
styleId: undefined,
score: undefined,
score: {
resolution: 480,
tempos: [
{
position: 0,
tempo: 120,
},
],
timeSignatures: [
{
position: 0,
beats: 4,
beatType: 4,
},
],
notes: [],
},
renderPhrases: [],
// NOTE: UIの状態は試行のためsinging.tsに局所化する+Hydrateが必要
isShowSinger: true,
Expand Down

0 comments on commit 749b48a

Please sign in to comment.