Untitled

 avatar
unknown
plain_text
a year ago
2.9 kB
5
Indexable
    const fetchAndDecodeAudio = async (url: string): Promise<AudioBuffer> => {
      const response = await fetch(url);
      const audioData = await response.arrayBuffer();
      const audioContext = new AudioContext();
      return audioContext.decodeAudioData(audioData);
    };

    const analyzePlaybackAudio = (
      audioBuffer: AudioBuffer,
      segmentDuration: number
    ) => {
      const sampleRate = audioBuffer.sampleRate;
      const segmentSize = Math.floor(segmentDuration * sampleRate);
      const totalSamples = audioBuffer.length;
      const numberOfSegments = Math.ceil(audioBuffer.length / segmentSize);
      const volumeData = [];
      for (let i = 0; i < numberOfSegments; i++) {
        const startSample = i * segmentSize;
        const endSample = Math.min(startSample + segmentSize, totalSamples);
        const segment = audioBuffer
          .getChannelData(0)
          .slice(startSample, endSample);
        const rms = Math.sqrt(
          segment.reduce((sum, value) => sum + value * value, 0) /
            segment.length
        );
        volumeData.push(rms);
      }
      return volumeData;
    };

    const drawPlaybackRecording = async (
      volumeData: number[],
      canvas: HTMLCanvasElement
    ) => {
      const ctx = canvas.getContext("2d");

      if (!ctx) return;

      const width = canvas.width;
      const height = canvas.height;
      const gap = 2;
      const totalGapWidth = (volumeData.length - 1) * gap;
      const availableWidth = width - totalGapWidth;
      const barWidth = availableWidth / volumeData.length;
      const sliceWidth = barWidth + gap;

      ctx.clearRect(0, 0, width, height);
      ctx.fillStyle = "white";

      let maxVolume = volumeData[0];
      let minVolume = volumeData[0];

      volumeData.forEach((volume) => {
        if (volume > maxVolume) {
          maxVolume = volume;
        }
        if (volume < minVolume) {
          minVolume = volume;
        }
      });

      let normalizedVolumeData = volumeData.map(
        (volume) => (volume - minVolume) / (maxVolume - minVolume)
      );

      let x = 0;

      normalizedVolumeData.forEach((volume, index) => {
        const barHeight = (Math.log10(volume * 100) * height) / 5;
        console.log(Math.log10(volume * 1000));
        let y = (height - barHeight) / 2;
        ctx.fillRect(x, y, barWidth, barHeight);
        x += sliceWidth;
      });
    };

    const processAndVisualizePlayback = async (
      audioUrl: string,
      segmentDuration: number
    ) => {
      const audioBuffer = await fetchAndDecodeAudio(audioUrl);
      const analyzedData = analyzePlaybackAudio(audioBuffer, segmentDuration);

      playbackCanvas.value = document.querySelector(
        "#playback"
      ) as HTMLCanvasElement;
      drawPlaybackRecording(analyzedData, playbackCanvas.value);
    };
Editor is loading...
Leave a Comment