Audio completely drops in Ableton Live (AU - MAC)


#1

Program runs fine, can close window, re-open window.

Audio Unit loads fine in host, and sometimes runs great in Ableton, but not always. Works perfect in Audio Plugin Host everytime. I am removing the component from within users/library and placing it directly in library/audio/plug-ins which requires a password to place in location.

I debugged a copy and removed all errors, however still possible to replicate with no warnings.


#2

processBlock (AudioBuffer& buffer, MidiBuffer& midiMessages)
{
ScopedNoDenormals noDenormals;

auto totalNumInputChannels  = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

// const float gainVolume = *tree.getRawParameterValue("gain");

for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
{
    buffer.clear (i, 0, buffer.getNumSamples());
}

for(int i = 0; i < oscOneSynth.getNumVoices(); i++)
{
    // DBG("Toggle State: " + String(*tree.getRawParameterValue("envOneToggleState")));
    
    if((oscOneVoice = dynamic_cast<SynthVoice*>(oscOneSynth.getVoice(i))) &&
       *tree.getRawParameterValue("envOneToggleState") == 1)
    {
        oscOneVoice->getOscType(tree.getRawParameterValue("oscOne"));
        
        oscOneVoice->getEnvelopeParameters(tree.getRawParameterValue("attackOne"),
                                           tree.getRawParameterValue("decayOne"),
                                           tree.getRawParameterValue("sustainOne"),
                                           tree.getRawParameterValue("releaseOne"));
        
        oscOneVoice->getOscOneToggleState(tree.getRawParameterValue("oscOneToggleState"));
        
        oscOneVoice->getOscOneVolume(tree.getRawParameterValue("oscOneGain"));
    }
    
    else if((oscOneVoice = dynamic_cast<SynthVoice*>(oscOneSynth.getVoice(i))) &&
            *tree.getRawParameterValue("envOneToggleState") == 0)
    {
        oscOneVoice->getOscType(tree.getRawParameterValue("oscOne"));
        
        oscOneVoice->getEnvelopeParameters(tree.getRawParameterValue("attackMaster"),
                                           tree.getRawParameterValue("decayMaster"),
                                           tree.getRawParameterValue("sustainMaster"),
                                           tree.getRawParameterValue("releaseMaster"));
        
        oscOneVoice->getOscOneToggleState(tree.getRawParameterValue("oscOneToggleState"));
        
        oscOneVoice->getOscOneVolume(tree.getRawParameterValue("oscOneGain"));
        
    }
}

for(int i = 0; i < oscTwoSynth.getNumVoices(); ++i)
{
    if((oscTwoVoice = dynamic_cast<SynthVoiceTwo*>(oscTwoSynth.getVoice(i))) &&
       *tree.getRawParameterValue("envTwoToggleState") == 1)
    {
        oscTwoVoice->getOscType(tree.getRawParameterValue("oscTwo"));
        
        oscTwoVoice->getEnvelopeParameters(tree.getRawParameterValue("attackTwo"),
                                           tree.getRawParameterValue("decayTwo"),
                                           tree.getRawParameterValue("sustainTwo"),
                                           tree.getRawParameterValue("releaseTwo"));
        
        oscTwoVoice->getOscTwoToggleState(tree.getRawParameterValue("oscTwoToggleState"));
        
         oscTwoVoice->getOscTwoVolume(tree.getRawParameterValue("oscTwoGain"));
    }
    
    else if((oscTwoVoice = dynamic_cast<SynthVoiceTwo*>(oscTwoSynth.getVoice(i))) &&
            *tree.getRawParameterValue("envTwoToggleState") == 0)
    {
        oscTwoVoice->getOscType(tree.getRawParameterValue("oscTwo"));
        
        oscTwoVoice->getEnvelopeParameters(tree.getRawParameterValue("attackMaster"),
                                           tree.getRawParameterValue("decayMaster"),
                                           tree.getRawParameterValue("sustainMaster"),
                                           tree.getRawParameterValue("releaseMaster"));
        
        oscTwoVoice->getOscTwoToggleState(tree.getRawParameterValue("oscTwoToggleState"));
        
        oscTwoVoice->getOscTwoVolume(tree.getRawParameterValue("oscTwoGain"));
        
    }
}

for(int i = 0; i < oscThreeSynth.getNumVoices(); ++i)
{
    if((oscThreeVoice = dynamic_cast<SynthVoiceThree*>(oscThreeSynth.getVoice(i))) &&
       *tree.getRawParameterValue("envThreeToggleState") == 1)
    {
        oscThreeVoice->getOscType(tree.getRawParameterValue("oscThree"));
        
        oscThreeVoice->getEnvelopeParameters(tree.getRawParameterValue("attackThree"),
                                             tree.getRawParameterValue("decayThree"),
                                             tree.getRawParameterValue("sustainThree"),
                                             tree.getRawParameterValue("releaseThree"));
        
        oscThreeVoice->getOscThreeToggleState(tree.getRawParameterValue("oscThreeToggleState"));
        
        oscThreeVoice->getOscThreeVolume(tree.getRawParameterValue("oscThreeGain"));
        
    }
    
    else if((oscThreeVoice = dynamic_cast<SynthVoiceThree*>(oscThreeSynth.getVoice(i))) &&
            *tree.getRawParameterValue("envThreeToggleState") == 0)
    {
        oscThreeVoice->getOscType(tree.getRawParameterValue("oscThree"));
        
        oscThreeVoice->getEnvelopeParameters(tree.getRawParameterValue("attackMaster"),
                                             tree.getRawParameterValue("decayMaster"),
                                             tree.getRawParameterValue("sustainMaster"),
                                             tree.getRawParameterValue("releaseMaster"));
        
        oscThreeVoice->getOscThreeToggleState(tree.getRawParameterValue("oscThreeToggleState"));
        
        oscThreeVoice->getOscThreeVolume(tree.getRawParameterValue("oscThreeGain"));
        
    }
}

midiCollector.removeNextBlockOfMessages (midiMessages, buffer.getNumSamples());
keyboardState.processNextMidiBuffer(midiMessages, 0, buffer.getNumSamples(), true);

buffer.clear();

oscOneSynth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
oscTwoSynth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
oscThreeSynth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());

// DBG("Midi Messages: " + String(midiMessages.getNumEvents() * 100));

for(int ch = 0; ch < buffer.getNumChannels(); ++ch)
{
    float* data = buffer.getWritePointer(ch);
 
    for(int i = 0; i < buffer.getNumSamples(); ++i)
    {
        data[i] = data[i] * (*tree.getRawParameterValue("gain"));

        // data[i] = gainVolume * std::sin (2.0f * float_Pi * 440.0f * static_cast<float>(pos++) / rate);
        // data[i] = gainVolume * testOsc.sinewave(440);
    }
}

}


#3

I’m using:

FloatVectorOperations::disableDenormalisedNumberSupport();

That should work to avoid denormal issues.
Not sure if ScopedNoDenormals noDenormals; alone does something useful.


#4

ScopeNoDenormals noDenormals; does more than FloatVectorOperations::disableDenormalisedNumberSupport(); since both the constructor and the destructor of ScopeNoDenormals are called. See:


#5

It seems almost like a build issue I am experiencing. I have tried debug, and release versions. However, sometimes when loading the plugin in Ableton the audio will drop and never come back, even if I try deleting plugin from midi channel and closing/re-opening Ableton, still no audio. I did not have this issue on my windows computer, and just re-wrote the code as xcode doesn’t like my code versatility.


#6

This sounds like a float NAN or INF issue. I would verify if the plugin produces invalid float values at startup. The cause could be uninitialised values, an overflow or zero division. Such values can destroy a whole channel if the values make it into a filter history state.


#7

How would one go about doing this? DBG?


#8

I would add a jassert if you are lucky and can reproduce it with a debugger attached. Otherwise i would try to log. DBG maybe is a good idea. You can also write into a file.

You can check NaN with following statement:

f != f will be true only if f is NaN.

You maybe also check for values > 1 and values < -1 to catch the INF case.

My solution is often to comment out parts of the plugin code to get an idea where the problem is.