wrapInWavHeader function

Uint8List wrapInWavHeader(
  1. Uint8List pcmBytes, {
  2. required int sampleRate,
  3. required int channels,
})

Wraps raw PCM audio bytes in a WAV header for playback.

TTS models typically output raw PCM bytes (16-bit signed integers). This function adds the required WAV header for audio players.

Parameters:

  • pcmBytes: Raw PCM audio data (16-bit signed, little-endian)
  • sampleRate: Sample rate in Hz (e.g., 24000 for Kokoro TTS)
  • channels: Number of audio channels (typically 1 for mono)

Example:

final result = await model.run(envelope);
final pcmBytes = result.audioBytes!;
final wavBytes = wrapInWavHeader(pcmBytes, sampleRate: 24000, channels: 1);
// Now wavBytes can be played with just_audio or saved as a .wav file

Implementation

Uint8List wrapInWavHeader(
  Uint8List pcmBytes, {
  required int sampleRate,
  required int channels,
}) {
  const bitsPerSample = 16;
  final byteRate = sampleRate * channels * bitsPerSample ~/ 8;
  final blockAlign = channels * bitsPerSample ~/ 8;
  final dataSize = pcmBytes.length;
  final fileSize = 36 + dataSize;

  final header = BytesBuilder();
  header.add('RIFF'.codeUnits);
  header.add(_int32ToBytes(fileSize));
  header.add('WAVE'.codeUnits);
  header.add('fmt '.codeUnits);
  header.add(_int32ToBytes(16)); // Subchunk1Size for PCM
  header.add(_int16ToBytes(1)); // AudioFormat: 1 = PCM
  header.add(_int16ToBytes(channels));
  header.add(_int32ToBytes(sampleRate));
  header.add(_int32ToBytes(byteRate));
  header.add(_int16ToBytes(blockAlign));
  header.add(_int16ToBytes(bitsPerSample));
  header.add('data'.codeUnits);
  header.add(_int32ToBytes(dataSize));

  final result = BytesBuilder();
  result.add(header.toBytes());
  result.add(pcmBytes);
  return result.toBytes();
}