Click here to Skip to main content
15,887,135 members

Welcome to the Lounge

   

For discussing anything related to a software developer's life but is not for programming questions. Got a programming question?

The Lounge is rated Safe For Work. If you're about to post something inappropriate for a shared office environment, then don't post it. No ads, no abuse, and no programming questions. Trolling, (political, climate, religious or whatever) will result in your account being removed.

 
GeneralOi! Greg Utas! Pin
OriginalGriff4-May-22 23:49
mveOriginalGriff4-May-22 23:49 
JokeRe: Oi! Greg Utas! Pin
Peter_in_27805-May-22 1:05
professionalPeter_in_27805-May-22 1:05 
GeneralRevenge of the 5th Pin
Jacquers4-May-22 19:03
Jacquers4-May-22 19:03 
GeneralHow did they do it? PinPopular
honey the codewitch4-May-22 18:37
mvahoney the codewitch4-May-22 18:37 
GeneralRe: How did they do it? Pin
David O'Neil4-May-22 18:59
professionalDavid O'Neil4-May-22 18:59 
GeneralRe: How did they do it? Pin
honey the codewitch4-May-22 19:03
mvahoney the codewitch4-May-22 19:03 
GeneralRe: How did they do it? Pin
Kirk 103898216-May-22 4:36
Kirk 103898216-May-22 4:36 
GeneralRe: How did they do it? Pin
honey the codewitch6-May-22 6:31
mvahoney the codewitch6-May-22 6:31 
Kirk 10389821 wrote:
Finally, your problem reminds me of a Computer Engineering Class, where we built circuits that were run through a simulator. The simulator used a queue design, where "events" would trigger through the queue, and the simulator was able to be fast, because it ignored the timing signals, allowing it to "not wait" any time before processing an item. (I got in trouble in the class, because I wrote obscenely inefficient but SIMPLE code, reducing the homework to a TRIVIAL problem, avoiding the timing issues others were busy coding around).

anyways, I could envision a queue that is managing N queues of inputs, and only when you take off an item, do you go to the stream to pull in another item.


You're describing the problem pretty well, which I actually solved last night. I won't paste the implementation here, but here is using it with a queue q

Forgive the grotty code. It's just test stuff I've been banging on

C++
#ifndef ARDUINO
#include <sfx_midi_file.hpp>
#include <sfx_midi_clock.hpp>
#include <sfx_midi_utility.hpp>
#include <queue>
#include <stdio.h>
#include <math.h>
using namespace sfx;

void dump_midi(stream* stm, const midi_file& file) {
  printf("Type: %d\nTimebase: %d\n",(int)file.type,(int)file.timebase);
  printf("Tracks: %d\n",(int)file.tracks_size);
  for(int i = 0;i<(int)file.tracks_size;++i) {
    printf("\tOffset: %d, Size: %d, Preview: ",(int)file.tracks[i].offset,(int)file.tracks[i].size);
    stm->seek(file.tracks[i].offset);
    uint8_t buf[16];
    size_t tsz = file.tracks[i].size;
    size_t sz=stm->read(buf,tsz<16?tsz:16);
    for(int j = 0;j<sz;++j) {
      printf("%02x",(int)buf[j]);
    }
    printf("\n");
  }
}
void dump_midi(const midi_message& msg) {
  switch(msg.type()) {
  case midi_message_type::note_off:
    printf("Note Off: %d, %d\n",(int)msg.lsb(),(int)msg.msb());
    break;
  case midi_message_type::note_on:
    printf("Note On: %d, %d\n",(int)msg.lsb(),(int)msg.msb());
    break;
  case midi_message_type::polyphonic_pressure:
    printf("Poly pressure: %d, %d\n",(int)msg.lsb(),(int)msg.msb());
    break;
  case midi_message_type::control_change:
    printf("Control change: %d, %d\n",(int)msg.lsb(),(int)msg.msb());
    break;
  case midi_message_type::pitch_wheel_change:
    printf("Pitch wheel change: %d, %d\n",(int)msg.lsb(),(int)msg.msb());
    break;
  case midi_message_type::song_position:
    printf("Song position: %d, %d\n",(int)msg.lsb(),(int)msg.msb());
    break;
  case midi_message_type::program_change:
    printf("Program change: %d\n",(int)msg.value8);
    break;
  case midi_message_type::channel_pressure:
    printf("Channel pressure: %d\n",(int)msg.value8);
    break;
  case midi_message_type::song_select:
    printf("Song select: %d\n",(int)msg.value8);
    break;
  case midi_message_type::system_exclusive:
    printf("Systex data: Size of %d\n",(int)msg.sysex.size);
    break;
  case midi_message_type::reset:
    if(msg.meta.data==nullptr) {
      printf("Reset\n");
    
    } else {
        int32_t result;
        const uint8_t* p=midi_utility::decode_varlen(msg.meta.encoded_length,&result);
        if(p!=nullptr) {
            printf("Meta message: Type of %02x, Size of %d\n",(int)msg.meta.type, (int)result);
        } else {
          printf("Error reading message\n");
        }
    }
    break;
  case midi_message_type::end_system_exclusive:
    printf("End sysex\n");
    break;
  case midi_message_type::active_sensing:
    printf("Active sensing\n");
    break;
  case midi_message_type::start_playback:
    printf("Start playback\n");
    break;
  case midi_message_type::stop_playback:
    printf("Stop playback\n");
    break;
  case midi_message_type::tune_request:
    printf("Tune request\n");
    break;
  case midi_message_type::timing_clock:
    printf("Timing clock\n");
    break;
  default:
    printf("Illegal message: %02x\n",(int)msg.status);
    while(true);
  }
}
using midi_queue = std::queue<midi_stream_event>;
int main(int argc, char** argv) {
  
  midi_clock mclock;
  
  static const char* def = "data\\sonata.mid";
  const char* sz;
  if(argc<2) {
    //printf("Too few arguments. Must have at least 1.\n");
    //return (int)sfx_result::invalid_argument;
    sz = def;
  } else {
    sz=argv[1];
  }
  file_stream fstm(sz);
  midi_file f;
  midi_queue q;
  sfx_result r=midi_file::read(&fstm,&f);
  if(sfx_result::success!=r) {
    printf("Error opening file: %d\n",(int)r);
    return (int)r;
  }
  dump_midi(&fstm,f);
  fstm.seek(0);
  midi_file_source msrc;
  struct mstate {
    midi_clock* clock;
    midi_queue* queue;
    midi_file_source* source;
  };
  midi_stream_event* queue = (midi_stream_event*)calloc(4,sizeof(midi_stream_event));
  if(queue==nullptr) {
    printf("out of memory");
    return (int)sfx_result::out_of_memory;
  }
  mstate st;
  st.clock = &mclock;
  st.queue = &q;
  mclock.tick_callback([](uint32_t pending,unsigned long long elapsed,void* state){
    mstate st=*(mstate*)state;
    
    while(true) {
      if(st.queue->size()) {
        const midi_stream_event& event=st.queue->front();
      
        bool first = true;
        if(event.absolute<=elapsed) {
          if(event.message.type()==midi_message_type::meta_event && event.message.meta.type==0x51) {
            int32_t mt = (event.message.meta.data[0] << 16) | (event.message.meta.data[1] << 8) | event.message.meta.data[2];
            printf("Set tempo to %f\n",midi_utility::microtempo_to_tempo(mt));
            st.clock->microtempo(mt);
          }
          printf("delta: %lli - ",(long long)event.delta);
          dump_midi(event.message);
          event.message.~midi_message();
          st.queue->pop();
        } else {
          break;
        }
      } else {
      break; 
      }
    
    }
  },&st);
  r = midi_file_source::open(&fstm,&msrc);
  if(sfx_result::success!=r) {
    printf("Error opening file: %d\n",(int)r);
    return (int)r;
  }

  mclock.timebase(msrc.file().timebase);
  mclock.start();
  while(true) {
    midi_event e;
    if(q.size()>=16) {
      mclock.update();
      continue;
    }
    sfx_result r=msrc.receive(&e);
    if(r!=sfx_result::success) {
      if(r==sfx_result::end_of_stream) {
        mclock.update();
        if(!q.size()) {
          printf("Exiting\n");
          break;
        }
        continue;
      } else {
        printf("Error receiving message: %d\n",(int)r);
      }
      printf("Exiting\n");
      break;
    } else {
      q.push({(unsigned long long)msrc.elapsed(),e.delta,e.message});
      printf("queue size: %d\n",(int)q.size());
      mclock.update();
    }
  }
}

#endif

To err is human. Fortune favors the monsters.

GeneralRe: How did they do it? Pin
Peter_in_27804-May-22 19:11
professionalPeter_in_27804-May-22 19:11 
GeneralRe: How did they do it? Pin
honey the codewitch5-May-22 15:19
mvahoney the codewitch5-May-22 15:19 
GeneralRe: How did they do it? Pin
User 4909744-May-22 22:36
User 4909744-May-22 22:36 
GeneralRe: How did they do it? Pin
CPallini5-May-22 2:50
mveCPallini5-May-22 2:50 
GeneralRe: How did they do it? Pin
Wizard of Sleeves5-May-22 20:51
Wizard of Sleeves5-May-22 20:51 
GeneralRe: How did they do it? Pin
honey the codewitch6-May-22 1:57
mvahoney the codewitch6-May-22 1:57 
GeneralRe: How did they do it? Pin
Dougy835-May-22 21:18
Dougy835-May-22 21:18 
GeneralRe: How did they do it? Pin
honey the codewitch6-May-22 1:18
mvahoney the codewitch6-May-22 1:18 
GeneralRe: How did they do it? Pin
Dougy836-May-22 1:48
Dougy836-May-22 1:48 
GeneralRe: How did they do it? Pin
honey the codewitch6-May-22 1:55
mvahoney the codewitch6-May-22 1:55 
GeneralRe: How did they do it? Pin
Dougy836-May-22 1:57
Dougy836-May-22 1:57 
GeneralRe: How did they do it? Pin
Dougy836-May-22 1:56
Dougy836-May-22 1:56 
GeneralRe: How did they do it? Pin
Cpichols6-May-22 1:49
Cpichols6-May-22 1:49 
GeneralRe: How did they do it? Pin
honey the codewitch6-May-22 1:58
mvahoney the codewitch6-May-22 1:58 
GeneralRe: How did they do it? Pin
Gary Wheeler6-May-22 2:02
Gary Wheeler6-May-22 2:02 
GeneralRe: How did they do it? Pin
honey the codewitch6-May-22 2:44
mvahoney the codewitch6-May-22 2:44 
GeneralRe: How did they do it? Pin
Gary Wheeler6-May-22 2:48
Gary Wheeler6-May-22 2:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.