AmEvent* ArpVelocityMapFilter::HandleEvent(AmEvent* event, const am_filter_params* /*params*/) { if (!event) return event; ArpVALIDATE(mAddOn != NULL && mHolder != NULL, return event); event->SetNextFilter(mHolder->ConnectionAt(0) ); if (event->Type() != event->NOTEON_TYPE) return event; AmNoteOn* e = dynamic_cast<AmNoteOn*>(event); if (!e || !in_range(e, mFromRange) ) return event; int32 fromStart = mFromRange.start, fromEnd = mFromRange.end; int32 toStart = mToRange.start, toEnd = mToRange.end; /* If both the from and start are reversed, but them back to normal. * Otherwise leave them skewed, to allow users to invert the range. */ if (fromEnd < fromStart && toEnd < toStart) { fromStart = mFromRange.end; fromEnd = mFromRange.start; toStart = mToRange.end; toEnd = mToRange.start; } float scale = fabs(float(fromEnd - fromStart) / float(toEnd - toStart)); if (mToRange.end < mToRange.start) scale = -scale; int32 newVel = int32(toStart + ((e->Velocity() - fromStart) * scale)); if (toStart < toEnd) { if (newVel < toStart) newVel = toStart; else if (newVel > toEnd) newVel = toEnd; } else { if (newVel < toEnd) newVel = toEnd; else if (newVel > toStart) newVel = toStart; } e->SetVelocity(newVel); return event; }
AmEvent* ArpAccentRandomizerFilter::HandleEvent(AmEvent* event, const am_filter_params* /*params*/) { if(!event) return event; ArpVALIDATE(mAddOn != 0 && mHolder != 0, return event); event->SetNextFilter(mHolder->FirstConnection() ); if( (event->Type() == event->NOTEON_TYPE) && (0 < mRandomizeAmount) ) { AmNoteOn* note = dynamic_cast<AmNoteOn*>(event); if(!note) return event; int32 delta = rand() % mRandomizeAmount; if(rand() % 2) // flip sign with 50% chance delta *= -1; int32 vel = note->Velocity(); vel += delta; if(vel > 127) vel = 127; if(vel < 0) vel = 0; note->SetVelocity(vel); } 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* 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; }
void _AmControlTarget::Perform(const AmSong* song, const AmSelectionsI* selections) { if (!song || !selections) return; const AmTrack* track = song->Track(TrackWinProperties().OrderedTrackAt(0).TrackId()); if (!track) return; AmFilterHolderI* output = track->Filter(OUTPUT_PIPELINE); if (!output) return; AmEvent* event = selections->AsPlaybackList(song); if (!event) return; AmNoteOn* on = new AmNoteOn(64, 100, 0); if (!on) { event->DeleteChain(); return; } on->SetNextFilter(output); event = on->MergeEvent(event); if (!event) return; AmEvent* e = event; while ( e->NextEvent() ) e = e->NextEvent(); if (e) on->SetEndTime( e->EndTime() ); if (on->Duration() < PPQN / 8) on->SetEndTime( on->StartTime() + (PPQN / 8) ); mPerformer.SetBPM(song->BPM() ); mPerformer.Play(event); }
AmEvent* ArpVaccineFilter::HandleEvent(AmEvent* event, const am_filter_params* params) { if (!event) return event; if (mFrequency == 0 || mAmount == 0) return event; if (event->Type() != event->NOTEON_TYPE && event->Type() != event->NOTEOFF_TYPE) return event; if ( !ShouldVaccinate(mFrequency) ) return event; ArpVALIDATE(params && params->cur_signature, return event); const AmSignature* curSig = params->cur_signature; AmSignature sig; if ( !get_signature(event->StartTime(), curSig, sig) ) return event; int32 prox = (int32)(proximity_to_beat(event->StartTime(), sig) * 100); float prox2 = (float)abs(mProximity - prox) / 100; // printf("proximity is %ld, that puts prox2 at %f\n", prox, prox2); if (prox2 < 0) prox2 = 0; else if (prox2 > 1) prox2 = 1; prox2 = 1 - prox2; /* If there are tool params, set my amount based on the param data. */ int32 amount = mAmount; if (params->flags&AMFF_TOOL_PARAMS) { if (mAmount >= 0) amount = (int32)(params->view_orig_y_pixel - params->view_cur_y_pixel); else amount = (int32)(params->view_cur_y_pixel - params->view_orig_y_pixel); if (amount < MIN_AMOUNT) amount = MIN_AMOUNT; else if (amount > MAX_AMOUNT) amount = MAX_AMOUNT; } if (event->Type() == event->NOTEON_TYPE) { AmNoteOn* noe = dynamic_cast<AmNoteOn*>(event); if (noe) { int32 vel = noe->Velocity(); float scale = ((float)amount / 100) * prox2; vel = vel + (int32)(vel * scale); if (vel < 0) vel = 0; else if (vel > 127) vel = 127; noe->SetVelocity(vel); } } else if (event->Type() == event->NOTEOFF_TYPE) { } return event; }
void AmFilterTest1::TestBasic01() { int i; printf("Making a vector.\n"); vector<int, allocator<int> > myVect(2); myVect[0] = 1; printf("Making a map.\n"); map< int, int, less<int>, allocator<int> > myMap; myMap[0] = 1; printf("Creating example filter object...\n"); fflush(stdout); ArpExampleFilterAddon* exAddon = new ArpExampleFilterAddon; AmFilterHolder* exHolder = new AmFilterHolder; exHolder->SetFilter(exAddon->NewInstance(exHolder)); printf("Creating BSynth filter object...\n"); fflush(stdout); #if 1 AmConsumerFilterAddon* syAddon = new AmConsumerFilterAddon(); #else AmConsumerFilterAddon* syAddon = new AmConsumerFilterAddon("<midi port name>"); #endif /* NOTE: The second consumer filter is not valid. You need to * supply the name of the midi port you want to use. */ AmFilterHolder* syHolder = new AmFilterHolder; syHolder->SetFilter(syAddon->NewInstance(syHolder)); printf("Creating debug filter object...\n"); fflush(stdout); ArpDebugFilterAddon* dbAddon = new ArpDebugFilterAddon(true); AmFilterHolder* dbHolder = new AmFilterHolder; dbHolder->SetFilter(dbAddon->NewInstance(dbHolder)); printf("Attaching BSynth filter to example filter...\n"); fflush(stdout); exHolder->AddSuccessor(syHolder); printf("Attaching debug filter to BSynth filter...\n"); fflush(stdout); syHolder->AddSuccessor(dbHolder); printf("Creating a chain of NoteOn events...\n"); fflush(stdout); AmEventI* evHead=NULL; AmEventI* evTail=NULL; for( i=1; i<=4; i++ ) { { AmProgramChange* ev = new AmProgramChange((i-1)*10, PPQN*4*i-((PPQN*3)/2)); if( !evHead ) { evHead = ev; } else { evTail->AppendEvent(ev); } ev->SetNextFilter(exHolder); evTail = ev; } { AmNoteOn* ev = new AmNoteOn(60+5*i,100,PPQN*4*i); ev->SetRelVelocity(80); if( !evHead ) { evHead = ev; } else { evTail->AppendEvent(ev); } ev->SetNextFilter(exHolder); evTail = ev; } { AmTempoChange* ev = new AmTempoChange(120 + 40*i,PPQN*4*i); if( !evHead ) { evHead = ev; } else { evTail->AppendEvent(ev); } ev->SetNextFilter(exHolder); evTail = ev; } } printf("Initial Event Chain:\n"); fflush(stdout); PrintEventChain(evHead); fflush(stdout); printf("Processing filters on event chain...\n"); fflush(stdout); evHead = ArpExecFilters(evHead); printf("Final event chain:\n"); fflush(stdout); PrintEventChain(evHead); fflush(stdout); printf("Performing the song!\n"); fflush(stdout); { AmPerformer p; p.Start(evHead); // this is a bit of a hack to wait for it to finish; // it will be better when we flesh out the performer // interface to be able to send messages. do { snooze(1 * 1000000); // wait for a sec } while( p.IsPlaying() ); } fflush(stdout); printf("Placing the BSynth filter in its own list...\n"); fflush(stdout); exHolder->RemoveSuccessor(syHolder); syHolder->RemoveSuccessor(dbHolder); printf("Creating a chain of sixteenth notes...\n"); fflush(stdout); evHead = evTail = new AmProgramChange(B_KALIMBA, 0); evTail->SetNextFilter(syHolder); evTail->AppendEvent(new AmTempoChange(480, 0)); evTail = evTail->TailEvent(); evTail->SetNextFilter(syHolder); for( i=1; i<=4*4*4; i++ ) { { AmNoteOn* ev = new AmNoteOn(70+2*(i/(4*4)),100,PPQN*i/4); ev->SetDuration(PPQN/8); ev->SetRelVelocity(80); if( !evHead ) { evHead = ev; } else { evTail->AppendEvent(ev); } ev->SetNextFilter(syHolder); evTail = ev; } } printf("Performing the next song!\n"); fflush(stdout); { AmPerformer p; p.Start(evHead); // this is a bit of a hack to wait for it to finish; // it will be better when we flesh out the performer // interface to be able to send messages. do { snooze(1 * 1000000); // wait for a sec } while( p.IsPlaying() ); } fflush(stdout); printf("Deleting filters -- WHICH FOR SOME REASON IS CRASHING, SO IT'S BEEN REMOVED.\n"); #if 0 exHolder->Delete(); exAddon->RemReference(); syHolder->Delete(); syAddon->RemReference(); dbHolder->Delete(); dbAddon->RemReference(); #endif DoBigTest(); printf("Repeating test...\n"); fflush(stdout); DoBigTest(); }
AmEvent* ErodeFilter::HandleEvent(AmEvent* event, const am_filter_params* /*params*/) { if (!event) return event; ArpVALIDATE(mAddOn != NULL && mHolder != NULL, return event); event->SetNextFilter(mHolder->FirstConnection() ); if (event->Type() == event->NOTEON_TYPE || event->Type() == event->NOTEOFF_TYPE) { AmNoteOn* note; note = dynamic_cast<AmNoteOn*>( event ); if( !note ) return event; AmTime stoppingCondition = note->Duration() / 64; if (stoppingCondition <= 0) return event; AmNoteOn* nextNote = dynamic_cast<AmNoteOn*>( note->Copy() ); AmNoteOn* prevNote = note; while ( nextNote != NULL && nextNote->Duration() >= stoppingCondition ) { if (nextNote->Duration() <= 0) { nextNote->Delete(); return event; } if ( prevNote->Duration() < 4 ) return event; nextNote->SetDuration(prevNote->Duration () * 0.75 ); nextNote->SetStartTime(prevNote->EndTime() + 1); prevNote->AppendEvent(nextNote); prevNote = nextNote; nextNote = dynamic_cast<AmNoteOn*> ( nextNote->Copy() ); } } 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; }