Skip to content

Utils: cplay: Fix WAV header parsing for multi-channel (5.1/7.1) formats#32

Open
singalsu wants to merge 1 commit intoalsa-project:masterfrom
singalsu:fix_multichannel_wav
Open

Utils: cplay: Fix WAV header parsing for multi-channel (5.1/7.1) formats#32
singalsu wants to merge 1 commit intoalsa-project:masterfrom
singalsu:fix_multichannel_wav

Conversation

@singalsu
Copy link

Multi-channel WAV files (>2 channels) use WAVE_FORMAT_EXTENSIBLE (type 0xFFFE) with a larger fmt chunk that includes a channel mask and subformat GUID. The existing parser only handled basic PCM (type 0x0001), causing several issues with 5.1 (6ch) and 7.1 (8ch) content:

  • The fixed-size fread of struct wave_header (44 bytes) misaligned the data chunk read when the fmt chunk was larger than 16 bytes, resulting in audio data being read from the wrong file offset.

  • No chunk scanning was performed, so intermediate chunks (fact, LIST, PEAK) between fmt and data caused parse failures.

  • The WAV channel mask (speaker positions FL, FR, FC, LFE, BL, BR, SL, SR) was never extracted, so firmware received ch_mode=0 and could not determine the correct channel-to-speaker routing.

Add parse_wave_file() that properly scans chunks, handles both basic PCM and WAVE_FORMAT_EXTENSIBLE formats, extracts the channel mask, and positions the file pointer at the start of audio data. For basic PCM files with >2 channels, a standard default channel mask is generated per the Microsoft WAV specification.

The channel mask is passed to firmware via snd_codec.ch_mode so it can correctly map channels to speaker positions. Also add 24-bit sample format support (SNDRV_PCM_FORMAT_S24_LE).

Multi-channel WAV files (>2 channels) use WAVE_FORMAT_EXTENSIBLE
(type 0xFFFE) with a larger fmt chunk that includes a channel mask
and subformat GUID. The existing parser only handled basic PCM
(type 0x0001), causing several issues with 5.1 (6ch) and 7.1 (8ch)
content:

 - The fixed-size fread of struct wave_header (44 bytes) misaligned
   the data chunk read when the fmt chunk was larger than 16 bytes,
   resulting in audio data being read from the wrong file offset.

 - No chunk scanning was performed, so intermediate chunks (fact,
   LIST, PEAK) between fmt and data caused parse failures.

 - The WAV channel mask (speaker positions FL, FR, FC, LFE, BL, BR,
   SL, SR) was never extracted, so firmware received ch_mode=0 and
   could not determine the correct channel-to-speaker routing.

Add parse_wave_file() that properly scans chunks, handles both basic
PCM and WAVE_FORMAT_EXTENSIBLE formats, extracts the channel mask,
and positions the file pointer at the start of audio data. For basic
PCM files with >2 channels, a standard default channel mask is
generated per the Microsoft WAV specification.

The channel mask is passed to firmware via snd_codec.ch_mode so it
can correctly map channels to speaker positions. Also add 24-bit
sample format support (SNDRV_PCM_FORMAT_S24_LE).

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant