| 28 | } |
| 29 | char * base = eback(); |
| 30 | char * next = gptr(); |
| 31 | char * end = egptr(); |
| 32 | char * target = nullptr; |
| 33 | if (dir == std::ios_base::beg) { |
| 34 | target = base + offset; |
| 35 | } else if (dir == std::ios_base::cur) { |
| 36 | target = next + offset; |
| 37 | } else if (dir == std::ios_base::end) { |
| 38 | target = end + offset; |
| 39 | } |
| 40 | if (target == nullptr || target < base || target > end) { |
| 41 | return pos_type(off_type(-1)); |
| 42 | } |
| 43 | setg(base, target, end); |
| 44 | return pos_type(target - base); |
| 45 | } |
| 46 | |
| 47 | pos_type seekpos(pos_type position, std::ios_base::openmode which) override { |
| 48 | return seekoff(off_type(position), std::ios_base::beg, which); |
| 49 | } |
| 50 | }; |
| 51 | |
| 52 | template <typename T> |
| 53 | T read_scalar(std::istream & input) { |
| 54 | T value{}; |
| 55 | input.read(reinterpret_cast<char *>(&value), sizeof(T)); |
| 56 | if (!input) { |
| 57 | throw std::runtime_error("failed to read WAV scalar"); |
| 58 | } |
| 59 | return value; |
| 60 | } |
| 61 | |
| 62 | void skip_bytes(std::istream & input, std::streamoff count) { |
| 63 | input.seekg(count, std::ios::cur); |
| 64 | if (!input) { |
| 65 | throw std::runtime_error("failed to seek inside WAV file"); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | // WAVE format tags. EXTENSIBLE is the one that matters in practice: many |
| 70 | // encoders emit it for ordinary PCM16 whenever there are more than two channels |
| 71 | // or a channel mask is set, and the real codec then lives in a SubFormat GUID |
| 72 | // rather than in the format tag itself. |
| 73 | constexpr uint16_t kFormatPcm = 0x0001; |
| 74 | constexpr uint16_t kFormatFloat = 0x0003; |
| 75 | constexpr uint16_t kFormatALaw = 0x0006; |
| 76 | constexpr uint16_t kFormatMuLaw = 0x0007; |
| 77 | constexpr uint16_t kFormatExtensible = 0xFFFE; |
| 78 | |
| 79 | // Bytes 2..15 of every KSDATAFORMAT_SUBTYPE_* GUID: |
| 80 | // XXXXXXXX-0000-0010-8000-00aa00389b71. |
| 81 | constexpr std::array<char, 14> kKsDataFormatSubtypeTail = { |
| 82 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, static_cast<char>(0x80), |
| 83 | 0x00, 0x00, static_cast<char>(0xAA), 0x00, 0x38, static_cast<char>(0x9B), 0x71, |
| 84 | }; |
| 85 | |
| 86 | // Names a container we can recognise but not decode, so the error can say what |
| 87 | // the file actually is instead of "invalid WAV RIFF header". |
no test coverage detected