soiz1 commited on
Commit
da99b9f
·
1 Parent(s): 5c309e0

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +78 -53
index.html CHANGED
@@ -413,11 +413,8 @@
413
  </div>
414
  </div>
415
  </div>
416
- <script type="module">
417
- import * as soundtouch from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/soundtouch.min.js';
418
- window.soundtouch = soundtouch;
419
- </script>
420
- <script>
421
 
422
  document.addEventListener('DOMContentLoaded', function() {
423
  // 要素を取得
@@ -697,71 +694,99 @@
697
  });
698
  }
699
 
700
- function playAudio(file, startTime) {
701
- if (!audioBuffers[file]) return;
702
 
703
- // 既存のソースがあれば停止
704
- if (audioSources[file]) {
705
  try {
706
- audioSources[file].stop();
707
  } catch(e) {
708
- console.log("Audio source already stopped");
709
  }
710
- }
711
-
712
- const source = audioContext.createBufferSource();
713
- source.buffer = audioBuffers[file];
714
-
715
- // SoundTouch プロセッサーを作成
716
- soundTouchNodes[file] = new soundtouch.SoundTouch(audioBuffers[file].sampleRate);
717
- soundTouchNodes[file].tempo = currentPlaybackRate;
718
- soundTouchNodes[file].pitch = 1; // ピッチ変更なし
719
-
720
- // SimpleFilter を作成し、Web Audio Node を取得
721
- const soundTouchProcessor = new soundtouch.SimpleFilter(audioContext, source, soundTouchNodes[file]);
722
-
723
- // soundtouch.getWebAudioNode() を使用してノードを取得
724
- const soundTouchNode = soundtouch.getWebAudioNode(
725
- audioContext,
726
- source,
727
- soundTouchNodes[file]
728
- );
729
 
730
- // ボリュームスライダーの値を取得
731
- const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
732
- const volume = parseFloat(volumeSlider.value) * parseFloat(globalVolumeSlider.value);
 
 
 
 
 
 
 
 
 
 
733
 
734
- // ゲインノードを設定
735
- gainNodes[file].gain.value = volume;
 
 
 
 
 
 
 
736
 
737
- // 接続
738
- soundTouchNode.connect(gainNodes[file]);
739
- gainNodes[file].connect(audioContext.destination);
 
740
 
741
- // 再生
742
- const duration = video.duration || videoDuration;
743
- const endTime = parseFloat(endTimeInput.value) || duration;
744
- const loop = loopCheckbox.checked;
745
 
746
- // 再生範囲を計算
747
- const playStartTime = Math.max(startTime, parseFloat(startTimeInput.value) || 0);
748
- const playEndTime = Math.min(endTime, duration);
749
- const playDuration = playEndTime - playStartTime;
 
 
750
 
751
- // 再生時間が正の場合のみ再生
752
- if (playDuration > 0) {
753
  source.start(0, playStartTime, playDuration);
754
- }
755
 
756
- // ループ設定
757
- if (loop) {
758
  source.loop = true;
759
  source.loopStart = parseFloat(startTimeInput.value) || 0;
760
  source.loopEnd = endTime;
 
 
 
 
 
 
 
 
761
  }
762
 
763
- audioSources[file] = source;
764
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
765
 
766
  // 再生関数
767
  function playMedia() {
 
413
  </div>
414
  </div>
415
  </div>
416
+ <script type="module">
417
+ import { SoundTouch, SimpleFilter, getWebAudioNode } from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/soundtouch.min.js';
 
 
 
418
 
419
  document.addEventListener('DOMContentLoaded', function() {
420
  // 要素を取得
 
694
  });
695
  }
696
 
697
+ function playAudio(file, startTime) {
698
+ if (!audioBuffers[file]) return;
699
 
700
+ // 既存のソースがあれば停止
701
+ if (audioSources[file]) {
702
  try {
703
+ audioSources[file].stop();
704
  } catch(e) {
705
+ console.log("Audio source already stopped");
706
  }
707
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
 
709
+ const source = audioContext.createBufferSource();
710
+ source.buffer = audioBuffers[file];
711
+
712
+ // SoundTouch プロセッサーを作成
713
+ const soundTouch = new SoundTouch(audioBuffers[file].sampleRate);
714
+ soundTouch.tempo = currentPlaybackRate;
715
+ soundTouch.pitch = 1;
716
+
717
+ // BufferSourceを作成
718
+ const bufferSource = new soundtouch.BufferSource(audioBuffers[file].getChannelData(0));
719
+
720
+ // SimpleFilterを作成
721
+ const filter = new SimpleFilter(soundTouch, bufferSource);
722
 
723
+ // ScriptProcessorNodeを作成
724
+ const processor = audioContext.createScriptProcessor(4096, 1, 1);
725
+ processor.onaudioprocess = (event) => {
726
+ const outputBuffer = event.outputBuffer.getChannelData(0);
727
+ const framesExtracted = filter.extract(outputBuffer, outputBuffer.length);
728
+ if (framesExtracted === 0) {
729
+ processor.disconnect();
730
+ }
731
+ };
732
 
733
+ // ボリュームコントロール
734
+ const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
735
+ const volume = parseFloat(volumeSlider.value) * parseFloat(globalVolumeSlider.value);
736
+ gainNodes[file].gain.value = volume;
737
 
738
+ // 接続チェーン
739
+ source.connect(processor);
740
+ processor.connect(gainNodes[file]);
741
+ gainNodes[file].connect(audioContext.destination);
742
 
743
+ // 再生時間計算
744
+ const duration = video.duration || videoDuration;
745
+ const endTime = parseFloat(endTimeInput.value) || duration;
746
+ const playStartTime = Math.max(startTime, parseFloat(startTimeInput.value) || 0);
747
+ const playEndTime = Math.min(endTime, duration);
748
+ const playDuration = playEndTime - playStartTime;
749
 
750
+ if (playDuration > 0) {
 
751
  source.start(0, playStartTime, playDuration);
752
+ }
753
 
754
+ // ループ設定
755
+ if (loopCheckbox.checked) {
756
  source.loop = true;
757
  source.loopStart = parseFloat(startTimeInput.value) || 0;
758
  source.loopEnd = endTime;
759
+ }
760
+
761
+ audioSources[file] = {
762
+ source: source,
763
+ processor: processor,
764
+ filter: filter
765
+ };
766
+ soundTouchNodes[file] = soundTouch;
767
  }
768
 
769
+ // 一時停止関数も修正
770
+ function pauseMedia() {
771
+ if (!isPlaying) return;
772
+
773
+ video.pause();
774
+ audioFiles.forEach(file => {
775
+ if (audioSources[file]) {
776
+ try {
777
+ audioSources[file].source.stop();
778
+ audioSources[file].processor.disconnect();
779
+ } catch(e) {
780
+ console.log("Audio source already stopped");
781
+ }
782
+ audioSources[file] = null;
783
+ }
784
+ });
785
+
786
+ isPlaying = false;
787
+ isVideoPlaying = false;
788
+ playPauseBtn.textContent = '▶';
789
+ }
790
 
791
  // 再生関数
792
  function playMedia() {