decode method

  1. @override
Future<({AudioData audioData, int sampleRate})> decode(
  1. Uint8List bytes
)
override

Implementation

@override
Future<({AudioData audioData, int sampleRate})> decode(Uint8List bytes) async {
  final data = ByteData.sublistView(bytes);

  // WAV header positions
  final sampleRate = data.getUint32(24, Endian.little);
  final bitsPerSample = data.getUint16(34, Endian.little);
  final channels = data.getUint16(22, Endian.little);

  if (bitsPerSample != 16) {
    throw UnsupportedError(
      'Only 16-bit PCM WAV files are currently supported.',
    );
  }

  // Find "data" chunk
  int dataOffset = -1;
  int dataSize = 0;

  for (int i = 12; i < bytes.length - 8; i++) {
    if (bytes[i] == 0x64 && // d
        bytes[i + 1] == 0x61 && // a
        bytes[i + 2] == 0x74 && // t
        bytes[i + 3] == 0x61) { // a

      dataOffset = i + 8;
      dataSize = data.getUint32(i + 4, Endian.little);
      break;
    }
  }

  if (dataOffset == -1) {
    throw FormatException('Invalid WAV file: data chunk not found');
  }

  final sampleCount =
      dataSize ~/ (bitsPerSample ~/ 8) ~/ channels;

  final samples = Float32List(sampleCount);

  int sampleIndex = 0;

  for (int i = 0; i < sampleCount; i++) {
    double monoSample = 0;

    for (int ch = 0; ch < channels; ch++) {
      final offset =
          dataOffset + ((i * channels + ch) * 2);

      final value =
      data.getInt16(offset, Endian.little);

      monoSample += value / 32768.0;
    }

    samples[sampleIndex++] =
        monoSample / channels;
  }

  return (audioData: samples, sampleRate: sampleRate);
}