diff --git a/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp index 058ff733fe..7461dcd480 100644 --- a/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp +++ b/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp @@ -927,12 +927,6 @@ public: ~WavAudioFormatWriter() { - if ((bytesWritten & 1) != 0) // pad to an even length - { - ++bytesWritten; - output->writeByte (0); - } - writeHeader(); } @@ -972,6 +966,20 @@ public: return true; } + bool flush() override + { + const int64 lastWritePos = output->getPosition(); + writeHeader(); + + if (output->setPosition (lastWritePos)) + return true; + + // if this fails, you've given it an output stream that can't seek! It needs + // to be able to seek back to write the header + jassertfalse; + return false; + } + private: MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk; uint64 lengthInSamples, bytesWritten; @@ -998,13 +1006,21 @@ private: void writeHeader() { - using namespace WavFileHelpers; - const bool seekedOk = output->setPosition (headerPosition); - (void) seekedOk; + if ((bytesWritten & 1) != 0) // pad to an even length + { + ++bytesWritten; + output->writeByte (0); + } - // if this fails, you've given it an output stream that can't seek! It needs - // to be able to seek back to write the header - jassert (seekedOk); + using namespace WavFileHelpers; + + if (headerPosition != output->getPosition() && ! output->setPosition (headerPosition)) + { + // if this fails, you've given it an output stream that can't seek! It needs to be + // able to seek back to go back and write the header after the data has been written. + jassertfalse; + return; + } const size_t bytesPerFrame = numChannels * bitsPerSample / 8; uint64 audioDataSize = bytesPerFrame * lengthInSamples; diff --git a/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp b/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp index cd1ffc9a73..ac9e79c722 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp +++ b/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp @@ -183,6 +183,11 @@ bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& sou return writeFromFloatArrays (chans, numSourceChannels, numSamples); } +bool AudioFormatWriter::flush() +{ + return false; +} + //============================================================================== class AudioFormatWriter::ThreadedWriter::Buffer : private TimeSliceClient { diff --git a/modules/juce_audio_formats/format/juce_AudioFormatWriter.h b/modules/juce_audio_formats/format/juce_AudioFormatWriter.h index ceb54dabe5..12292b860f 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatWriter.h +++ b/modules/juce_audio_formats/format/juce_AudioFormatWriter.h @@ -91,8 +91,18 @@ public: to pass it into the method. @param numSamples the number of samples to write */ - virtual bool write (const int** samplesToWrite, - int numSamples) = 0; + virtual bool write (const int** samplesToWrite, int numSamples) = 0; + + /** Some formats may support a flush operation that makes sure the file is in a + valid state before carrying on. + If supported, this means that by calling flush periodically when writing data + to a large file, then it should still be left in a readable state if your program + crashes. + It goes without saying that this method must be called from the same thread that's + calling write()! + If the format supports flushing and the operation succeeds, this returns true. + */ + virtual bool flush(); //============================================================================== /** Reads a section of samples from an AudioFormatReader, and writes these to