Quellcode durchsuchen

LibAudio: Add support for WAVE_FORMAT_EXTENSIBLE

This enables support for playing float32 and float64
WAVE_FORMAT_EXTENSIBLE files.

The PCM data format is encoded in the
first two bytes of the SubFormat GUID inside of the
WAVE_FORMAT_EXTENSIBLE `fmt` chunk.

Also, fixed the RIFF header size check to allow up to
maximum_wav_size (currently defined as 1 GiB).
The RIFF header size is the size of the entire
file, so it should be checked against the largest Wave size.
Nick Miller vor 4 Jahren
Ursprung
Commit
2b789adc16
1 geänderte Dateien mit 24 neuen und 4 gelöschten Zeilen
  1. 24 4
      Userland/Libraries/LibAudio/WavLoader.cpp

+ 24 - 4
Userland/Libraries/LibAudio/WavLoader.cpp

@@ -100,6 +100,7 @@ void WavLoaderPlugin::seek(const int sample_index)
     }
 }
 
+// Specification reference: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
 bool WavLoaderPlugin::parse_header()
 {
     if (!m_stream)
@@ -149,7 +150,7 @@ bool WavLoaderPlugin::parse_header()
     CHECK_OK("RIFF header");
 
     u32 sz = read_u32();
-    ok = ok && sz < 1024 * 1024 * 1024; // arbitrary
+    ok = ok && sz < maximum_wav_size;
     CHECK_OK("File size");
 
     u32 wave = read_u32();
@@ -157,16 +158,16 @@ bool WavLoaderPlugin::parse_header()
     CHECK_OK("WAVE header");
 
     u32 fmt_id = read_u32();
-    ok = ok && fmt_id == 0x20746D66; // "FMT"
+    ok = ok && fmt_id == 0x20746D66; // "fmt "
     CHECK_OK("FMT header");
 
     u32 fmt_size = read_u32();
-    ok = ok && fmt_size == 16;
+    ok = ok && (fmt_size == 16 || fmt_size == 18 || fmt_size == 40);
     CHECK_OK("FMT size");
 
     u16 audio_format = read_u16();
     CHECK_OK("Audio format"); // incomplete read check
-    ok = ok && (audio_format == WAVE_FORMAT_PCM || audio_format == WAVE_FORMAT_IEEE_FLOAT);
+    ok = ok && (audio_format == WAVE_FORMAT_PCM || audio_format == WAVE_FORMAT_IEEE_FLOAT || audio_format == WAVE_FORMAT_EXTENSIBLE);
     CHECK_OK("Audio format PCM/Float"); // value check
 
     m_num_channels = read_u16();
@@ -184,6 +185,25 @@ bool WavLoaderPlugin::parse_header()
 
     u16 bits_per_sample = read_u16();
     CHECK_OK("Bits per sample"); // incomplete read check
+
+    if (audio_format == WAVE_FORMAT_EXTENSIBLE) {
+        ok = ok && (fmt_size == 40);
+        CHECK_OK("Extensible fmt size"); // value check
+
+        // Discard everything until the GUID.
+        // We've already read 16 bytes from the stream. The GUID starts in another 8 bytes.
+        read_u32();
+        read_u32();
+        CHECK_OK("Discard until GUID");
+
+        // Get the underlying audio format from the first two bytes of GUID
+        u16 guid_subformat = read_u16();
+        ok = ok && (guid_subformat == WAVE_FORMAT_PCM || guid_subformat == WAVE_FORMAT_IEEE_FLOAT);
+        CHECK_OK("GUID SubFormat");
+
+        audio_format = guid_subformat;
+    }
+
     if (audio_format == WAVE_FORMAT_PCM) {
         ok = ok && (bits_per_sample == 8 || bits_per_sample == 16 || bits_per_sample == 24);
         CHECK_OK("Bits per sample (PCM)"); // value check