Пример #1
0
static double get_num_beats(const struct SeqTrack *seqtrack, const struct SeqBlock *seqblock, LPB_Iterator *iterator, int audioframes_to_add, const char *from_where, bool *curr_num_beats_is_valid){
  struct Blocks *block = seqblock->block;

  double time = seqtrack->start_time - seqblock->time;

#if DEBUG_BUGS
  R_ASSERT_NON_RELEASE(time > -(RADIUM_BLOCKSIZE*ATOMIC_DOUBLE_GET(block->reltempo)));
#endif
  
  if (time < 0) // Happens when switching between two seqblocks at a non-audio block alignment (i.e. delta time > 0). To avoid this minor inaccuracy, it seems necessary to break the use of constant 64 frame audio block sizes, so it's probably not worth it.
    time = 0;
  
  double time_to_add = (double)audioframes_to_add * ATOMIC_DOUBLE_GET(block->reltempo);

#if DEBUG_BUGS
  printf("Get num_beats. from_where: %s, time: %f, time_to_add: %f, pc->start_time_f: %f, stime2place: %f\n",
         from_where,
         time,
         time_to_add,
         ATOMIC_DOUBLE_GET(seqtrack->start_time_f),
         STime2Place_f(block, time+time_to_add)
         );
#endif

  if (time+time_to_add > getBlockSTimeLength(block)) // can happen when switching block
    *curr_num_beats_is_valid = false;
  
  return
    iterator->num_beats_played_so_far +
    scale_double(STime2Place_f(block, time+time_to_add),
                 iterator->place1_f, iterator->place2_f,
                 0.0, iterator->num_beats_between_place1_and_place2
                 );
}
Пример #2
0
double RT_LPB_get_current_BPM(const struct SeqTrack *seqtrack){
  if (ATOMIC_GET(is_starting_up))
    return 120.0;
  
  else if (is_playing())
    return seqtrack->lpb_iterator.curr_bpm;
  
  else {
    struct Blocks *block = ATOMIC_GET(g_curr_block);
    
    if (block==NULL)
      return (double)root->tempo;
    else
      return (double)root->tempo * ATOMIC_DOUBLE_GET(block->reltempo);
  }

}
Пример #3
0
void PlayerTask(double reltime){

  
        if (ATOMIC_GET(is_starting_up))
          return;


        
        pc->reltime     = reltime;


        
        Player_State player_state = ATOMIC_GET(pc->player_state);


        
        if (player_state==PLAYER_STATE_PROGRAM_NOT_READY){
          //printf("player: program not ready\n");
          return;

        } else if (player_state==PLAYER_STATE_ENDING) {
          return;

        } else if (player_state==PLAYER_STATE_STOPPING) {
          //PC_ReturnElements();

          g_time_was_stopped = true;

          SCHEDULER_reset_all_timing();

          if (SCHEDULER_clear_all()) {
            ATOMIC_SET(pc->player_state, PLAYER_STATE_STOPPED);  // Finished. SCHEDULER_clear() cleared everything.
            //RT_BACKUP_reset_timer(); // Don't want to take backup right after stopping to play. It's quite annoying. (we handle this directly in Qt_AutoBackups instead)
            
            player_state = PLAYER_STATE_STOPPED;
            
          } else            
            return; // Must run SCHEDULER_clear() at least one more time. We don't want clear too much at once since it could cause CPU spikes.
          
          //} else if (player_state==PLAYER_STATE_STOPPED) {
          //  return;
        }

        
        
        R_ASSERT(player_state==PLAYER_STATE_STARTING_TO_PLAY || player_state==PLAYER_STATE_PLAYING || player_state==PLAYER_STATE_STOPPED);

        
        if (player_state != PLAYER_STATE_STOPPED)
          if(g_time_was_stopped){
            OS_InitMidiTiming();
            OS_InitAudioTiming();
            g_time_was_stopped = false;
          }


        bool is_finished = true;
        

        
        ALL_SEQTRACKS_FOR_EACH(){

            double reltempo = 1.0;

            struct SeqBlock *curr_seqblock = seqtrack->curr_seqblock;
            struct Blocks *block = curr_seqblock==NULL ? NULL : curr_seqblock->block;
            
            if(block!=NULL)
              reltempo = ATOMIC_DOUBLE_GET(block->reltempo);
            
            double seqreltime  = (double)reltime * reltempo;

            //if(reltempo!=1.0)
            //  printf("Curr_seqblock: %p. seqrelteim: %f\n", curr_seqblock,seqreltime);
                   
            pc->is_treating_editor_events = true; {
              
              if (SCHEDULER_called_per_block(seqtrack, seqreltime) > 0)
                is_finished = false;
              
            } pc->is_treating_editor_events = false;
          

            if (player_state != PLAYER_STATE_STOPPED){

              if (curr_seqblock != NULL) {
                
                bool set_player_time = false;

                if (pc->playtype==PLAYBLOCK && seqtrack==&root->song->block_seqtrack)
                  set_player_time = true;

                else if (pc->playtype==PLAYSONG && seqtrack==root->song->seqtracks.elements[root->song->curr_seqtracknum])
                  set_player_time = true;
                  
                if (set_player_time)
                  ATOMIC_DOUBLE_SET(block->player_time, seqtrack->start_time - curr_seqblock->time);
                //else ATOMIC_DOUBLE_SET(block->player_time, -100); // Not necessary (-100 is set in scheduler_seqtrack.c when switching block), and we also need to check if we are playing block, etc.
              }
              
            }
          
        }END_ALL_SEQTRACKS_FOR_EACH;

        
        
        if (player_state==PLAYER_STATE_STOPPED)
          return;        

        pc->absabstime += RADIUM_BLOCKSIZE;
        
        if(pc->playtype==PLAYSONG) {
          double song_abstime = ATOMIC_DOUBLE_GET(pc->song_abstime);
          double new_song_abstime = song_abstime + reltime;
          ATOMIC_DOUBLE_SET(pc->song_abstime, new_song_abstime);

        }
        
#ifdef WITH_PD
        RT_PD_set_absolute_time(ATOMIC_DOUBLE_GET(pc->song_abstime));
#endif

        
        if (player_state == PLAYER_STATE_STARTING_TO_PLAY)
          ATOMIC_SET(pc->player_state, PLAYER_STATE_PLAYING);

        
        //printf("num_scheduled: %d. state: %d\n",num_scheduled_events,player_state);
        if(player_state == PLAYER_STATE_PLAYING && is_finished)
          ATOMIC_SET(pc->player_state, PLAYER_STATE_STOPPING);

        if(pc->playtype==PLAYSONG){
          if (SEQUENCER_is_looping()){
            if (ATOMIC_DOUBLE_GET(pc->song_abstime) >= SEQUENCER_get_loop_end()){
              ATOMIC_SET(pc->player_state, PLAYER_STATE_STOPPING);
            }
          }
        }
}