0
0

Hey there,

This is my third attempt at getting help for this problem hopefully the addition of some code will help :) anyway here it goes. I’ve been trying to create an ADSR envelope for use with a synthesizer, i have the logic there but i’m using enums to change the state of the envelope i.e. change from ATTACK to DECAY to SUSTAIN etc. Here in lies the problem as when i lift up from a key the channel the oscillator is using is stopped using the Channel::stop(); function. I’d like the ADSR to be on a per channel basis rather then affecting everything being output, like the effects included in FMOD e.g. echo, reverb etc.

Any ideas out there as to how to improve this, heres the code so far anyway……

//Heres the custom ADSR dsp

[code:2btzu10o]float attackRate = 0.00001f;
float decayRate = 0.000001f;
float releaseRate = 0.0001f;
float sustainLevel = 1.0f;
float target = 1.0f;
float value = 0.0f;

enum adsrState {
ATTACK,
DECAY,
SUSTAIN,
RELEASE,
DONE
}
state;

FMOD_RESULT F_CALLBACK ADSR(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels)
{
unsigned int userdata = 0;
char name[256] = {0};
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;

thisdsp->getInfo(name, 0, 0, 0, 0);

thisdsp->getUserData((void **)&userdata);


for (unsigned int sample = 0; sample < length; sample++) 
    { 

    switch (state) {
        case ATTACK:
            value += attackRate;
            if (value >= target)
                            {
                value = target;
                target = sustainLevel;
                state = DECAY;
            }
        break;
        case DECAY:
            value -= decayRate;
            if(value <= sustainLevel)
                            {
                value = sustainLevel;
                state = SUSTAIN;
            }
        break;
        case RELEASE:
            value -= releaseRate;
            if(value <= 0.0)
                            {
                value = 0.0f;
                state = DONE;
            }
        break;
        default:
            break;
    }

    for (int chan = 0; chan < outchannels; chan++)
    {
        outbuffer[(sample * outchannels) + chan] = inbuffer[(sample * inchannels) + chan] * value;
    }
} 

return FMOD_OK; 

}
[/code:2btzu10o]

//Then when i stop a note the state is changed, thus changing the state of all channels playing
[code:2btzu10o]
– (void)stopNoteC{

FMOD_RESULT result = FMOD_OK;
state = RELEASE;
if (noteC)
{
    state = RELEASE;
    result = noteC->stop();
    if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE) && (result !=            FMOD_ERR_CHANNEL_STOLEN))
    {
        CHECKERR(result);
    }
}

}
[/code:2btzu10o]

This is more of a logical thing i can’t work out – would really like some help on this pleasseee :)

Thanks A lot

  • You must to post comments
0
0

It looks like you just have a single state variable. I presume that you have each note with its own channel. Thus, each channel will have to have its own state variable as well. Furthermore, you are probably pushing everything through the same DSP callback. But you want to set it up such that the userdata for each channel is different, so that it can check its own state individually.

Perhaps a simple way of approaching this is to have an array of states, with each element of the array corresponding to the channel number. Then pass the appropriate element through the callback userdata on setup.

Hope that helps.

  • George
  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.