Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 92 additions & 1 deletion src/store/singing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,20 @@ const syncPhraseSequences = (
phraseSingingVoices: Map<SingingVoiceKey, SingingVoice>,
tempos: Tempo[],
tpqn: number,
callbacks: {
onSequenceGeneratedAndRegistered: (
phraseKey: PhraseKey,
sequenceId: SequenceId,
) => void;
onSequenceDeleted: (phraseKey: PhraseKey) => void;
},
) => {
// 不要になったシーケンスを削除する
deleteUnnecessarySequences(phrases, phraseSequenceInfos);
deleteUnnecessarySequences(
phrases,
phraseSequenceInfos,
callbacks.onSequenceDeleted,
);

// 不足しているシーケンスを新しく作成する
createMissingSequences(
Expand All @@ -455,6 +466,7 @@ const syncPhraseSequences = (
tempos,
tpqn,
phraseSequenceInfos,
callbacks.onSequenceGeneratedAndRegistered,
);
};

Expand All @@ -469,6 +481,7 @@ const syncPhraseSequences = (
const deleteUnnecessarySequences = (
phrases: Map<PhraseKey, Phrase>,
phraseSequenceInfos: Map<PhraseKey, PhraseSequenceInfo>,
onSequenceDeleted: (phraseKey: PhraseKey) => void,
) => {
for (const [phraseKey, sequenceInfo] of phraseSequenceInfos) {
const phrase = phrases.get(phraseKey);
Expand Down Expand Up @@ -500,6 +513,8 @@ const deleteUnnecessarySequences = (
if (isRegisteredSequence(sequenceInfo.sequenceId)) {
deleteSequence(sequenceInfo.sequenceId);
logger.info(`Deleted sequence. ID: ${sequenceInfo.sequenceId}`);

onSequenceDeleted(phraseKey);
}
}
}
Expand All @@ -514,6 +529,10 @@ const createMissingSequences = (
tempos: Tempo[],
tpqn: number,
phraseSequenceInfos: Map<PhraseKey, PhraseSequenceInfo>,
onSequenceGeneratedAndRegistered: (
phraseKey: PhraseKey,
sequenceId: SequenceId,
) => void,
) => {
for (const [phraseKey, phrase] of phrases) {
// 既にシーケンスが存在する場合は、この関数では何もしない
Expand All @@ -528,6 +547,7 @@ const createMissingSequences = (
phrase,
phraseSingingVoices,
phraseSequenceInfos,
onSequenceGeneratedAndRegistered,
);
} else {
createNoteSequenceForPhrase(
Expand All @@ -536,6 +556,7 @@ const createMissingSequences = (
tempos,
tpqn,
phraseSequenceInfos,
onSequenceGeneratedAndRegistered,
);
}
}
Expand All @@ -549,6 +570,10 @@ const createAudioSequenceForPhrase = (
phrase: Phrase,
phraseSingingVoices: Map<SingingVoiceKey, SingingVoice>,
phraseSequenceInfos: Map<PhraseKey, PhraseSequenceInfo>,
onSequenceGeneratedAndRegistered: (
phraseKey: PhraseKey,
sequenceId: SequenceId,
) => void,
) => {
if (phrase.singingVoiceKey == undefined) {
throw new UnreachableError("phrase.singingVoiceKey is undefined.");
Expand Down Expand Up @@ -577,6 +602,8 @@ const createAudioSequenceForPhrase = (
) {
registerSequence(newSequenceId, audioSequence);
logger.info(`Registered audio sequence. ID: ${newSequenceId}`);

onSequenceGeneratedAndRegistered(phraseKey, newSequenceId);
}
});
};
Expand All @@ -590,6 +617,10 @@ const createNoteSequenceForPhrase = (
tempos: Tempo[],
tpqn: number,
phraseSequenceInfos: Map<PhraseKey, PhraseSequenceInfo>,
onSequenceGeneratedAndRegistered: (
phraseKey: PhraseKey,
sequenceId: SequenceId,
) => void,
) => {
const newSequenceId = SequenceId(uuid4());
phraseSequenceInfos.set(phraseKey, {
Expand All @@ -606,6 +637,8 @@ const createNoteSequenceForPhrase = (

registerSequence(newSequenceId, noteSequence);
logger.info(`Registered note sequence. ID: ${newSequenceId}`);

onSequenceGeneratedAndRegistered(phraseKey, newSequenceId);
};

/**
Expand Down Expand Up @@ -695,6 +728,7 @@ export const singingStoreState: SingingStoreState = {
phraseQueries: new Map(),
phraseSingingPitches: new Map(),
phraseSingingVolumes: new Map(),
phraseSequenceIds: new Map(),
sequencerZoomX: 0.5,
sequencerZoomY: 0.75,
sequencerSnapType: 16,
Expand Down Expand Up @@ -984,6 +1018,23 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
},
},

GET_SEQUENCE_AUDIO_BUFFER: {
getter: () => (sequenceId: SequenceId) => {
const sequence = sequences.get(sequenceId);
if (sequence == undefined) {
throw new Error(`Sequence with id ${sequenceId} is not registered.`);
}
if (sequence.type === "audio") {
if (sequence.audioEvents.length !== 1) {
throw new Error("AudioSequence has invalid number of AudioEvents.");
}
return sequence.audioEvents[0].buffer;
} else {
return undefined;
}
},
},

SET_NOTES: {
mutation(state, { notes, trackId }) {
state.editingLyricNoteId = undefined;
Expand Down Expand Up @@ -1219,6 +1270,20 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
*/
CREATE_AND_SETUP_SONG_TRACK_RENDERER: {
async action({ state, actions, mutations }) {
const onSequenceGeneratedAndRegistered = (
phraseKey: PhraseKey,
sequenceId: SequenceId,
) => {
mutations.SET_PHRASE_SEQUENCE_ID({
phraseKey,
sequenceId,
});
};

const onSequenceDeleted = (phraseKey: PhraseKey) => {
mutations.DELETE_PHRASE_SEQUENCE_ID({ phraseKey });
};

/**
* `phrasesGenerated` イベントのハンドラ。
* フレーズが生成された直後に呼び出される。現状ログ出力のみ。
Expand Down Expand Up @@ -1332,6 +1397,10 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
phraseSingingVoices,
event.snapshot.tempos,
event.snapshot.tpqn,
{
onSequenceGeneratedAndRegistered,
onSequenceDeleted,
},
);

logger.info("Cache loaded and applied to phrases.");
Expand Down Expand Up @@ -1457,6 +1526,10 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
phraseSingingVoices,
event.snapshot.tempos,
event.snapshot.tpqn,
{
onSequenceGeneratedAndRegistered,
onSequenceDeleted,
},
);

logger.info("Phrase rendering complete.");
Expand Down Expand Up @@ -1714,6 +1787,24 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
},
},

SET_PHRASE_SEQUENCE_ID: {
mutation(
state,
{
phraseKey,
sequenceId,
}: { phraseKey: PhraseKey; sequenceId: SequenceId },
) {
state.phraseSequenceIds.set(phraseKey, sequenceId);
},
},

DELETE_PHRASE_SEQUENCE_ID: {
mutation(state, { phraseKey }: { phraseKey: PhraseKey }) {
state.phraseSequenceIds.delete(phraseKey);
},
},

SELECTED_TRACK: {
getter(state) {
return getSelectedTrackWithFallback(state);
Expand Down
13 changes: 13 additions & 0 deletions src/store/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ export type SingingStoreState = {
phraseQueries: Map<EditorFrameAudioQueryKey, EditorFrameAudioQuery>;
phraseSingingPitches: Map<SingingPitchKey, SingingPitch>;
phraseSingingVolumes: Map<SingingVolumeKey, SingingVolume>;
phraseSequenceIds: Map<PhraseKey, SequenceId>;
sequencerZoomX: number;
sequencerZoomY: number;
sequencerSnapType: number;
Expand Down Expand Up @@ -1156,6 +1157,14 @@ export type SingingStoreTypes = {
mutation: { singingVolumeKey: SingingVolumeKey };
};

SET_PHRASE_SEQUENCE_ID: {
mutation: { phraseKey: PhraseKey; sequenceId: SequenceId };
};

DELETE_PHRASE_SEQUENCE_ID: {
mutation: { phraseKey: PhraseKey };
};

SELECTED_TRACK: {
getter: Track;
};
Expand Down Expand Up @@ -1476,6 +1485,10 @@ export type SingingStoreTypes = {
fileTypeLabel: string;
}): Promise<SaveResultObject>;
};

GET_SEQUENCE_AUDIO_BUFFER: {
getter(sequenceId: SequenceId): AudioBuffer | undefined;
};
};

// eslint-disable-next-line @typescript-eslint/no-empty-object-type
Expand Down
Loading