| 209 | } |
| 210 | |
| 211 | Status DecodeLin16WaveAsFloatVector(const string& wav_string, |
| 212 | std::vector<float>* float_values, |
| 213 | uint32* sample_count, uint16* channel_count, |
| 214 | uint32* sample_rate) { |
| 215 | int offset = 0; |
| 216 | TF_RETURN_IF_ERROR(ExpectText(wav_string, kRiffChunkId, &offset)); |
| 217 | uint32 total_file_size; |
| 218 | TF_RETURN_IF_ERROR(ReadValue<uint32>(wav_string, &total_file_size, &offset)); |
| 219 | TF_RETURN_IF_ERROR(ExpectText(wav_string, kRiffType, &offset)); |
| 220 | TF_RETURN_IF_ERROR(ExpectText(wav_string, kFormatChunkId, &offset)); |
| 221 | uint32 format_chunk_size; |
| 222 | TF_RETURN_IF_ERROR( |
| 223 | ReadValue<uint32>(wav_string, &format_chunk_size, &offset)); |
| 224 | if ((format_chunk_size != 16) && (format_chunk_size != 18)) { |
| 225 | return errors::InvalidArgument( |
| 226 | "Bad file size for WAV: Expected 16 or 18, but got", format_chunk_size); |
| 227 | } |
| 228 | uint16 audio_format; |
| 229 | TF_RETURN_IF_ERROR(ReadValue<uint16>(wav_string, &audio_format, &offset)); |
| 230 | if (audio_format != 1) { |
| 231 | return errors::InvalidArgument( |
| 232 | "Bad audio format for WAV: Expected 1 (PCM), but got", audio_format); |
| 233 | } |
| 234 | TF_RETURN_IF_ERROR(ReadValue<uint16>(wav_string, channel_count, &offset)); |
| 235 | if (*channel_count < 1) { |
| 236 | return errors::InvalidArgument( |
| 237 | "Bad number of channels for WAV: Expected at least 1, but got ", |
| 238 | *channel_count); |
| 239 | } |
| 240 | TF_RETURN_IF_ERROR(ReadValue<uint32>(wav_string, sample_rate, &offset)); |
| 241 | uint32 bytes_per_second; |
| 242 | TF_RETURN_IF_ERROR(ReadValue<uint32>(wav_string, &bytes_per_second, &offset)); |
| 243 | uint16 bytes_per_sample; |
| 244 | TF_RETURN_IF_ERROR(ReadValue<uint16>(wav_string, &bytes_per_sample, &offset)); |
| 245 | // Confusingly, bits per sample is defined as holding the number of bits for |
| 246 | // one channel, unlike the definition of sample used elsewhere in the WAV |
| 247 | // spec. For example, bytes per sample is the memory needed for all channels |
| 248 | // for one point in time. |
| 249 | uint16 bits_per_sample; |
| 250 | TF_RETURN_IF_ERROR(ReadValue<uint16>(wav_string, &bits_per_sample, &offset)); |
| 251 | if (bits_per_sample != 16) { |
| 252 | return errors::InvalidArgument( |
| 253 | "Can only read 16-bit WAV files, but received ", bits_per_sample); |
| 254 | } |
| 255 | const uint32 expected_bytes_per_sample = |
| 256 | ((bits_per_sample * *channel_count) + 7) / 8; |
| 257 | if (bytes_per_sample != expected_bytes_per_sample) { |
| 258 | return errors::InvalidArgument( |
| 259 | "Bad bytes per sample in WAV header: Expected ", |
| 260 | expected_bytes_per_sample, " but got ", bytes_per_sample); |
| 261 | } |
| 262 | const uint32 expected_bytes_per_second = bytes_per_sample * *sample_rate; |
| 263 | if (bytes_per_second != expected_bytes_per_second) { |
| 264 | return errors::InvalidArgument( |
| 265 | "Bad bytes per second in WAV header: Expected ", |
| 266 | expected_bytes_per_second, " but got ", bytes_per_second, |
| 267 | " (sample_rate=", *sample_rate, ", bytes_per_sample=", bytes_per_sample, |
| 268 | ")"); |