diff --git a/public/howtouse.md b/public/howtouse.md
index 4f5f1fa6f4..e316c3a0ab 100644
--- a/public/howtouse.md
+++ b/public/howtouse.md
@@ -323,7 +323,7 @@ VOICEVOX では、歌声合成機能がプロトタイプ版として提供さ
### ピッチ編集
-「設定」の「実験的機能」から「ソング:ピッチ編集機能」をONにすることで、歌の音程を細かく制御することができます。
+「設定」→「オプション」→「実験的機能」から「ソング:ピッチ編集機能」をONにすることで、歌の音程を細かく制御することができます。
### ソング機能のよくある質問
diff --git a/src/components/Sing/SequencerPitch.vue b/src/components/Sing/SequencerPitch.vue
index 3d350a5f5b..9e30597baa 100644
--- a/src/components/Sing/SequencerPitch.vue
+++ b/src/components/Sing/SequencerPitch.vue
@@ -47,7 +47,7 @@ const props = defineProps<{
| { type: "erase"; startFrame: number; frameLength: number };
}>();
-const { warn } = createLogger("SequencerPitch");
+const { warn, error } = createLogger("SequencerPitch");
const store = useStore();
const singingGuides = computed(() => [...store.state.singingGuides.values()]);
const pitchEditData = computed(() => {
@@ -274,9 +274,6 @@ const updateOriginalPitchDataSectionMap = async () => {
throw new Error("phonemes.length is 0.");
}
const f0 = singingGuide.query.f0;
- const startTime = singingGuide.startTime;
- const startFrame = Math.round(startTime * frameRate);
- const endFrame = startFrame + f0.length;
// 各フレームの音素の配列を生成する
const framePhonemes = convertToFramePhonemes(phonemes);
@@ -284,19 +281,29 @@ const updateOriginalPitchDataSectionMap = async () => {
throw new Error("f0.length and framePhonemes.length do not match.");
}
+ // 歌い方の開始フレームと終了フレームを計算する
+ const singingGuideFrameLength = f0.length;
+ const singingGuideStartFrame = Math.round(
+ singingGuide.startTime * frameRate,
+ );
+ const singingGuideEndFrame =
+ singingGuideStartFrame + singingGuideFrameLength;
+
// 無声子音区間以外のf0をtempDataにコピーする
// NOTE: 無声子音区間は音程が無く、f0の値が大きく上下するので表示しない
- if (tempData.length < endFrame) {
- const valuesToPush = new Array(endFrame - tempData.length).fill(
- VALUE_INDICATING_NO_DATA,
- );
+ if (tempData.length < singingGuideEndFrame) {
+ const valuesToPush = new Array(
+ singingGuideEndFrame - tempData.length,
+ ).fill(VALUE_INDICATING_NO_DATA);
tempData.push(...valuesToPush);
}
- for (let i = 0; i < f0.length; i++) {
- const phoneme = framePhonemes[i];
+ const startFrame = Math.max(0, singingGuideStartFrame);
+ const endFrame = singingGuideEndFrame;
+ for (let i = startFrame; i < endFrame; i++) {
+ const phoneme = framePhonemes[i - singingGuideStartFrame];
const unvoiced = unvoicedPhonemes.includes(phoneme);
if (!unvoiced) {
- tempData[startFrame + i] = f0[i];
+ tempData[i] = f0[i - singingGuideStartFrame];
}
}
}
@@ -425,6 +432,13 @@ onMountedOrActivated(() => {
});
stage = new PIXI.Container();
+ // webGLVersionをチェックする
+ // 2未満の場合、ピッチの表示ができないのでエラーとしてロギングする
+ const webGLVersion = renderer.context.webGLVersion;
+ if (webGLVersion < 2) {
+ error(`webGLVersion is less than 2. webGLVersion: ${webGLVersion}`);
+ }
+
const callback = () => {
if (renderInNextFrame) {
render();
diff --git a/src/components/Sing/ToolBar/EditTargetSwicher.vue b/src/components/Sing/ToolBar/EditTargetSwicher.vue
index a93a4569ce..04e0d7412d 100644
--- a/src/components/Sing/ToolBar/EditTargetSwicher.vue
+++ b/src/components/Sing/ToolBar/EditTargetSwicher.vue
@@ -22,13 +22,14 @@
class="margin-right"
@click="editTarget !== 'PITCH' && changeEditTarget('PITCH')"
>ピッチ編集
Ctrl+クリックで消去ピッチ編集
{{ !isMac ? "Ctrl" : "Cmd" }}+クリックで消去