Skip to content

Commit

Permalink
refactor: audioPlayer.tsを新規作成しaudio.tsの一部機能を移転 (VOICEVOX#1579)
Browse files Browse the repository at this point in the history
  • Loading branch information
thiramisu authored Sep 24, 2023
1 parent c188c0c commit dea4a57
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 137 deletions.
112 changes: 0 additions & 112 deletions src/store/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,16 +248,6 @@ export function applyAudioPresetToAudioItem(
}

const audioBlobCache: Record<string, Blob> = {};
// ユニットテストが落ちるのを回避するための遅延読み込み
const getAudioElement = (() => {
let audioElement: HTMLAudioElement | undefined = undefined;
return () => {
if (audioElement == undefined) {
audioElement = new Audio();
}
return audioElement;
};
})();

export const audioStoreState: AudioStoreState = {
characterInfos: {},
Expand All @@ -268,7 +258,6 @@ export const audioStoreState: AudioStoreState = {
audioStates: {},
// audio elementの再生オフセット
audioPlayStartPoint: undefined,
nowPlayingAudioKey: undefined,
nowPlayingContinuously: false,
};

Expand Down Expand Up @@ -305,24 +294,6 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
},
},

NOW_PLAYING: {
getter(state, getters) {
const activeAudioKey = getters.ACTIVE_AUDIO_KEY;
return (
activeAudioKey != undefined &&
activeAudioKey === state.nowPlayingAudioKey
);
},
},

ACTIVE_AUDIO_ELEM_CURRENT_TIME: {
getter: (state) => {
return state._activeAudioKey !== undefined
? getAudioElement().currentTime
: undefined;
},
},

LOAD_CHARACTER: {
action: createUILockAction(async ({ commit, dispatch }, { engineId }) => {
const speakers = await dispatch("INSTANTIATE_ENGINE_CONNECTOR", {
Expand Down Expand Up @@ -574,15 +545,6 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
},
},

SET_AUDIO_NOW_PLAYING: {
mutation(
state,
{ audioKey, nowPlaying }: { audioKey: AudioKey; nowPlaying: boolean }
) {
state.nowPlayingAudioKey = nowPlaying ? audioKey : undefined;
},
},

SET_AUDIO_NOW_GENERATING: {
mutation(
state,
Expand Down Expand Up @@ -1797,13 +1759,6 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
),
},

// NOTE: リファクタリング中、別ファイルに移動予定
SET_AUDIO_SOURCE: {
mutation(_, { audioBlob }: { audioBlob: Blob }) {
getAudioElement().src = URL.createObjectURL(audioBlob);
},
},

PLAY_AUDIO_BLOB: {
action: createUILockAction(
async (
Expand Down Expand Up @@ -1831,73 +1786,6 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
),
},

// NOTE: リファクタリング中、別ファイルに移動予定
PLAY_AUDIO_PLAYER: {
async action(
{ state, commit },
{ offset, audioKey }: { offset?: number; audioKey?: AudioKey }
) {
const audioElement = getAudioElement();

if (offset !== undefined) {
audioElement.currentTime = offset;
}

// 一部ブラウザではsetSinkIdが実装されていないので、その環境では無視する
if (audioElement.setSinkId) {
audioElement
.setSinkId(state.savingSetting.audioOutputDevice)
.catch((err) => {
const stop = () => {
audioElement.pause();
audioElement.removeEventListener("canplay", stop);
};
audioElement.addEventListener("canplay", stop);
window.electron.showMessageDialog({
type: "error",
title: "エラー",
message: "再生デバイスが見つかりません",
});
throw new Error(err);
});
}

// 再生終了時にresolveされるPromiseを返す
const played = async () => {
if (audioKey) {
commit("SET_AUDIO_NOW_PLAYING", { audioKey, nowPlaying: true });
}
};
audioElement.addEventListener("play", played);

let paused: () => void;
const audioPlayPromise = new Promise<boolean>((resolve) => {
paused = () => {
resolve(audioElement.ended);
};
audioElement.addEventListener("pause", paused);
}).finally(async () => {
audioElement.removeEventListener("play", played);
audioElement.removeEventListener("pause", paused);
if (audioKey) {
commit("SET_AUDIO_NOW_PLAYING", { audioKey, nowPlaying: false });
}
});

audioElement.play();

return audioPlayPromise;
},
},

STOP_AUDIO: {
// 停止中でも呼び出して問題ない
action() {
// PLAY_ でonpause時の処理が設定されているため、pauseするだけで良い
getAudioElement().pause();
},
},

SET_AUDIO_PRESET_KEY: {
mutation(
state,
Expand Down
122 changes: 122 additions & 0 deletions src/store/audioPlayer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/**
* HTMLAudioElement周りの音声再生・停止などを担当する。
*/
import { createPartialStore } from "./vuex";
import { AudioPlayerStoreState, AudioPlayerStoreTypes } from "./type";
import { AudioKey } from "@/type/preload";

// ユニットテストが落ちるのを回避するための遅延読み込み
const getAudioElement = (() => {
let audioElement: HTMLAudioElement | undefined = undefined;
return () => {
if (audioElement == undefined) {
audioElement = new Audio();
}
return audioElement;
};
})();

export const audioPlayerStoreState: AudioPlayerStoreState = {
nowPlayingAudioKey: undefined,
};

export const audioPlayerStore = createPartialStore<AudioPlayerStoreTypes>({
ACTIVE_AUDIO_ELEM_CURRENT_TIME: {
getter: (state) => {
return state._activeAudioKey !== undefined
? getAudioElement().currentTime
: undefined;
},
},

NOW_PLAYING: {
getter(state, getters) {
const activeAudioKey = getters.ACTIVE_AUDIO_KEY;
return (
activeAudioKey != undefined &&
activeAudioKey === state.nowPlayingAudioKey
);
},
},

SET_AUDIO_NOW_PLAYING: {
mutation(
state,
{ audioKey, nowPlaying }: { audioKey: AudioKey; nowPlaying: boolean }
) {
state.nowPlayingAudioKey = nowPlaying ? audioKey : undefined;
},
},

SET_AUDIO_SOURCE: {
mutation(_, { audioBlob }: { audioBlob: Blob }) {
getAudioElement().src = URL.createObjectURL(audioBlob);
},
},

PLAY_AUDIO_PLAYER: {
async action(
{ state, commit },
{ offset, audioKey }: { offset?: number; audioKey?: AudioKey }
) {
const audioElement = getAudioElement();

if (offset !== undefined) {
audioElement.currentTime = offset;
}

// 一部ブラウザではsetSinkIdが実装されていないので、その環境では無視する
if (audioElement.setSinkId) {
audioElement
.setSinkId(state.savingSetting.audioOutputDevice)
.catch((err) => {
const stop = () => {
audioElement.pause();
audioElement.removeEventListener("canplay", stop);
};
audioElement.addEventListener("canplay", stop);
window.electron.showMessageDialog({
type: "error",
title: "エラー",
message: "再生デバイスが見つかりません",
});
throw new Error(err);
});
}

// 再生終了時にresolveされるPromiseを返す
const played = async () => {
if (audioKey) {
commit("SET_AUDIO_NOW_PLAYING", { audioKey, nowPlaying: true });
}
};
audioElement.addEventListener("play", played);

let paused: () => void;
const audioPlayPromise = new Promise<boolean>((resolve) => {
paused = () => {
resolve(audioElement.ended);
};
audioElement.addEventListener("pause", paused);
}).finally(async () => {
audioElement.removeEventListener("play", played);
audioElement.removeEventListener("pause", paused);
if (audioKey) {
commit("SET_AUDIO_NOW_PLAYING", { audioKey, nowPlaying: false });
}
});

audioElement.play();

return audioPlayPromise;
},
},

STOP_AUDIO: {
// 停止中でも呼び出して問題ない
action() {
// PLAY_ でonpause時の処理が設定されているため、pauseするだけで良い
getAudioElement().pause();
},
},
});
5 changes: 5 additions & 0 deletions src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
audioCommandStoreState,
getCharacterInfo,
} from "./audio";
import { audioPlayerStoreState, audioPlayerStore } from "./audioPlayer";
import { projectStoreState, projectStore } from "./project";
import { uiStoreState, uiStore } from "./ui";
import { settingStoreState, settingStore } from "./setting";
Expand Down Expand Up @@ -349,6 +350,7 @@ export const store = createStore<State, AllGetters, AllActions, AllMutations>({
state: {
...uiStoreState,
...audioStoreState,
...audioPlayerStoreState,
...commandStoreState,
...engineStoreState,
...projectStoreState,
Expand All @@ -363,6 +365,7 @@ export const store = createStore<State, AllGetters, AllActions, AllMutations>({
getters: {
...uiStore.getters,
...audioStore.getters,
...audioPlayerStore.getters,
...commandStore.getters,
...engineStore.getters,
...projectStore.getters,
Expand All @@ -377,6 +380,7 @@ export const store = createStore<State, AllGetters, AllActions, AllMutations>({
mutations: {
...uiStore.mutations,
...audioStore.mutations,
...audioPlayerStore.mutations,
...commandStore.mutations,
...engineStore.mutations,
...projectStore.mutations,
Expand All @@ -391,6 +395,7 @@ export const store = createStore<State, AllGetters, AllActions, AllMutations>({
actions: {
...uiStore.actions,
...audioStore.actions,
...audioPlayerStore.actions,
...engineStore.actions,
...commandStore.actions,
...projectStore.actions,
Expand Down
Loading

0 comments on commit dea4a57

Please sign in to comment.