Example #1
0
/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_Init(u32 mode)
{
  // initialize the Notestack
#if 0
  NOTESTACK_Init(&notestack, NOTESTACK_MODE_PUSH_TOP, &notestack_items[0], NOTESTACK_SIZE);
#else
  // for an arpeggiator we prefer sorted mode
  // activate hold mode as well. Stack will be cleared whenever no note is played anymore
  NOTESTACK_Init(&notestack, NOTESTACK_MODE_SORT_HOLD, &notestack_items[0], NOTESTACK_SIZE);
#endif

  // and the arp counter
  arp_counter = 0;

  // reset sequencer
  SEQ_Reset();

  // init BPM generator
  SEQ_BPM_Init(0);

  SEQ_BPM_PPQN_Set(384);
  SEQ_BPM_Set(120.0);

  return 0; // no error
}
Example #2
0
/////////////////////////////////////////////////////////////////////////////
// Resets song position of sequencer
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_Reset(u8 play_off_events)
{
  // since timebase has been changed, ensure that Off-Events are played 
  // (otherwise they will be played much later...)
  if( play_off_events )
    SEQ_PlayOffEvents();

  // release pause and FFWD mode
  seq_pause = 0;
  ffwd_silent_mode = 0;
  next_prefetch = 0;
  prefetch_offset = 0;

  // restart song
  MID_PARSER_RestartSong();

  // set initial BPM (according to MIDI file spec)
  SEQ_BPM_PPQN_Set(384); // not specified
  SEQ_BPM_Set(120.0);

  // reset BPM tick
  SEQ_BPM_TickSet(0);

  return 0; // no error
}
Example #3
0
void MClock_SetBPM(float bpm) {
    if (SEQ_BPM_Set(bpm) < 0) {
        mClock.status.run = 0;                                                  // handle failure by pausing master clock
    } else {
        mClock.bpm = bpm;                                                       // store the tempo
    }
    
}
Example #4
0
/////////////////////////////////////////////////////////////////////////////
//! Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 MBNG_SEQ_Init(u32 mode)
{
  if( mode != 0 )
    return -1; // only mode 0 supported

  // init BPM generator
  SEQ_BPM_Init(0);
  SEQ_BPM_Set(120.0);

  // reset sequencer
  MBNG_SEQ_Reset();

  // disable pause after power-on
  MBNG_SEQ_SetPauseMode(0);

  return 0; // no error
}
Example #5
0
/////////////////////////////////////////////////////////////////////////////
// (Public) Tap Tempo Function
// Can also be accessed by pressing MENU+PLAY
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BPM_TapTempo(void)
{
  // determine current timestamp
  u32 timestamp = MIOS32_TIMESTAMP_Get();
  u32 delay = MIOS32_TIMESTAMP_GetDelay(tap_tempo_last_timestamp);

  // if delay < 100 (mS) we assume a bouncing button - ignore this tap!
  if( delay < 100 )
    return -1;

  // reset counter if last timestamp zero (first tap) or difference between timestamps > 2 seconds (< 30 BPM...)
  if( !tap_tempo_last_timestamp || delay > 2000 ) {
    resetTapTempo();
  } else {    
    // store measured delay
    tap_tempo_delay[tap_tempo_beat_ix] = delay;

    // increment index, wrap at number of stored tap delays
    tap_tempo_beat_ix = (tap_tempo_beat_ix + 1) % TAP_DELAY_STORAGE_SIZE;
  }

  // store timestamp
  tap_tempo_last_timestamp = timestamp;

  // take over BPM and start sequencer once we reached the 5th tap
  if( tap_tempo_beat_ctr >= TAP_DELAY_STORAGE_SIZE ) {
    // hold counter at delay storage size + 1 (for display)
    tap_tempo_beat_ctr = TAP_DELAY_STORAGE_SIZE + 1;

    // determine BPM
    int tap;
    int accumulated_delay = 0;
    for(tap=0; tap<TAP_DELAY_STORAGE_SIZE; ++tap)
      accumulated_delay += tap_tempo_delay[tap];
    u32 bpm = 60000000 / (accumulated_delay / TAP_DELAY_STORAGE_SIZE);

    // set BPM
    float bpmF = bpm / 1000.0;
    seq_core_bpm_preset_tempo[seq_core_bpm_preset_num] = bpmF;
    SEQ_BPM_Set(bpmF);

    // if in auto mode and BPM generator is clocked in slave mode:
    // change to master mode
    SEQ_BPM_CheckAutoMaster();

    // if sequencer not running: start it!
    if( !SEQ_BPM_IsRunning() )
      SEQ_BPM_Start();

  } else {
    // increment counter
    ++tap_tempo_beat_ctr;
  }

  // print message
  char buffer1[30];
  if( tap_tempo_beat_ctr > TAP_DELAY_STORAGE_SIZE ) {
    float bpm = SEQ_BPM_Get();
    sprintf(buffer1, "Tap Tempo: %3d.%d", (int)bpm, (int)(10*bpm)%10);
  } else
    sprintf(buffer1, "Tap Tempo: ???.?");

  char buffer2[30];
  int i;
  for(i=0; i<((tap_tempo_beat_ix+1)*4); ++i)
    buffer2[i] = '>';
  for(; i<16; ++i)
    buffer2[i] = ' ';
  buffer2[i] = 0;
  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 2000, buffer1, buffer2);

  return 0; // no error
}
Example #6
0
/////////////////////////////////////////////////////////////////////////////
// called when a Meta event should be played/processed at a given tick
/////////////////////////////////////////////////////////////////////////////
static s32 SEQ_PlayMeta(u8 track, u8 meta, u32 len, u8 *buffer, u32 tick)
{
  switch( meta ) {
    case 0x00: // Sequence Number
      if( len == 2 ) {
	u32 seq_number = (buffer[0] << 8) | buffer[1];
#if DEBUG_VERBOSE_LEVEL >= 2
	DEBUG_MSG("[SEQ:%d:%u] Meta - Sequence Number %u\n", track, tick, seq_number);
#endif
      } else {
#if DEBUG_VERBOSE_LEVEL >= 2
	DEBUG_MSG("[SEQ:%d:%u] Meta - Sequence Number with %d bytes -- ERROR: expecting 2 bytes!\n", track, tick, len);
#endif
      }
      break;

    case 0x01: // Text Event
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Text: %s\n", track, tick, buffer);
#endif
      break;

    case 0x02: // Copyright Notice
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Copyright: %s\n", track, tick, buffer);
#endif
      break;

    case 0x03: // Sequence/Track Name
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Track Name: %s\n", track, tick, buffer);
#endif
      break;

    case 0x04: // Instrument Name
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Instr. Name: %s\n", track, tick, buffer);
#endif
      break;

    case 0x05: // Lyric
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Lyric: %s\n", track, tick, buffer);
#endif
      break;

    case 0x06: // Marker
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Marker: %s\n", track, tick, buffer);
#endif
      break;

    case 0x07: // Cue Point
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - Cue Point: %s\n", track, tick, buffer);
#endif
      break;

    case 0x20: // Channel Prefix
      if( len == 1 ) {
	u32 prefix = *buffer;
#if DEBUG_VERBOSE_LEVEL >= 2
	DEBUG_MSG("[SEQ:%d:%u] Meta - Channel Prefix %u\n", track, tick, prefix);
#endif
      } else {
#if DEBUG_VERBOSE_LEVEL >= 2
	DEBUG_MSG("[SEQ:%d:%u] Meta - Channel Prefix with %d bytes -- ERROR: expecting 1 byte!\n", track, tick, len);
#endif
      }
      break;

    case 0x2f: // End of Track
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ:%d:%u] Meta - End of Track\n", track, tick, meta);
#endif
      break;

    case 0x51: // Set Tempo
      if( len == 3 ) {
	u32 tempo_us = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
	float bpm = 60.0 * (1E6 / (float)tempo_us);
	SEQ_BPM_PPQN_Set(MIDI_PARSER_PPQN_Get());

	// set tempo immediately on first tick
	if( tick == 0 ) {
	  SEQ_BPM_Set(bpm);
	} else {
	  // put tempo change request into the queue
	  mios32_midi_package_t tempo_package; // or Softis?
	  tempo_package.ALL = (u32)bpm;
	  SEQ_MIDI_OUT_Send(DEFAULT, tempo_package, SEQ_MIDI_OUT_TempoEvent, tick, 0);
	}

#if DEBUG_VERBOSE_LEVEL >= 2
	DEBUG_MSG("[SEQ:%d:%u] Meta - Tempo to %u uS -> %u BPM\n", track, tick, tempo_us, (u32)bpm);
#endif
      } else {
#if DEBUG_VERBOSE_LEVEL >= 2
	DEBUG_MSG("[SEQ:%d:%u] Meta - Tempo with %u bytes -- ERROR: expecting 3 bytes!\n", track, tick, len);
#endif
      }
      break;

    // other known events which are not handled here:
    // 0x54: SMPTE offset
    // 0x58: Time Signature
    // 0x59: Key Signature
    // 0x7f: Sequencer Specific Meta Event

#if DEBUG_VERBOSE_LEVEL >= 2
    default:
      DEBUG_MSG("[SEQ:%d:%u] Meta Event 0x%02x with length %u not processed\n", track, tick, meta, len);
#endif
  }

  return 0;
}
static void mclkBpmSet(u32 ix, u16 value)     { SEQ_BPM_Set((float)value); }