///////////////////////////////////////////////////////
| 243 | |
| 244 | //////////////////////////////////////////////////////////// |
| 245 | void SoundFileWriterWav::writeHeader(unsigned int sampleRate, unsigned int channelCount, unsigned int channelMask) |
| 246 | { |
| 247 | assert(m_file.good() && "Most recent I/O operation failed"); |
| 248 | |
| 249 | // Write the main chunk ID |
| 250 | static constexpr std::array mainChunkId = {'R', 'I', 'F', 'F'}; |
| 251 | m_file.write(mainChunkId.data(), mainChunkId.size()); |
| 252 | |
| 253 | // Write the main chunk header |
| 254 | encode(m_file, std::uint32_t{0}); // 0 is a placeholder, will be written later |
| 255 | static constexpr std::array mainChunkFormat = {'W', 'A', 'V', 'E'}; |
| 256 | m_file.write(mainChunkFormat.data(), mainChunkFormat.size()); |
| 257 | |
| 258 | // Write the sub-chunk 1 ("format") id and size |
| 259 | static constexpr std::array fmtChunkId = {'f', 'm', 't', ' '}; |
| 260 | m_file.write(fmtChunkId.data(), fmtChunkId.size()); |
| 261 | |
| 262 | if (channelCount > 2) |
| 263 | { |
| 264 | const std::uint32_t fmtChunkSize = 40; |
| 265 | encode(m_file, fmtChunkSize); |
| 266 | |
| 267 | // Write the format (Extensible) |
| 268 | const std::uint16_t format = 65534; |
| 269 | encode(m_file, format); |
| 270 | } |
| 271 | else |
| 272 | { |
| 273 | const std::uint32_t fmtChunkSize = 16; |
| 274 | encode(m_file, fmtChunkSize); |
| 275 | |
| 276 | // Write the format (PCM) |
| 277 | const std::uint16_t format = 1; |
| 278 | encode(m_file, format); |
| 279 | } |
| 280 | |
| 281 | // Write the sound attributes |
| 282 | encode(m_file, static_cast<std::uint16_t>(channelCount)); |
| 283 | encode(m_file, sampleRate); |
| 284 | const std::uint32_t byteRate = sampleRate * channelCount * 2; |
| 285 | encode(m_file, byteRate); |
| 286 | const auto blockAlign = static_cast<std::uint16_t>(channelCount * 2); |
| 287 | encode(m_file, blockAlign); |
| 288 | const std::uint16_t bitsPerSample = 16; |
| 289 | encode(m_file, bitsPerSample); |
| 290 | |
| 291 | if (channelCount > 2) |
| 292 | { |
| 293 | const std::uint16_t extensionSize = 16; |
| 294 | encode(m_file, extensionSize); |
| 295 | encode(m_file, bitsPerSample); |
| 296 | encode(m_file, channelMask); |
| 297 | // Write the subformat (PCM) |
| 298 | static constexpr std::array subformat = |
| 299 | {'\x01', '\x00', '\x00', '\x00', '\x00', '\x00', '\x10', '\x00', '\x80', '\x00', '\x00', '\xAA', '\x00', '\x38', '\x9B', '\x71'}; |
| 300 | m_file.write(subformat.data(), subformat.size()); |
| 301 | } |
| 302 |