Load file databuffer null hits exception

I am having difficulties loading file to a audio plug in.
first of all i have a button and when i click it i use Filechooser to select the file.
Next I call processor function loadFile to read the file.

void TESTAudioProcessorEditor::buttonClicked(Button* button)
{
if (button == &openFile)
{
FileChooser chooser(“Select a Wav file to play…”,
File::getSpecialLocation(File::userHomeDirectory),
"*.wav");
if (chooser.browseForFileToOpen())
{
File file(chooser.getResult());
processor.loadFile(file);
}
}
}

void TESTAudioProcessor::loadFile(File& file)
{

ScopedPointer<AudioFormatReader>reader = formatManager.createReaderFor(file);

if (reader != nullptr && dataBuffer != nullptr)
{
    int total = reader->lengthInSamples;
    dataBuffer->setSize(reader->numChannels, total);
    reader->read(dataBuffer, 0, total, 0, true, true);
}

}

But whenever i try to debug seems that never enters the if statement because databuffer is null.
and i get that exception triggered if (newNumSamples != size || newNumChannels != numChannels)

Well, where are you setting databuffer?

1 Like

Thnx for the answer bazrush …
On my processor header file under the private variables
ScopedPointerdataBuffer;

Post the whole thing maybe? Maybe you need something like dataBuffer = new AudioSampleBuffer() somewhere?

1 Like

Thnak you again for the quick response .
So these are my files in my pluginprocessor.cpp I have in the constructor
dataBuffer = new AudioSampleBuffer();.

But I think that the real problem is the way I load my file because when I debug my code loaded files doesnot have proper structure .

It 's my first plugin loading files and play them .So please be gentle :smiley:

http://www.megafileupload.com/js8y/PluginEditor.h
http://www.megafileupload.com/js8x/PluginEditor.cpp

http://www.megafileupload.com/js8w/PluginProcessor.h
http://www.megafileupload.com/js8t/PluginProcessor.cpp

Ok -
So this is like a bare-bones sample player at the moment?

I don’t know why you’re getting your data buffer as a nullptr at that line. You are setting it up in the constructor, and then using it in a function that will be called after the constructor has completed. And at no point are you assigning it to null.

However you do have a possible threading issue that could cause a crash. You have the UI thread updating the AudIoSampleBuffer size whilst the audio thread is using the buffer.

1 Like

I guess there are a few ways around that problem, but some sort of lock will be a cheap fix.

You don’t want to block on the audio thread though. So using a CriticalSection with the tryEnter() method inside processBlock() (and the exit method), and then use a ScopedLock in your loadFile() method (which can block).

1 Like

But i think that the problem is something else because I still get the exception when I debug

jassert (isPositiveAndBelow (sourceChannel, source.numChannels));

Before that in the PluginProcessor.cpp my reader->read(dataBuffer, 0, total, 0, true, false);has these arguments and
databuffer has these values inside
{object=0x00c8a750 {numChannels=1 size=986473 allocatedBytes=3945952 ...} }

So it seems that databuffer has the right values, but sourceChannel, and source.numChannels even though are equal still getting that error.

Is that assertion triggering from here:

				for (int i = 0; i < buffer.getNumChannels(); ++i)
				{
					buffer.copyFrom(i, 0, *dataBuffer, i, start, samples);
				}

Where you’re reading a mono file in and then trying to play it back in stereo?

1 Like

Just had to do this for a project today - it’s not for a plugin so the audio callback looks slightly different:

void setFile(const File & f)
{
	ScopedLock lock(loadingSample); 

	pointer = 0; 

	auto reader = audioFormatManager.createReaderFor(f);

	if (reader)
	{
		sampleBuffer.setSize(reader->numChannels, reader->lengthInSamples);
		reader->read(&sampleBuffer, 0, reader->lengthInSamples, 0, true, true);
		auditionPreview.setSource(&sampleBuffer, reader->sampleRate);
	}
}


void audioDeviceIOCallback(const float**, int, float** outputChannelData, int numOutputChannels, int numSamples) override
{
	if (!loadingSample.tryEnter())
        {
		for (int chan = 0; chan < numOutputChannels; ++chan)
			FloatVectorOperations::clear(outputChannelData[chan], numSamples);
		return;
	}

	

	if (sampleBuffer.getNumChannels() == 0)
	{
		for (int chan = 0; chan < numOutputChannels; ++chan)
			FloatVectorOperations::clear(outputChannelData[chan], numSamples);
	}
	else
	{
		const bool isMono = sampleBuffer.getNumChannels() == 1;
		const float * sample[2];
		sample[0] = sampleBuffer.getReadPointer(0);
		sample[1] = sampleBuffer.getReadPointer(isMono ? 0 : 1);

		for (int samp = 0; samp < numSamples; ++samp)
		{
			for (int chan = 0; chan < numOutputChannels; ++chan)
			{
				if (pointer < sampleBuffer.getNumSamples())
					outputChannelData[chan][samp] = sample[chan][pointer];
				else
					outputChannelData[chan][samp] = 0.0f;
			}

			pointer++;
		}
	}

	auditionPreview.setPosition(pointer);  // must be thread safe

	loadingSample.exit(); 
}

CriticalSection loadingSample;
AudioDeviceManager audioDeviceManager;
AudioSampleBuffer sampleBuffer;
1 Like

Thank you for you help , yes first I wanted to load stereo files and I left the buffer handling stereo files … :yum:

I managed to play sound but when I choose another file crushes .I find it very difficult to manage the thread problem for now since I don’t have so much experience .

Another thing I want to do is to have a midi controller to control the playback is it possible ?Can I control when the audio file is played or stopped through a midi controller ?I could use some example code if you can .Because I am lookngjuce tutorials andjuce demo - the tutorials are very specific and thejuce demo is just huge :smiley: Thank you again.!!!

There ought to be a sampler tutorial … but I don’t think there is.

Read these:
https://www.juce.com/doc/classSamplerSound
https://www.juce.com/doc/classSynthesiser

There’s a bug in the code I posted. It lets the pointer increment even when the sample isn’t playing. If you leave it running overnight you’ll get an integer overflow. The fix is to either use an int64 for the sample pointer, or to not increment the value when the sample has reached the end, like this:

		for (int samp = 0; samp < numSamples; ++samp)
		{
			if (pointer < sampleBuffer.getNumSamples())
			{
				for (int chan = 0; chan < numOutputChannels; ++chan)
					outputChannelData[chan][samp] = sample[chan][pointer];

				pointer++;
			}
			else
			{
				for (int chan = 0; chan < numOutputChannels; ++chan)
					outputChannelData[chan][samp] = 0.0f;
			}
		}

Thank you bazrush that worked .It is a little bit tricky for someone with basic audio programming knowledge but I think eventually I ll manage to understand it .Thanks again.

1 Like

Take it slowly. It’ll all make sense in the end*.

*Except filter theory - which will work but will never quite make sense…

Hahahaha until then I will :smiley: