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:
parent
829e39594d
commit
7f1a8bb1d7
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue