Exemplo n.º 1
0
/////////////////////////////////////////////////////////////////////////////
// Should be called whenever a Note event has been received.
// We expect, that velocity is 0 on a Note Off event
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_NotifyNoteOn(u8 note, u8 velocity)
{
  u8 clear_stack = 0;

  if( velocity )
    // push note into note stack
    NOTESTACK_Push(&notestack, note, velocity);
  else {
    // remove note from note stack
    // function returns 2 if no note played anymore (all keys depressed)
    if( NOTESTACK_Pop(&notestack, note) == 2 )
      clear_stack = 1;
  }

  // At least one note played?
  if( !clear_stack && notestack.len > 0 ) {
    // start sequencer if it isn't already running
    if( !SEQ_BPM_IsRunning() )
      SEQ_BPM_Start();
  } else {
    // clear stack
    NOTESTACK_Clear(&notestack);

    // no key is pressed anymore: stop sequencer
    SEQ_BPM_Stop();
  }


#if 1
  // optional debug messages
  NOTESTACK_SendDebugMessage(&notestack);
#endif

  return 0; // no error
}
Exemplo n.º 2
0
/////////////////////////////////////////////////////////////////////////////
// This hook is called when a MIDI package has been received
/////////////////////////////////////////////////////////////////////////////
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
{
  // Note On received?
  if( midi_package.type == NoteOn &&
      midi_package.chn == Chn1 &&
      midi_package.velocity > 0 ) {

    // determine base key number (0=C, 1=C#, 2=D, ...)
    u8 base_key = midi_package.note % 12;

    // branch depending on note
    switch( base_key ) {
      case 0: // "C" starts the sequencer
	MIOS32_MIDI_SendDebugMessage("Start\n");
	// if in auto mode and BPM generator is clocked in slave mode:
	// change to master mode
	SEQ_BPM_CheckAutoMaster();
	// start sequencer
	SEQ_BPM_Start();
	break;

      case 2: // "D" stops the sequencer. If pressed twice, the sequencer will be reset
	MIOS32_MIDI_SendDebugMessage("Stop\n");
	if( SEQ_BPM_IsRunning() )
	  SEQ_BPM_Stop();          // stop sequencer
	else
	  SEQ_Reset(1);            // reset sequencer
	break;

      case 4: // "E" pauses the sequencer
	// if in auto mode and BPM generator is clocked in slave mode:
	// change to master mode
	SEQ_BPM_CheckAutoMaster();

	// toggle pause mode
	seq_pause ^= 1;

	MIOS32_MIDI_SendDebugMessage("Pause %s\n", seq_pause ? "on" : "off");

	// execute stop/continue depending on new mode
	if( seq_pause )
	  SEQ_BPM_Stop();         // stop sequencer
	else
	  SEQ_BPM_Cont();         // continue sequencer
	break;

      case 5: // "F" switches to next file
	MIOS32_MIDI_SendDebugMessage("Next File\n");
	SEQ_PlayFileReq(1);
	break;
    }
  }
}
Exemplo n.º 3
0
/////////////////////////////////////////////////////////////////////////////
//! To control the play button function
/////////////////////////////////////////////////////////////////////////////
s32 MBNG_SEQ_PlayButton(void)
{
  // if in auto mode and BPM generator is not clocked in slave mode:
  // change to master mode
  SEQ_BPM_CheckAutoMaster();

  if( MBNG_SEQ_PauseEnabled() ) {
    // continue sequencer
    MBNG_SEQ_SetPauseMode(0);
    SEQ_BPM_Cont();
  } else {
    // reset sequencer
    MBNG_SEQ_Reset();

    // and start
    SEQ_BPM_Start();
  }

  return 0; // no error
}
Exemplo n.º 4
0
/////////////////////////////////////////////////////////////////////////////
// Plays the first .mid file if next == 0, the next file if next != 0
/////////////////////////////////////////////////////////////////////////////
static s32 SEQ_PlayFile(u32 next)
{
  // play off events before loading new file
  SEQ_PlayOffEvents();

  char next_file[13];
  if( MID_FILE_FindNext(next ? MID_FILE_UI_NameGet() : NULL, next_file) == 1 ||
      MID_FILE_FindNext(NULL, next_file) == 1 ) { // if next file not found, try first file
#if DEBUG_VERBOSE_LEVEL >= 1
    DEBUG_MSG("[SEQ] next file found '%s'\n", next_file);
#endif
    SEQ_BPM_Stop();                  // stop BPM generator
    if( MID_FILE_open(next_file) ) { // try to open next file
#if DEBUG_VERBOSE_LEVEL >= 1
      DEBUG_MSG("[SEQ] file %s cannot be opened (wrong directory?)\n", next_file);
#endif
      return -1; // file cannot be opened
    }
    if( MID_PARSER_Read() < 0 ) { // read file, stop on failure
#if DEBUG_VERBOSE_LEVEL >= 1
      DEBUG_MSG("[SEQ] file %s is invalid!\n", next_file);
#endif
      return -2; // file is invalid
    } 
    SEQ_BPM_Start();          // start BPM generator
  } else {
    SEQ_BPM_Stop();           // stop BPM generator

#if DEBUG_VERBOSE_LEVEL >= 1
    DEBUG_MSG("[SEQ] no file found\n");
#endif
    return -1; // file not found
  }

  return 0; // no error
}
Exemplo n.º 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
}
Exemplo n.º 6
0
void MClock_User_Start(void) {
    SEQ_BPM_Start();
}
Exemplo n.º 7
0
/////////////////////////////////////////////////////////////////////////////
// This task is called periodically each mS to handle sequencer requests
/////////////////////////////////////////////////////////////////////////////
static void TASK_SEQ(void *pvParameters)
{
  portTickType xLastExecutionTime;
  u16 sdcard_check_ctr = 0;

  // Initialise the xLastExecutionTime variable on task entry
  xLastExecutionTime = xTaskGetTickCount();

  while( 1 ) {
    vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS);

    // execute sequencer handler
    SEQ_Handler();

    // send timestamped MIDI events
    SEQ_MIDI_OUT_Handler();

    // each second: check if SD Card (still) available
    if( ++sdcard_check_ctr >= 1000 ) {
      sdcard_check_ctr = 0;

      // use a mutex if multiple tasks access the SD Card!
      MUTEX_SDCARD_TAKE;
      s32 status = FILE_CheckSDCard();

      if( status == 1 ) {
	MIOS32_MIDI_SendDebugMessage("SD Card connected: %s\n", FILE_VolumeLabel());
      } else if( status == 2 ) {
	MIOS32_MIDI_SendDebugMessage("SD Card disconnected\n");

	// stop sequencer
	SEQ_BPM_Stop();

	// change filename
	sprintf(MID_FILE_UI_NameGet(), "No SD Card");
      } else if( status == 3 ) {
	if( !FILE_SDCardAvailable() ) {
	  MIOS32_MIDI_SendDebugMessage("SD Card not found\n");
	  // change filename
	  sprintf(MID_FILE_UI_NameGet(), "No SD Card");
	} else if( !FILE_VolumeAvailable() ) {
	  MIOS32_MIDI_SendDebugMessage("ERROR: SD Card contains invalid FAT!\n");
	  MIOS32_BOARD_LED_Set(0x1, 0x0); // turn off LED
	  // change filename
	  sprintf(MID_FILE_UI_NameGet(), "No FAT");
	  // stop sequencer
	  SEQ_BPM_Stop();
	} else {
	  // change filename
	  sprintf(MID_FILE_UI_NameGet(), "SDCard found");
	  // if in auto mode and BPM generator is clocked in slave mode:
	  // change to master mode
	  SEQ_BPM_CheckAutoMaster();
	  // reset sequencer
	  SEQ_Reset(1);
	  // request to play the first file
	  SEQ_PlayFileReq(0);
	  // start sequencer
	  SEQ_BPM_Start();
	}
      }
      MUTEX_SDCARD_GIVE;
    }
  }
}