AmEvent* ArpUncertainChorusFilter::HandleEvent(AmEvent* event, const am_filter_params* params)
{
    if (event && mHolder) event->SetNextFilter(mHolder->FirstConnection() );
    if (!event || !should_chorus(mFrequency) ) return event;

    int32		newNote = rand() % 128;
    if (newNote < 0) newNote = 0;
    else if (newNote > 127) newNote = 127;

    if (event->Type() == event->NOTEON_TYPE) {
        AmNoteOn*	e = dynamic_cast<AmNoteOn*>(event);
        if (!e) return event;
        if (e->Note() != newNote) {
            AmNoteOn*	e2 = dynamic_cast<AmNoteOn*>(e->Copy() );
            if (e2) {
                e2->SetNote(uint8(newNote) );
                e->AppendEvent(e2);
            }
        }
    } else if (event->Type() == event->NOTEOFF_TYPE) {
        AmNoteOff*	e = dynamic_cast<AmNoteOff*>(event);
        if (!e) return event;
        if (e->Note() != newNote) {
            AmNoteOff*	e2 = dynamic_cast<AmNoteOff*>(e->Copy() );
            if (e2) {
                e2->SetNote(uint8(newNote) );
                e->AppendEvent(e2);
            }
        }
    }

    return event;
}
AmEvent* ArpUncertainChorusFilter::HandleToolEvent(	AmEvent* event, const am_filter_params* params,
        const am_tool_filter_params* toolParams)
{
    if (event && mHolder) event->SetNextFilter(mHolder->FirstConnection() );
    if (!event || !toolParams) return event;
    if (event->Type() == event->NOTEON_TYPE) {
        AmNoteOn*	e = dynamic_cast<AmNoteOn*>(event);
        if (!e) return event;
        BuildTable(e->Note(), toolParams);
        for (uint32 k = 0; k < NOTE_SIZE; k++) {
            if (mNotes[k] ) {
                AmNoteOn*	e2 = dynamic_cast<AmNoteOn*>(e->Copy() );
                if (e2) {
                    e2->SetNote(k);
                    e->AppendEvent(e2);
                }
            }
        }
    } else if (event->Type() == event->NOTEOFF_TYPE) {
        AmNoteOff*	e = dynamic_cast<AmNoteOff*>(event);
        if (!e) return event;
        BuildTable(e->Note(), toolParams);
        for (uint32 k = 0; k < NOTE_SIZE; k++) {
            if (mNotes[k] ) {
                AmNoteOff*	e2 = dynamic_cast<AmNoteOff*>(e->Copy() );
                if (e2) {
                    e2->SetNote(k);
                    e->AppendEvent(e2);
                }
            }
        }
    }

    return event;
}
AmEvent* ParticleDecayFilter::HandleEvent(AmEvent* event, const am_filter_params* /*params*/)
{
	if (!event) return event;
	ArpVALIDATE(mAddOn != NULL && mHolder != NULL, return event);

	event->SetNextFilter(mHolder->FirstConnection() );
	double  nextVal, cons=0.65;  // it would be nice to one day make 'cons' user defined.
	int counter;
	
	if (event->Type() == event->NOTEON_TYPE || event->Type() == event->NOTEOFF_TYPE) {
	
		AmNoteOn* note = dynamic_cast<AmNoteOn*>( event );
		if( !note ) return event;

		AmNoteOn* nextNote = dynamic_cast<AmNoteOn*>( note->Copy() );
		
		if (nextNote->Duration() <= 0) {
			nextNote->Delete();
			return event;
		}

		AmNoteOn* prevNote = note;
	//	AmNoteOn* firstNote = note;
	
		VossRand pn;
	
		for ( counter = 1; counter <= 10; counter++ ) { //also this user definable
			nextVal = pn.GetValue(prevNote->Note(), cons); 
			nextNote->SetStartTime(prevNote->EndTime() + 1);
			nextNote->SetNote(int(nextVal));
			prevNote->AppendEvent(nextNote);
			prevNote = nextNote;
			nextNote = dynamic_cast<AmNoteOn*> ( nextNote->Copy() );
		}
	}
		return event;
}