⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 playmidi.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 3 页
字号:
	voice[i].velocity=e->b;	recompute_amp(i);	apply_envelope_to_amp(i);	return;      }}static void adjust_panning(int c){  int i=voices;  while (i--)    if ((voice[i].channel==c) &&	(voice[i].status==VOICE_ON || voice[i].status==VOICE_SUSTAINED))      {	if (voice[i].clone_type != NOT_CLONE) continue;	voice[i].panning=channel[c].panning;	recompute_amp(i);	apply_envelope_to_amp(i);      }}static void drop_sustain(int c){  int i=voices;  while (i--)    if (voice[i].status==VOICE_SUSTAINED && voice[i].channel==c)      finish_note(i);}static void adjust_pitchbend(int c){  int i=voices;  while (i--)    if (voice[i].status!=VOICE_FREE && voice[i].channel==c)      {	recompute_freq(i);      }}static void adjust_volume(int c){  int i=voices;  while (i--)    if (voice[i].channel==c &&	(voice[i].status==VOICE_ON || voice[i].status==VOICE_SUSTAINED))      {	recompute_amp(i);	apply_envelope_to_amp(i);      }}static void seek_forward(int32 until_time){  reset_voices();  while (current_event->time < until_time)    {      switch(current_event->type)	{	  /* All notes stay off. Just handle the parameter changes. */	case ME_PITCH_SENS:	  channel[current_event->channel].pitchsens=	    current_event->a;	  channel[current_event->channel].pitchfactor=0;	  break;	  	case ME_PITCHWHEEL:	  channel[current_event->channel].pitchbend=	    current_event->a + current_event->b * 128;	  channel[current_event->channel].pitchfactor=0;	  break;	  	case ME_MAINVOLUME:	  channel[current_event->channel].volume=current_event->a;	  break;	  	case ME_MASTERVOLUME:	  adjust_master_volume(current_event->a + (current_event->b <<7));	  break;	  	case ME_PAN:	  channel[current_event->channel].panning=current_event->a;	  break;	      	case ME_EXPRESSION:	  channel[current_event->channel].expression=current_event->a;	  break;	  	case ME_PROGRAM:	  /* if (ISDRUMCHANNEL(current_event->channel)) */	  if (channel[current_event->channel].kit)	    /* Change drum set */	    channel[current_event->channel].bank=current_event->a;	  else	    channel[current_event->channel].program=current_event->a;	  break;	case ME_SUSTAIN:	  channel[current_event->channel].sustain=current_event->a;	  break;	case ME_REVERBERATION:	  channel[current_event->channel].reverberation=current_event->a;	  break;	case ME_CHORUSDEPTH:	  channel[current_event->channel].chorusdepth=current_event->a;	  break;	case ME_HARMONICCONTENT:	  channel[current_event->channel].harmoniccontent=current_event->a;	  break;	case ME_RELEASETIME:	  channel[current_event->channel].releasetime=current_event->a;	  break;	case ME_ATTACKTIME:	  channel[current_event->channel].attacktime=current_event->a;	  break;	case ME_BRIGHTNESS:	  channel[current_event->channel].brightness=current_event->a;	  break;	case ME_TONE_KIT:	  if (current_event->a==SFX_BANKTYPE)		{		    channel[current_event->channel].sfx=SFXBANK;		    channel[current_event->channel].kit=0;		}	  else		{		    channel[current_event->channel].sfx=0;		    channel[current_event->channel].kit=current_event->a;		}	  break;	case ME_RESET_CONTROLLERS:	  reset_controllers(current_event->channel);	  break;	      	case ME_TONE_BANK:	  channel[current_event->channel].bank=current_event->a;	  break;	  	case ME_EOT:	  current_sample=current_event->time;	  return;	}      current_event++;    }  /*current_sample=current_event->time;*/  if (current_event != event_list)    current_event--;  current_sample=until_time;}static void skip_to(int32 until_time){  if (current_sample > until_time)    current_sample=0;  reset_midi();  buffered_count=0;  buffer_pointer=common_buffer;  current_event=event_list;    if (until_time)    seek_forward(until_time);  ctl->reset();}static int apply_controls(void){  int rc, i, did_skip=0;  int32 val;  /* ASCII renditions of CD player pictograms indicate approximate effect */  do    switch(rc=ctl->read(&val))      {      case RC_QUIT: /* [] */      case RC_LOAD_FILE:	        case RC_NEXT: /* >>| */      case RC_REALLY_PREVIOUS: /* |<< */	return rc;	      case RC_CHANGE_VOLUME:	if (val>0 || amplification > -val)	  amplification += val;	else 	  amplification=0;	if (amplification > MAX_AMPLIFICATION)	  amplification=MAX_AMPLIFICATION;	adjust_amplification();	for (i=0; i<voices; i++)	  if (voice[i].status != VOICE_FREE)	    {	      recompute_amp(i);	      apply_envelope_to_amp(i);	    }	ctl->master_volume(amplification);	break;      case RC_PREVIOUS: /* |<< */	if (current_sample < 2*play_mode->rate)	  return RC_REALLY_PREVIOUS;	return RC_RESTART;      case RC_RESTART: /* |<< */	skip_to(0);	did_skip=1;	break;	      case RC_JUMP:	if (val >= sample_count)	  return RC_NEXT;	skip_to(val);	return rc;	      case RC_FORWARD: /* >> */	if (val+current_sample >= sample_count)	  return RC_NEXT;	skip_to(val+current_sample);	did_skip=1;	break;	      case RC_BACK: /* << */	if (current_sample > val)	  skip_to(current_sample-val);	else	  skip_to(0); /* We can't seek to end of previous song. */	did_skip=1;	break;      }  while (rc!= RC_NONE);   /* Advertise the skip so that we stop computing the audio buffer */  if (did_skip)    return RC_JUMP;   else    return rc;}static void do_compute_data(uint32 count){  int i;  if (!count) return; /* (gl) */  memset(buffer_pointer, 0, count * num_ochannels * 4);  for (i=0; i<voices; i++)    {      if(voice[i].status != VOICE_FREE)	{	  if (!voice[i].sample_offset && voice[i].echo_delay_count)	    {		if ((uint32)voice[i].echo_delay_count >= count) voice[i].echo_delay_count -= count;		else		  {	            mix_voice(buffer_pointer+voice[i].echo_delay_count, i, count-voice[i].echo_delay_count);		    voice[i].echo_delay_count = 0;		  }	    }	  else mix_voice(buffer_pointer, i, count);	}    }  current_sample += count;}/* count=0 means flush remaining buffered data to output device, then   flush the device itself */static int compute_data(void *stream, int32 count){  int rc, channels;  if ( play_mode->encoding & PE_MONO )    channels = 1;  else    channels = num_ochannels;  if (!count)    {      if (buffered_count)          s32tobuf(stream, common_buffer, channels*buffered_count);      buffer_pointer=common_buffer;      buffered_count=0;      return RC_NONE;    }  while ((count+buffered_count) >= AUDIO_BUFFER_SIZE)    {      do_compute_data(AUDIO_BUFFER_SIZE-buffered_count);      count -= AUDIO_BUFFER_SIZE-buffered_count;      s32tobuf(stream, common_buffer, channels*AUDIO_BUFFER_SIZE);      buffer_pointer=common_buffer;      buffered_count=0;            ctl->current_time(current_sample);      if ((rc=apply_controls())!=RC_NONE)	return rc;    }  if (count>0)    {      do_compute_data(count);      buffered_count += count;      buffer_pointer += count * channels;    }  return RC_NONE;}int Timidity_PlaySome(void *stream, int samples){  int rc = RC_NONE;  int32 end_sample;    if ( ! midi_playing ) {    return RC_NONE;  }  end_sample = current_sample+samples;  while ( current_sample < end_sample ) {    /* Handle all events that should happen at this time */    while (current_event->time <= current_sample) {      switch(current_event->type) {        /* Effects affecting a single note */        case ME_NOTEON:	  current_event->a += channel[current_event->channel].transpose;          if (!(current_event->b)) /* Velocity 0? */            note_off(current_event);          else            note_on(current_event);          break;          case ME_NOTEOFF:	  current_event->a += channel[current_event->channel].transpose;          note_off(current_event);          break;          case ME_KEYPRESSURE:          adjust_pressure(current_event);          break;            /* Effects affecting a single channel */          case ME_PITCH_SENS:          channel[current_event->channel].pitchsens=current_event->a;          channel[current_event->channel].pitchfactor=0;          break;                  case ME_PITCHWHEEL:          channel[current_event->channel].pitchbend=            current_event->a + current_event->b * 128;          channel[current_event->channel].pitchfactor=0;          /* Adjust pitch for notes already playing */          adjust_pitchbend(current_event->channel);          ctl->pitch_bend(current_event->channel,               channel[current_event->channel].pitchbend);          break;                  case ME_MAINVOLUME:          channel[current_event->channel].volume=current_event->a;          adjust_volume(current_event->channel);          ctl->volume(current_event->channel, current_event->a);          break;	case ME_MASTERVOLUME:	  adjust_master_volume(current_event->a + (current_event->b <<7));	  break;	      	case ME_REVERBERATION:	  channel[current_event->channel].reverberation=current_event->a;	  break;	case ME_CHORUSDEPTH:	  channel[current_event->channel].chorusdepth=current_event->a;	  break;        case ME_PAN:          channel[current_event->channel].panning=current_event->a;          if (adjust_panning_immediately)            adjust_panning(current_event->channel);          ctl->panning(current_event->channel, current_event->a);          break;                  case ME_EXPRESSION:          channel[current_event->channel].expression=current_event->a;          adjust_volume(current_event->channel);          ctl->expression(current_event->channel, current_event->a);          break;          case ME_PROGRAM:          /* if (ISDRUMCHANNEL(current_event->channel)) { */	  if (channel[current_event->channel].kit) {            /* Change drum set */            channel[current_event->channel].bank=current_event->a;          }          else          {            channel[current_event->channel].program=current_event->a;          }          ctl->program(current_event->channel, current_event->a);          break;          case ME_SUSTAIN:          channel[current_event->channel].sustain=current_event->a;          if (!current_event->a)            drop_sustain(current_event->channel);          ctl->sustain(current_event->channel, current_event->a);          break;                  case ME_RESET_CONTROLLERS:          reset_controllers(current_event->channel);          redraw_controllers(current_event->channel);          break;          case ME_ALL_NOTES_OFF:          all_notes_off(current_event->channel);          break;                  case ME_ALL_SOUNDS_OFF:          all_sounds_off(current_event->channel);          break;	case ME_HARMONICCONTENT:	  channel[current_event->channel].harmoniccontent=current_event->a;	  break;	case ME_RELEASETIME:	  channel[current_event->channel].releasetime=current_event->a;	  break;	case ME_ATTACKTIME:	  channel[current_event->channel].attacktime=current_event->a;	  break;	case ME_BRIGHTNESS:	  channel[current_event->channel].brightness=current_event->a;	  break;        case ME_TONE_BANK:          channel[current_event->channel].bank=current_event->a;          break;	case ME_TONE_KIT:	  if (current_event->a==SFX_BANKTYPE)	  {	    channel[current_event->channel].sfx=SFXBANK;	    channel[current_event->channel].kit=0;	  }	  else	  {	    channel[current_event->channel].sfx=0;	    channel[current_event->channel].kit=current_event->a;	  }	  break;        case ME_EOT:          /* Give the last notes a couple of seconds to decay  */          ctl->cmsg(CMSG_INFO, VERB_VERBOSE,            "Playing time: ~%d seconds", current_sample/play_mode->rate+2);          ctl->cmsg(CMSG_INFO, VERB_VERBOSE,            "Notes cut: %d", cut_notes);          ctl->cmsg(CMSG_INFO, VERB_VERBOSE,          "Notes lost totally: %d", lost_notes);          midi_playing = 0;          return RC_TUNE_END;        }      current_event++;    }    if (current_event->time > end_sample)      rc=compute_data(stream, end_sample-current_sample);    else      rc=compute_data(stream, current_event->time-current_sample);    ctl->refresh();    if ( (rc!=RC_NONE) && (rc!=RC_JUMP))      break;  }  return rc;}void Timidity_SetVolume(int volume){  int i;  if (volume > MAX_AMPLIFICATION)    amplification=MAX_AMPLIFICATION;  else  if (volume < 0)    amplification=0;  else    amplification=volume;  adjust_amplification();  for (i=0; i<voices; i++)    if (voice[i].status != VOICE_FREE)      {        recompute_amp(i);        apply_envelope_to_amp(i);      }  ctl->master_volume(amplification);}MidiSong *Timidity_LoadSong(char *midifile){  MidiSong *song;  int32 events;  SDL_RWops *rw;  /* Allocate memory for the song */  song = (MidiSong *)safe_malloc(sizeof(*song));  memset(song, 0, sizeof(*song));  /* Open the file */  strcpy(midi_name, midifile);  rw = SDL_RWFromFile(midifile, "rb");  if ( rw != NULL ) {    song->events=read_midi_file(rw, &events, &song->samples);    SDL_RWclose(rw);  }  /* Make sure everything is okay */  if (!song->events) {    free(song);    song = NULL;  }  return(song);}MidiSong *Timidity_LoadSong_RW(SDL_RWops *rw){  MidiSong *song;  int32 events;  /* Allocate memory for the song */  song = (MidiSong *)safe_malloc(sizeof(*song));  memset(song, 0, sizeof(*song));  strcpy(midi_name, "SDLrwops source");  song->events=read_midi_file(rw, &events, &song->samples);  /* Make sure everything is okay */  if (!song->events) {    free(song);    song = NULL;  }  return(song);}void Timidity_Start(MidiSong *song){  load_missing_instruments();  adjust_amplification();  sample_count = song->samples;  event_list = song->events;  lost_notes=cut_notes=0;  skip_to(0);  midi_playing = 1;}int Timidity_Active(void){	return(midi_playing);}void Timidity_Stop(void){  midi_playing = 0;}void Timidity_FreeSong(MidiSong *song){  if (free_instruments_afterwards)    free_instruments();    free(song->events);  free(song);}void Timidity_Close(void){  if (resample_buffer) {    free(resample_buffer);    resample_buffer=NULL;  }  if (common_buffer) {    free(common_buffer);    common_buffer=NULL;  }  free_instruments();  free_pathlist();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -