| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 ChunkHeader header; | 55 ChunkHeader header; |
| 56 } data; | 56 } data; |
| 57 }; | 57 }; |
| 58 static_assert(sizeof(WavHeader) == kWavHeaderSize, "no padding in header"); | 58 static_assert(sizeof(WavHeader) == kWavHeaderSize, "no padding in header"); |
| 59 | 59 |
| 60 } // namespace | 60 } // namespace |
| 61 | 61 |
| 62 bool CheckWavParameters(int num_channels, | 62 bool CheckWavParameters(int num_channels, |
| 63 int sample_rate, | 63 int sample_rate, |
| 64 WavFormat format, | 64 WavFormat format, |
| 65 int bytes_per_sample, | 65 size_t bytes_per_sample, |
| 66 uint32_t num_samples) { | 66 size_t num_samples) { |
| 67 // num_channels, sample_rate, and bytes_per_sample must be positive, must fit | 67 // num_channels, sample_rate, and bytes_per_sample must be positive, must fit |
| 68 // in their respective fields, and their product must fit in the 32-bit | 68 // in their respective fields, and their product must fit in the 32-bit |
| 69 // ByteRate field. | 69 // ByteRate field. |
| 70 if (num_channels <= 0 || sample_rate <= 0 || bytes_per_sample <= 0) | 70 if (num_channels <= 0 || sample_rate <= 0 || bytes_per_sample == 0) |
| 71 return false; | 71 return false; |
| 72 if (static_cast<uint64_t>(sample_rate) > std::numeric_limits<uint32_t>::max()) | 72 if (static_cast<uint64_t>(sample_rate) > std::numeric_limits<uint32_t>::max()) |
| 73 return false; | 73 return false; |
| 74 if (static_cast<uint64_t>(num_channels) > | 74 if (static_cast<uint64_t>(num_channels) > |
| 75 std::numeric_limits<uint16_t>::max()) | 75 std::numeric_limits<uint16_t>::max()) |
| 76 return false; | 76 return false; |
| 77 if (static_cast<uint64_t>(bytes_per_sample) * 8 > | 77 if (static_cast<uint64_t>(bytes_per_sample) * 8 > |
| 78 std::numeric_limits<uint16_t>::max()) | 78 std::numeric_limits<uint16_t>::max()) |
| 79 return false; | 79 return false; |
| 80 if (static_cast<uint64_t>(sample_rate) * num_channels * bytes_per_sample > | 80 if (static_cast<uint64_t>(sample_rate) * num_channels * bytes_per_sample > |
| (...skipping 11 matching lines...) Expand all Loading... |
| 92 case kWavFormatMuLaw: | 92 case kWavFormatMuLaw: |
| 93 if (bytes_per_sample != 1) | 93 if (bytes_per_sample != 1) |
| 94 return false; | 94 return false; |
| 95 break; | 95 break; |
| 96 default: | 96 default: |
| 97 return false; | 97 return false; |
| 98 } | 98 } |
| 99 | 99 |
| 100 // The number of bytes in the file, not counting the first ChunkHeader, must | 100 // The number of bytes in the file, not counting the first ChunkHeader, must |
| 101 // be less than 2^32; otherwise, the ChunkSize field overflows. | 101 // be less than 2^32; otherwise, the ChunkSize field overflows. |
| 102 const uint32_t max_samples = | 102 const size_t header_size = kWavHeaderSize - sizeof(ChunkHeader); |
| 103 (std::numeric_limits<uint32_t>::max() | 103 const size_t max_samples = |
| 104 - (kWavHeaderSize - sizeof(ChunkHeader))) / | 104 (std::numeric_limits<uint32_t>::max() - header_size) / bytes_per_sample; |
| 105 bytes_per_sample; | |
| 106 if (num_samples > max_samples) | 105 if (num_samples > max_samples) |
| 107 return false; | 106 return false; |
| 108 | 107 |
| 109 // Each channel must have the same number of samples. | 108 // Each channel must have the same number of samples. |
| 110 if (num_samples % num_channels != 0) | 109 if (num_samples % num_channels != 0) |
| 111 return false; | 110 return false; |
| 112 | 111 |
| 113 return true; | 112 return true; |
| 114 } | 113 } |
| 115 | 114 |
| 116 #ifdef WEBRTC_ARCH_LITTLE_ENDIAN | 115 #ifdef WEBRTC_ARCH_LITTLE_ENDIAN |
| 117 static inline void WriteLE16(uint16_t* f, uint16_t x) { *f = x; } | 116 static inline void WriteLE16(uint16_t* f, uint16_t x) { *f = x; } |
| 118 static inline void WriteLE32(uint32_t* f, uint32_t x) { *f = x; } | 117 static inline void WriteLE32(uint32_t* f, uint32_t x) { *f = x; } |
| 119 static inline void WriteFourCC(uint32_t* f, char a, char b, char c, char d) { | 118 static inline void WriteFourCC(uint32_t* f, char a, char b, char c, char d) { |
| 120 *f = static_cast<uint32_t>(a) | 119 *f = static_cast<uint32_t>(a) |
| 121 | static_cast<uint32_t>(b) << 8 | 120 | static_cast<uint32_t>(b) << 8 |
| 122 | static_cast<uint32_t>(c) << 16 | 121 | static_cast<uint32_t>(c) << 16 |
| 123 | static_cast<uint32_t>(d) << 24; | 122 | static_cast<uint32_t>(d) << 24; |
| 124 } | 123 } |
| 125 | 124 |
| 126 static inline uint16_t ReadLE16(uint16_t x) { return x; } | 125 static inline uint16_t ReadLE16(uint16_t x) { return x; } |
| 127 static inline uint32_t ReadLE32(uint32_t x) { return x; } | 126 static inline uint32_t ReadLE32(uint32_t x) { return x; } |
| 128 static inline std::string ReadFourCC(uint32_t x) { | 127 static inline std::string ReadFourCC(uint32_t x) { |
| 129 return std::string(reinterpret_cast<char*>(&x), 4); | 128 return std::string(reinterpret_cast<char*>(&x), 4); |
| 130 } | 129 } |
| 131 #else | 130 #else |
| 132 #error "Write be-to-le conversion functions" | 131 #error "Write be-to-le conversion functions" |
| 133 #endif | 132 #endif |
| 134 | 133 |
| 135 static inline uint32_t RiffChunkSize(uint32_t bytes_in_payload) { | 134 static inline uint32_t RiffChunkSize(size_t bytes_in_payload) { |
| 136 return bytes_in_payload + kWavHeaderSize - sizeof(ChunkHeader); | 135 return static_cast<uint32_t>( |
| 136 bytes_in_payload + kWavHeaderSize - sizeof(ChunkHeader)); |
| 137 } | 137 } |
| 138 | 138 |
| 139 static inline uint32_t ByteRate(int num_channels, int sample_rate, | 139 static inline uint32_t ByteRate(int num_channels, int sample_rate, |
| 140 int bytes_per_sample) { | 140 size_t bytes_per_sample) { |
| 141 return static_cast<uint32_t>(num_channels) * sample_rate * bytes_per_sample; | 141 return static_cast<uint32_t>(num_channels * sample_rate * bytes_per_sample); |
| 142 } | 142 } |
| 143 | 143 |
| 144 static inline uint16_t BlockAlign(int num_channels, int bytes_per_sample) { | 144 static inline uint16_t BlockAlign(int num_channels, size_t bytes_per_sample) { |
| 145 return num_channels * bytes_per_sample; | 145 return static_cast<uint16_t>(num_channels * bytes_per_sample); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void WriteWavHeader(uint8_t* buf, | 148 void WriteWavHeader(uint8_t* buf, |
| 149 int num_channels, | 149 int num_channels, |
| 150 int sample_rate, | 150 int sample_rate, |
| 151 WavFormat format, | 151 WavFormat format, |
| 152 int bytes_per_sample, | 152 size_t bytes_per_sample, |
| 153 uint32_t num_samples) { | 153 size_t num_samples) { |
| 154 RTC_CHECK(CheckWavParameters(num_channels, sample_rate, format, | 154 RTC_CHECK(CheckWavParameters(num_channels, sample_rate, format, |
| 155 bytes_per_sample, num_samples)); | 155 bytes_per_sample, num_samples)); |
| 156 | 156 |
| 157 WavHeader header; | 157 WavHeader header; |
| 158 const uint32_t bytes_in_payload = bytes_per_sample * num_samples; | 158 const size_t bytes_in_payload = bytes_per_sample * num_samples; |
| 159 | 159 |
| 160 WriteFourCC(&header.riff.header.ID, 'R', 'I', 'F', 'F'); | 160 WriteFourCC(&header.riff.header.ID, 'R', 'I', 'F', 'F'); |
| 161 WriteLE32(&header.riff.header.Size, RiffChunkSize(bytes_in_payload)); | 161 WriteLE32(&header.riff.header.Size, RiffChunkSize(bytes_in_payload)); |
| 162 WriteFourCC(&header.riff.Format, 'W', 'A', 'V', 'E'); | 162 WriteFourCC(&header.riff.Format, 'W', 'A', 'V', 'E'); |
| 163 | 163 |
| 164 WriteFourCC(&header.fmt.header.ID, 'f', 'm', 't', ' '); | 164 WriteFourCC(&header.fmt.header.ID, 'f', 'm', 't', ' '); |
| 165 WriteLE32(&header.fmt.header.Size, kFmtSubchunkSize); | 165 WriteLE32(&header.fmt.header.Size, kFmtSubchunkSize); |
| 166 WriteLE16(&header.fmt.AudioFormat, format); | 166 WriteLE16(&header.fmt.AudioFormat, format); |
| 167 WriteLE16(&header.fmt.NumChannels, num_channels); | 167 WriteLE16(&header.fmt.NumChannels, static_cast<uint16_t>(num_channels)); |
| 168 WriteLE32(&header.fmt.SampleRate, sample_rate); | 168 WriteLE32(&header.fmt.SampleRate, sample_rate); |
| 169 WriteLE32(&header.fmt.ByteRate, ByteRate(num_channels, sample_rate, | 169 WriteLE32(&header.fmt.ByteRate, ByteRate(num_channels, sample_rate, |
| 170 bytes_per_sample)); | 170 bytes_per_sample)); |
| 171 WriteLE16(&header.fmt.BlockAlign, BlockAlign(num_channels, bytes_per_sample)); | 171 WriteLE16(&header.fmt.BlockAlign, BlockAlign(num_channels, bytes_per_sample)); |
| 172 WriteLE16(&header.fmt.BitsPerSample, 8 * bytes_per_sample); | 172 WriteLE16(&header.fmt.BitsPerSample, |
| 173 static_cast<uint16_t>(8 * bytes_per_sample)); |
| 173 | 174 |
| 174 WriteFourCC(&header.data.header.ID, 'd', 'a', 't', 'a'); | 175 WriteFourCC(&header.data.header.ID, 'd', 'a', 't', 'a'); |
| 175 WriteLE32(&header.data.header.Size, bytes_in_payload); | 176 WriteLE32(&header.data.header.Size, static_cast<uint32_t>(bytes_in_payload)); |
| 176 | 177 |
| 177 // Do an extra copy rather than writing everything to buf directly, since buf | 178 // Do an extra copy rather than writing everything to buf directly, since buf |
| 178 // might not be correctly aligned. | 179 // might not be correctly aligned. |
| 179 memcpy(buf, &header, kWavHeaderSize); | 180 memcpy(buf, &header, kWavHeaderSize); |
| 180 } | 181 } |
| 181 | 182 |
| 182 bool ReadWavHeader(ReadableWav* readable, | 183 bool ReadWavHeader(ReadableWav* readable, |
| 183 int* num_channels, | 184 int* num_channels, |
| 184 int* sample_rate, | 185 int* sample_rate, |
| 185 WavFormat* format, | 186 WavFormat* format, |
| 186 int* bytes_per_sample, | 187 size_t* bytes_per_sample, |
| 187 uint32_t* num_samples) { | 188 size_t* num_samples) { |
| 188 WavHeader header; | 189 WavHeader header; |
| 189 if (readable->Read(&header, kWavHeaderSize - sizeof(header.data)) != | 190 if (readable->Read(&header, kWavHeaderSize - sizeof(header.data)) != |
| 190 kWavHeaderSize - sizeof(header.data)) | 191 kWavHeaderSize - sizeof(header.data)) |
| 191 return false; | 192 return false; |
| 192 | 193 |
| 193 const uint32_t fmt_size = ReadLE32(header.fmt.header.Size); | 194 const uint32_t fmt_size = ReadLE32(header.fmt.header.Size); |
| 194 if (fmt_size != kFmtSubchunkSize) { | 195 if (fmt_size != kFmtSubchunkSize) { |
| 195 // There is an optional two-byte extension field permitted to be present | 196 // There is an optional two-byte extension field permitted to be present |
| 196 // with PCM, but which must be zero. | 197 // with PCM, but which must be zero. |
| 197 int16_t ext_size; | 198 int16_t ext_size; |
| 198 if (kFmtSubchunkSize + sizeof(ext_size) != fmt_size) | 199 if (kFmtSubchunkSize + sizeof(ext_size) != fmt_size) |
| 199 return false; | 200 return false; |
| 200 if (readable->Read(&ext_size, sizeof(ext_size)) != sizeof(ext_size)) | 201 if (readable->Read(&ext_size, sizeof(ext_size)) != sizeof(ext_size)) |
| 201 return false; | 202 return false; |
| 202 if (ext_size != 0) | 203 if (ext_size != 0) |
| 203 return false; | 204 return false; |
| 204 } | 205 } |
| 205 if (readable->Read(&header.data, sizeof(header.data)) != sizeof(header.data)) | 206 if (readable->Read(&header.data, sizeof(header.data)) != sizeof(header.data)) |
| 206 return false; | 207 return false; |
| 207 | 208 |
| 208 // Parse needed fields. | 209 // Parse needed fields. |
| 209 *format = static_cast<WavFormat>(ReadLE16(header.fmt.AudioFormat)); | 210 *format = static_cast<WavFormat>(ReadLE16(header.fmt.AudioFormat)); |
| 210 *num_channels = ReadLE16(header.fmt.NumChannels); | 211 *num_channels = ReadLE16(header.fmt.NumChannels); |
| 211 *sample_rate = ReadLE32(header.fmt.SampleRate); | 212 *sample_rate = ReadLE32(header.fmt.SampleRate); |
| 212 *bytes_per_sample = ReadLE16(header.fmt.BitsPerSample) / 8; | 213 *bytes_per_sample = ReadLE16(header.fmt.BitsPerSample) / 8; |
| 213 const uint32_t bytes_in_payload = ReadLE32(header.data.header.Size); | 214 const size_t bytes_in_payload = ReadLE32(header.data.header.Size); |
| 214 if (*bytes_per_sample <= 0) | 215 if (*bytes_per_sample == 0) |
| 215 return false; | 216 return false; |
| 216 *num_samples = bytes_in_payload / *bytes_per_sample; | 217 *num_samples = bytes_in_payload / *bytes_per_sample; |
| 217 | 218 |
| 218 // Sanity check remaining fields. | 219 // Sanity check remaining fields. |
| 219 if (ReadFourCC(header.riff.header.ID) != "RIFF") | 220 if (ReadFourCC(header.riff.header.ID) != "RIFF") |
| 220 return false; | 221 return false; |
| 221 if (ReadFourCC(header.riff.Format) != "WAVE") | 222 if (ReadFourCC(header.riff.Format) != "WAVE") |
| 222 return false; | 223 return false; |
| 223 if (ReadFourCC(header.fmt.header.ID) != "fmt ") | 224 if (ReadFourCC(header.fmt.header.ID) != "fmt ") |
| 224 return false; | 225 return false; |
| 225 if (ReadFourCC(header.data.header.ID) != "data") | 226 if (ReadFourCC(header.data.header.ID) != "data") |
| 226 return false; | 227 return false; |
| 227 | 228 |
| 228 if (ReadLE32(header.riff.header.Size) < RiffChunkSize(bytes_in_payload)) | 229 if (ReadLE32(header.riff.header.Size) < RiffChunkSize(bytes_in_payload)) |
| 229 return false; | 230 return false; |
| 230 if (ReadLE32(header.fmt.ByteRate) != | 231 if (ReadLE32(header.fmt.ByteRate) != |
| 231 ByteRate(*num_channels, *sample_rate, *bytes_per_sample)) | 232 ByteRate(*num_channels, *sample_rate, *bytes_per_sample)) |
| 232 return false; | 233 return false; |
| 233 if (ReadLE16(header.fmt.BlockAlign) != | 234 if (ReadLE16(header.fmt.BlockAlign) != |
| 234 BlockAlign(*num_channels, *bytes_per_sample)) | 235 BlockAlign(*num_channels, *bytes_per_sample)) |
| 235 return false; | 236 return false; |
| 236 | 237 |
| 237 return CheckWavParameters(*num_channels, *sample_rate, *format, | 238 return CheckWavParameters(*num_channels, *sample_rate, *format, |
| 238 *bytes_per_sample, *num_samples); | 239 *bytes_per_sample, *num_samples); |
| 239 } | 240 } |
| 240 | 241 |
| 241 | 242 |
| 242 } // namespace webrtc | 243 } // namespace webrtc |
| OLD | NEW |