Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
416 tk 1
// $Id: seq_record.c 2322 2016-03-15 19:08:38Z tk $
2
/*
3
 * Sequencer Recording 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
 
419 tk 23
#include "seq_record.h"
416 tk 24
#include "seq_core.h"
419 tk 25
#include "seq_layer.h"
26
#include "seq_par.h"
27
#include "seq_cc.h"
1320 tk 28
#include "seq_live.h"
416 tk 29
#include "seq_ui.h"
419 tk 30
#include "tasks.h"
416 tk 31
 
32
 
33
/////////////////////////////////////////////////////////////////////////////
34
// Local definitions
35
/////////////////////////////////////////////////////////////////////////////
36
 
37
// for optional debugging messages via DEBUG_MSG (defined in mios32_config.h)
1319 tk 38
// select 1 by default to allow error messages (recommended)
39
#define DEBUG_VERBOSE_LEVEL 1
416 tk 40
 
41
 
42
/////////////////////////////////////////////////////////////////////////////
43
// Global variables
44
/////////////////////////////////////////////////////////////////////////////
45
 
46
seq_record_options_t seq_record_options;
47
seq_record_state_t seq_record_state;
48
 
1121 tk 49
u8 seq_record_quantize;
416 tk 50
 
1319 tk 51
// one bit for each note, 32*4 = 128 notes supported (covers all notes of one MIDI channel)
52
// also used by seq_core for SEQ_MIDI_OUT_ReSchedule in record mode, therefore global
53
u32 seq_record_played_notes[4];
54
 
55
 
460 tk 56
/////////////////////////////////////////////////////////////////////////////
1319 tk 57
// Local variables
460 tk 58
/////////////////////////////////////////////////////////////////////////////
416 tk 59
 
1319 tk 60
// for step recording mode: timestamp to measure the length of the played
61
// notes (deluxe version: separate timestamp for each note!)
62
u16 seq_record_note_timestamp_ms[128];
460 tk 63
 
64
 
416 tk 65
/////////////////////////////////////////////////////////////////////////////
66
// Initialisation
67
/////////////////////////////////////////////////////////////////////////////
68
s32 SEQ_RECORD_Init(u32 mode)
69
{
70
  seq_record_options.ALL = 0;
1316 tk 71
  seq_record_options.AUTO_START = 0;
1121 tk 72
  seq_record_options.FWD_MIDI = 1;
1319 tk 73
  seq_record_options.POLY_RECORD = 1;
1325 tk 74
  seq_record_quantize = 10;
416 tk 75
 
76
  seq_record_state.ALL = 0;
77
 
1316 tk 78
#ifndef MBSEQV4L
79
  // default for MBSEQ V4
80
  seq_record_state.ARMED_TRACKS = 0x0001; // first track -- currently not relevant, could be provided for MBSEQV4 later
81
#else
82
  // default for MBSEQ V4L
83
  seq_record_state.ARMED_TRACKS = 0x00ff; // first sequence
84
#endif
85
 
1341 tk 86
  SEQ_RECORD_ResetAllTracks();
416 tk 87
 
1319 tk 88
  SEQ_RECORD_AllNotesOff();
89
 
416 tk 90
  return 0; // no error
91
}
92
 
93
 
94
/////////////////////////////////////////////////////////////////////////////
95
// called whenever record variables should be reseted (e.g. on track restart)
96
/////////////////////////////////////////////////////////////////////////////
419 tk 97
s32 SEQ_RECORD_Reset(u8 track)
416 tk 98
{
419 tk 99
  // exit if track number too high
100
  if( track >= SEQ_CORE_NUM_TRACKS )
101
    return -1; // unsupported track
102
 
103
  seq_core_trk_t *t = &seq_core_trk[track];
104
 
105
  // init track specific variables
106
  MIOS32_IRQ_Disable();
457 tk 107
  t->state.REC_DONT_OVERWRITE_NEXT_STEP = 0;
419 tk 108
  t->rec_timestamp = 0;
109
  t->rec_poly_ctr = 0;
110
  MIOS32_IRQ_Enable();
460 tk 111
 
1319 tk 112
  return 0; // no error
113
}
419 tk 114
 
1341 tk 115
/////////////////////////////////////////////////////////////////////////////
116
// resets the variables of all tracks
117
/////////////////////////////////////////////////////////////////////////////
118
s32 SEQ_RECORD_ResetAllTracks(void)
119
{
120
  s32 status = 0;
1319 tk 121
 
1341 tk 122
  u8 track;
123
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
124
    status |= SEQ_RECORD_Reset(track);
125
 
126
  return status;
127
}
128
 
129
 
1319 tk 130
/////////////////////////////////////////////////////////////////////////////
131
// should be called whenever the MIDI channel or port is changed
132
/////////////////////////////////////////////////////////////////////////////
133
s32 SEQ_RECORD_AllNotesOff(void)
134
{
460 tk 135
  int i;
1319 tk 136
  for(i=0; i<128; ++i)
137
    seq_record_note_timestamp_ms[i] = 0;
138
 
460 tk 139
  for(i=0; i<4; ++i)
1319 tk 140
    seq_record_played_notes[i] = 0;
951 tk 141
 
1319 tk 142
  return 0;
416 tk 143
}
144
 
145
 
146
/////////////////////////////////////////////////////////////////////////////
2154 tk 147
// This function enables recording and takes over active live notes
148
/////////////////////////////////////////////////////////////////////////////
2168 tk 149
s32 SEQ_RECORD_Enable(u8 enable, u8 reset_timestamps)
2154 tk 150
{
151
  // take over live notes on transition 0->1
152
  if( !seq_record_state.ENABLED && enable ) {
153
 
2168 tk 154
    if( reset_timestamps ) {
155
      u32 timestamp = MIOS32_TIMESTAMP_Get();
156
      int i;
157
      for(i=0; i<128; ++i)
158
    seq_record_note_timestamp_ms[i] = timestamp;
159
 
160
      for(i=0; i<4; ++i) {
161
    seq_record_played_notes[i] = seq_live_played_notes[i];
162
      }
2154 tk 163
    }
164
  }
165
 
166
  // clear record notes if recording disabled
167
  if( seq_record_state.ENABLED && !enable ) {
2168 tk 168
    if( reset_timestamps ) {
169
      SEQ_RECORD_AllNotesOff();
170
    }
2154 tk 171
  }
172
 
173
  seq_record_state.ENABLED = enable;
174
 
175
  return 0; // no error
176
}
177
 
178
 
179
/////////////////////////////////////////////////////////////////////////////
416 tk 180
// This function interacts with the UI to print the edit screen when an
181
// event has been recorded or changed
182
/////////////////////////////////////////////////////////////////////////////
183
s32 SEQ_RECORD_PrintEditScreen(void)
184
{
1316 tk 185
#ifndef MBSEQV4L
416 tk 186
  // for 2 seconds
187
  ui_hold_msg_ctr = 2000;
1316 tk 188
#endif
416 tk 189
 
190
  // select visible steps depending on record step
191
  ui_selected_step_view = ui_selected_step/16;
192
 
1316 tk 193
#ifndef MBSEQV4L
416 tk 194
  // update immediately
195
  seq_ui_display_update_req = 1;
1316 tk 196
#endif
416 tk 197
 
198
  return 0; // no error
199
}
200
 
201
 
202
/////////////////////////////////////////////////////////////////////////////
203
// Called from SEQ_MIDI_IN_Receive() if MIDI event has been received on
204
// matching IN port and channel
205
/////////////////////////////////////////////////////////////////////////////
206
s32 SEQ_RECORD_Receive(mios32_midi_package_t midi_package, u8 track)
207
{
1341 tk 208
  // step recording mode?
209
  // Note: if sequencer is not running, "Live Recording" will be handled like "Step Recording"
210
  u8 step_record_mode = seq_record_options.STEP_RECORD || !SEQ_BPM_IsRunning();
211
 
1316 tk 212
#if MBSEQV4L
213
  // extra for MBSEQ V4L: seq_record_state.ARMED_TRACKS and auto-assignment
214
  if( !seq_record_state.ARMED_TRACKS )
215
    return 0; // no track armed
216
 
217
  track = 0;
218
  if( seq_record_state.ARMED_TRACKS & 0xff00)
219
    track = 8;
220
 
221
  // search for free track/layer
222
  if( (midi_package.event == NoteOn) || (midi_package.event == NoteOff) ) {
223
    // fine, we will record Note in selected track
224
  } else if( midi_package.event == PitchBend ) {
225
    track += 3; // G1T4 resp. G3T4
226
  } else if( midi_package.event == CC ) {
1978 tk 227
    const u8 track_layer_cc_table[19][2] = {
228
      { 4, 0 },
229
      { 5, 0 },
230
      { 6, 0 },
231
      { 7, 0 },
232
      { 7, 1 }, { 7, 2 }, { 7, 3 },
233
      { 6, 1 }, { 6, 2 }, { 6, 3 },
234
      { 5, 1 }, { 5, 2 }, { 5, 3 },
235
      { 4, 1 }, { 4, 2 }, { 4, 3 },
236
      { 3, 1 }, { 3, 2 }, { 3, 3 },
237
    };
238
 
1316 tk 239
    // search for same (or free) CC entry
1978 tk 240
    // new track/layer search algorithm since V4L.082
241
    u8 seq_track_offset = track; // depends on sequence
242
    int par_layer = 0;
243
    int i;
1316 tk 244
    u8 free_layer_found = 0;
1978 tk 245
    for(i=0; i<19 && !free_layer_found; ++i) {
246
      track = seq_track_offset + track_layer_cc_table[i][0];
247
      par_layer = track_layer_cc_table[i][1];
248
      seq_cc_trk_t *tcc = &seq_cc_trk[track];
249
      u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16 + par_layer];
250
      u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16 + par_layer];
1316 tk 251
 
1978 tk 252
      if( *layer_type_ptr == SEQ_PAR_Type_CC &&
253
      (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) &&
254
      (seq_record_state.ARMED_TRACKS & (1 << track)) ) {
1316 tk 255
 
1978 tk 256
    if( *layer_cc_ptr >= 0x80 ) {
257
      *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track
1316 tk 258
 
1978 tk 259
      // initialize whole layer with invalid value 0xc0 (indicates: not recorded)
260
      int num_p_steps = SEQ_PAR_NumStepsGet(track);
261
      int instrument = 0;
262
      int step;
263
      for(step=0; step<num_p_steps; ++step)
264
        SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0);
1319 tk 265
#if DEBUG_VERBOSE_LEVEL >= 2
1978 tk 266
      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);
1316 tk 267
#endif
1978 tk 268
    }
1316 tk 269
 
1978 tk 270
    free_layer_found = 1;
1316 tk 271
      }
272
    }
273
 
274
    if( !free_layer_found ) {
1319 tk 275
#if DEBUG_VERBOSE_LEVEL >= 2
1316 tk 276
      DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number);
277
#endif
278
      return 0; // no free layer
279
    }
280
  } else {
281
    return 0; // event not relevant
282
  }
283
 
284
  // exit if track not armed
285
  if( !(seq_record_state.ARMED_TRACKS & (1 << track)) )
286
    return 0;
1811 tk 287
#else
288
  // MBSEQV4 (without L)
289
  if( midi_package.event == CC && track == SEQ_UI_VisibleTrackGet() ) {
290
    // search for same (or free) CC entry
291
    seq_cc_trk_t *tcc = &seq_cc_trk[track];
292
    u8 free_layer_found = 0;
293
    {
294
      u8 num_p_layers = SEQ_PAR_NumLayersGet(track);
295
      u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
296
      u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16];
297
      int par_layer;
298
      for(par_layer=0; par_layer<num_p_layers && !free_layer_found; ++par_layer, ++layer_type_ptr, ++layer_cc_ptr) {
299
    if( *layer_type_ptr == SEQ_PAR_Type_CC &&
300
        (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) ) {
301
 
302
      if( *layer_cc_ptr >= 0x80 ) {
303
        *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track
304
 
305
        // initialize whole layer with invalid value 0xc0 (indicates: not recorded)
306
        int num_p_steps = SEQ_PAR_NumStepsGet(track);
307
        int instrument = 0;
308
        int step;
309
        for(step=0; step<num_p_steps; ++step)
310
          SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0);
311
#if DEBUG_VERBOSE_LEVEL >= 2
312
        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);
1316 tk 313
#endif
1811 tk 314
      }
1316 tk 315
 
1811 tk 316
      free_layer_found = 1;
317
      break;
318
    }
319
      }
320
    }
321
 
322
    if( !free_layer_found ) {
1319 tk 323
#if DEBUG_VERBOSE_LEVEL >= 2
1811 tk 324
      DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number);
325
#endif
326
      return 0; // no free layer
327
    }
328
  }
329
#endif
330
 
331
#if DEBUG_VERBOSE_LEVEL >= 2
416 tk 332
  DEBUG_MSG("[SEQ_RECORD_Receive] %02x %02x %02x -> track #%d\n",
333
        midi_package.evnt0, midi_package.evnt1, midi_package.evnt2,
334
        track+1);
335
#endif
336
 
337
  // exit if track number too high
338
  if( track >= SEQ_CORE_NUM_TRACKS )
339
    return -1; // unsupported track
340
 
419 tk 341
  seq_core_trk_t *t = &seq_core_trk[track];
342
  seq_cc_trk_t *tcc = &seq_cc_trk[track];
343
 
2308 tk 344
  // Auto-Start: start with first step
2322 tk 345
  if( !SEQ_BPM_IsRunning() && seq_record_options.AUTO_START && !seq_record_options.STEP_RECORD ) {
2308 tk 346
    ui_selected_step = 0;
347
  }
348
 
416 tk 349
  // branch depending on event
419 tk 350
  u8 rec_event = 0;
460 tk 351
  u8 send_note_off = 0;
416 tk 352
  switch( midi_package.event ) {
353
    case NoteOff:
354
    case NoteOn: {
460 tk 355
      midi_package.note &= 0x7f; // to avoid array overwrites
951 tk 356
      u32 note_mask = 1 << (midi_package.note & 0x1f);
460 tk 357
 
358
      // if Note Off and new note number matches with recorded note number
416 tk 359
      if( midi_package.event == NoteOff || midi_package.velocity == 0 ) {
1319 tk 360
    if( seq_record_played_notes[midi_package.note>>5] & note_mask ) {
416 tk 361
      MIOS32_IRQ_Disable();
460 tk 362
      // note not active anymore
1319 tk 363
      seq_record_played_notes[midi_package.note>>5] &= ~note_mask;
460 tk 364
 
1319 tk 365
      // determine duration in mS (for step recording function)
1911 tk 366
      u16 duration_ms = MIOS32_TIMESTAMP_Get() - seq_record_note_timestamp_ms[midi_package.note];
1319 tk 367
      // map to BPM
2050 tk 368
      int duration = (int)((float)duration_ms / ((1000.0*60.0) / SEQ_BPM_EffectiveGet() / (float)SEQ_BPM_PPQN_Get()));
1319 tk 369
#if DEBUG_VERBOSE_LEVEL >= 3
370
      DEBUG_MSG("[SEQ_RECORD_Receive] duration of note 0x%02x was %d mS (%d ticks)\n",
371
            midi_package.note, duration_ms, duration);
372
#endif    
373
 
419 tk 374
      // insert length into current step
375
      u8 instrument = 0;
1318 tk 376
      int len;
1341 tk 377
      if( step_record_mode ) {
1319 tk 378
        len = 71; // 75%
379
        if( tcc->event_mode != SEQ_EVENT_MODE_Drum )
380
          len = (duration <= 96) ? duration : 96; // for duration >= 96 the length will be stretched after record
1318 tk 381
      } else {
382
        len = SEQ_BPM_TickGet() - t->rec_timestamp;
1319 tk 383
 
384
        if( len < 1 )
385
          len = 1;
386
        else if( len > 95 )
387
          len = 95;
1318 tk 388
      }
1316 tk 389
 
2166 tk 390
      int len_step = step_record_mode ? ui_selected_step : t->step;
1319 tk 391
      u8 num_p_layers = SEQ_PAR_NumLayersGet(track);
392
 
393
      while( 1 ) {
394
        if( tcc->event_mode == SEQ_EVENT_MODE_Combined ) {
395
          // extra for MBSEQ V4L:
396
          // search for note in track 1/8, insert length into track 3/10
397
          int par_layer;
398
          for(par_layer=0; par_layer<num_p_layers; ++par_layer) {
399
        if( SEQ_PAR_Get(track, len_step, par_layer, instrument) == midi_package.note ) {
400
          SEQ_PAR_Set(track+2, len_step, par_layer, instrument, len);
401
          break;
402
        }
403
          }
404
        } else {
405
          if( tcc->link_par_layer_length >= 0 )
406
        SEQ_PAR_Set(track, len_step, tcc->link_par_layer_length, instrument, len);
407
        }
408
 
1341 tk 409
        if( !step_record_mode )
1319 tk 410
          break;
411
        if( tcc->event_mode == SEQ_EVENT_MODE_Drum )
412
          break;
413
        if( duration <= 0 )
414
          break;
415
        duration -= 96;
416
 
417
        // insert length into all following steps until a gate is set
418
        if( ++len_step > tcc->length ) // TODO: handle this correctly if track is played backwards
419
          len_step = tcc->loop;
420
 
421
        if( SEQ_TRG_GateGet(track, len_step, instrument) )
422
          break;
423
 
424
        len = (duration > 0) ? 96 : -duration;
425
 
426
        // copy notes
427
        u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
1316 tk 428
        int par_layer;
1319 tk 429
        for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) {
2274 tk 430
          if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord1 || *layer_type_ptr == SEQ_PAR_Type_Chord2 ) {
2166 tk 431
        u8 note = SEQ_PAR_Get(track, ui_selected_step, par_layer, instrument);
1319 tk 432
        SEQ_PAR_Set(track, len_step, par_layer, instrument, note);
1316 tk 433
          }
434
        }
419 tk 435
      }
1319 tk 436
 
416 tk 437
      MIOS32_IRQ_Enable();
438
    }
439
 
1341 tk 440
    if( step_record_mode && seq_record_options.FWD_MIDI ) {
1319 tk 441
      // send Note Off events of current track if no key is played anymore
442
      u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3];
443
      if( !any_note_played )
444
        send_note_off = 1;    
1318 tk 445
    }
416 tk 446
      } else {
447
    MIOS32_IRQ_Disable();
1318 tk 448
 
1341 tk 449
    if( step_record_mode && tcc->event_mode != SEQ_EVENT_MODE_Drum ) {
1318 tk 450
      // check if another note is already played
1319 tk 451
      u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3];
1318 tk 452
      // if not: clear poly counter and all notes (so that new chord can be entered if all keys were released)
453
      if( !any_note_played ) {
454
        t->rec_poly_ctr = 0;
455
 
456
        u8 num_p_layers = SEQ_PAR_NumLayersGet(track);
457
        u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
458
        int par_layer;
459
        u8 instrument = 0;
460
        for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) {
2274 tk 461
          if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord1 || *layer_type_ptr == SEQ_PAR_Type_Chord2 )
2166 tk 462
        SEQ_PAR_Set(track, ui_selected_step, par_layer, instrument, 0x00);
1318 tk 463
        }
464
      }
465
    }
466
 
460 tk 467
    // note is active
1319 tk 468
    seq_record_played_notes[midi_package.note>>5] |= note_mask;
416 tk 469
    // start measuring length
419 tk 470
    t->rec_timestamp = SEQ_BPM_TickGet();
1319 tk 471
    // for step record function: independent from BPM
1911 tk 472
    seq_record_note_timestamp_ms[midi_package.note & 0x7f] = MIOS32_TIMESTAMP_Get(); // note: 16bit only
1319 tk 473
 
416 tk 474
    MIOS32_IRQ_Enable();
475
 
476
    // record event
477
    rec_event = 1;
478
      }
479
    } break;
480
 
419 tk 481
    case CC:
482
    case PitchBend: {
416 tk 483
      rec_event = 1;
484
    } break;
485
 
486
    default: {
1319 tk 487
#if DEBUG_VERBOSE_LEVEL >= 2
416 tk 488
      DEBUG_MSG("[SEQ_RECORD_Receive] event %x not supported.\n", midi_package.event);
489
#endif
490
      return -2; // unsupported event
491
    }
492
  }
493
 
419 tk 494
  // create step event
495
  seq_layer_evnt_t layer_event;
496
  layer_event.midi_package = midi_package;
497
  layer_event.midi_package.cable = track; // used as tag
498
  layer_event.len = 71; // 75%
499
  layer_event.midi_package.chn = tcc->midi_chn;
500
 
457 tk 501
  // take MIDI Out/Sequencer semaphore
502
  MUTEX_MIDIOUT_TAKE;
503
 
460 tk 504
  if( send_note_off ) {
2048 tk 505
    if( SEQ_BPM_IsRunning() ) {
1319 tk 506
      SEQ_MIDI_OUT_ReSchedule(track, SEQ_MIDI_OUT_OffEvent, 0, seq_record_played_notes);
2048 tk 507
    } else {
419 tk 508
      SEQ_MIDI_OUT_FlushQueue();
2048 tk 509
    }
510
 
511
    // also for the live function
512
    if( seq_record_options.FWD_MIDI )
513
      SEQ_LIVE_AllNotesOff();
460 tk 514
  }
416 tk 515
 
460 tk 516
  if( rec_event ) {
2250 tk 517
    // start sequencer if not running and auto start enabled
518
    if( !SEQ_BPM_IsRunning() && seq_record_options.AUTO_START ) {
519
      // if in auto mode and BPM generator is clocked in slave mode:
520
      // change to master mode
521
      SEQ_BPM_CheckAutoMaster();
522
      // start generator
523
      SEQ_BPM_Start();
524
    }
525
 
1341 tk 526
    if( !step_record_mode ) {
2166 tk 527
      u8 prev_step = ui_selected_step;
419 tk 528
      u8 new_step = t->step;
460 tk 529
 
2166 tk 530
      ui_selected_step = new_step;
457 tk 531
 
532
      // take next step if it will be reached "soon" (>80% of current step)
533
      if( SEQ_BPM_IsRunning() ) {
534
    u32 timestamp = SEQ_BPM_TickGet();
535
    u8 shift_event = 0;
536
    if( t->timestamp_next_step_ref <= timestamp )
537
      shift_event = 1;
538
    else {
539
      s32 diff = (s32)t->timestamp_next_step_ref - (s32)timestamp;
1121 tk 540
      u32 tolerance = (t->step_length * seq_record_quantize) / 100; // usually 20% of 96 ticks -> 19 ticks
457 tk 541
      // TODO: we could vary the tolerance depending on the BPM rate: than slower the clock, than lower the tolerance
542
      // as a simple replacement for constant time measuring
543
      if( diff < tolerance)
544
        shift_event = 1;
545
    }
546
 
547
    if( shift_event ) {
2166 tk 548
      int next_step = ui_selected_step + 1; // tmp. variable used for u8 -> u32 conversion to handle 256 steps properly
457 tk 549
      if( next_step > tcc->length ) // TODO: handle this correctly if track is played backwards
550
        next_step = tcc->loop;
1319 tk 551
#if DEBUG_VERBOSE_LEVEL >= 2
2166 tk 552
      MIOS32_MIDI_SendDebugMessage("Shifted step %d -> %d\n", ui_selected_step, next_step);
460 tk 553
#endif
2166 tk 554
      ui_selected_step = next_step;
457 tk 555
      t->state.REC_DONT_OVERWRITE_NEXT_STEP = 1; // next step won't be overwritten
556
    }
557
      }
460 tk 558
 
2166 tk 559
      if( ui_selected_step != prev_step )
460 tk 560
    t->rec_poly_ctr = 0;
419 tk 561
    }
416 tk 562
 
419 tk 563
    // insert event into track (function will return >= 0 if event
564
    // has been inserted into the (returned) layer.
565
    // if < 0, no event has been inserted.
566
    int insert_layer;
2166 tk 567
    if( (insert_layer=SEQ_LAYER_RecEvent(track, ui_selected_step, layer_event)) < 0 )
419 tk 568
      rec_event = 0;
569
    else {
1316 tk 570
#ifndef MBSEQV4L
419 tk 571
      // change layer on UI
572
      if( tcc->event_mode == SEQ_EVENT_MODE_Drum ) {
573
    ui_selected_instrument = insert_layer;
574
    ui_selected_par_layer = 0;
575
    ui_selected_trg_layer = 0;
576
      } else {
577
    ui_selected_instrument = 0;
578
    ui_selected_par_layer = insert_layer;
579
    ui_selected_trg_layer = 0;
580
      }
1316 tk 581
#endif
419 tk 582
 
1341 tk 583
      if( step_record_mode && seq_record_options.FWD_MIDI ) {
2048 tk 584
    if( tcc->event_mode == SEQ_EVENT_MODE_Drum || midi_package.type != NoteOn ) {
585
      // Drum mode or no note: play only the single event
1341 tk 586
      SEQ_LIVE_PlayEvent(track, midi_package);
587
    } else {
588
      seq_layer_evnt_t layer_events[16];
2166 tk 589
      u8 record_step = ui_selected_step;
1316 tk 590
#ifdef MBSEQV4L
1341 tk 591
      // extra MBSEQ V4L if CC track: read 16th step in step record mode
592
      // could also be provided for normal MBSEQ V4 later (has to be made more flexible!)
593
      if( step_record_mode && tcc->clkdiv.value == 0x03 )
594
        record_step *= 4;
1316 tk 595
#endif
596
 
1341 tk 597
      s32 number_of_events = SEQ_LAYER_GetEvents(track, record_step, layer_events, 0);
598
      if( number_of_events > 0 ) {
599
        int i;
600
        seq_layer_evnt_t *e = &layer_events[0];
601
        for(i=0; i<number_of_events; ++e, ++i)
602
          SEQ_LIVE_PlayEvent(track, e->midi_package);
603
      }
419 tk 604
    }
605
      }
606
 
1341 tk 607
      if( step_record_mode && !seq_record_options.POLY_RECORD ) {
2166 tk 608
    int next_step = (ui_selected_step + seq_record_options.STEPS_PER_KEY) % ((int)tcc->length+1);
419 tk 609
 
610
    int i;
611
    for(i=0; i<SEQ_CORE_NUM_TRACKS; ++i)
612
      SEQ_RECORD_Reset(i);
613
 
2166 tk 614
    ui_selected_step = next_step;
419 tk 615
      }
616
    }
1319 tk 617
  }
416 tk 618
 
1341 tk 619
  if( seq_record_options.FWD_MIDI && (!rec_event || !step_record_mode) ) {
1319 tk 620
    // forward event directly in live mode or if it hasn't been recorded
1320 tk 621
    SEQ_LIVE_PlayEvent(track, layer_event.midi_package);
419 tk 622
  }
623
 
457 tk 624
  // give MIDI Out/Sequencer semaphore
625
  MUTEX_MIDIOUT_GIVE;
626
 
416 tk 627
  // temporary print edit screen
1341 tk 628
  // MBSEQV4L: only if a note ON event has been played
629
#ifdef MBSEQV4L
2101 tk 630
  if( rec_event && midi_package.event == NoteOn ) {
631
#else
632
  if( rec_event ) {
1341 tk 633
#endif
634
    SEQ_RECORD_PrintEditScreen();
2101 tk 635
  }
416 tk 636
 
637
  return 0; // no error
638
}
419 tk 639
 
640
 
641
/////////////////////////////////////////////////////////////////////////////
642
// Called from SEQ_CORE_Tick() when a new step is played
643
// It can modify the current and previous step depending on recording mode
644
/////////////////////////////////////////////////////////////////////////////
645
s32 SEQ_RECORD_NewStep(u8 track, u8 prev_step, u8 new_step, u32 bpm_tick)
646
{
1313 tk 647
  if( !seq_record_state.ENABLED )
419 tk 648
    return -1; // not in recording page
649
 
650
  if( seq_record_options.STEP_RECORD )
651
    return -2; // only in live record mode
652
 
1341 tk 653
  // this is a proper workaround for Auto Start feature in Live Recording mode
654
  // t->state.REC_DONT_OVERWRITE_NEXT_STEP has been cleared by SEQ_CORE_Reset(), this
655
  // will cause that the first step will be overwritten
656
  if( bpm_tick == 0 )
657
    return 0; // silently ignore (we don't expect a live recording event at the very first step)
658
 
1316 tk 659
#ifndef MBSEQV4L
419 tk 660
  if( track != SEQ_UI_VisibleTrackGet() )
661
    return -3; // only for visible track
1316 tk 662
#else
663
  if( !(seq_record_state.ARMED_TRACKS & (1 << track)) )
664
    return -3; // MBSEQV4L: only for armed track
665
#endif
419 tk 666
 
667
  if( track >= SEQ_CORE_NUM_TRACKS )
668
    return -4; // unsupported track
669
 
670
  seq_core_trk_t *t = &seq_core_trk[track];
671
  seq_cc_trk_t *tcc = &seq_cc_trk[track];
672
 
460 tk 673
  // take over new timestamp
674
  t->rec_timestamp = bpm_tick;
419 tk 675
 
460 tk 676
  // branch depending on drum/normal mode
677
  u8 instrument = 0;
1319 tk 678
  u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3];
419 tk 679
 
460 tk 680
  // if at least one note is played and step can be overwritten
681
  if( any_note_played && !t->state.REC_DONT_OVERWRITE_NEXT_STEP ) {
419 tk 682
 
460 tk 683
    if( tcc->event_mode == SEQ_EVENT_MODE_Drum ) {
684
      // check for matching notes
685
      u8 num_instruments = SEQ_TRG_NumInstrumentsGet(track);
686
      for(instrument=0; instrument<num_instruments; ++instrument) {
687
    u8 note = tcc->lay_const[0*16 + instrument];
1319 tk 688
    if( seq_record_played_notes[note>>5] & (1 << (note & 0x1f)) ) {
2149 tk 689
      u8 gate = 0;
690
      u8 accent = 0;
691
      // BEGIN live pattern insertion
2152 tk 692
      if( !seq_record_options.STEP_RECORD ) {
2154 tk 693
        seq_live_pattern_slot_t *slot = (seq_live_pattern_slot_t *)&seq_live_pattern_slot[1+instrument];
2149 tk 694
        if( slot->enabled ) {
695
          seq_live_arp_pattern_t *pattern = (seq_live_arp_pattern_t *)&seq_live_arp_pattern[slot->pattern];
696
          u16 mask = 1 << (new_step % 16);
697
          gate = (pattern->gate & mask) ? 1 : 0;
698
          accent = (pattern->accent & mask) ? 1 : 0;
699
 
700
          if( tcc->link_par_layer_velocity >= 0 ) {
701
        SEQ_PAR_Set(track, new_step, tcc->link_par_layer_velocity, instrument, slot->velocity);
702
          }
703
        }
704
      }
705
      // END live pattern insertion
706
 
707
      SEQ_TRG_GateSet(track, new_step, instrument, gate);
708
      SEQ_TRG_AccentSet(track, new_step, instrument, accent);
460 tk 709
    }
710
      }
711
    } else {
2149 tk 712
      u8 gate = 0;
713
      u8 accent = 0;
714
      u8 length_prev_step = 95;
715
      u8 length_new_step = 1;
716
      int velocity = -1; // take over new velocity if >= 0
717
      // BEGIN live pattern insertion
2152 tk 718
      if( !seq_record_options.STEP_RECORD ) {
2154 tk 719
    seq_live_pattern_slot_t *slot = (seq_live_pattern_slot_t *)&seq_live_pattern_slot[0];
2149 tk 720
    if( slot->enabled ) {
721
      seq_live_arp_pattern_t *pattern = (seq_live_arp_pattern_t *)&seq_live_arp_pattern[slot->pattern];
722
      u16 mask = 1 << (new_step % 16);
723
      gate = (pattern->gate & mask) ? 1 : 0;
724
      accent = (pattern->accent & mask) ? 1 : 0;
725
      velocity = slot->velocity;
726
      length_prev_step = slot->len;
727
      length_new_step = slot->len;
728
    }
729
      }
730
      // END live pattern insertion
731
 
732
      // disable gate of new step
733
      SEQ_TRG_GateSet(track, new_step, instrument, gate);
734
      SEQ_TRG_AccentSet(track, new_step, instrument, accent);
735
 
1318 tk 736
      // copy notes of previous step to new step
737
      u8 num_p_layers = SEQ_PAR_NumLayersGet(track);
738
      u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
739
      int par_layer;
740
      for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) {
2274 tk 741
    if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord1 || *layer_type_ptr == SEQ_PAR_Type_Chord2 ) {
1318 tk 742
      u8 note = SEQ_PAR_Get(track, prev_step, par_layer, instrument);
743
      SEQ_PAR_Set(track, new_step, par_layer, instrument, note);
744
    }
745
      }
746
 
457 tk 747
      // set length of previous step to maximum, and of the new step to minimum
1316 tk 748
      if( tcc->event_mode == SEQ_EVENT_MODE_Combined ) {
749
    // extra for MBSEQ V4L:
750
    // search for note in track 1/8, insert length into track 3/10
1318 tk 751
    for(par_layer=0; par_layer<num_p_layers; ++par_layer) {
752
      u8 note = SEQ_PAR_Get(track, prev_step, par_layer, instrument);
1319 tk 753
      if( seq_record_played_notes[note>>5] & (1 << (note&0x1f)) ) {
2149 tk 754
        SEQ_PAR_Set(track+2, prev_step, par_layer, instrument, length_prev_step);
755
        SEQ_PAR_Set(track+2, new_step, par_layer, instrument, length_new_step);
1316 tk 756
      }
757
    }
2149 tk 758
 
759
    // insert velocity into track 2/9
760
    if( velocity >= 0 ) {
761
      SEQ_PAR_Set(track+1, new_step, par_layer, instrument, velocity);
762
    }
1316 tk 763
      } else {
764
    if( tcc->link_par_layer_length >= 0 ) {
2149 tk 765
      SEQ_PAR_Set(track, prev_step, tcc->link_par_layer_length, instrument, length_prev_step);
766
      SEQ_PAR_Set(track, new_step, tcc->link_par_layer_length, instrument, length_new_step);
1316 tk 767
    }
2149 tk 768
    if( velocity >= 0 && tcc->link_par_layer_velocity >= 0 ) {
769
      SEQ_PAR_Set(track, new_step, tcc->link_par_layer_velocity, instrument, velocity);
770
    }
457 tk 771
      }
419 tk 772
    }
773
  }
774
 
457 tk 775
  t->state.REC_DONT_OVERWRITE_NEXT_STEP = 0;
776
 
419 tk 777
  return 0; // no error
778
}