73 lines
		
	
	
	
		
			1.7 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
	
		
			1.7 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// Copyright 2023 Signal Messenger, LLC
 | 
						|
// SPDX-License-Identifier: AGPL-3.0-only
 | 
						|
 | 
						|
import { noop } from 'lodash';
 | 
						|
import { useEffect, useState } from 'react';
 | 
						|
import { computePeaks } from '../components/VoiceNotesPlaybackContext';
 | 
						|
import * as log from '../logging/log';
 | 
						|
 | 
						|
type WaveformData = {
 | 
						|
  peaks: ReadonlyArray<number>;
 | 
						|
  duration: number;
 | 
						|
};
 | 
						|
 | 
						|
export function useComputePeaks({
 | 
						|
  audioUrl,
 | 
						|
  activeDuration,
 | 
						|
  barCount,
 | 
						|
  onCorrupted,
 | 
						|
}: {
 | 
						|
  audioUrl: string | undefined;
 | 
						|
  activeDuration: number | undefined;
 | 
						|
  barCount: number;
 | 
						|
  onCorrupted: () => void;
 | 
						|
}): { peaks: ReadonlyArray<number>; hasPeaks: boolean; duration: number } {
 | 
						|
  const [waveformData, setWaveformData] = useState<WaveformData | undefined>(
 | 
						|
    undefined
 | 
						|
  );
 | 
						|
 | 
						|
  // This effect loads audio file and computes its RMS peak for displaying the
 | 
						|
  // waveform.
 | 
						|
  useEffect(() => {
 | 
						|
    if (!audioUrl) {
 | 
						|
      return noop;
 | 
						|
    }
 | 
						|
 | 
						|
    log.info('MessageAudio: loading audio and computing waveform');
 | 
						|
 | 
						|
    let canceled = false;
 | 
						|
 | 
						|
    void (async () => {
 | 
						|
      try {
 | 
						|
        const { peaks: newPeaks, duration: newDuration } = await computePeaks(
 | 
						|
          audioUrl,
 | 
						|
          barCount
 | 
						|
        );
 | 
						|
        if (canceled) {
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        setWaveformData({
 | 
						|
          peaks: newPeaks,
 | 
						|
          duration: Math.max(newDuration, 1e-23),
 | 
						|
        });
 | 
						|
      } catch (err) {
 | 
						|
        log.error(
 | 
						|
          'MessageAudio: computePeaks error, marking as corrupted',
 | 
						|
          err
 | 
						|
        );
 | 
						|
 | 
						|
        onCorrupted();
 | 
						|
      }
 | 
						|
    })();
 | 
						|
 | 
						|
    return () => {
 | 
						|
      canceled = true;
 | 
						|
    };
 | 
						|
  }, [audioUrl, barCount, onCorrupted]);
 | 
						|
 | 
						|
  return {
 | 
						|
    duration: waveformData?.duration ?? activeDuration ?? 1e-23,
 | 
						|
    hasPeaks: waveformData !== undefined,
 | 
						|
    peaks: waveformData?.peaks ?? new Array(barCount).fill(0),
 | 
						|
  };
 | 
						|
}
 |