calculateSpectrogram function

List<Float64List> calculateSpectrogram(
  1. List<double> samples, {
  2. int? hopSize,
  3. int fftSize = 2048,
})

Computes the power spectrogram via Short-Time Fourier Transform (STFT).

Returns a list of Float64List, where each element represents the power spectrum of a frame.

samples: The audio signal. hopSize: Number of samples between frames. Defaults to fftSize / 4. fftSize: Size of the FFT window.

Implementation

List<Float64List> calculateSpectrogram(
  List<double> samples, {
  int? hopSize,
  int fftSize = 2048,
}) {
  final hop = hopSize ?? fftSize ~/ 4;
  final padAmount = fftSize ~/ 2;

  if (samples.length < padAmount) {
    throw ArgumentError(
      'Signal length (${samples.length}) must be >= fftSize // 2 ($padAmount).',
    );
  }
  final paddedSamples = Float64List.fromList(_padReflect(samples, padAmount));

  final window = Float64List(fftSize);
  for (int i = 0; i < fftSize; i++) {
    window[i] = 0.5 * (1.0 - cos(2.0 * pi * i / fftSize));
  }

  final stft = STFT(fftSize, window);
  final spectrogram = <Float64List>[];

  stft.run(paddedSamples, (Float64x2List freq) {
    final bins = freq.discardConjugates();
    final expectedBins = fftSize ~/ 2 + 1;
    if (bins.length != expectedBins) {
      throw StateError('STFT bin mismatch.');
    }
    final mags = bins.magnitudes();
    for (int i = 0; i < mags.length; i++) {
      mags[i] *= mags[i];
    }
    spectrogram.add(mags);
  }, hop);

  return spectrogram;
}