Subversion Repositories svn.mios32

Rev

Rev 1809 | Rev 1813 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
262 tk 1
// $Id: seq_core.c 1810 2013-06-17 21:14:23Z tk $
2
/*
3
 * Sequencer Core Routines
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
19
#include <string.h>
20
#include <seq_bpm.h>
21
#include <seq_midi_out.h>
22
 
1806 tk 23
#include "tasks.h"
24
 
262 tk 25
#include "seq_core.h"
1316 tk 26
#include "seq_song.h"
262 tk 27
#include "seq_random.h"
28
#include "seq_cc.h"
29
#include "seq_layer.h"
337 tk 30
#include "seq_scale.h"
339 tk 31
#include "seq_groove.h"
345 tk 32
#include "seq_humanize.h"
690 tk 33
#include "seq_morph.h"
599 tk 34
#include "seq_lfo.h"
690 tk 35
#include "seq_midi_port.h"
262 tk 36
#include "seq_midi_in.h"
406 tk 37
#include "seq_midi_router.h"
262 tk 38
#include "seq_par.h"
39
#include "seq_trg.h"
40
#include "seq_pattern.h"
41
#include "seq_random.h"
416 tk 42
#include "seq_record.h"
1219 tk 43
#include "seq_live.h"
754 tk 44
#include "seq_midply.h"
758 tk 45
#include "seq_midexp.h"
46
#include "seq_midimp.h"
1083 tk 47
#include "seq_cv.h"
944 tk 48
#include "seq_statistics.h"
262 tk 49
#include "seq_ui.h"
50
 
51
 
1316 tk 52
 
262 tk 53
/////////////////////////////////////////////////////////////////////////////
54
// Local definitions
55
/////////////////////////////////////////////////////////////////////////////
56
 
57
// set this to 1 if performance of clock handler should be measured with a scope
58
// (LED toggling in APP_Background() has to be disabled!)
59
// set this to 2 to visualize forward delay during pattern changes
286 tk 60
#define LED_PERFORMANCE_MEASURING 0
262 tk 61
 
286 tk 62
// same for measuring with the stopwatch
63
// value is visible in menu (-> press exit button)
747 tk 64
// value is visible in INFO->System page (-> press exit button, go to last item)
961 tk 65
#define STOPWATCH_PERFORMANCE_MEASURING 1
262 tk 66
 
286 tk 67
 
262 tk 68
/////////////////////////////////////////////////////////////////////////////
69
// Local prototypes
70
/////////////////////////////////////////////////////////////////////////////
71
 
599 tk 72
static s32 SEQ_CORE_ResetTrkPos(u8 track, seq_core_trk_t *t, seq_cc_trk_t *tcc);
593 tk 73
static s32 SEQ_CORE_NextStep(seq_core_trk_t *t, seq_cc_trk_t *tcc, u8 no_progression, u8 reverse);
262 tk 74
 
75
 
76
/////////////////////////////////////////////////////////////////////////////
77
// Global variables
78
/////////////////////////////////////////////////////////////////////////////
79
 
1313 tk 80
u32 seq_core_timestamp_ms;
81
 
262 tk 82
seq_core_options_t seq_core_options;
83
u8 seq_core_steps_per_measure;
758 tk 84
u8 seq_core_steps_per_pattern;
262 tk 85
 
1015 tk 86
u16 seq_core_trk_muted;
1261 tk 87
u16 seq_core_trk_synched_mute;
88
u16 seq_core_trk_synched_unmute;
1206 tk 89
seq_core_slaveclk_mute_t seq_core_slaveclk_mute;
1015 tk 90
 
751 tk 91
u8 seq_core_step_update_req;
92
 
262 tk 93
u8 seq_core_global_scale;
94
u8 seq_core_global_scale_ctrl;
95
u8 seq_core_global_scale_root;
96
u8 seq_core_global_scale_root_selection;
97
u8 seq_core_keyb_scale_root;
98
 
1320 tk 99
u8 seq_core_global_transpose_enabled;
100
 
491 tk 101
u8 seq_core_bpm_preset_num;
102
float seq_core_bpm_preset_tempo[SEQ_CORE_NUM_BPM_PRESETS];
103
float seq_core_bpm_preset_ramp[SEQ_CORE_NUM_BPM_PRESETS];
104
 
718 tk 105
u8 seq_core_din_sync_pulse_ctr;
262 tk 106
 
524 tk 107
mios32_midi_port_t seq_core_metronome_port;
108
u8 seq_core_metronome_chn;
109
u8 seq_core_metronome_note_m;
110
u8 seq_core_metronome_note_b;
111
 
262 tk 112
seq_core_state_t seq_core_state;
113
seq_core_trk_t seq_core_trk[SEQ_CORE_NUM_TRACKS];
114
 
596 tk 115
seq_core_loop_mode_t seq_core_glb_loop_mode;
116
u8 seq_core_glb_loop_offset;
117
u8 seq_core_glb_loop_steps;
262 tk 118
 
491 tk 119
 
262 tk 120
/////////////////////////////////////////////////////////////////////////////
121
// Local variables
122
/////////////////////////////////////////////////////////////////////////////
123
 
124
static u32 bpm_tick_prefetch_req;
125
static u32 bpm_tick_prefetched_ctr;
126
 
491 tk 127
static float seq_core_bpm_target;
128
static float seq_core_bpm_sweep_inc;
262 tk 129
 
491 tk 130
 
262 tk 131
/////////////////////////////////////////////////////////////////////////////
132
// Initialisation
1794 tk 133
// \param mode if 0: clear all parameters, if 1: don't clear global parameters which are stored in the MBSEQ_GC.V4 file
262 tk 134
/////////////////////////////////////////////////////////////////////////////
135
s32 SEQ_CORE_Init(u32 mode)
136
{
491 tk 137
  int i;
138
 
1313 tk 139
  seq_core_timestamp_ms = 0;
1015 tk 140
  seq_core_trk_muted = 0;
1206 tk 141
  seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
262 tk 142
  seq_core_options.ALL = 0;
1794 tk 143
  if( mode == 0 ) {
144
    seq_core_options.INIT_CC = 64;
145
    seq_core_options.PASTE_CLR_ALL = 1;
146
    seq_core_options.PATTERN_MIXER_MAP_COUPLING = 0;
147
  }
325 tk 148
  seq_core_steps_per_measure = 16-1;
758 tk 149
  seq_core_steps_per_pattern = 16-1;
262 tk 150
  seq_core_global_scale = 0;
151
  seq_core_global_scale_ctrl = 0; // global
152
  seq_core_global_scale_root_selection = 0; // from keyboard
153
  seq_core_keyb_scale_root = 0; // taken if enabled in OPT menu
1320 tk 154
  seq_core_global_transpose_enabled = 0;
718 tk 155
  seq_core_din_sync_pulse_ctr = 0; // used to generate a 1 mS pulse
262 tk 156
 
1794 tk 157
  if( mode == 0 ) {
158
    seq_core_metronome_port = DEFAULT;
159
    seq_core_metronome_chn = 10;
160
    seq_core_metronome_note_m = 0x25; // C#1
161
    seq_core_metronome_note_b = 0x25; // C#1
162
  }
524 tk 163
 
491 tk 164
  seq_core_bpm_preset_num = 13; // 140.0
165
  for(i=0; i<SEQ_CORE_NUM_BPM_PRESETS; ++i) {
166
    seq_core_bpm_preset_tempo[i] = 75.0 + 5.0*i;
167
    seq_core_bpm_preset_ramp[i] = 0.0;
168
  }
169
  seq_core_bpm_sweep_inc = 0.0;
170
 
262 tk 171
  seq_core_state.ALL = 0;
172
 
596 tk 173
  seq_core_glb_loop_mode = SEQ_CORE_LOOP_MODE_ALL_TRACKS_VIEW;
174
  seq_core_glb_loop_offset = 0;
175
  seq_core_glb_loop_steps = 16-1;
176
 
751 tk 177
  seq_core_step_update_req = 0;
178
 
262 tk 179
  // set initial seed of random generator
180
  SEQ_RANDOM_Gen(0xdeadbabe);
181
 
182
  // reset layers
183
  SEQ_LAYER_Init(0);
184
 
185
  // reset patterns
186
  SEQ_PATTERN_Init(0);
187
 
188
  // reset force-to-scale module
189
  SEQ_SCALE_Init(0);
190
 
339 tk 191
  // reset groove module
192
  SEQ_GROOVE_Init(0);
193
 
473 tk 194
  // reset morph module
195
  SEQ_MORPH_Init(0);
196
 
345 tk 197
  // reset humanizer module
198
  SEQ_HUMANIZE_Init(0);
199
 
599 tk 200
  // reset LFO module
201
  SEQ_LFO_Init(0);
202
 
399 tk 203
  // reset song module
204
  SEQ_SONG_Init(0);
205
 
1219 tk 206
  // reset live play module
207
  SEQ_LIVE_Init(0);
208
 
419 tk 209
  // reset record module
210
  SEQ_RECORD_Init(0);
211
 
758 tk 212
  // init MIDI file player/exporter/importer
754 tk 213
  SEQ_MIDPLY_Init(0);
758 tk 214
  SEQ_MIDEXP_Init(0);
215
  SEQ_MIDIMP_Init(0);
754 tk 216
 
262 tk 217
  // clear registers which are not reset by SEQ_CORE_Reset()
218
  u8 track;
600 tk 219
  seq_core_trk_t *t = &seq_core_trk[0];
220
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t) {
262 tk 221
 
222
    // if track name only contains spaces, the UI will print 
223
    // the track number instead of an empty message
224
    // this ensures highest flexibility (e.g. any track can 
225
    // play patterns normaly assigned for other tracks w/o inconsistent messages)
226
    // -> see SEQ_LCD_PrintTrackName()
227
    int i;
316 tk 228
    for(i=0; i<80; ++i)
717 tk 229
      t->name[i] = ' ';
230
    t->name[80] = 0;
231
 
232
    // clear glide note storage
233
    for(i=0; i<4; ++i)
234
      t->glide_notes[i] = 0;
826 tk 235
 
236
    // don't select sections
828 tk 237
    t->play_section = 0;
262 tk 238
  }
239
 
240
  // reset sequencer
1145 tk 241
  SEQ_CORE_Reset(0);
262 tk 242
 
755 tk 243
  // reset MIDI player
244
  SEQ_MIDPLY_Reset();
245
 
262 tk 246
  // init BPM generator
247
  SEQ_BPM_Init(0);
248
 
249
  SEQ_BPM_PPQN_Set(384);
491 tk 250
  SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], 0.0);
262 tk 251
 
286 tk 252
#if STOPWATCH_PERFORMANCE_MEASURING
944 tk 253
  SEQ_STATISTICS_StopwatchInit();
286 tk 254
#endif
255
 
262 tk 256
  return 0; // no error
257
}
258
 
259
 
260
/////////////////////////////////////////////////////////////////////////////
261
// this sequencer handler is called periodically to check for new requests
262
// from BPM generator
263
/////////////////////////////////////////////////////////////////////////////
264
s32 SEQ_CORE_Handler(void)
265
{
266
  // handle requests
267
 
1313 tk 268
  ++seq_core_timestamp_ms; // mS accurate timestamp
269
 
262 tk 270
  u8 num_loops = 0;
271
  u8 again = 0;
272
  do {
273
    ++num_loops;
274
 
275
    // note: don't remove any request check - clocks won't be propagated
1044 tk 276
    // as long as any Stop/Cont/Start/SongPos event hasn't been flagged to the sequencer
262 tk 277
    if( SEQ_BPM_ChkReqStop() ) {
653 tk 278
      SEQ_MIDI_ROUTER_SendMIDIClockEvent(0xfc, 0);
262 tk 279
      SEQ_CORE_PlayOffEvents();
754 tk 280
      SEQ_MIDPLY_PlayOffEvents();
262 tk 281
    }
282
 
283
    if( SEQ_BPM_ChkReqCont() ) {
1206 tk 284
      // release slave mute
285
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
286
 
653 tk 287
      SEQ_MIDI_ROUTER_SendMIDIClockEvent(0xfb, 0);
1206 tk 288
 
262 tk 289
      // release pause mode
290
      ui_seq_pause = 0;
291
    }
292
 
293
    if( SEQ_BPM_ChkReqStart() ) {
1206 tk 294
      // release slave mute
295
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
296
 
653 tk 297
      SEQ_MIDI_ROUTER_SendMIDIClockEvent(0xfa, 0);
1145 tk 298
      SEQ_SONG_Reset(0);
299
      SEQ_CORE_Reset(0);
755 tk 300
      SEQ_MIDPLY_Reset();
1421 tk 301
 
302
      // song page: start song at current edit position
303
      if( ui_page == SEQ_UI_PAGE_SONG ) {
304
    SEQ_SONG_PosSet(ui_song_edit_pos);
305
      }
262 tk 306
    }
307
 
308
    u16 new_song_pos;
309
    if( SEQ_BPM_ChkReqSongPos(&new_song_pos) ) {
1206 tk 310
      // release slave mute
311
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
312
 
1145 tk 313
      u32 new_tick = new_song_pos * (SEQ_BPM_PPQN_Get() / 4);
314
      SEQ_CORE_Reset(new_tick);
315
      SEQ_SONG_Reset(new_tick);
338 tk 316
 
1145 tk 317
#if 0
318
      // fast forward to new song position
319
      if( new_tick ) {
320
    u32 bpm_tick;
321
    for(bpm_tick=0; bpm_tick<=new_tick; bpm_tick+=24) {
322
      SEQ_BPM_TickSet(bpm_tick);
323
      SEQ_CORE_Tick(bpm_tick, -1, 1); // mute all non-loopback tracks
324
    }
325
    SEQ_BPM_TickSet(new_tick);
326
      }
327
#endif
757 tk 328
      SEQ_MIDPLY_SongPos(new_song_pos, 1);
262 tk 329
    }
330
 
331
    u32 bpm_tick;
332
    if( SEQ_BPM_ChkReqClk(&bpm_tick) > 0 ) {
762 tk 333
      // check all requests again after execution of this part
334
      again = 1;
335
 
262 tk 336
      if( bpm_tick_prefetched_ctr ) {
337
    // ticks already generated due to prefetching - wait until we catch up
338
    --bpm_tick_prefetched_ctr;
762 tk 339
      } else {
340
    // it's possible to forward the sequencer on pattern changes
341
    // in this case bpm_tick_prefetch_req is > bpm_tick
342
    // in all other cases, we only generate a single tick (realtime play)
262 tk 343
 
762 tk 344
    u32 bpm_tick_target = bpm_tick;
345
    u8 is_prefetch = 0;
346
    if( bpm_tick_prefetch_req > bpm_tick ) {
347
      is_prefetch = 1;
348
      bpm_tick_target = bpm_tick_prefetch_req;
349
      bpm_tick_prefetched_ctr = bpm_tick_target - bpm_tick;
350
#if 0
351
      DEBUG_MSG("[SEQ_CORE:%u] bpm_tick:%u  bpm_tick_target:%u  bpm_tick_prefetched_ctr:%u\n",
352
            SEQ_BPM_TickGet(), bpm_tick, bpm_tick_target, bpm_tick_prefetched_ctr);
286 tk 353
#endif
262 tk 354
    }
762 tk 355
 
356
    // invalidate request before a new one will be generated (e.g. via SEQ_SONG_NextPos())
262 tk 357
    bpm_tick_prefetch_req = 0;
762 tk 358
 
359
    for(; bpm_tick<=bpm_tick_target; ++bpm_tick) {
262 tk 360
#if LED_PERFORMANCE_MEASURING == 1
762 tk 361
      MIOS32_BOARD_LED_Set(0xffffffff, 1);
262 tk 362
#endif
286 tk 363
#if STOPWATCH_PERFORMANCE_MEASURING == 1
944 tk 364
      SEQ_STATISTICS_StopwatchReset();
286 tk 365
#endif
762 tk 366
 
367
      // generate MIDI events
1145 tk 368
      SEQ_CORE_Tick(bpm_tick, -1, 0);
762 tk 369
      SEQ_MIDPLY_Tick(bpm_tick);
370
 
262 tk 371
#if LED_PERFORMANCE_MEASURING == 1
762 tk 372
      MIOS32_BOARD_LED_Set(0xffffffff, 0);
262 tk 373
#endif
286 tk 374
#if STOPWATCH_PERFORMANCE_MEASURING == 1
944 tk 375
      SEQ_STATISTICS_StopwatchCapture();
286 tk 376
#endif
762 tk 377
 
378
      // load new pattern/song step if reference step reached measure
379
      // (this code is outside SEQ_CORE_Tick() to save stack space!)
1493 tk 380
      if( (bpm_tick % 96) == 20 ) {
762 tk 381
        if( SEQ_SONG_ActiveGet() ) {
1493 tk 382
          if( ( seq_song_guide_track && seq_song_guide_track <= SEQ_CORE_NUM_TRACKS &&
1513 tk 383
            seq_core_state.ref_step_song == seq_cc_trk[seq_song_guide_track-1].length) ||
384
          (!seq_song_guide_track && seq_core_state.ref_step_song == seq_core_steps_per_pattern) ) {
1493 tk 385
 
386
        if( seq_song_guide_track ) {
387
          // request synch-to-measure for all tracks
388
          SEQ_CORE_ManualSynchToMeasure(0xffff);
1513 tk 389
 
390
          // corner case: we will load new tracks and the length of the guide track could change
391
          // in order to ensure that the reference step jumps back to 0, we've to force this here:
392
          seq_core_state.FORCE_REF_STEP_RESET = 1;
1493 tk 393
        }
394
 
395
        SEQ_SONG_NextPos();
396
          }
397
        } else {
398
          if( seq_core_options.SYNCHED_PATTERN_CHANGE &&
399
          seq_core_state.ref_step == seq_core_steps_per_pattern ) {
400
        SEQ_PATTERN_Handler();
401
          }
762 tk 402
        }
403
      }
404
    }
405
 
406
#if 0
407
    if( is_prefetch )
408
      DEBUG_MSG("[SEQ_CORE:%u] prefetching finished, saved %d ticks\n", SEQ_BPM_TickGet(), bpm_tick_target-SEQ_BPM_TickGet());
409
#endif
262 tk 410
      }
411
    }
412
  } while( again && num_loops < 10 );
413
 
414
  return 0; // no error
415
}
416
 
417
 
418
/////////////////////////////////////////////////////////////////////////////
419
// This function plays all "off" events
420
// Should be called on sequencer reset/restart/pause to avoid hanging notes
421
/////////////////////////////////////////////////////////////////////////////
759 tk 422
s32 SEQ_CORE_PlayOffEvents(void)
262 tk 423
{
424
  // play "off events"
425
  SEQ_MIDI_OUT_FlushQueue();
426
 
332 tk 427
  // clear sustain/stretch flags
262 tk 428
  u8 track;
600 tk 429
  seq_core_trk_t *t = &seq_core_trk[0];
430
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t) {
717 tk 431
    int i;
432
 
332 tk 433
    t->state.SUSTAINED = 0;
434
    t->state.STRETCHED_GL = 0;
717 tk 435
    for(i=0; i<4; ++i)
436
      t->glide_notes[i] = 0;
262 tk 437
  }
438
 
439
  return 0; // no error
440
}
441
 
442
 
443
/////////////////////////////////////////////////////////////////////////////
444
// Resets song position of sequencer
445
/////////////////////////////////////////////////////////////////////////////
1145 tk 446
s32 SEQ_CORE_Reset(u32 bpm_start)
262 tk 447
{
448
  ui_seq_pause = 0;
449
  seq_core_state.FIRST_CLK = 1;
450
 
1313 tk 451
  // reset latched PB/CC values
452
  SEQ_LAYER_ResetLatchedValues();
453
 
262 tk 454
  int track;
600 tk 455
  seq_core_trk_t *t = &seq_core_trk[0];
456
  seq_cc_trk_t *tcc = &seq_cc_trk[0];
457
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t, ++tcc) {
262 tk 458
    t->state.ALL = 0;
599 tk 459
    SEQ_CORE_ResetTrkPos(track, t, tcc);
1145 tk 460
 
1806 tk 461
    t->layer_muted_from_midi = 0;
462
    t->layer_muted_from_midi_next = 0;
1809 tk 463
    t->lfo_cc_muted_from_midi = 0;
464
    t->lfo_cc_muted_from_midi_next = 0;
1806 tk 465
 
1145 tk 466
    // add track offset depending on start position
467
    if( bpm_start ) {
468
#if 0
469
      u32 step_length = ((tcc->clkdiv.value+1) * (tcc->clkdiv.TRIPLETS ? 4 : 6));
470
#else
471
      // leads to bad result with Logic Audio: it starts one step earlier and assumes 16th steps!
472
      u32 step_length = 96;
473
#endif
474
      u8 pos_step = (u8)((bpm_start / step_length) % ((u32)tcc->length+1));
475
 
476
      // next part depends on forward/backward direction
477
      if( tcc->dir_mode == SEQ_CORE_TRKDIR_Backward ) {
478
    t->step = tcc->length - pos_step;
479
      } else {
480
    t->step = pos_step;
481
      }
482
    }
483
 
419 tk 484
    SEQ_RECORD_Reset(track);
262 tk 485
  }
486
 
487
  // since timebase has been changed, ensure that Off-Events are played 
488
  // (otherwise they will be played much later...)
489
  SEQ_CORE_PlayOffEvents();
490
 
1145 tk 491
  // set BPM tick
492
  SEQ_BPM_TickSet(bpm_start);
262 tk 493
 
494
  // cancel prefetch requests/counter
495
  bpm_tick_prefetch_req = 0;
496
  bpm_tick_prefetched_ctr = 0;
497
 
1205 tk 498
  // cancel stop and set step request
600 tk 499
  seq_core_state.MANUAL_TRIGGER_STOP_REQ = 0;
500
 
1145 tk 501
  // reset reference step
1513 tk 502
  seq_core_state.ref_step = (u16)((bpm_start / 96) % ((u32)seq_core_steps_per_measure+1));
503
  if( seq_song_guide_track ) {
504
    seq_core_state.ref_step_song = (u16)((bpm_start / 96) % ((u32)seq_cc_trk[seq_song_guide_track-1].length+1));
505
  } else {
506
    seq_core_state.ref_step_song = seq_core_state.ref_step;
507
  }
1145 tk 508
 
262 tk 509
  return 0; // no error
510
}
511
 
512
 
513
/////////////////////////////////////////////////////////////////////////////
514
// performs a single ppqn tick
761 tk 515
// if "export_track" is -1, all tracks will be played
516
// if "export_track" is between 0 and 15, only the given track + all loopback
759 tk 517
//   tracks will be played (for MIDI file export)
1145 tk 518
// if "mute_nonloopback_tracks" is set, the "normal" tracks won't be played
519
// this option is used for the "fast forward" function on song position changes
262 tk 520
/////////////////////////////////////////////////////////////////////////////
1145 tk 521
s32 SEQ_CORE_Tick(u32 bpm_tick, s8 export_track, u8 mute_nonloopback_tracks)
262 tk 522
{
757 tk 523
  // get MIDI File play mode (if set to SEQ_MIDPLY_MODE_Exclusive, all tracks will be muted)
1316 tk 524
  u8 midply_solo = SEQ_MIDPLY_RunModeGet() != 0 && SEQ_MIDPLY_ModeGet() == SEQ_MIDPLY_MODE_Exclusive;
757 tk 525
 
262 tk 526
  // increment reference step on each 16th note
527
  // set request flag on overrun (tracks can synch to measure)
528
  u8 synch_to_measure_req = 0;
1513 tk 529
  if( (bpm_tick % (384/4)) == 0 ) {
1518 tk 530
    seq_core_trk_t *t = &seq_core_trk[0];
531
    seq_cc_trk_t *tcc = &seq_cc_trk[0];
532
    u8 track;
533
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t, ++tcc) {
534
      if( seq_core_state.reset_trkpos_req & (1 << track) ) {
535
    SEQ_CORE_ResetTrkPos(track, t, tcc);
536
      }
1806 tk 537
 
538
      // NEW: temporary layer mutes on incoming MIDI
539
      // take over _next mutes
1810 tk 540
      int num_steps = (seq_core_options.LIVE_LAYER_MUTE_STEPS < 2) ? 1 : (seq_core_options.LIVE_LAYER_MUTE_STEPS-2+1);
541
      if( (bpm_tick % (num_steps*(384/4))) == 0 ) {
1809 tk 542
    // layer mutes
543
    t->layer_muted_from_midi = t->layer_muted_from_midi_next;
544
    t->layer_muted_from_midi_next = 0;
545
 
546
    // the same for the LFO CC
547
    t->lfo_cc_muted_from_midi = t->lfo_cc_muted_from_midi_next;
548
    t->lfo_cc_muted_from_midi_next = 0;
549
      }
1515 tk 550
    }
1518 tk 551
    seq_core_state.reset_trkpos_req = 0;
1515 tk 552
 
1513 tk 553
    if( seq_core_state.FIRST_CLK || seq_core_state.FORCE_REF_STEP_RESET ) {
554
      seq_core_state.FORCE_REF_STEP_RESET = 0;
555
      synch_to_measure_req = 1;
1145 tk 556
      seq_core_state.ref_step = 0;
1513 tk 557
      seq_core_state.ref_step_song = 0;
558
    } else {
559
      if( ++seq_core_state.ref_step > seq_core_steps_per_measure ) {
560
    seq_core_state.ref_step = 0;
561
      }
562
 
563
      if( seq_song_guide_track ) {
564
    if( ++seq_core_state.ref_step_song > seq_cc_trk[seq_song_guide_track-1].length ) {
565
      seq_core_state.ref_step_song = 0;
566
    }
567
      } else {
568
    seq_core_state.ref_step_song = seq_core_state.ref_step;
569
      }
570
 
571
      if( SEQ_SONG_ActiveGet() ) {
572
    if( seq_core_state.ref_step_song == 0 )
573
      synch_to_measure_req = 1;
574
      } else {
575
    if( seq_core_state.ref_step == 0 )
576
      synch_to_measure_req = 1;
577
      }
578
    }
262 tk 579
  }
580
 
1206 tk 581
  // disable slave clock mute if not in slave mode anymore
582
  // or start of if measure is reached and OffOnNextMeasure has been requested
1209 tk 583
  u8 is_master = SEQ_BPM_IsMaster();
584
  if( is_master ||
1206 tk 585
      (synch_to_measure_req && (seq_core_slaveclk_mute == SEQ_CORE_SLAVECLK_MUTE_OffOnNextMeasure)) ) {
586
    // enable ports
587
    seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
1209 tk 588
    if( !is_master ) {
589
      // release pause mode
590
      ui_seq_pause = 0;
591
      // TK: this makes sense! Request synch-to-measure for all tracks so that they restart properly
1315 tk 592
      SEQ_CORE_ManualSynchToMeasure(0xffff);
1209 tk 593
    }
1206 tk 594
  }
595
 
1145 tk 596
  // if no export and no mute:
597
  if( export_track == -1 && !mute_nonloopback_tracks ) {
1048 tk 598
    // send FA if external restart has been requested
599
    if( seq_core_state.EXT_RESTART_REQ && synch_to_measure_req ) {
600
      seq_core_state.EXT_RESTART_REQ = 0; // remove request
601
      seq_ui_display_update_req = 1; // request display update
602
      SEQ_MIDI_ROUTER_SendMIDIClockEvent(0xfa, bpm_tick);
603
    }
604
 
761 tk 605
    // send MIDI clock on each 16th tick (since we are working at 384ppqn)
606
    if( (bpm_tick % 16) == 0 )
607
      SEQ_MIDI_ROUTER_SendMIDIClockEvent(0xf8, bpm_tick);
262 tk 608
 
761 tk 609
    // trigger DIN Sync clock with a special event (0xf9 normaly used for "MIDI tick")
610
    // SEQ_MIDI_PORT_NotifyMIDITx filters it before it will be forwarded to physical ports
1083 tk 611
    if( (bpm_tick % SEQ_CV_ClkDividerGet()) == 0 ) {
761 tk 612
      mios32_midi_package_t p;
613
      p.ALL = 0;
614
      p.type = 0x5; // Single-byte system common message
615
      p.evnt0 = 0xf9;
616
      SEQ_MIDI_OUT_Send(0xff, p, SEQ_MIDI_OUT_ClkEvent, bpm_tick, 0);
617
    }
718 tk 618
 
761 tk 619
    // send metronome tick on each beat if enabled
1145 tk 620
    if( seq_core_state.METRONOME && seq_core_metronome_chn && (bpm_tick % 96) == 0 && (seq_core_state.ref_step % 4) == 0 ) {
761 tk 621
      mios32_midi_package_t p;
262 tk 622
 
761 tk 623
      p.type     = NoteOn;
624
      p.cable    = 15; // use tag of track #16 - unfortunately more than 16 tags are not supported
625
      p.event    = NoteOn;
626
      p.chn      = seq_core_metronome_chn-1;
627
      p.note     = seq_core_metronome_note_b;
628
      p.velocity = 96;
629
      u16 len = 20; // ca. 25% of a 16th
524 tk 630
 
1145 tk 631
      if( seq_core_state.ref_step == 0 ) {
761 tk 632
    if( seq_core_metronome_note_m )
633
      p.note = seq_core_metronome_note_m; // if this note isn't defined, use B note instead
634
    p.velocity = 127;
635
      }
636
 
637
      if( p.note )
638
    SEQ_MIDI_OUT_Send(seq_core_metronome_port, p, SEQ_MIDI_OUT_OnOffEvent, bpm_tick, len);
524 tk 639
    }
640
  }
641
 
1261 tk 642
  // delayed mute
643
  if( synch_to_measure_req ) {
644
    // the priority handling for each individual track ensures
645
    // that mute/unmute will be done depending on the current mute state
646
    // unmute has higher priority than mute
647
    seq_core_trk_muted |= (seq_core_trk_synched_mute & ~seq_core_trk_muted);
648
    seq_core_trk_synched_mute = 0;
524 tk 649
 
1261 tk 650
    seq_core_trk_muted &= ~(seq_core_trk_synched_unmute & seq_core_trk_muted);
651
    seq_core_trk_synched_unmute = 0;
652
  }
653
 
654
 
262 tk 655
  // process all tracks
718 tk 656
  // first the loopback port Bus1, thereafter parameters sent to common MIDI ports
302 tk 657
  int round;
658
  for(round=0; round<2; ++round) {
659
    seq_core_trk_t *t = &seq_core_trk[0];
660
    seq_cc_trk_t *tcc = &seq_cc_trk[0];
661
    int track;
662
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++t, ++tcc, ++track) {
262 tk 663
 
718 tk 664
      // round 0: loopback port Bus1, round 1: remaining ports
1023 tk 665
      u8 loopback_port = (tcc->midi_port & 0xf0) == 0xf0;
302 tk 666
      if( (!round && !loopback_port) || (round && loopback_port) )
262 tk 667
    continue;
306 tk 668
 
761 tk 669
      // for MIDI file export: (export_track != -1): only given track + all loopback tracks will be played
670
      if( round && export_track != -1 && export_track != track )
759 tk 671
    continue;
672
 
599 tk 673
      // handle LFO effect
674
      SEQ_LFO_HandleTrk(track, bpm_tick);
675
 
1809 tk 676
      // send LFO CC (if enabled and not muted)
677
      if( !(seq_core_trk_muted & (1 << track)) && !seq_core_slaveclk_mute && !t->lfo_cc_muted_from_midi ) {
599 tk 678
    mios32_midi_package_t p;
1787 tk 679
    if( SEQ_LFO_FastCC_Event(track, bpm_tick, &p, 0) > 0 ) {
741 tk 680
      if( loopback_port )
1675 tk 681
        SEQ_MIDI_IN_BusReceive(tcc->midi_port & 0x0f, p, 1); // forward to MIDI IN handler immediately
741 tk 682
      else
683
        SEQ_MIDI_OUT_Send(tcc->midi_port, p, SEQ_MIDI_OUT_CCEvent, bpm_tick, 0);
684
    }
599 tk 685
      }
686
 
330 tk 687
      // sustained note: play off event if sustain mode has been disabled and no stretched gatelength
473 tk 688
      if( t->state.SUSTAINED && !tcc->mode.SUSTAIN && !t->state.STRETCHED_GL ) {
717 tk 689
    int i;
690
 
691
    // important: play Note Off before new Note On to avoid that glide is triggered on the synth
1319 tk 692
    SEQ_MIDI_OUT_ReSchedule(track, SEQ_MIDI_OUT_OffEvent, bpm_tick ? (bpm_tick-1) : 0,
693
                seq_record_state.ENABLED ? seq_record_played_notes : NULL);
717 tk 694
    // clear state flag and note storage
332 tk 695
    t->state.SUSTAINED = 0;
717 tk 696
    for(i=0; i<4; ++i)
697
      t->glide_notes[i] = 0;
306 tk 698
      }
338 tk 699
 
302 tk 700
      // if "synch to measure" flag set: reset track if master has reached the selected number of steps
701
      // MEMO: we could also provide the option to synch to another track
600 tk 702
      if( synch_to_measure_req && (tcc->clkdiv.SYNCH_TO_MEASURE || t->state.SYNC_MEASURE) )
599 tk 703
        SEQ_CORE_ResetTrkPos(track, t, tcc);
1211 tk 704
 
1121 tk 705
      u8 skip_this_step = 0;
1211 tk 706
      u8 next_step_event = t->state.FIRST_CLK || bpm_tick >= t->timestamp_next_step;
1316 tk 707
      if( next_step_event ) {
338 tk 708
 
1639 tk 709
    {
1211 tk 710
      // calculate step length
711
      u16 step_length_pre = ((tcc->clkdiv.value+1) * (tcc->clkdiv.TRIPLETS ? 4 : 6));
712
      t->step_length = step_length_pre;
344 tk 713
 
1211 tk 714
      // set timestamp of next step w/o groove delay (reference timestamp)
715
      if( t->state.FIRST_CLK )
716
        t->timestamp_next_step_ref = bpm_tick + t->step_length;
717
      else
718
        t->timestamp_next_step_ref += t->step_length;
828 tk 719
 
1211 tk 720
      // increment step if not in arpeggiator mode or arp position == 0
1788 tk 721
      u8 inc_step = tcc->mode.playmode != SEQ_CORE_TRKMODE_Arpeggiator || !t->arp_pos;
1211 tk 722
 
1788 tk 723
      // wrap step position around length - especially required for "section selection" later,
724
      // which can set t->step beyond tcc->length+1
725
      u8 prev_step = (u8)((int)t->step % ((int)tcc->length + 1));
726
      t->step = prev_step; // store back wrapped step position
727
 
728
      u8 skip_ctr = 0;
729
      do {
730
        if( t->state.MANUAL_STEP_REQ ) {
731
          // manual step requested
732
          t->state.MANUAL_STEP_REQ = 0;
733
          t->step = t->manual_step;
734
          t->step_saved = t->manual_step;
735
          t->arp_pos = 0;
736
        } else {
737
          // determine next step depending on direction mode
738
          if( !t->state.FIRST_CLK && inc_step )
739
        SEQ_CORE_NextStep(t, tcc, 0, 0); // 0, 0=with progression, not reverse
740
          else {
741
        // ensure that position reset request is cleared
742
        t->state.POS_RESET = 0;
1211 tk 743
          }
1788 tk 744
        }
302 tk 745
 
1788 tk 746
        // clear "first clock" flag (on following clock ticks we can continue as usual)
747
        t->state.FIRST_CLK = 0;
302 tk 748
 
1788 tk 749
        // if skip flag set for this flag: try again
750
        if( SEQ_TRG_SkipGet(track, t->step, 0) )
751
          ++skip_ctr;
752
        else
753
          break;
754
 
755
      } while( skip_ctr < 32 ); // try 32 times maximum
344 tk 756
 
1788 tk 757
      // Section selection
758
      // Approach:
759
      // o enabled with t->play_section > 0
760
      // o section width matches with the Track length, which means that the sequencer will
761
      //   play steps beyond the "last step" with t->play_section > 0
762
      // o section controlled via UI, MIDI Keyboard or BLM
763
      // o lower priority than global loop mode
764
      if( t->play_section > 0 ) {
765
        // note: SEQ_TRG_Get() will return 0 if t->step beyond total track size - no need to consider this here
766
        int step_offset = t->play_section * ((int)tcc->length+1);
767
        t->step += step_offset;
768
      }
828 tk 769
 
1788 tk 770
      // global loop mode handling
771
      // requirements:
772
      // o loop all or only select tracks
773
      // o allow to loop the step view (16 step window) or a definable number of steps
774
      // o wrap step position properly when loop mode is activated so that this
775
      //   doesn't "dirsturb" the sequence output (ensure that the track doesn't get out of sync)
776
      if( seq_core_state.LOOP ) {
777
        u8 loop_active = 0;
778
        int step_offset = 0;
779
 
780
        switch( seq_core_glb_loop_mode ) {
781
        case SEQ_CORE_LOOP_MODE_ALL_TRACKS_STATIC:
782
          loop_active = 1;
783
          break;
596 tk 784
 
1788 tk 785
        case SEQ_CORE_LOOP_MODE_SELECTED_TRACK_STATIC:
786
          if( SEQ_UI_IsSelectedTrack(track) )
596 tk 787
        loop_active = 1;
1788 tk 788
          break;
596 tk 789
 
1788 tk 790
        case SEQ_CORE_LOOP_MODE_ALL_TRACKS_VIEW:
791
          loop_active = 1;
792
          // no break!
596 tk 793
 
1788 tk 794
        case SEQ_CORE_LOOP_MODE_SELECTED_TRACK_VIEW:
795
          if( SEQ_UI_IsSelectedTrack(track) )
596 tk 796
        loop_active = 1;
797
 
1788 tk 798
          step_offset = 16 * ui_selected_step_view;
799
          break;
800
        }
596 tk 801
 
1788 tk 802
        if( loop_active ) {
803
          // wrap step position within given boundaries if required
804
          step_offset += seq_core_glb_loop_offset;
805
          step_offset %= ((int)tcc->length+1);
596 tk 806
 
1788 tk 807
          int loop_steps = seq_core_glb_loop_steps + 1;
808
          int max_steps = (int)tcc->length + 1;
809
          if( loop_steps > max_steps )
810
        loop_steps = max_steps;
596 tk 811
 
1788 tk 812
          int new_step = (int)t->step;
813
          new_step = step_offset + ((new_step-step_offset) % loop_steps);
596 tk 814
 
1788 tk 815
          if( new_step > tcc->length )
816
        new_step = step_offset;
817
          t->step = new_step;
596 tk 818
        }
1788 tk 819
      }
596 tk 820
 
1788 tk 821
      // calculate number of cycles to next step
599 tk 822
#if 0
1788 tk 823
      t->timestamp_next_step = t->timestamp_next_step_ref + SEQ_GROOVE_DelayGet(track, t->step + 1);
599 tk 824
#else
1788 tk 825
      t->timestamp_next_step = t->timestamp_next_step_ref + SEQ_GROOVE_DelayGet(track, seq_core_state.ref_step + 1);
599 tk 826
#endif
419 tk 827
 
1788 tk 828
      skip_this_step = !seq_record_options.FWD_MIDI && t->state.REC_DONT_OVERWRITE_NEXT_STEP;
829
      // forward new step to recording function (only used in live recording mode)
830
      SEQ_RECORD_NewStep(track, prev_step, t->step, bpm_tick);
751 tk 831
 
1788 tk 832
      // inform UI about a new step (UI will clear this variable)
833
      seq_core_step_update_req = 1;
1211 tk 834
    }
338 tk 835
 
302 tk 836
        // solo function: don't play MIDI event if track not selected
837
        // mute function
330 tk 838
        // track disabled
1145 tk 839
    // mute for non-loopback tracks activated
757 tk 840
    // MIDI player in exclusive mode
1121 tk 841
    // Record Mode, new step and FWD_MIDI off
338 tk 842
        if( (seq_ui_button_state.SOLO && !SEQ_UI_IsSelectedTrack(track)) ||
1015 tk 843
        (seq_core_trk_muted & (1 << track)) || // Track Mute function
1206 tk 844
        seq_core_slaveclk_mute || // Slave Clock Mute Function
607 tk 845
        SEQ_MIDI_PORT_OutMuteGet(tcc->midi_port) || // Port Mute Function
757 tk 846
        tcc->mode.playmode == SEQ_CORE_TRKMODE_Off || // track disabled
1145 tk 847
        (round && mute_nonloopback_tracks) || // all non-loopback tracks should be muted
1121 tk 848
        midply_solo || // MIDI player in exclusive mode
849
        skip_this_step ) { // Record Mode, new step and FWD_MIDI off
419 tk 850
 
338 tk 851
      if( t->state.STRETCHED_GL || t->state.SUSTAINED ) {
717 tk 852
        int i;
853
 
854
        if( !t->state.STRETCHED_GL ) // important: play Note Off before new Note On to avoid that glide is triggered on the synth
1319 tk 855
          SEQ_MIDI_OUT_ReSchedule(track, SEQ_MIDI_OUT_OffEvent, bpm_tick ? (bpm_tick-1) : 0,
856
                      seq_record_state.ENABLED ? seq_record_played_notes : NULL);
717 tk 857
        else // Glide
1319 tk 858
          SEQ_MIDI_OUT_ReSchedule(track, SEQ_MIDI_OUT_OffEvent, bpm_tick,
859
                      seq_record_state.ENABLED ? seq_record_played_notes : NULL);
717 tk 860
 
861
        // clear state flags and note storage
338 tk 862
        t->state.STRETCHED_GL = 0;
863
        t->state.SUSTAINED = 0;
717 tk 864
        for(i=0; i<4; ++i)
865
          t->glide_notes[i] = 0;
338 tk 866
      }
419 tk 867
 
330 tk 868
      continue;
338 tk 869
    }
1211 tk 870
 
302 tk 871
        // if random gate trigger set: play step with 1:1 probability
328 tk 872
        if( SEQ_TRG_RandomGateGet(track, t->step, 0) && (SEQ_RANDOM_Gen(0) & 1) )
302 tk 873
      continue;
334 tk 874
 
1219 tk 875
    // parameter layer mute flags (only if not in drum mode)
1806 tk 876
    u16 layer_muted = (tcc->event_mode != SEQ_EVENT_MODE_Drum) ? (t->layer_muted | t->layer_muted_from_midi) : 0;
1219 tk 877
 
473 tk 878
    // check probability if not in drum mode
334 tk 879
    // if probability < 100: play step with given probability
473 tk 880
    // in drum mode, the probability is checked for each individual instrument inside the layer event loop
334 tk 881
    if( tcc->event_mode != SEQ_EVENT_MODE_Drum ) {
882
      u8 rnd_probability;
1219 tk 883
      if( (rnd_probability=SEQ_PAR_ProbabilityGet(track, t->step, 0, layer_muted)) < 100 &&
334 tk 884
          SEQ_RANDOM_Gen_Range(0, 99) >= rnd_probability )
885
        continue;
886
    }
419 tk 887
 
717 tk 888
    // store last glide notes before they will be cleared
889
    u32 last_glide_notes[4];
890
    memcpy(last_glide_notes, t->glide_notes, 4*4);
419 tk 891
 
323 tk 892
        seq_layer_evnt_t layer_events[16];
1211 tk 893
        s32 number_of_events = 0;
894
 
1316 tk 895
    number_of_events = SEQ_LAYER_GetEvents(track, t->step, layer_events, 0);
1211 tk 896
    if( number_of_events > 0 ) {
328 tk 897
      int i;
419 tk 898
 
899
      //////////////////////////////////////////////////////////////////////////////////////////
900
      // First pass: handle length and apply functions which modify the MIDI events
901
      //////////////////////////////////////////////////////////////////////////////////////////
902
      u16 prev_bpm_tick_delay = t->bpm_tick_delay;
903
      u8 gen_on_events = 0; // new On Events will be generated
904
      u8 gen_sustained_events = 0; // new sustained On Events will be generated
608 tk 905
      u8 gen_off_events = 0; // Off Events of previous step will be generated, the variable contains the remaining gatelength
419 tk 906
 
323 tk 907
          seq_layer_evnt_t *e = &layer_events[0];
908
          for(i=0; i<number_of_events; ++e, ++i) {
909
            mios32_midi_package_t *p = &e->midi_package;
328 tk 910
 
332 tk 911
        // instrument layers only used for drum tracks
686 tk 912
        u8 instrument = (tcc->event_mode == SEQ_EVENT_MODE_Drum) ? e->layer_tag : 0;
330 tk 913
 
334 tk 914
        // individual for each instrument in drum mode:
915
        // if probability < 100: play step with given probability
916
        if( tcc->event_mode == SEQ_EVENT_MODE_Drum ) {
917
          u8 rnd_probability;
1219 tk 918
          if( (rnd_probability=SEQ_PAR_ProbabilityGet(track, t->step, instrument, layer_muted)) < 100 &&
334 tk 919
          SEQ_RANDOM_Gen_Range(0, 99) >= rnd_probability )
920
        continue;
921
        }
922
 
323 tk 923
            // transpose notes/CCs
924
            SEQ_CORE_Transpose(t, tcc, p);
330 tk 925
 
1142 tk 926
            // glide trigger
927
            if( e->len > 0 && tcc->event_mode != SEQ_EVENT_MODE_Drum ) {
928
          if( SEQ_TRG_GlideGet(track, t->step, instrument) )
929
        e->len = 96; // Glide
930
            }
931
 
932
        // if glided note already played: omit new note event by setting velocity to 0
933
        if( t->state.STRETCHED_GL && (last_glide_notes[p->note / 32] & (1 << (p->note % 32))) ) {
934
          p->velocity = 0;
935
        }
936
 
937
            // skip if velocity has been cleared by transpose or glide function
323 tk 938
            // (e.g. no key pressed in transpose mode)
330 tk 939
            if( p->type == NoteOn && !p->velocity ) {
940
          // stretched note, length < 96: queue off event
419 tk 941
          if( t->state.STRETCHED_GL && t->state.SUSTAINED && (e->len < 96) )
608 tk 942
        gen_off_events = (t->step_length * e->len) / 96;
323 tk 943
          continue;
330 tk 944
        }
306 tk 945
 
338 tk 946
        // get delay of step (0..95)
947
        // note: negative delays stored in step parameters would require to pre-generate bpm_ticks, 
948
        // which would reduce the immediate response on value/trigger changes
949
        // therefore negative delays are only supported for groove patterns, and they are
950
        // applied over the whole track (e.g. drum mode: all instruments of the appr. track)
1219 tk 951
        t->bpm_tick_delay = SEQ_PAR_StepDelayGet(track, t->step, instrument, layer_muted);
338 tk 952
 
339 tk 953
        // scale delay (0..95) over next clock counter to consider the selected clock divider
954
        if( t->bpm_tick_delay )
344 tk 955
          t->bpm_tick_delay = (t->bpm_tick_delay * t->step_length) / 96;
339 tk 956
 
957
 
419 tk 958
            if( p->type != NoteOn ) {
1024 tk 959
          // apply Pre-FX
960
          if( !SEQ_TRG_NoFxGet(track, t->step, instrument) ) {
961
        SEQ_LFO_Event(track, e);
962
          }
963
 
330 tk 964
            } else if( p->note && p->velocity && (e->len >= 0) ) {
419 tk 965
          // Note Event
330 tk 966
 
339 tk 967
          // groove it
599 tk 968
#if 0
339 tk 969
          SEQ_GROOVE_Event(track, t->step, e);
599 tk 970
#else
971
          SEQ_GROOVE_Event(track, seq_core_state.ref_step, e);
972
#endif
339 tk 973
 
608 tk 974
          // apply Pre-FX before force-to-scale
599 tk 975
          if( !SEQ_TRG_NoFxGet(track, t->step, instrument) ) {
473 tk 976
        SEQ_HUMANIZE_Event(track, t->step, e);
599 tk 977
        SEQ_LFO_Event(track, e);
608 tk 978
          }
979
 
980
          // force to scale
981
          if( tcc->mode.FORCE_SCALE ) {
982
        u8 scale, root_selection, root;
983
        SEQ_CORE_FTS_GetScaleAndRoot(&scale, &root_selection, &root);
984
        SEQ_SCALE_Note(p, scale, root);
985
          }
986
 
987
          // apply Pre-FX after force-to-scale
988
          if( !SEQ_TRG_NoFxGet(track, t->step, instrument) ) {
600 tk 989
        SEQ_CORE_Limit(t, tcc, e); // should be the last Fx in the chain!
599 tk 990
          }
345 tk 991
 
1117 tk 992
          // force velocity to 0x7f (drum mode: selectable value) if accent flag set
993
          if( SEQ_TRG_AccentGet(track, t->step, instrument) ) {
994
        if( tcc->event_mode == SEQ_EVENT_MODE_Drum )
995
          p->velocity = tcc->lay_const[2*16 + i];
996
        else
997
          p->velocity = 0x7f;
998
          }
999
 
330 tk 1000
          // sustained or stretched note: play off event of previous step
419 tk 1001
          if( t->state.SUSTAINED )
1002
        gen_off_events = 1;
330 tk 1003
 
717 tk 1004
          if( tcc->mode.SUSTAIN || e->len >= 96 )
419 tk 1005
        gen_sustained_events = 1;
717 tk 1006
          else {
419 tk 1007
        // generate common On event with given length
1008
        gen_on_events = 1;
1009
          }
717 tk 1010
        } else if( t->state.STRETCHED_GL && t->state.SUSTAINED && (e->len < 96) ) {
419 tk 1011
          // stretched note, length < 96: queue off events
608 tk 1012
          gen_off_events = (t->step_length * e->len) / 96;
419 tk 1013
        }
1014
      }
328 tk 1015
 
419 tk 1016
      // should Note Off events be played before new events are queued?
1017
      if( gen_off_events ) {
717 tk 1018
        int i;
1019
 
1020
        u32 rescheduled_tick = bpm_tick + prev_bpm_tick_delay + gen_off_events;
1021
        if( !t->state.STRETCHED_GL ) // important: play Note Off before new Note On to avoid that glide is triggered on the synth
1022
          rescheduled_tick -= 1;
1319 tk 1023
        SEQ_MIDI_OUT_ReSchedule(track, SEQ_MIDI_OUT_OffEvent, rescheduled_tick,
1024
                    seq_record_state.ENABLED ? seq_record_played_notes : NULL);
717 tk 1025
 
1026
        // clear state flag and note storage
419 tk 1027
        t->state.SUSTAINED = 0;
1028
        t->state.STRETCHED_GL = 0;
717 tk 1029
        for(i=0; i<4; ++i)
1030
          t->glide_notes[i] = 0;
419 tk 1031
      }
1032
 
1033
 
1034
      //////////////////////////////////////////////////////////////////////////////////////////
1035
      // Second pass: schedule new events
1036
      //////////////////////////////////////////////////////////////////////////////////////////
1037
          e = &layer_events[0];
1675 tk 1038
      u8 reset_stacks_done = 0;
419 tk 1039
          for(i=0; i<number_of_events; ++e, ++i) {
1040
            mios32_midi_package_t *p = &e->midi_package;
1041
 
1042
        // instrument layers only used for drum tracks
686 tk 1043
        u8 instrument = (tcc->event_mode == SEQ_EVENT_MODE_Drum) ? e->layer_tag : 0;
419 tk 1044
 
1045
        if( p->type != NoteOn ) {
1422 tk 1046
          // e.g. CC, PitchBend, ProgramChange
600 tk 1047
          if( loopback_port )
1675 tk 1048
        SEQ_MIDI_IN_BusReceive(tcc->midi_port & 0x0f, *p, 1); // forward to MIDI IN handler immediately
600 tk 1049
          else
1050
        SEQ_MIDI_OUT_Send(tcc->midi_port, *p, SEQ_MIDI_OUT_CCEvent, bpm_tick + t->bpm_tick_delay, 0);
419 tk 1051
          t->vu_meter = 0x7f; // for visualisation in mute menu
1052
        } else {
1319 tk 1053
          // skip in record mode if the same note is already played
1054
          if( seq_record_state.ENABLED &&
1055
          (seq_record_played_notes[p->note>>5] & (1 << (p->note&0x1f))) )
1056
        continue;
1057
 
717 tk 1058
          // sustained/glided note: play note at timestamp, and queue off event at 0xffffffff (so that it can be re-scheduled)      
419 tk 1059
          if( gen_sustained_events ) {
761 tk 1060
        // for visualisation in mute menu
1061
        t->vu_meter = p->velocity;
1062
 
1638 tk 1063
        if( loopback_port ) {
1675 tk 1064
          if( !reset_stacks_done ) {
1065
            // reset current stack
1066
            SEQ_MIDI_IN_ResetSingleTransArpStacks(tcc->midi_port & 0x0f);
1067
            reset_stacks_done = 1;
1068
          }
1638 tk 1069
          // forward to MIDI IN handler immediately
1675 tk 1070
          SEQ_MIDI_IN_BusReceive(tcc->midi_port & 0x0f, *p, 1);
1638 tk 1071
        } else {
1072
          u32 scheduled_tick = bpm_tick + t->bpm_tick_delay;
984 tk 1073
 
1638 tk 1074
          // glide: if same note already played, play the new one a tick later for 
1075
          // proper handling of "fingered portamento" function on some synths
1076
          if( last_glide_notes[p->note / 32] & (1 << (p->note % 32)) )
1077
            scheduled_tick += 1;
1078
 
1079
          // Note On
1080
          SEQ_MIDI_OUT_Send(tcc->midi_port, *p, SEQ_MIDI_OUT_OnEvent, scheduled_tick, 0);
1081
 
1082
          // apply Post-FX
1083
          if( !SEQ_TRG_NoFxGet(track, t->step, instrument) ) {
1084
            u8 local_gatelength = 95; // echo only with reduced gatelength to avoid killed notes
1085
            SEQ_CORE_Echo(t, tcc, *p, bpm_tick + t->bpm_tick_delay, local_gatelength);
1086
          }
1087
 
1088
          // Note Off
1089
          p->velocity = 0;
1090
          SEQ_MIDI_OUT_Send(tcc->midi_port, *p, SEQ_MIDI_OUT_OffEvent, 0xffffffff, 0);
984 tk 1091
        }
1092
 
419 tk 1093
        // notify stretched gatelength if not in sustain mode
1094
        t->state.SUSTAINED = 1;
717 tk 1095
        if( !tcc->mode.SUSTAIN ) {
419 tk 1096
          t->state.STRETCHED_GL = 1;
717 tk 1097
          // store glide note number in 128 bit array for later checks
1098
          t->glide_notes[p->note / 32] |= (1 << (p->note % 32));
1099
        }
984 tk 1100
 
419 tk 1101
          } else if( gen_on_events ) {
1102
        // for visualisation in mute menu
1103
        t->vu_meter = p->velocity;
1104
 
323 tk 1105
        if( loopback_port ) {
1675 tk 1106
          if( !reset_stacks_done ) {
1107
            reset_stacks_done = 1;
1108
            // reset current stack
1109
            SEQ_MIDI_IN_ResetSingleTransArpStacks(tcc->midi_port & 0x0f);
1110
          }
323 tk 1111
          // forward to MIDI IN handler immediately
1675 tk 1112
          SEQ_MIDI_IN_BusReceive(tcc->midi_port & 0x0f, *p, 1);
323 tk 1113
          // multi triggers, but also echo not possible on loopback ports
273 tk 1114
        } else {
419 tk 1115
          u16 gatelength = e->len;
1116
          u8 triggers = 1;
1117
 
1118
          // roll/flam?
1119
          // get roll mode from parameter layer
1219 tk 1120
          u8 roll_mode = SEQ_PAR_RollModeGet(track, t->step, instrument, layer_muted);
1024 tk 1121
          u8 roll2_mode = 0; // taken if roll1 not assigned
419 tk 1122
          // with less priority (parameter == 0): force roll mode if Roll trigger is set
1123
          if( !roll_mode && SEQ_TRG_RollGet(track, t->step, instrument) )
1023 tk 1124
            roll_mode = 0x0a; // 2D10
419 tk 1125
          // if roll mode != 0: increase number of triggers
1024 tk 1126
          if( roll_mode ) {
419 tk 1127
            triggers = ((roll_mode & 0x30)>>4) + 2;
1024 tk 1128
          } else {
1219 tk 1129
            roll2_mode = SEQ_PAR_Roll2ModeGet(track, t->step, instrument, layer_muted);
1024 tk 1130
            if( roll2_mode )
1131
              triggers = (roll2_mode >> 5) + 2;
1132
          }
419 tk 1133
 
1024 tk 1134
 
323 tk 1135
          if( triggers > 1 ) {
1024 tk 1136
            if( roll2_mode ) {
1137
              // force gatelength depending on roll2 value
1138
              gatelength = (8 - 2*(roll2_mode >> 5)) * ((roll2_mode&0x1f)+1);
339 tk 1139
 
1024 tk 1140
              // scale length (0..95) over next clock counter to consider the selected clock divider
1141
              int gatelength = (4 - (roll2_mode >> 5)) * ((roll2_mode&0x1f)+1);
337 tk 1142
 
1024 tk 1143
              u32 half_gatelength = gatelength/2;
1144
              if( !half_gatelength )
1145
            half_gatelength = 1;
323 tk 1146
 
1024 tk 1147
              int i;
1148
              for(i=triggers-1; i>=0; --i)
1149
            SEQ_MIDI_OUT_Send(tcc->midi_port, *p, SEQ_MIDI_OUT_OnOffEvent, bpm_tick + t->bpm_tick_delay + i*gatelength, half_gatelength);
1150
            } else {
1151
              // force gatelength depending on number of triggers
1152
              if( triggers < 6 ) {
1153
            //       number of triggers:    2   3   4   5
1154
            const u8 gatelength_tab[4] = { 48, 32, 36, 32 };
1155
            // strategy:
1156
            // 2 triggers: played within 1 step at 0 and 48
1157
            // 3 triggers: played within 1 step at 0, 32 and 64
1158
            // 4 triggers: played within 1.5 steps at 0, 36, 72 and 108
1159
            // 5 triggers: played within 1.5 steps at 0, 32, 64, 96 and 128
1160
 
1161
            // in addition, scale length (0..95) over next clock counter to consider the selected clock divider
1162
            gatelength = (gatelength_tab[triggers-2] * t->step_length) / 96;
334 tk 1163
              }
1024 tk 1164
 
1165
              u32 half_gatelength = gatelength/2;
1166
              if( !half_gatelength )
1167
            half_gatelength = 1;
1168
 
1169
              mios32_midi_package_t p_multi = *p;
1170
              u16 roll_attenuation = 256 - (2 * triggers * (16 - (roll_mode & 0x0f))); // magic formula for nice effects
1171
              if( roll_mode & 0x40 ) { // upwards
1172
            int i;
1173
            for(i=triggers-1; i>=0; --i) {
1174
              SEQ_MIDI_OUT_Send(tcc->midi_port, p_multi, SEQ_MIDI_OUT_OnOffEvent, bpm_tick + t->bpm_tick_delay + i*gatelength, half_gatelength);
334 tk 1175
              u16 velocity = roll_attenuation * p_multi.velocity;
1176
              p_multi.velocity = velocity >> 8;
1177
            }
1024 tk 1178
              } else { // downwards
1179
            int i;
1180
            for(i=0; i<triggers; ++i) {
1181
              SEQ_MIDI_OUT_Send(tcc->midi_port, p_multi, SEQ_MIDI_OUT_OnOffEvent, bpm_tick + t->bpm_tick_delay + i*gatelength, half_gatelength);
1182
              if( roll_mode ) {
1183
                u16 velocity = roll_attenuation * p_multi.velocity;
1184
                p_multi.velocity = velocity >> 8;
1185
              }
1186
            }
334 tk 1187
              }
1188
            }
302 tk 1189
          } else {
323 tk 1190
            if( !gatelength )
1191
              gatelength = 1;
339 tk 1192
            else // scale length (0..95) over next clock counter to consider the selected clock divider
344 tk 1193
              gatelength = (gatelength * t->step_length) / 96;
338 tk 1194
            SEQ_MIDI_OUT_Send(tcc->midi_port, *p, SEQ_MIDI_OUT_OnOffEvent, bpm_tick + t->bpm_tick_delay, gatelength);
419 tk 1195
          }
323 tk 1196
 
600 tk 1197
          // apply Post-FX
419 tk 1198
          if( !SEQ_TRG_NoFxGet(track, t->step, instrument) ) {
1199
            if( tcc->echo_repeats && gatelength )
1200
              SEQ_CORE_Echo(t, tcc, *p, bpm_tick + t->bpm_tick_delay, gatelength);
1201
          }
323 tk 1202
        }
262 tk 1203
          }
323 tk 1204
            }
1205
          }
302 tk 1206
        }
262 tk 1207
      }
1208
    }
1209
  }
761 tk 1210
 
262 tk 1211
  // clear "first clock" flag if it was set before
1212
  seq_core_state.FIRST_CLK = 0;
1213
 
600 tk 1214
  // if manual trigger function requested stop: stop sequencer at end of reference step
1215
  if( seq_core_state.MANUAL_TRIGGER_STOP_REQ && (bpm_tick % 96) == 95 )
1216
    SEQ_BPM_Stop();
1217
 
262 tk 1218
  return 0; // no error
1219
}
1220
 
1221
 
1222
/////////////////////////////////////////////////////////////////////////////
1223
// Resets the step position variables of a track
1224
/////////////////////////////////////////////////////////////////////////////
599 tk 1225
static s32 SEQ_CORE_ResetTrkPos(u8 track, seq_core_trk_t *t, seq_cc_trk_t *tcc)
262 tk 1226
{
600 tk 1227
  // synch to measure done
1228
  t->state.SYNC_MEASURE = 0;
1229
 
262 tk 1230
  // don't increment on first clock event
1231
  t->state.FIRST_CLK = 1;
1232
 
338 tk 1233
  // clear delay
1234
  t->bpm_tick_delay = 0;
1235
 
593 tk 1236
  // reset step progression counters
262 tk 1237
  t->step_replay_ctr = 0;
1238
  t->step_fwd_ctr = 0;
593 tk 1239
  t->step_interval_ctr = 0;
1240
  t->step_repeat_ctr = 0;
1241
  t->step_skip_ctr = 0;
262 tk 1242
 
1243
  // next part depends on forward/backward direction
1244
  if( tcc->dir_mode == SEQ_CORE_TRKDIR_Backward ) {
1245
    // only for Backward mode
1246
    t->state.BACKWARD = 1;
1247
    t->step = tcc->length;
1248
  } else {
1249
    // for Forward/PingPong/Pendulum/Random/...
1250
    t->state.BACKWARD = 0;
1251
    t->step = 0;
1252
  }
1253
 
1254
  // save position (for repeat function)
1255
  t->step_saved = t->step;
1256
 
1257
  t->arp_pos = 0;
1258
 
599 tk 1259
  // reset LFO
1260
  SEQ_LFO_ResetTrk(track);
1261
 
262 tk 1262
  return 0; // no error
1263
}
1264
 
1265
 
1266
/////////////////////////////////////////////////////////////////////////////
1205 tk 1267
// Resets the step position variables of all tracks
1268
/////////////////////////////////////////////////////////////////////////////
1269
s32 SEQ_CORE_ResetTrkPosAll(void)
1270
{
1271
  seq_core_trk_t *t = &seq_core_trk[0];
1272
  seq_cc_trk_t *tcc = &seq_cc_trk[0];
1273
  u8 track;
1274
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t, ++tcc)
1275
    SEQ_CORE_ResetTrkPos(track, t, tcc);
1276
 
1277
  return 0; // no error
1278
}
1279
 
1280
/////////////////////////////////////////////////////////////////////////////
262 tk 1281
// Determine next step depending on direction mode
1282
/////////////////////////////////////////////////////////////////////////////
593 tk 1283
static s32 SEQ_CORE_NextStep(seq_core_trk_t *t, seq_cc_trk_t *tcc, u8 no_progression, u8 reverse)
262 tk 1284
{
1285
  int i;
1286
  u8 save_step = 0;
1287
  u8 new_step = 1;
1288
 
1289
  // handle progression parameters if position shouldn't be reset
593 tk 1290
  if( !no_progression && !t->state.POS_RESET ) {
262 tk 1291
    if( ++t->step_fwd_ctr > tcc->steps_forward ) {
1292
      t->step_fwd_ctr = 0;
1293
      if( tcc->steps_jump_back ) {
593 tk 1294
    for(i=0; i<tcc->steps_jump_back; ++i)
1295
      SEQ_CORE_NextStep(t, tcc, 1, 1); // 1=no progression, 1=reverse
262 tk 1296
      }
1297
      if( ++t->step_replay_ctr > tcc->steps_replay ) {
1298
    t->step_replay_ctr = 0;
1299
    save_step = 1; // request to save the step in t->step_saved at the end of this routine
1300
      } else {
1301
    t->step = t->step_saved;
1302
    new_step = 0; // don't calculate new step
1303
      }
1304
    }
593 tk 1305
 
1306
    if( ++t->step_interval_ctr > tcc->steps_rs_interval ) {
1307
      t->step_interval_ctr = 0;
1308
      t->step_repeat_ctr = tcc->steps_repeat;
1309
      t->step_skip_ctr = tcc->steps_skip;
1310
    }
1311
 
1312
    if( t->step_repeat_ctr ) {
1313
      --t->step_repeat_ctr;
1314
      new_step = 0; // repeat step until counter reached zero
1315
    } else {
1316
      while( t->step_skip_ctr ) {
1317
    SEQ_CORE_NextStep(t, tcc, 1, 0); // 1=no progression, 0=not reverse
1318
    --t->step_skip_ctr;
1319
      }
1320
    }
262 tk 1321
  }
1322
 
1323
  if( new_step ) {
1324
    // special cases:
1325
    switch( tcc->dir_mode ) {
1326
      case SEQ_CORE_TRKDIR_Forward:
1327
    t->state.BACKWARD = 0; // force backward flag
1328
    break;
1329
 
1330
      case SEQ_CORE_TRKDIR_Backward:
1331
    t->state.BACKWARD = 1; // force backward flag
1332
    break;
1333
 
1334
      case SEQ_CORE_TRKDIR_PingPong:
1335
      case SEQ_CORE_TRKDIR_Pendulum:
1336
    // nothing else to do...
1337
    break;
1338
 
1339
      case SEQ_CORE_TRKDIR_Random_Dir:
1340
    // set forward/backward direction with 1:1 probability
1341
    t->state.BACKWARD = SEQ_RANDOM_Gen(0) & 1;
1342
        break;
1343
 
1344
      case SEQ_CORE_TRKDIR_Random_Step:
1345
    t->step = SEQ_RANDOM_Gen_Range(tcc->loop, tcc->length);
1346
    new_step = 0; // no new step calculation required anymore
1347
        break;
1348
 
1349
      case SEQ_CORE_TRKDIR_Random_D_S:
1350
    {
1351
      // we continue with a probability of 50%
1352
      // we change the direction with a probability of 25%
1353
      // we jump to a new step with a probability of 25%
1354
      u32 rnd;
1355
      if( ((rnd=SEQ_RANDOM_Gen(0)) & 0xff) < 0x80 ) {
1356
        if( rnd < 0x40 ) {
1357
          // set forward/backward direction with 1:1 probability
1358
          t->state.BACKWARD = SEQ_RANDOM_Gen(0) & 1;
1359
        } else {
1360
          t->step = SEQ_RANDOM_Gen_Range(tcc->loop, tcc->length);
1361
          new_step = 0; // no new step calculation required anymore
1362
        }
1363
      }
1364
    }
1365
    break;
1366
    }
1367
  }
1368
 
1369
  if( new_step ) { // note: new_step will be cleared in SEQ_CORE_TRKDIR_Random_Step mode
1370
    // branch depending on forward/backward mode, take reverse flag into account
1371
    if( t->state.BACKWARD ^ reverse ) {
1372
      // jump to last step if first loop step has been reached or a position reset has been requested
1373
      // in pendulum mode: switch to forward direction
1374
      if( t->state.POS_RESET || t->step <= tcc->loop ) {
1375
    if( tcc->dir_mode == SEQ_CORE_TRKDIR_Pendulum ) {
1376
      t->state.BACKWARD = 0;
1377
    } else {
1378
      t->step = tcc->length;
1379
    }
1380
    // reset arp position as well
1381
    t->arp_pos = 0;
1382
      } else {
1383
    // no reset required; decrement step
1384
    --t->step;
1385
 
1386
    // in pingpong mode: turn direction if loop step has been reached after this decrement
1387
    if( t->step <= tcc->loop && tcc->dir_mode == SEQ_CORE_TRKDIR_PingPong )
1388
      t->state.BACKWARD = 0;
1389
      }
1390
    } else {
1391
      // jump to first (loop) step if last step has been reached or a position reset has been requested
1392
      // in pendulum mode: switch to backward direction
1393
      if( t->state.POS_RESET || t->step >= tcc->length ) {
1394
    if( tcc->dir_mode == SEQ_CORE_TRKDIR_Pendulum ) {
1395
      t->state.BACKWARD = 1;
1396
    } else {
1397
      t->step = tcc->loop;
1398
    }
1399
    // reset arp position as well
1400
    t->arp_pos = 0;
1401
      } else {
1402
    // no reset required; increment step
1403
    ++t->step;
1404
 
1405
    // in pingpong mode: turn direction if last step has been reached after this increment
1406
    if( t->step >= tcc->length && tcc->dir_mode == SEQ_CORE_TRKDIR_PingPong )
1407
      t->state.BACKWARD = 1;
1408
      }
1409
    }
1410
  }
1411
 
1412
  if( !reverse ) {
1413
    // requested by progression handler
1414
    if( save_step )
1415
      t->step_saved = t->step;
1416
 
1417
    t->state.POS_RESET = 0;
1418
  }
1419
 
1420
  return 0; // no error
1421
}
1422
 
1423
 
1424
/////////////////////////////////////////////////////////////////////////////
1425
// Transposes if midi_package contains a Note Event
1426
/////////////////////////////////////////////////////////////////////////////
1219 tk 1427
s32 SEQ_CORE_Transpose(seq_core_trk_t *t, seq_cc_trk_t *tcc, mios32_midi_package_t *p)
262 tk 1428
{
1422 tk 1429
  u8 is_cc = p->type != NoteOn && p->type != NoteOff; // CC, Pitchbender, Programchange
262 tk 1430
 
1422 tk 1431
  if( is_cc && tcc->event_mode != SEQ_EVENT_MODE_CC ) // only transpose CC/Pitchbender/Program Change in CC mode
1024 tk 1432
    return -1;
1433
 
1434
  int note = is_cc ? p->value : p->note;
1435
 
262 tk 1436
  int inc_oct = tcc->transpose_oct;
1437
  if( inc_oct >= 8 )
1438
    inc_oct -= 16;
1439
 
1440
  int inc_semi = tcc->transpose_semi;
1441
  if( inc_semi >= 8 )
1442
    inc_semi -= 16;
1443
 
1444
  // in transpose or arp playmode we allow to transpose notes and CCs
1320 tk 1445
  if( tcc->mode.playmode == SEQ_CORE_TRKMODE_Transpose ||
1446
      (!is_cc && seq_core_global_transpose_enabled) ) {
1023 tk 1447
    int tr_note = SEQ_MIDI_IN_TransposerNoteGet(tcc->busasg.bus, tcc->mode.HOLD);
262 tk 1448
 
1449
    if( tr_note < 0 ) {
1450
      p->velocity = 0; // disable note and exit
1451
      return -1; // note has been disabled
1452
    }
1453
 
1322 tk 1454
    inc_semi += tr_note - 0x3c; // C-3 is the base note
262 tk 1455
  }
1456
  else if( tcc->mode.playmode == SEQ_CORE_TRKMODE_Arpeggiator ) {
1457
    int key_num = (note >> 2) & 0x3;
1458
    int arp_oct = (note >> 4) & 0x7;
1459
 
1460
    if( arp_oct < 2 ) { // Multi Arp Event
1461
      inc_oct += ((note >> 2) & 7) - 4;
1462
      key_num = t->arp_pos;
1463
    } else {
1464
      inc_oct += arp_oct - 4;
1465
    }
1466
 
1023 tk 1467
    int arp_note = SEQ_MIDI_IN_ArpNoteGet(tcc->busasg.bus, tcc->mode.HOLD, !tcc->mode.UNSORTED, key_num);
262 tk 1468
 
1469
    if( arp_note & 0x80 ) {
1470
      t->arp_pos = 0;
1471
    } else {
1472
      if( arp_oct < 2 ) { // Multi Arp Event
1473
    // play next key, step will be incremented once t->arp_pos reaches 0 again
1474
    if( ++t->arp_pos >= 4 )
1475
      t->arp_pos = 0;
1476
      }
1477
    }
1478
 
1479
    note = arp_note & 0x7f;
1480
 
1481
    if( !note ) { // disable note and exit
1482
      p->velocity = 0;
1483
      return -1; // note has been disabled
1484
    }
1485
  }
1486
 
1487
  // apply transpose octave/semitones parameter
1488
  if( inc_oct ) {
1489
    note += 12 * inc_oct;
1490
  }
1491
 
1492
  if( inc_semi ) {
1493
    note += inc_semi;
1494
  }
1495
 
1746 tk 1496
  // ensure that note is in the 0..127 range
1497
  note = SEQ_CORE_TrimNote(note, 0, 127);
1498
 
1422 tk 1499
  if( is_cc ) // if CC, Pitchbender, ProgramChange
1024 tk 1500
    p->value = note;
1501
  else
1502
    p->note = note;
262 tk 1503
 
1504
  return 0; // no error
1505
}
1506
 
1507
 
1508
/////////////////////////////////////////////////////////////////////////////
1509
// Returns the selected scale and root note selection depending on
1510
// global/group specific settings
1511
// scale and root note are for interest while playing the sequence -> SEQ_CORE
1512
// scale and root selection are for interest when editing the settings -> SEQ_UI_OPT
1320 tk 1513
// Both modules are calling this function to ensure consistency
262 tk 1514
/////////////////////////////////////////////////////////////////////////////
1515
s32 SEQ_CORE_FTS_GetScaleAndRoot(u8 *scale, u8 *root_selection, u8 *root)
1516
{
1517
  if( seq_core_global_scale_ctrl > 0 ) {
1518
    // scale/root selection from a specific pattern group
1519
    u8 group = seq_core_global_scale_ctrl-1;
1520
    *scale = seq_cc_trk[(group*SEQ_CORE_NUM_TRACKS_PER_GROUP)+2].shared.scale;
1521
    *root_selection = seq_cc_trk[(group*SEQ_CORE_NUM_TRACKS_PER_GROUP)+3].shared.scale_root;
1522
  } else {
1523
    // global scale/root selection
1524
    *scale = seq_core_global_scale;
1525
    *root_selection = seq_core_global_scale_root_selection;
1526
  }
1527
  *root = (*root_selection == 0) ? seq_core_keyb_scale_root : (*root_selection-1);
1528
 
1529
  return 0; // no error
1530
}
1531
 
1532
 
1533
/////////////////////////////////////////////////////////////////////////////
600 tk 1534
// Limit Fx
1535
/////////////////////////////////////////////////////////////////////////////
1219 tk 1536
s32 SEQ_CORE_Limit(seq_core_trk_t *t, seq_cc_trk_t *tcc, seq_layer_evnt_t *e)
600 tk 1537
{
1538
  u8 lower = tcc->limit_lower;
1539
  u8 upper = tcc->limit_upper;
1540
 
1541
  // check if any limit defined
1542
  if( !lower && !upper )
1543
    return 0; // no limit
1544
 
1545
  // exit if no note event
1546
  mios32_midi_package_t *p = &e->midi_package;
1547
  if( p->type != NoteOn )
1548
    return 0; // no Note
1549
 
1746 tk 1550
  // if not set: allow full range
1551
  if( !upper )
1552
    upper = 127;
1553
 
600 tk 1554
  // swap if lower value is greater than upper
1555
  if( lower > upper ) {
1556
    u8 tmp = upper;
1557
    upper=lower;
1558
    lower=tmp;
1559
  }
1560
 
1561
  // apply limit
1746 tk 1562
  p->note = SEQ_CORE_TrimNote(p->note, lower, upper);
600 tk 1563
 
1564
  return 0; // no error
1565
}
1566
 
1567
 
747 tk 1568
 
600 tk 1569
/////////////////////////////////////////////////////////////////////////////
747 tk 1570
// Name of Delay mode (we should outsource the echo function to seq_echo.c later)
1571
/////////////////////////////////////////////////////////////////////////////
774 tk 1572
// Note: newer gcc versions don't allow to return a "const" parameter, therefore
1573
// this array is declared outside the SEQ_CORE_Echo_GetDelayModeName() function
1121 tk 1574
 
1219 tk 1575
#define NUM_DELAY_VALUES 23
1121 tk 1576
static const char delay_str[NUM_DELAY_VALUES+1][5] = {
747 tk 1577
    " 64T",
1578
    " 64 ",
1579
    " 32T",
1580
    " 32 ",
1581
    " 16T",
1582
    " 16 ",
1583
    "  8T",
1584
    "  8 ",
1585
    "  4T",
1586
    "  4 ",
1587
    "  2T",
1588
    "  2 ",
1589
    "  1T",
1590
    "  1 ",
1591
    "Rnd1",
1592
    "Rnd2",
1121 tk 1593
    " 64d", // new with Beta30
1594
    " 32d", // new with Beta30
1595
    " 16d", // new with Beta30
1596
    "  8d", // new with Beta30
1597
    "  4d", // new with Beta30
1598
    "  2d", // new with Beta30
1219 tk 1599
    "  0 ", // new with Beta42
747 tk 1600
    "????",
1601
  };
1602
 
774 tk 1603
const char *SEQ_CORE_Echo_GetDelayModeName(u8 delay_mode)
1604
{
1121 tk 1605
  if( delay_mode < NUM_DELAY_VALUES )
747 tk 1606
    return delay_str[delay_mode];
1607
 
1121 tk 1608
  return delay_str[NUM_DELAY_VALUES];
747 tk 1609
}
1610
 
1611
 
1612
/////////////////////////////////////////////////////////////////////////////
1121 tk 1613
// Maps delay values from old to new format
1614
// Used to keep pattern binaries compatible to enhanced delay entries
1615
/////////////////////////////////////////////////////////////////////////////
1616
static const u8 delay_value_map[NUM_DELAY_VALUES] = {
1219 tk 1617
  22, //"  0 ",
1121 tk 1618
  0,  //" 64T",
1619
  1,  //" 64 ",
1620
  2,  //" 32T",
1621
  16, //" 64d",
1622
  3,  //" 32 ",
1623
  4,  //" 16T",
1624
  17, //" 32d",
1625
  5,  //" 16 ",
1626
  6,  //"  8T",
1627
  18, //" 16d",
1628
  7,  //"  8 ",
1629
  8,  //"  4T",
1630
  19, //"  8d",
1631
  9,  //"  4 ",
1632
  10, //"  2T",
1633
  20, //"  4d",
1634
  11, //"  2 ",
1635
  12, //"  1T",
1636
  21, //"  2d",
1637
  13, //"  1 ",
1638
  14, //"Rnd1",
1639
  15, //"Rnd2",
1640
};
1641
 
1642
u8 SEQ_CORE_Echo_MapUserToInternal(u8 user_value)
1643
{
1644
  if( user_value < NUM_DELAY_VALUES )
1645
    return delay_value_map[user_value];
1646
 
1647
  return 0;
1648
}
1649
 
1650
u8 SEQ_CORE_Echo_MapInternalToUser(u8 internal_value)
1651
{
1652
  int i;
1653
  for(i=0; i<NUM_DELAY_VALUES; ++i)
1654
    if( delay_value_map[i] == internal_value )
1655
      return i;
1656
 
1657
  return 0;
1658
}
1659
 
1660
 
1661
/////////////////////////////////////////////////////////////////////////////
262 tk 1662
// Echo Fx
1663
/////////////////////////////////////////////////////////////////////////////
1219 tk 1664
s32 SEQ_CORE_Echo(seq_core_trk_t *t, seq_cc_trk_t *tcc, mios32_midi_package_t p, u32 bpm_tick, u32 gatelength)
262 tk 1665
{
1666
  // thanks to MIDI queuing mechanism, this is a no-brainer :)
1667
 
1219 tk 1668
  // 64T, 64, 32T, 32, 16T, 16, ... 1, Rnd1 and Rnd2, 64d..2d (new), 0 (supernew)
1121 tk 1669
  s32 fb_ticks;
742 tk 1670
  s32 echo_delay = tcc->echo_delay;
1219 tk 1671
  if( echo_delay >= 22 ) // new zero delay
1672
    fb_ticks = 0;
1673
  else if ( echo_delay >= 16 ) // new dotted delays
1121 tk 1674
    fb_ticks = 36 * (1 << (echo_delay-16));
1675
  else {
1676
    if( echo_delay >= 14 ) // Rnd1 and Rnd2
1677
      echo_delay = SEQ_RANDOM_Gen_Range(3, 7); // between 32 and 8
1678
    fb_ticks = ((tcc->echo_delay & 1) ? 24 : 16) * (1 << (echo_delay>>1));
1679
  }
262 tk 1680
 
1681
  s32 fb_note = p.note;
1682
  s32 fb_note_base = fb_note; // for random function
1683
 
1684
  // TODO: echo port and MIDI channel
1685
 
1686
  // the initial velocity value allows to start with a low velocity,
1687
  // and to increase it with each step via FB velocity value
1688
  s32 fb_velocity = p.velocity;
1689
  if( tcc->echo_velocity != 20 ) { // 20 == 100% -> no change
1690
    fb_velocity = (fb_velocity * 5*tcc->echo_velocity) / 100;
1691
    if( fb_velocity > 127 )
1692
      fb_velocity = 127;
1693
    p.velocity = (u8)fb_velocity;
1694
  }
1695
 
273 tk 1696
  seq_midi_out_event_type_t event_type = SEQ_MIDI_OUT_OnOffEvent;
1422 tk 1697
  if( (p.type == CC || p.type == PitchBend || p.type == ProgramChange) && !gatelength )
273 tk 1698
    event_type = SEQ_MIDI_OUT_CCEvent;
262 tk 1699
 
276 tk 1700
  // for the case that force-to-scale is activated
1701
  u8 scale, root_selection, root;
1702
  SEQ_CORE_FTS_GetScaleAndRoot(&scale, &root_selection, &root);
1703
 
262 tk 1704
  u32 echo_offset = fb_ticks;
1705
  int i;
1706
  for(i=0; i<tcc->echo_repeats; ++i) {
1707
    if( i ) { // no feedback of velocity or echo ticks on first step
1708
      if( tcc->echo_fb_velocity != 20 ) { // 20 == 100% -> no change
1709
    fb_velocity = (fb_velocity * 5*tcc->echo_fb_velocity) / 100;
1710
    if( fb_velocity > 127 )
1711
      fb_velocity = 127;
1712
    p.velocity = (u8)fb_velocity;
1713
      }
1714
 
1715
      if( tcc->echo_fb_ticks != 20 ) { // 20 == 100% -> no change
1716
    fb_ticks = (fb_ticks * 5*tcc->echo_fb_ticks) / 100;
1717
      }
1718
      echo_offset += fb_ticks;
1719
    }
1720
 
1721
    if( tcc->echo_fb_note != 24 ) { // 24 == 0 -> no change
1722
      if( tcc->echo_fb_note == 49 ) // random
1723
    fb_note = fb_note_base + ((s32)SEQ_RANDOM_Gen_Range(0, 48) - 24);
1724
      else
1725
    fb_note = fb_note + ((s32)tcc->echo_fb_note-24);
1726
 
1746 tk 1727
      // ensure that note is in the 0..127 range
1728
      fb_note = SEQ_CORE_TrimNote(fb_note, 0, 127);
1729
 
262 tk 1730
      p.note = (u8)fb_note;
1731
    }
1732
 
1733
    if( gatelength && tcc->echo_fb_gatelength != 20 ) { // 20 == 100% -> no change
1734
      gatelength = (gatelength * 5*tcc->echo_fb_gatelength) / 100;
1735
      if( !gatelength )
1736
    gatelength = 1;
1737
    }
1738
 
276 tk 1739
    // force to scale
1740
    if( tcc->mode.FORCE_SCALE ) {
1741
      SEQ_SCALE_Note(&p, scale, root);
1742
    }
1743
 
273 tk 1744
    SEQ_MIDI_OUT_Send(tcc->midi_port, p, event_type, bpm_tick + echo_offset, gatelength);
262 tk 1745
  }
1746
 
1747
  return 0; // no error
1748
}
1749
 
1750
 
1751
/////////////////////////////////////////////////////////////////////////////
600 tk 1752
// Manually triggers a step of all selected tracks
1753
/////////////////////////////////////////////////////////////////////////////
1754
s32 SEQ_CORE_ManualTrigger(u8 step)
1755
{
1756
  MIOS32_IRQ_Disable();
1757
 
1758
  u8 track;
1759
  seq_core_trk_t *t = &seq_core_trk[0];
1760
  seq_cc_trk_t *tcc = &seq_cc_trk[0];
1761
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t, ++tcc) {
1762
    if( SEQ_UI_IsSelectedTrack(track) ) {
1205 tk 1763
      if( !SEQ_BPM_IsRunning() ) {
1764
    // reset track position
1765
    SEQ_CORE_ResetTrkPos(track, t, tcc);
600 tk 1766
 
1205 tk 1767
    // change step
1768
    t->step = step;
1769
    t->step_saved = t->step;
1770
      } else {
1771
    // request next step
1772
    t->manual_step = step;
1773
    t->state.MANUAL_STEP_REQ = 1;
1774
      }
600 tk 1775
    }
1776
  }
1777
 
1778
  if( !SEQ_BPM_IsRunning() ) {
1205 tk 1779
    // start sequencer if not running, but only for one step
600 tk 1780
    SEQ_BPM_Cont();
1781
    seq_core_state.MANUAL_TRIGGER_STOP_REQ = 1;
1782
  }
1783
 
1784
  MIOS32_IRQ_Enable();
1785
 
1786
  return 0; // no error
1787
}
1788
 
1789
 
1790
/////////////////////////////////////////////////////////////////////////////
1315 tk 1791
// Manually requests synch to measure for given tracks
600 tk 1792
/////////////////////////////////////////////////////////////////////////////
1315 tk 1793
s32 SEQ_CORE_ManualSynchToMeasure(u16 tracks)
600 tk 1794
{
1795
  MIOS32_IRQ_Disable();
1796
 
1797
  u8 track;
1798
  seq_core_trk_t *t = &seq_core_trk[0];
1799
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t)
1315 tk 1800
    if( tracks & (1 << track) )
600 tk 1801
      t->state.SYNC_MEASURE = 1;
1802
 
1803
  MIOS32_IRQ_Enable();
1804
 
1805
  return 0; // no error
1806
}
1807
 
1808
 
1809
/////////////////////////////////////////////////////////////////////////////
1806 tk 1810
// This function is called by the "Live" function on incoming MIDI events,
1811
// currently we use it to control the temporary layer mutes.
1812
/////////////////////////////////////////////////////////////////////////////
1813
s32 SEQ_CORE_NotifyIncomingMIDIEvent(u8 track, mios32_midi_package_t p)
1814
{
1815
  if( track >= SEQ_CORE_NUM_TRACKS )
1816
    return -1; // invalid track
1817
 
1810 tk 1818
  if( !seq_core_options.LIVE_LAYER_MUTE_STEPS )
1819
    return 0; // disabled
1820
 
1806 tk 1821
  seq_core_trk_t *t = &seq_core_trk[track];
1822
  seq_cc_trk_t *tcc = &seq_cc_trk[track];
1823
 
1824
  if( tcc->event_mode == SEQ_EVENT_MODE_Drum )
1825
    return 0; // (currently) not relevant in drum mode
1826
 
1827
  switch( p.event ) {
1828
  //case NoteOff:
1829
  case NoteOn: {
1830
    if( p.velocity == 0 ) // ignore Note Offs
1831
      break;
1832
 
1833
    // temporary mute layers which are assigned to notes or chords
1834
    u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
1835
    int par_layer;
1836
    int num_p_layers = SEQ_PAR_NumLayersGet(track);
1837
    u16 mask = 1;
1838
    for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr, mask <<= 1) {
1839
      if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord ) {
1840
    // hm... should we also play a note off for active notes?
1841
    // and should we mute the sequencer notes as long as no Note Off has been played?
1842
    // problem: we would have to track all actively played MIDI notes, this consumes a lot of memory
1843
 
1844
    portENTER_CRITICAL();
1810 tk 1845
    if( seq_core_options.LIVE_LAYER_MUTE_STEPS == 1 ) {
1846
      t->layer_muted |= mask;      // mute layer immediately
1847
    } else {
1848
      t->layer_muted_from_midi |= mask;      // mute layer immediately
1849
      t->layer_muted_from_midi_next |= mask; // and for the next step
1850
    }
1806 tk 1851
    portEXIT_CRITICAL();
1852
      }
1853
    }
1854
  } break;
1855
 
1856
  //case PolyPressure:
1857
  case CC:
1858
  case ProgramChange:
1859
  //case Aftertouch:
1860
  case PitchBend: {
1861
    // temporary mute layers which are assigned to the corresponding event
1862
    u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
1863
    int par_layer;
1864
    int num_p_layers = SEQ_PAR_NumLayersGet(track);
1865
    u16 mask = 1;
1810 tk 1866
    u8 apply_mask = 0;
1806 tk 1867
    for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr, mask <<= 1) {
1868
      switch( *layer_type_ptr ) {
1869
      case SEQ_PAR_Type_CC: {
1870
    if( p.event == CC && p.cc_number == tcc->lay_const[1*16 + par_layer] ) {
1810 tk 1871
      apply_mask = 1;
1806 tk 1872
    }
1873
      } break;
1874
 
1875
      case SEQ_PAR_Type_PitchBend: {
1876
    if( p.event == PitchBend ) {
1810 tk 1877
      apply_mask = 1;
1806 tk 1878
    }
1879
      } break;
1880
 
1881
      case SEQ_PAR_Type_ProgramChange: {
1882
    if( p.event == ProgramChange ) {
1810 tk 1883
      apply_mask = 1;
1884
    }
1885
      } break;
1886
      }
1887
 
1888
      if( apply_mask ) {
1889
    portENTER_CRITICAL();
1890
    if( seq_core_options.LIVE_LAYER_MUTE_STEPS == 1 ) {
1891
      t->layer_muted |= mask;      // mute layer immediately
1892
    } else {
1806 tk 1893
      t->layer_muted_from_midi |= mask;      // mute layer immediately
1894
      t->layer_muted_from_midi_next |= mask; // and for the next step
1895
    }
1810 tk 1896
    portEXIT_CRITICAL();
1806 tk 1897
      }
1898
    }
1809 tk 1899
 
1810 tk 1900
    // check also LFO CC (note: only handled as temporary change)
1809 tk 1901
    if( p.event == CC && p.cc_number == tcc->lfo_cc ) {
1902
      portENTER_CRITICAL();
1903
      t->lfo_cc_muted_from_midi = 1;
1904
      t->lfo_cc_muted_from_midi_next = 1;
1905
      portEXIT_CRITICAL();
1906
    }
1907
 
1806 tk 1908
  } break;
1909
  }
1910
 
1911
  return 0; // no error
1912
}
1913
 
1914
 
1915
/////////////////////////////////////////////////////////////////////////////
262 tk 1916
// This function requests to pre-generate sequencer ticks for a given time
1917
// It returns -1 if the previously requested delay hasn't passed yet
1918
/////////////////////////////////////////////////////////////////////////////
1919
s32 SEQ_CORE_AddForwardDelay(u16 delay_ms)
1920
{
1921
  if( bpm_tick_prefetch_req )
1922
    return -1; // ongoing request
1923
 
1924
  // calculate how many BPM ticks have to be forwarded
1925
  bpm_tick_prefetch_req = SEQ_BPM_TickGet() + SEQ_BPM_TicksFor_mS(delay_ms);
1926
 
1927
  return 0; // no error
1928
}
491 tk 1929
 
1930
 
1931
/////////////////////////////////////////////////////////////////////////////
1932
// This function updates the BPM rate in a given sweep time
1933
/////////////////////////////////////////////////////////////////////////////
1934
s32 SEQ_CORE_BPM_Update(float bpm, float sweep_ramp)
1935
{
1936
  if( sweep_ramp <= 0.0 ) {
1937
    seq_core_bpm_target = bpm;
1938
    SEQ_BPM_Set(seq_core_bpm_target);
1939
    seq_core_bpm_sweep_inc = 0.0;
1940
  } else {
1941
    seq_core_bpm_target = bpm;
1942
    seq_core_bpm_sweep_inc = (seq_core_bpm_target - SEQ_BPM_Get()) / (10.0 * sweep_ramp);
1943
  }
1944
 
1945
  return 0; // no error
1946
}
1947
 
1948
/////////////////////////////////////////////////////////////////////////////
1949
// This function should be called each mS to update the BPM
1950
/////////////////////////////////////////////////////////////////////////////
1951
s32 SEQ_CORE_BPM_SweepHandler(void)
1952
{
1953
  static u8 prescaler = 0;
1954
 
1955
  // next step each 100 mS
1956
  if( ++prescaler < 100 )
1957
    return 0;
1958
  prescaler = 0;
1959
 
1960
  if( seq_core_bpm_sweep_inc != 0.0 ) {
1961
    float current_bpm = SEQ_BPM_Get();
1962
    float tolerance = 0.1;
1963
 
1964
    if( (seq_core_bpm_sweep_inc > 0.0 && current_bpm >= (seq_core_bpm_target-tolerance)) ||
1965
    (seq_core_bpm_sweep_inc < 0.0 && current_bpm <= (seq_core_bpm_target+tolerance)) ) {
1966
      seq_core_bpm_sweep_inc = 0.0; // final value reached
1967
      SEQ_BPM_Set(seq_core_bpm_target);
1968
    } else {
1969
      SEQ_BPM_Set(current_bpm + seq_core_bpm_sweep_inc);
1970
    }
1971
  }
1972
 
1973
  return 0; // no error
1974
}
1975
 
607 tk 1976
 
1977
/////////////////////////////////////////////////////////////////////////////
1978
// Scrub function called from UI when SCRUB button pressed and Datawheel
1979
// is moved
1980
/////////////////////////////////////////////////////////////////////////////
1981
s32 SEQ_CORE_Scrub(s32 incrementer)
1982
{
1983
  // simple but useful: increment/decrement the step of each track
1984
  // (in MBSEQ V3 we only generated some additional clocks, which had
1985
  // the disadvantage, that sequences couldn't be scrubbed back)
1986
 
1987
  // this simplified method currently has following disadvantages:
1988
  // - clock dividers not taken into account (difficult, needs some code restructuring in SEQ_CORE_Tick())
1989
  // - ...and?
1990
  // advantage:
1991
  // - sequencer stays in sync with outgoing/incoming MIDI clock!
1992
  // - reverse scrubbing for some interesting effects while played live (MB-808 has a similar function: nudge)
1993
 
1994
  u8 track;
1995
  seq_core_trk_t *t = &seq_core_trk[0];
1996
  seq_cc_trk_t *tcc = &seq_cc_trk[0];
1997
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t, ++tcc) {
1998
    SEQ_CORE_NextStep(t, tcc, 0, incrementer >= 0 ? 0 : 1);
1999
  }
2000
 
2001
#if 0
2002
  // disabled so that we stay in Sync with MIDI clock!
2003
  // increment/decrement reference step
2004
  if( incrementer >= 0 ) {
2005
    if( ++seq_core_state.ref_step > seq_core_steps_per_measure )
2006
      seq_core_state.ref_step = 0;
2007
  } else {
2008
    if( seq_core_state.ref_step )
2009
      --seq_core_state.ref_step;
2010
    else
2011
      seq_core_state.ref_step = seq_core_steps_per_measure;
2012
  }
2013
#endif
2014
 
2015
  return 0; // no error
2016
}
1746 tk 2017
 
2018
 
2019
/////////////////////////////////////////////////////////////////////////////
2020
// This function ensures, that a (transposed) note is within
2021
// the <lower>..<upper> range.
2022
//
2023
// If the note is outside the range, it will be "trimmed" in the semitone
2024
// range, and the octave will be kept.
2025
/////////////////////////////////////////////////////////////////////////////
2026
u8 SEQ_CORE_TrimNote(s32 note, u8 lower, u8 upper)
2027
{
2028
  // negative note (e.g. after transpose?)
2029
  // shift it to the positive range
2030
  if( note < 0 )
2031
    note = 11 - ((-note - 1) % 12);
2032
 
2033
  // check for lower boundary
2034
  if( note < (s32)lower ) {
2035
    note = 12*(lower/12) + (note % 12);
2036
  }
2037
 
2038
  // check for upper boundary
2039
  if( note > (s32)upper ) {
2040
    note = 12*(upper/12) + (note % 12);
2041
 
2042
    // if note still > upper value (e.g. upper is set to >= 120)
2043
    // an if (instead of while) should work in all cases, because note will be (12*int(127/12)) + 11 = 131 in worst case!
2044
    if( note > upper )
2045
      note -= 12;
2046
  }
2047
 
2048
  return note;
2049
}
2050