1
0
Fork 0

Write valid .WAV header with dummy sample count at start of run.

As a result, the .WAV file is somewhat usable even during the recording run.
This commit is contained in:
Joris van Rantwijk 2014-01-03 18:50:12 +01:00
parent 829e39594d
commit 7f1a8bb1d7
2 changed files with 44 additions and 31 deletions

View File

@ -141,10 +141,9 @@ WavAudioOutput::WavAudioOutput(const std::string& filename,
return;
}
// Write a 44-byte placeholder for the header.
// Write initial header with a dummy sample count.
// This will be replaced with the actual header once the WavFile is closed.
size_t k = fwrite("[44-byte WAV-file header -- to be filled in]", 1, 44, m_stream);
if (k != 44) {
if (!write_header(0x7fff0000)) {
m_error = "can not write to '" + filename + "' (" +
strerror(errno) + ")";
m_zombie = true;
@ -157,17 +156,10 @@ WavAudioOutput::~WavAudioOutput()
{
// We need to go back and fill in the header ...
const unsigned bytesPerSample = 2;
const unsigned bitsPerSample = 16;
enum wFormatTagId
{
WAVE_FORMAT_PCM = 0x0001,
WAVE_FORMAT_IEEE_FLOAT = 0x0003
};
if (!m_zombie) {
const unsigned bytesPerSample = 2;
const long currentPosition = ftell(m_stream);
assert((currentPosition - 44) % bytesPerSample == 0);
@ -176,28 +168,10 @@ WavAudioOutput::~WavAudioOutput()
assert(totalNumberOfSamples % numberOfChannels == 0);
// synthesize header
uint8_t wavHeader[44];
encode_chunk_id (wavHeader + 0, "RIFF");
set_value<uint32_t>(wavHeader + 4, 36 + totalNumberOfSamples * bytesPerSample);
encode_chunk_id (wavHeader + 8, "WAVE");
encode_chunk_id (wavHeader + 12, "fmt ");
set_value<uint32_t>(wavHeader + 16, 16);
set_value<uint16_t>(wavHeader + 20, WAVE_FORMAT_PCM);
set_value<uint16_t>(wavHeader + 22, numberOfChannels);
set_value<uint32_t>(wavHeader + 24, sampleRate ); // sample rate
set_value<uint32_t>(wavHeader + 28, sampleRate * numberOfChannels * bytesPerSample); // byte rate
set_value<uint16_t>(wavHeader + 32, numberOfChannels * bytesPerSample); // block size
set_value<uint16_t>(wavHeader + 34, bitsPerSample);
encode_chunk_id (wavHeader + 36, "data");
set_value<uint32_t>(wavHeader + 40, totalNumberOfSamples * bytesPerSample);
// Put header in front
if (fseek(m_stream, 0, SEEK_SET) == 0) {
fwrite(wavHeader, 1, 44, m_stream);
write_header(totalNumberOfSamples);
}
}
@ -231,6 +205,42 @@ bool WavAudioOutput::write(const SampleVector& samples)
}
// (Re)write .WAV header.
bool WavAudioOutput::write_header(unsigned int nsamples)
{
const unsigned bytesPerSample = 2;
const unsigned bitsPerSample = 16;
enum wFormatTagId
{
WAVE_FORMAT_PCM = 0x0001,
WAVE_FORMAT_IEEE_FLOAT = 0x0003
};
assert(nsamples % numberOfChannels == 0);
// synthesize header
uint8_t wavHeader[44];
encode_chunk_id (wavHeader + 0, "RIFF");
set_value<uint32_t>(wavHeader + 4, 36 + nsamples * bytesPerSample);
encode_chunk_id (wavHeader + 8, "WAVE");
encode_chunk_id (wavHeader + 12, "fmt ");
set_value<uint32_t>(wavHeader + 16, 16);
set_value<uint16_t>(wavHeader + 20, WAVE_FORMAT_PCM);
set_value<uint16_t>(wavHeader + 22, numberOfChannels);
set_value<uint32_t>(wavHeader + 24, sampleRate ); // sample rate
set_value<uint32_t>(wavHeader + 28, sampleRate * numberOfChannels * bytesPerSample); // byte rate
set_value<uint16_t>(wavHeader + 32, numberOfChannels * bytesPerSample); // block size
set_value<uint16_t>(wavHeader + 34, bitsPerSample);
encode_chunk_id (wavHeader + 36, "data");
set_value<uint32_t>(wavHeader + 40, nsamples * bytesPerSample);
return fwrite(wavHeader, 1, 44, m_stream) == 44;
}
void WavAudioOutput::encode_chunk_id(uint8_t * ptr, const char * chunkname)
{
for (unsigned i = 0; i < 4; ++i)

View File

@ -97,6 +97,9 @@ public:
private:
/** (Re-)Write .WAV header. */
bool write_header(unsigned int nsamples);
static void encode_chunk_id(uint8_t * ptr, const char * chunkname);
template <typename T>