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 |