Home | History | Annotate | Download | only in common_audio
      1 /*
      2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <limits>
     12 
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 #include "webrtc/common_audio/wav_header.h"
     15 
     16 namespace webrtc {
     17 
     18 // Doesn't take ownership of the buffer.
     19 class ReadableWavBuffer : public ReadableWav {
     20  public:
     21   ReadableWavBuffer(const uint8_t* buf, size_t size)
     22       : buf_(buf),
     23         size_(size),
     24         pos_(0),
     25         buf_exhausted_(false),
     26         check_read_size_(true) {}
     27   ReadableWavBuffer(const uint8_t* buf, size_t size, bool check_read_size)
     28       : buf_(buf),
     29         size_(size),
     30         pos_(0),
     31         buf_exhausted_(false),
     32         check_read_size_(check_read_size) {}
     33 
     34   virtual ~ReadableWavBuffer() {
     35     // Verify the entire buffer has been read.
     36     if (check_read_size_)
     37       EXPECT_EQ(size_, pos_);
     38   }
     39 
     40   virtual size_t Read(void* buf, size_t num_bytes) {
     41     // Verify we don't try to read outside of a properly sized header.
     42     if (size_ >= kWavHeaderSize)
     43       EXPECT_GE(size_, pos_ + num_bytes);
     44     EXPECT_FALSE(buf_exhausted_);
     45 
     46     const size_t bytes_remaining = size_ - pos_;
     47     if (num_bytes > bytes_remaining) {
     48       // The caller is signalled about an exhausted buffer when we return fewer
     49       // bytes than requested. There should not be another read attempt after
     50       // this point.
     51       buf_exhausted_ = true;
     52       num_bytes = bytes_remaining;
     53     }
     54     memcpy(buf, &buf_[pos_], num_bytes);
     55     pos_ += num_bytes;
     56     return num_bytes;
     57   }
     58 
     59  private:
     60   const uint8_t* buf_;
     61   const size_t size_;
     62   size_t pos_;
     63   bool buf_exhausted_;
     64   const bool check_read_size_;
     65 };
     66 
     67 // Try various choices of WAV header parameters, and make sure that the good
     68 // ones are accepted and the bad ones rejected.
     69 TEST(WavHeaderTest, CheckWavParameters) {
     70   // Try some really stupid values for one parameter at a time.
     71   EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 1, 0));
     72   EXPECT_FALSE(CheckWavParameters(0, 8000, kWavFormatPcm, 1, 0));
     73   EXPECT_FALSE(CheckWavParameters(0x10000, 8000, kWavFormatPcm, 1, 0));
     74   EXPECT_FALSE(CheckWavParameters(1, 0, kWavFormatPcm, 1, 0));
     75   EXPECT_FALSE(CheckWavParameters(1, 8000, WavFormat(0), 1, 0));
     76   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 0, 0));
     77 
     78   // Try invalid format/bytes-per-sample combinations.
     79   EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 2, 0));
     80   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 4, 0));
     81   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatALaw, 2, 0));
     82   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatMuLaw, 2, 0));
     83 
     84   // Too large values.
     85   EXPECT_FALSE(CheckWavParameters(1 << 20, 1 << 20, kWavFormatPcm, 1, 0));
     86   EXPECT_FALSE(CheckWavParameters(
     87       1, 8000, kWavFormatPcm, 1, std::numeric_limits<uint32_t>::max()));
     88 
     89   // Not the same number of samples for each channel.
     90   EXPECT_FALSE(CheckWavParameters(3, 8000, kWavFormatPcm, 1, 5));
     91 }
     92 
     93 TEST(WavHeaderTest, ReadWavHeaderWithErrors) {
     94   size_t num_channels = 0;
     95   int sample_rate = 0;
     96   WavFormat format = kWavFormatPcm;
     97   size_t bytes_per_sample = 0;
     98   size_t num_samples = 0;
     99 
    100   // Test a few ways the header can be invalid. We start with the valid header
    101   // used in WriteAndReadWavHeader, and invalidate one field per test. The
    102   // invalid field is indicated in the array name, and in the comments with
    103   // *BAD*.
    104   {
    105     static const uint8_t kBadRiffID[] = {
    106       'R', 'i', 'f', 'f',  // *BAD*
    107       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    108       'W', 'A', 'V', 'E',
    109       'f', 'm', 't', ' ',
    110       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
    111       6, 0,  // format: A-law (6)
    112       17, 0,  // channels: 17
    113       0x39, 0x30, 0, 0,  // sample rate: 12345
    114       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    115       17, 0,  // block align: NumChannels * BytesPerSample
    116       8, 0,  // bits per sample: 1 * 8
    117       'd', 'a', 't', 'a',
    118       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    119     };
    120     ReadableWavBuffer r(kBadRiffID, sizeof(kBadRiffID));
    121     EXPECT_FALSE(
    122         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    123                       &bytes_per_sample, &num_samples));
    124   }
    125   {
    126     static const uint8_t kBadBitsPerSample[] = {
    127       'R', 'I', 'F', 'F',
    128       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    129       'W', 'A', 'V', 'E',
    130       'f', 'm', 't', ' ',
    131       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
    132       6, 0,  // format: A-law (6)
    133       17, 0,  // channels: 17
    134       0x39, 0x30, 0, 0,  // sample rate: 12345
    135       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    136       17, 0,  // block align: NumChannels * BytesPerSample
    137       1, 0,  // bits per sample: *BAD*
    138       'd', 'a', 't', 'a',
    139       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    140     };
    141     ReadableWavBuffer r(kBadBitsPerSample, sizeof(kBadBitsPerSample));
    142     EXPECT_FALSE(
    143         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    144                       &bytes_per_sample, &num_samples));
    145   }
    146   {
    147     static const uint8_t kBadByteRate[] = {
    148       'R', 'I', 'F', 'F',
    149       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    150       'W', 'A', 'V', 'E',
    151       'f', 'm', 't', ' ',
    152       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
    153       6, 0,  // format: A-law (6)
    154       17, 0,  // channels: 17
    155       0x39, 0x30, 0, 0,  // sample rate: 12345
    156       0x00, 0x33, 0x03, 0,  // byte rate: *BAD*
    157       17, 0,  // block align: NumChannels * BytesPerSample
    158       8, 0,  // bits per sample: 1 * 8
    159       'd', 'a', 't', 'a',
    160       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    161     };
    162     ReadableWavBuffer r(kBadByteRate, sizeof(kBadByteRate));
    163     EXPECT_FALSE(
    164         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    165                       &bytes_per_sample, &num_samples));
    166   }
    167   {
    168     static const uint8_t kBadFmtHeaderSize[] = {
    169       'R', 'I', 'F', 'F',
    170       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    171       'W', 'A', 'V', 'E',
    172       'f', 'm', 't', ' ',
    173       17, 0, 0, 0,  // size of fmt block *BAD*. Only 16 and 18 permitted.
    174       6, 0,  // format: A-law (6)
    175       17, 0,  // channels: 17
    176       0x39, 0x30, 0, 0,  // sample rate: 12345
    177       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    178       17, 0,  // block align: NumChannels * BytesPerSample
    179       8, 0,  // bits per sample: 1 * 8
    180       0,  // extra (though invalid) header byte
    181       'd', 'a', 't', 'a',
    182       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    183     };
    184     ReadableWavBuffer r(kBadFmtHeaderSize, sizeof(kBadFmtHeaderSize), false);
    185     EXPECT_FALSE(
    186         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    187                       &bytes_per_sample, &num_samples));
    188   }
    189   {
    190     static const uint8_t kNonZeroExtensionField[] = {
    191       'R', 'I', 'F', 'F',
    192       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    193       'W', 'A', 'V', 'E',
    194       'f', 'm', 't', ' ',
    195       18, 0, 0, 0,  // size of fmt block - 8: 24 - 8
    196       6, 0,  // format: A-law (6)
    197       17, 0,  // channels: 17
    198       0x39, 0x30, 0, 0,  // sample rate: 12345
    199       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    200       17, 0,  // block align: NumChannels * BytesPerSample
    201       8, 0,  // bits per sample: 1 * 8
    202       1, 0,  // non-zero extension field *BAD*
    203       'd', 'a', 't', 'a',
    204       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    205     };
    206     ReadableWavBuffer r(kNonZeroExtensionField, sizeof(kNonZeroExtensionField),
    207                         false);
    208     EXPECT_FALSE(
    209         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    210                       &bytes_per_sample, &num_samples));
    211   }
    212   {
    213     static const uint8_t kMissingDataChunk[] = {
    214       'R', 'I', 'F', 'F',
    215       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    216       'W', 'A', 'V', 'E',
    217       'f', 'm', 't', ' ',
    218       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
    219       6, 0,  // format: A-law (6)
    220       17, 0,  // channels: 17
    221       0x39, 0x30, 0, 0,  // sample rate: 12345
    222       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    223       17, 0,  // block align: NumChannels * BytesPerSample
    224       8, 0,  // bits per sample: 1 * 8
    225     };
    226     ReadableWavBuffer r(kMissingDataChunk, sizeof(kMissingDataChunk));
    227     EXPECT_FALSE(
    228         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    229                       &bytes_per_sample, &num_samples));
    230   }
    231   {
    232     static const uint8_t kMissingFmtAndDataChunks[] = {
    233       'R', 'I', 'F', 'F',
    234       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    235       'W', 'A', 'V', 'E',
    236     };
    237     ReadableWavBuffer r(kMissingFmtAndDataChunks,
    238                         sizeof(kMissingFmtAndDataChunks));
    239     EXPECT_FALSE(
    240         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    241                       &bytes_per_sample, &num_samples));
    242   }
    243 }
    244 
    245 // Try writing and reading a valid WAV header and make sure it looks OK.
    246 TEST(WavHeaderTest, WriteAndReadWavHeader) {
    247   static const int kSize = 4 + kWavHeaderSize + 4;
    248   uint8_t buf[kSize];
    249   memset(buf, 0xa4, sizeof(buf));
    250   WriteWavHeader(buf + 4, 17, 12345, kWavFormatALaw, 1, 123457689);
    251   static const uint8_t kExpectedBuf[] = {
    252     0xa4, 0xa4, 0xa4, 0xa4,  // untouched bytes before header
    253     'R', 'I', 'F', 'F',
    254     0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
    255     'W', 'A', 'V', 'E',
    256     'f', 'm', 't', ' ',
    257     16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
    258     6, 0,  // format: A-law (6)
    259     17, 0,  // channels: 17
    260     0x39, 0x30, 0, 0,  // sample rate: 12345
    261     0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    262     17, 0,  // block align: NumChannels * BytesPerSample
    263     8, 0,  // bits per sample: 1 * 8
    264     'd', 'a', 't', 'a',
    265     0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    266     0xa4, 0xa4, 0xa4, 0xa4,  // untouched bytes after header
    267   };
    268   static_assert(sizeof(kExpectedBuf) == kSize, "buffer size");
    269   EXPECT_EQ(0, memcmp(kExpectedBuf, buf, kSize));
    270 
    271   size_t num_channels = 0;
    272   int sample_rate = 0;
    273   WavFormat format = kWavFormatPcm;
    274   size_t bytes_per_sample = 0;
    275   size_t num_samples = 0;
    276   ReadableWavBuffer r(buf + 4, sizeof(buf) - 8);
    277   EXPECT_TRUE(
    278       ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    279                     &bytes_per_sample, &num_samples));
    280   EXPECT_EQ(17u, num_channels);
    281   EXPECT_EQ(12345, sample_rate);
    282   EXPECT_EQ(kWavFormatALaw, format);
    283   EXPECT_EQ(1u, bytes_per_sample);
    284   EXPECT_EQ(123457689u, num_samples);
    285 }
    286 
    287 // Try reading an atypical but valid WAV header and make sure it's parsed OK.
    288 TEST(WavHeaderTest, ReadAtypicalWavHeader) {
    289   static const uint8_t kBuf[] = {
    290     'R', 'I', 'F', 'F',
    291     0x3d, 0xd1, 0x5b, 0x07,  // size of whole file - 8 + an extra 128 bytes of
    292                              // "metadata": 123457689 + 44 - 8 + 128. (atypical)
    293     'W', 'A', 'V', 'E',
    294     'f', 'm', 't', ' ',
    295     18, 0, 0, 0,  // size of fmt block (with an atypical extension size field)
    296     6, 0,  // format: A-law (6)
    297     17, 0,  // channels: 17
    298     0x39, 0x30, 0, 0,  // sample rate: 12345
    299     0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
    300     17, 0,  // block align: NumChannels * BytesPerSample
    301     8, 0,  // bits per sample: 1 * 8
    302     0, 0,  // zero extension size field (atypical)
    303     'd', 'a', 't', 'a',
    304     0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
    305   };
    306 
    307   size_t num_channels = 0;
    308   int sample_rate = 0;
    309   WavFormat format = kWavFormatPcm;
    310   size_t bytes_per_sample = 0;
    311   size_t num_samples = 0;
    312   ReadableWavBuffer r(kBuf, sizeof(kBuf));
    313   EXPECT_TRUE(
    314       ReadWavHeader(&r, &num_channels, &sample_rate, &format,
    315                     &bytes_per_sample, &num_samples));
    316   EXPECT_EQ(17u, num_channels);
    317   EXPECT_EQ(12345, sample_rate);
    318   EXPECT_EQ(kWavFormatALaw, format);
    319   EXPECT_EQ(1u, bytes_per_sample);
    320   EXPECT_EQ(123457689u, num_samples);
    321 }
    322 
    323 }  // namespace webrtc
    324