@@ -12,10 +12,11 @@ use std::{
1212
1313#[ cfg( feature = "audio-decode-vorbis" ) ]
1414use symphonia:: core:: codecs:: CODEC_TYPE_VORBIS ;
15- #[ cfg( feature = "audio-decode-wav" ) ]
16- use symphonia:: core:: sample:: SampleFormat ;
1715use symphonia:: core:: {
18- audio:: SampleBuffer ,
16+ audio:: {
17+ AudioBufferRef ,
18+ SampleBuffer ,
19+ } ,
1920 codecs:: {
2021 Decoder ,
2122 DecoderOptions ,
@@ -193,6 +194,7 @@ fn decode_track_to_interleaved_f32(
193194
194195 let mut sample_rate: Option < u32 > = None ;
195196 let mut channel_count: Option < u16 > = None ;
197+ let mut wav_sample_format_validated = false ;
196198
197199 loop {
198200 let packet = match format. next_packet ( ) {
@@ -269,6 +271,15 @@ fn decode_track_to_interleaved_f32(
269271 }
270272
271273 let frames = decoded. frames ( ) ;
274+ if frames == 0 {
275+ continue ;
276+ }
277+
278+ if source_description == "WAV" && !wav_sample_format_validated {
279+ validate_wav_decoded_sample_format ( & decoded) ?;
280+ wav_sample_format_validated = true ;
281+ }
282+
272283 let mut sample_buffer =
273284 SampleBuffer :: < f32 > :: new ( frames as u64 , * decoded. spec ( ) ) ;
274285 sample_buffer. copy_interleaved_ref ( decoded) ;
@@ -299,6 +310,43 @@ fn decode_track_to_interleaved_f32(
299310 } ) ;
300311}
301312
313+ fn validate_wav_decoded_sample_format (
314+ decoded : & AudioBufferRef < ' _ > ,
315+ ) -> Result < ( ) , AudioDecodeError > {
316+ match decoded {
317+ AudioBufferRef :: S16 ( _)
318+ | AudioBufferRef :: S24 ( _)
319+ | AudioBufferRef :: F32 ( _) => {
320+ return Ok ( ( ) ) ;
321+ }
322+ other => {
323+ return Err ( AudioDecodeError :: UnsupportedFormat {
324+ details : format ! (
325+ "unsupported WAV decoded sample format: {}" ,
326+ wav_decoded_sample_format_name( other)
327+ ) ,
328+ } ) ;
329+ }
330+ }
331+ }
332+
333+ fn wav_decoded_sample_format_name (
334+ decoded : & AudioBufferRef < ' _ > ,
335+ ) -> & ' static str {
336+ match decoded {
337+ AudioBufferRef :: U8 ( _) => "U8" ,
338+ AudioBufferRef :: U16 ( _) => "U16" ,
339+ AudioBufferRef :: U24 ( _) => "U24" ,
340+ AudioBufferRef :: U32 ( _) => "U32" ,
341+ AudioBufferRef :: S8 ( _) => "S8" ,
342+ AudioBufferRef :: S16 ( _) => "S16" ,
343+ AudioBufferRef :: S24 ( _) => "S24" ,
344+ AudioBufferRef :: S32 ( _) => "S32" ,
345+ AudioBufferRef :: F32 ( _) => "F32" ,
346+ AudioBufferRef :: F64 ( _) => "F64" ,
347+ }
348+ }
349+
302350/// Decode WAV bytes into interleaved `f32` samples.
303351#[ cfg( feature = "audio-decode-wav" ) ]
304352pub fn decode_wav_bytes (
@@ -314,22 +362,6 @@ pub fn decode_wav_bytes(
314362 }
315363 } ;
316364
317- let sample_format =
318- codec_params
319- . sample_format
320- . ok_or ( AudioDecodeError :: UnsupportedFormat {
321- details : "WAV sample format is unspecified" . to_string ( ) ,
322- } ) ?;
323-
324- match sample_format {
325- SampleFormat :: S16 | SampleFormat :: S24 | SampleFormat :: F32 => { }
326- other => {
327- return Err ( AudioDecodeError :: UnsupportedFormat {
328- details : format ! ( "unsupported WAV sample format: {other:?}" ) ,
329- } ) ;
330- }
331- }
332-
333365 let mut decoder = symphonia:: default:: get_codecs ( )
334366 . make ( & codec_params, & DecoderOptions :: default ( ) )
335367 . map_err ( |error| map_read_or_decode_error ( "WAV" , error) ) ?;
@@ -387,6 +419,36 @@ pub fn decode_ogg_vorbis_bytes(
387419mod tests {
388420 use super :: * ;
389421
422+ #[ cfg( feature = "audio-decode-wav" ) ]
423+ const TONE_S16_MONO_44100_WAV : & [ u8 ] = include_bytes ! ( concat!(
424+ env!( "CARGO_MANIFEST_DIR" ) ,
425+ "/assets/audio/tone_s16_mono_44100.wav"
426+ ) ) ;
427+
428+ #[ cfg( feature = "audio-decode-wav" ) ]
429+ const TONE_S16_STEREO_44100_WAV : & [ u8 ] = include_bytes ! ( concat!(
430+ env!( "CARGO_MANIFEST_DIR" ) ,
431+ "/assets/audio/tone_s16_stereo_44100.wav"
432+ ) ) ;
433+
434+ #[ cfg( feature = "audio-decode-wav" ) ]
435+ const TONE_S24_MONO_44100_WAV : & [ u8 ] = include_bytes ! ( concat!(
436+ env!( "CARGO_MANIFEST_DIR" ) ,
437+ "/assets/audio/tone_s24_mono_44100.wav"
438+ ) ) ;
439+
440+ #[ cfg( feature = "audio-decode-wav" ) ]
441+ const TONE_F32_STEREO_44100_WAV : & [ u8 ] = include_bytes ! ( concat!(
442+ env!( "CARGO_MANIFEST_DIR" ) ,
443+ "/assets/audio/tone_f32_stereo_44100.wav"
444+ ) ) ;
445+
446+ #[ cfg( feature = "audio-decode-vorbis" ) ]
447+ const SLASH_VORBIS_STEREO_48000_OGG : & [ u8 ] = include_bytes ! ( concat!(
448+ env!( "CARGO_MANIFEST_DIR" ) ,
449+ "/assets/audio/slash_vorbis_stereo_48000.ogg"
450+ ) ) ;
451+
390452 #[ cfg( feature = "audio-decode-wav" ) ]
391453 #[ test]
392454 fn wav_decode_rejects_invalid_bytes ( ) {
@@ -400,6 +462,50 @@ mod tests {
400462 return ;
401463 }
402464
465+ #[ cfg( feature = "audio-decode-wav" ) ]
466+ #[ test]
467+ fn wav_decode_s16_mono_fixture_decodes ( ) {
468+ let decoded =
469+ decode_wav_bytes ( TONE_S16_MONO_44100_WAV ) . expect ( "decode failed" ) ;
470+ assert_eq ! ( decoded. sample_rate, 44100 ) ;
471+ assert_eq ! ( decoded. channels, 1 ) ;
472+ assert_eq ! ( decoded. samples. len( ) , 4410 ) ;
473+ return ;
474+ }
475+
476+ #[ cfg( feature = "audio-decode-wav" ) ]
477+ #[ test]
478+ fn wav_decode_s16_stereo_fixture_decodes ( ) {
479+ let decoded =
480+ decode_wav_bytes ( TONE_S16_STEREO_44100_WAV ) . expect ( "decode failed" ) ;
481+ assert_eq ! ( decoded. sample_rate, 44100 ) ;
482+ assert_eq ! ( decoded. channels, 2 ) ;
483+ assert_eq ! ( decoded. samples. len( ) , 4410 * 2 ) ;
484+ return ;
485+ }
486+
487+ #[ cfg( feature = "audio-decode-wav" ) ]
488+ #[ test]
489+ fn wav_decode_s24_mono_fixture_decodes ( ) {
490+ let decoded =
491+ decode_wav_bytes ( TONE_S24_MONO_44100_WAV ) . expect ( "decode failed" ) ;
492+ assert_eq ! ( decoded. sample_rate, 44100 ) ;
493+ assert_eq ! ( decoded. channels, 1 ) ;
494+ assert_eq ! ( decoded. samples. len( ) , 4410 ) ;
495+ return ;
496+ }
497+
498+ #[ cfg( feature = "audio-decode-wav" ) ]
499+ #[ test]
500+ fn wav_decode_f32_stereo_fixture_decodes ( ) {
501+ let decoded =
502+ decode_wav_bytes ( TONE_F32_STEREO_44100_WAV ) . expect ( "decode failed" ) ;
503+ assert_eq ! ( decoded. sample_rate, 44100 ) ;
504+ assert_eq ! ( decoded. channels, 2 ) ;
505+ assert_eq ! ( decoded. samples. len( ) , 4410 * 2 ) ;
506+ return ;
507+ }
508+
403509 #[ cfg( feature = "audio-decode-vorbis" ) ]
404510 #[ test]
405511 fn ogg_vorbis_decode_rejects_invalid_bytes ( ) {
@@ -412,4 +518,15 @@ mod tests {
412518 ) ) ;
413519 return ;
414520 }
521+
522+ #[ cfg( feature = "audio-decode-vorbis" ) ]
523+ #[ test]
524+ fn ogg_vorbis_decode_fixture_decodes ( ) {
525+ let decoded = decode_ogg_vorbis_bytes ( SLASH_VORBIS_STEREO_48000_OGG )
526+ . expect ( "decode failed" ) ;
527+ assert_eq ! ( decoded. sample_rate, 48000 ) ;
528+ assert_eq ! ( decoded. channels, 2 ) ;
529+ assert ! ( !decoded. samples. is_empty( ) ) ;
530+ return ;
531+ }
415532}
0 commit comments