///////////////////////////////////////////////////////////////////////////// // returns the first layer which plays a chord ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_ChordGet(u8 track, u8 step, u8 par_instrument) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; if( (par_layer=tcc->link_par_layer_chord) >= 0 ) return SEQ_PAR_Get(track, step, par_layer, par_instrument); return 0; }
///////////////////////////////////////////////////////////////////////////// // returns the roll2 mode if assigned to any parameter layer // 0: none // 1.. 31: 2x.. // 32.. 63: 3x.. // 64.. 95: 4x.. // 96..127: 5x.. ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_Roll2ModeGet(u8 track, u8 step, u8 par_instrument) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; if( (par_layer=tcc->link_par_layer_roll2) >= 0 ) { return SEQ_PAR_Get(track, step, par_layer, par_instrument); } return 0; // no roll2 }
///////////////////////////////////////////////////////////////////////////// // returns the roll mode if assigned to any parameter layer // 0: none // 1.. 15: 2D01..2D15 // 16.. 31: 3D00..3D15 // 32.. 47: 4D00..4D15 // 48.. 63: 5D00..5D15 // 64.. 79: 2U00..2U15 // 80.. 95: 3U00..3U15 // 96..111: 4U00..4U15 // 112..127: 5U00..5U15 ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_RollModeGet(u8 track, u8 step, u8 par_instrument, u16 layer_muted) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; if( (par_layer=tcc->link_par_layer_roll) >= 0 && !(layer_muted & (1 << par_layer)) ) { return SEQ_PAR_Get(track, step, par_layer, par_instrument); } return 0; // no roll }
///////////////////////////////////////////////////////////////////////////// // returns the step delay if assigned to any parameter layer // Delay ranges from 0..95 ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_StepDelayGet(u8 track, u8 step, u8 par_instrument) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; if( (par_layer=tcc->link_par_layer_delay) >= 0 ) { s32 value = SEQ_PAR_Get(track, step, par_layer, par_instrument); return (value > 95) ? 95 : value; } return 0; // no delay }
///////////////////////////////////////////////////////////////////////////// // returns the play probability if assigned to any parameter layer // Probability ranges from 0 to 100 for 0%..100% // (the stored value is inverted, to that 0 results into 100%) ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_ProbabilityGet(u8 track, u8 step, u8 par_instrument) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; if( (par_layer=tcc->link_par_layer_probability) >= 0 ) { u8 value = SEQ_PAR_Get(track, step, par_layer, par_instrument); return (value >= 100) ? 0 : 100-value; } return 100; // 100% probability }
///////////////////////////////////////////////////////////////////////////// // returns the first layer which controls velocity // if not assigned to a layer, returns 100 as default velocity ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_VelocityGet(u8 track, u8 step, u8 par_instrument) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; // note: due to performance reasons, similar code exists in SEQ_LAYER_GetEvents() if( (par_layer=tcc->link_par_layer_velocity) >= 0 ) return SEQ_PAR_Get(track, step, par_layer, par_instrument); return 100; // default velocity }
///////////////////////////////////////////////////////////////////////////// // returns the first layer which controls note length // returns 1..96 (96 for glide, 71 if no length assigned) ///////////////////////////////////////////////////////////////////////////// s32 SEQ_PAR_LengthGet(u8 track, u8 step, u8 par_instrument) { seq_cc_trk_t *tcc = &seq_cc_trk[track]; s8 par_layer; // note: due to performance reasons, similar code exists in SEQ_LAYER_GetEvents() if( (par_layer=tcc->link_par_layer_length) >= 0 ) { u8 value = SEQ_PAR_Get(track, step, par_layer, par_instrument); return ((value > 95) ? 95 : value) + 1; } return 71; // no assignment }
///////////////////////////////////////////////////////////////////////////// // Called from SEQ_MIDI_IN_Receive() if MIDI event has been received on // matching IN port and channel ///////////////////////////////////////////////////////////////////////////// s32 SEQ_RECORD_Receive(mios32_midi_package_t midi_package, u8 track) { // step recording mode? // Note: if sequencer is not running, "Live Recording" will be handled like "Step Recording" u8 step_record_mode = seq_record_options.STEP_RECORD || !SEQ_BPM_IsRunning(); #if MBSEQV4L // extra for MBSEQ V4L: seq_record_state.ARMED_TRACKS and auto-assignment if( !seq_record_state.ARMED_TRACKS ) return 0; // no track armed track = 0; if( seq_record_state.ARMED_TRACKS & 0xff00) track = 8; // search for free track/layer if( (midi_package.event == NoteOn) || (midi_package.event == NoteOff) ) { // fine, we will record Note in selected track } else if( midi_package.event == PitchBend ) { track += 3; // G1T4 resp. G3T4 } else if( midi_package.event == CC ) { const u8 track_layer_cc_table[19][2] = { { 4, 0 }, { 5, 0 }, { 6, 0 }, { 7, 0 }, { 7, 1 }, { 7, 2 }, { 7, 3 }, { 6, 1 }, { 6, 2 }, { 6, 3 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 4, 1 }, { 4, 2 }, { 4, 3 }, { 3, 1 }, { 3, 2 }, { 3, 3 }, }; // search for same (or free) CC entry // new track/layer search algorithm since V4L.082 u8 seq_track_offset = track; // depends on sequence int par_layer = 0; int i; u8 free_layer_found = 0; for(i=0; i<19 && !free_layer_found; ++i) { track = seq_track_offset + track_layer_cc_table[i][0]; par_layer = track_layer_cc_table[i][1]; seq_cc_trk_t *tcc = &seq_cc_trk[track]; u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16 + par_layer]; u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16 + par_layer]; if( *layer_type_ptr == SEQ_PAR_Type_CC && (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) && (seq_record_state.ARMED_TRACKS & (1 << track)) ) { if( *layer_cc_ptr >= 0x80 ) { *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track // initialize whole layer with invalid value 0xc0 (indicates: not recorded) int num_p_steps = SEQ_PAR_NumStepsGet(track); int instrument = 0; int step; for(step=0; step<num_p_steps; ++step) SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0); #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] free CC layer found for CC#%d in track #%d.%c\n", midi_package.cc_number, track+1, 'A'+par_layer); #endif } free_layer_found = 1; } } if( !free_layer_found ) { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number); #endif return 0; // no free layer } } else { return 0; // event not relevant } // exit if track not armed if( !(seq_record_state.ARMED_TRACKS & (1 << track)) ) return 0; #else // MBSEQV4 (without L) if( midi_package.event == CC && track == SEQ_UI_VisibleTrackGet() ) { // search for same (or free) CC entry seq_cc_trk_t *tcc = &seq_cc_trk[track]; u8 free_layer_found = 0; { u8 num_p_layers = SEQ_PAR_NumLayersGet(track); u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16]; u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16]; int par_layer; for(par_layer=0; par_layer<num_p_layers && !free_layer_found; ++par_layer, ++layer_type_ptr, ++layer_cc_ptr) { if( *layer_type_ptr == SEQ_PAR_Type_CC && (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) ) { if( *layer_cc_ptr >= 0x80 ) { *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track // initialize whole layer with invalid value 0xc0 (indicates: not recorded) int num_p_steps = SEQ_PAR_NumStepsGet(track); int instrument = 0; int step; for(step=0; step<num_p_steps; ++step) SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0); #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] free CC layer found for CC#%d in track #%d.%c\n", midi_package.cc_number, track+1, 'A'+par_layer); #endif } free_layer_found = 1; break; } } } if( !free_layer_found ) { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number); #endif return 0; // no free layer } } #endif #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] %02x %02x %02x -> track #%d\n", midi_package.evnt0, midi_package.evnt1, midi_package.evnt2, track+1); #endif // exit if track number too high if( track >= SEQ_CORE_NUM_TRACKS ) return -1; // unsupported track seq_core_trk_t *t = &seq_core_trk[track]; seq_cc_trk_t *tcc = &seq_cc_trk[track]; // branch depending on event u8 rec_event = 0; u8 send_note_off = 0; switch( midi_package.event ) { case NoteOff: case NoteOn: { midi_package.note &= 0x7f; // to avoid array overwrites u32 note_mask = 1 << (midi_package.note & 0x1f); // if Note Off and new note number matches with recorded note number if( midi_package.event == NoteOff || midi_package.velocity == 0 ) { if( seq_record_played_notes[midi_package.note>>5] & note_mask ) { MIOS32_IRQ_Disable(); // note not active anymore seq_record_played_notes[midi_package.note>>5] &= ~note_mask; // determine duration in mS (for step recording function) u16 duration_ms = MIOS32_TIMESTAMP_Get() - seq_record_note_timestamp_ms[midi_package.note]; // map to BPM int duration = (int)((float)duration_ms / ((1000.0*60.0) / SEQ_BPM_EffectiveGet() / (float)SEQ_BPM_PPQN_Get())); #if DEBUG_VERBOSE_LEVEL >= 3 DEBUG_MSG("[SEQ_RECORD_Receive] duration of note 0x%02x was %d mS (%d ticks)\n", midi_package.note, duration_ms, duration); #endif // insert length into current step u8 instrument = 0; int len; if( step_record_mode ) { len = 71; // 75% if( tcc->event_mode != SEQ_EVENT_MODE_Drum ) len = (duration <= 96) ? duration : 96; // for duration >= 96 the length will be stretched after record } else { len = SEQ_BPM_TickGet() - t->rec_timestamp; if( len < 1 ) len = 1; else if( len > 95 ) len = 95; } int len_step = step_record_mode ? ui_selected_step : t->step; u8 num_p_layers = SEQ_PAR_NumLayersGet(track); while( 1 ) { if( tcc->event_mode == SEQ_EVENT_MODE_Combined ) { // extra for MBSEQ V4L: // search for note in track 1/8, insert length into track 3/10 int par_layer; for(par_layer=0; par_layer<num_p_layers; ++par_layer) { if( SEQ_PAR_Get(track, len_step, par_layer, instrument) == midi_package.note ) { SEQ_PAR_Set(track+2, len_step, par_layer, instrument, len); break; } } } else { if( tcc->link_par_layer_length >= 0 ) SEQ_PAR_Set(track, len_step, tcc->link_par_layer_length, instrument, len); } if( !step_record_mode ) break; if( tcc->event_mode == SEQ_EVENT_MODE_Drum ) break; if( duration <= 0 ) break; duration -= 96; // insert length into all following steps until a gate is set if( ++len_step > tcc->length ) // TODO: handle this correctly if track is played backwards len_step = tcc->loop; if( SEQ_TRG_GateGet(track, len_step, instrument) ) break; len = (duration > 0) ? 96 : -duration; // copy notes u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16]; int par_layer; for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) { if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord ) { u8 note = SEQ_PAR_Get(track, ui_selected_step, par_layer, instrument); SEQ_PAR_Set(track, len_step, par_layer, instrument, note); } } } MIOS32_IRQ_Enable(); } if( step_record_mode && seq_record_options.FWD_MIDI ) { // send Note Off events of current track if no key is played anymore u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3]; if( !any_note_played ) send_note_off = 1; } } else { MIOS32_IRQ_Disable(); if( step_record_mode && tcc->event_mode != SEQ_EVENT_MODE_Drum ) { // check if another note is already played u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3]; // if not: clear poly counter and all notes (so that new chord can be entered if all keys were released) if( !any_note_played ) { t->rec_poly_ctr = 0; u8 num_p_layers = SEQ_PAR_NumLayersGet(track); u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16]; int par_layer; u8 instrument = 0; for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) { if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord ) SEQ_PAR_Set(track, ui_selected_step, par_layer, instrument, 0x00); } } } // note is active seq_record_played_notes[midi_package.note>>5] |= note_mask; // start measuring length t->rec_timestamp = SEQ_BPM_TickGet(); // for step record function: independent from BPM seq_record_note_timestamp_ms[midi_package.note & 0x7f] = MIOS32_TIMESTAMP_Get(); // note: 16bit only MIOS32_IRQ_Enable(); // record event rec_event = 1; } } break; case CC: case PitchBend: { rec_event = 1; } break; default: { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] event %x not supported.\n", midi_package.event); #endif return -2; // unsupported event } }