[FR] AudioFormatReader dontDeleteStream flag


#1

So I have an OwnedArray of MemoryInputStream

OwnedArray<MemoryInputStream> streamArray;

and I iterate through them…

for (int j = 0; j < numFiles; ++j)
    {
    FlacAudioFormat flac;
    
    MemoryInputStream* pis = streamArray[j];
    
    AudioFormatReader* pReader = flac.createReaderFor (pis, true);
    
    if (pReader != nullptr)
        {
        pReader->setDeleteStreamOnExitFlag (false);  // My method

        // Do some stuff....
        
        delete pReader;
        }
    }

the problem is that when the array goes out of scope and attempts to delete the objects – they no longer exist.

I added a public method and changed the destructor to:

AudioFormatReader::~AudioFormatReader()
{
    if (deleteInputStreamOnExit)
        delete input;
}

which fixes the issue…

For backward compatibility deleteInputStreamOnExit is initialized to true.

Is this something you’d consider adding?

Thanks,

Rail


#2

Can’t you just do

MemoryInputStream* pis = streamArray.getUnchecked(i);
streamArray.set(i, nullptr, false);

instead of

MemoryInputStream* pis = streamArray[j];

#3

While that seems to work – it doesn’t look very elegant to me.

Rail


#4

I’m gonna bump this because I have a few situations now where this would be helpful (I wouldn’t have to keep a local copy of JUCE)…

In juce_AudioFormatReader.h

Add a private member variable:

bool deleteInputStreamOnExit;

Add a public member method:

void setDeleteStreamOnExitFlag (bool bFlag) { deleteInputStreamOnExit = bFlag;  }

In juce_AudioFormatReader.cpp

[code]
AudioFormatReader::AudioFormatReader (InputStream* const in, const String& name)
: sampleRate (0),
bitsPerSample (0),
lengthInSamples (0),
numChannels (0),
usesFloatingPointData (false),
input (in),
formatName (name),
deleteInputStreamOnExit (true)
{
}

AudioFormatReader::~AudioFormatReader()
{
if (deleteInputStreamOnExit)
delete input;
} [/code]

and also in the writer…

In juce_AudioFormatWriter.h

Add a private member variable:

bool deleteOutputStreamOnExit;

Add a public member method:

void setDeleteStreamOnExitFlag (bool bFlag) { deleteOutputStreamOnExit = bFlag;  }

In juce_AudioFormatWriter.cpp

[code]
AudioFormatWriter::AudioFormatWriter (OutputStream* const out,
const String& formatName_,
const double rate,
const unsigned int numChannels_,
const unsigned int bitsPerSample_)
: sampleRate (rate),
numChannels (numChannels_),
bitsPerSample (bitsPerSample_),
usesFloatingPointData (false),
output (out),
formatName (formatName_),
deleteOutputStreamOnExit (true)
{
}

AudioFormatWriter::~AudioFormatWriter()
{
if (deleteOutputStreamOnExit)
delete output;
}[/code]

This is backward compatible.

Thanks,

Rail


#5

What is your objection to

streamArray.set(j, nullptr, false);

? For me that clearly shows your intent, and it’s a single line. This is almost exactly the pattern we use in the recording pane in JuceDemo to avoid a double deletion, except we release() a ScopedPointer rather than set an OwnedArray element to nullptr. I don’t think replacing this line with

pReader->setDeleteStreamOnExitFlag (false);

is any better.


#6

I have other scenarios where I need to not have the Reader/Writer delete the stream.

Thanks,

Rail


#7

Could you please provide some examples?


#8

Hi Tom,

You have a PM

Thanks,

Rail