getWaveformBytes method

  1. @override
Future<List<double>> getWaveformBytes(
  1. Uint8List inputData,
  2. String formatHint,
  3. int numberOfSamples, {
  4. WaveformNormalization normalization = WaveformNormalization.perFile,
})
override

Implementation

@override
Future<List<double>> getWaveformBytes(
  Uint8List inputData,
  String formatHint,
  int numberOfSamples, {
  WaveformNormalization normalization = WaveformNormalization.perFile,
}) async {
  try {
    final buffer = await _decodeAudioData(inputData);
    final channelData = buffer.getChannelData(0).toDart;
    final totalSamples = channelData.length;

    if (totalSamples == 0) {
      return List.filled(numberOfSamples, 0.0);
    }

    final samplesPerWindow = max(1, totalSamples ~/ numberOfSamples);
    final waveform = <double>[];
    var maxRms = 0.0;

    for (var i = 0; i < numberOfSamples; i++) {
      final start = i * totalSamples ~/ numberOfSamples;
      final end = min(start + samplesPerWindow, totalSamples);
      if (start >= totalSamples) break;

      var sumSquares = 0.0;
      for (var j = start; j < end; j++) {
        final s = channelData[j];
        sumSquares += s * s;
      }
      final rms = sqrt(sumSquares / (end - start));
      waveform.add(rms);
      if (rms > maxRms) maxRms = rms;
    }

    // Web Audio API delivers samples already in [-1.0, 1.0], so absolute
    // normalization is the raw RMS value. Per-file normalization scales by
    // the loudest window in this file.
    final List<double> result;
    switch (normalization) {
      case WaveformNormalization.perFile:
        result = waveform.map((rms) => maxRms > 0 ? rms / maxRms : 0.0).toList();
      case WaveformNormalization.absolute:
        result = List<double>.from(waveform);
    }

    while (result.length < numberOfSamples) {
      result.add(0.0);
    }

    return result;
  } catch (e) {
    if (e is AudioConversionException) rethrow;
    throw AudioConversionException('Waveform extraction failed: $e');
  }
}