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

📄 playmidi.c

📁 play midi good
💻 C
📖 第 1 页 / 共 5 页
字号:
  voice[i].vid=vid;

  voice[i].tremolo_phase=0;
  voice[i].tremolo_phase_increment=voice[i].sample->tremolo_phase_increment;
  voice[i].tremolo_sweep=voice[i].sample->tremolo_sweep_increment;
  voice[i].tremolo_sweep_position=0;

  voice[i].vibrato_sweep=voice[i].sample->vibrato_sweep_increment;
  voice[i].vibrato_sweep_position=0;

  if(opt_nrpn_vibrato &&
     channel[ch].vibrato_ratio && voice[i].vibrato_depth > 0)
  {
      voice[i].vibrato_control_ratio = channel[ch].vibrato_ratio;
      voice[i].vibrato_depth = channel[ch].vibrato_depth;
      voice[i].vibrato_delay = channel[ch].vibrato_delay;
  }
  else
  {
      voice[i].vibrato_control_ratio = voice[i].sample->vibrato_control_ratio;
      voice[i].vibrato_depth = voice[i].sample->vibrato_depth;
      voice[i].vibrato_delay = 0;
  }
  voice[i].orig_vibrato_control_ratio = voice[i].sample->vibrato_control_ratio;

  voice[i].vibrato_control_counter=voice[i].vibrato_phase=0;
  for (j=0; j<VIBRATO_SAMPLE_INCREMENTS; j++)
    voice[i].vibrato_sample_increment[j]=0;

  /* Pan */
  if(channel[ch].panning != NO_PANNING) pan = channel[ch].panning;
  else pan = 64;
  if(ISDRUMCHANNEL(ch) &&
     channel[ch].drums[note] != NULL &&
     channel[ch].drums[note]->drum_panning != NO_PANNING)
      pan += channel[ch].drums[note]->drum_panning - 64;
  else
      pan += voice[i].sample->panning - 64;
  if (pan > 127) pan = 127;
  if (pan < 0) pan = 0;
  voice[i].panning = pan;

  voice[i].porta_control_counter = 0;
  if(channel[ch].portamento && !channel[ch].porta_control_ratio)
      update_portamento_controls(ch);
  if(channel[ch].porta_control_ratio)
  {
      if(channel[ch].last_note_fine == -1)
      {
	  /* first on */
	  channel[ch].last_note_fine = voice[i].note * 256;
	  channel[ch].porta_control_ratio = 0;
      }
      else
      {
	  voice[i].porta_control_ratio = channel[ch].porta_control_ratio;
	  voice[i].porta_dpb = channel[ch].porta_dpb;
	  voice[i].porta_pb = channel[ch].last_note_fine -
	      voice[i].note * 256;
	  if(voice[i].porta_pb == 0)
	      voice[i].porta_control_ratio = 0;
      }
  }

  if(cnt == 0)
      channel[ch].last_note_fine = voice[i].note * 256;

  recompute_freq(i);
  recompute_amp(i);
  if (voice[i].sample->modes & MODES_ENVELOPE)
    {
      /* Ramp up from 0 */
      voice[i].envelope_stage=0;
      voice[i].envelope_volume=0;
      voice[i].control_counter=0;
      recompute_envelope(i);
      apply_envelope_to_amp(i);
    }
  else
    {
      voice[i].envelope_increment=0;
      apply_envelope_to_amp(i);
    }

  voice[i].timeout = -1;
  if(!prescanning_flag)
      ctl_note_event(i);
}

static void finish_note(int i)
{
    if (voice[i].sample->modes & MODES_ENVELOPE)
    {
	/* We need to get the envelope out of Sustain stage. */
	/* Note that voice[i].envelope_stage < 3 */
	voice[i].status=VOICE_OFF;
	voice[i].envelope_stage=3;
	recompute_envelope(i);
	apply_envelope_to_amp(i);
	ctl_note_event(i);
    }
    else
    {
	if(current_file_info->pcm_mode != PCM_MODE_NON)
	{
	    free_voice(i);
	    ctl_note_event(i);
	}
	else
	{
	    /* Set status to OFF so resample_voice() will let this voice out
		of its loop, if any. In any case, this voice dies when it
		    hits the end of its data (ofs>=data_length). */
	    if(voice[i].status != VOICE_OFF)
	    {
		voice[i].status = VOICE_OFF;
		ctl_note_event(i);
	    }
	}
    }
}

static void set_envelope_time(int ch,int val,int stage)
{
	val = val & 0x7F;
	if(play_system_mode != GS_SYSTEM_MODE) {
		val = val / 2 + 32;
	}
	val -= 64;
	if(channel[ch].mapID == SC_55_TONE_MAP) {
		val *= 1.23;
		if(val > 63) {val = 63;}
		else if(val < -64) {val = -64;}
	}
	switch(stage) {
	case 0:	// Attack
		ctl->cmsg(CMSG_INFO,VERB_NOISY,"Attack Time (CH:%d VALUE:%d)",ch,val);
		break;
	case 1: // Decay
		ctl->cmsg(CMSG_INFO,VERB_NOISY,"Decay Time (CH:%d VALUE:%d)",ch,val);
		break;
	case 3:	// Release
		ctl->cmsg(CMSG_INFO,VERB_NOISY,"Release Time (CH:%d VALUE:%d)",ch,val);
		break;
	default:
		ctl->cmsg(CMSG_INFO,VERB_NOISY,"? Time (CH:%d VALUE:%d)",ch,val);
	}
	channel[ch].envelope_rate[stage] = val;
}

static void new_flanger_voice(int v1, int level1,int level2)
{
    int v2,i,fb_loop,level,ch,pan;
	double delay,width;
	int32 orig_frequency;

	ch = voice[v1].channel;
	fb_loop = abs(level2) / 16;
	level = (level2 + 64) >> 2;
	level1 += rand() % 64 - 32;
	width = 1.0 - level1 * 0.01;

	delay = 0;
	if((v2 = find_free_voice()) == -1) {return;}
	delay += width;
	voice[v2] = voice[v1];	/* copy all parameters */
	voice[v2].delay += (int)(play_mode->rate * delay / 1000);
	pan = rand() % 8 - 4;
	voice[v2].panning += pan;
	orig_frequency = voice[v1].orig_frequency;
	orig_frequency *= bend_fine[level];
	voice[v2].orig_frequency = orig_frequency;
	voice[v2].cache = NULL;
	recompute_amp(v2);
	apply_envelope_to_amp(v2);
	recompute_freq(v2);
	for(i=0;i<fb_loop;i++) {
		delay += width;
		if((v2 = find_free_voice()) == -1) {return;}
		voice[v2] = voice[v1];
		voice[v2].delay += (int)(play_mode->rate * delay / 1000);
		pan = rand() % 8 - 4;
		voice[v2].panning += pan;
		orig_frequency *= bend_fine[level];
		voice[v2].orig_frequency = orig_frequency;
		voice[v2].cache = NULL;
		recompute_amp(v2);
		apply_envelope_to_amp(v2);
		recompute_freq(v2);
	}
}


static void new_delay_voice(int v1, int level)
{
    int v2,i,fb_loop,ch=voice[v1].channel;
	int32 orig_frequency;
	double delay,vol,fb_ratio;
	uint8 pan;
	struct delay_status_t *status = get_delay_status();
	double threshold = 1.0;

	/* NRPN Delay Send Level of Drum */
	if(ISDRUMCHANNEL(ch) &&	channel[ch].drums[voice[v1].note] != NULL) {
		level *= (FLOAT_T)channel[ch].drums[voice[v1].note]->delay_level / 127.0;
	}

	fb_loop = status->fb_loop;
	fb_ratio = status->fb_ratio;

	vol = voice[v1].velocity * level * status->level_ratio_center;
	if (vol > threshold) {	/* First Delay */
		delay = 0;
		if((v2 = find_free_voice()) == -1) {return;}
		orig_frequency = voice[v1].orig_frequency;
		orig_frequency *= bend_fine[level >> 2];
		voice[v2].orig_frequency = orig_frequency;
		voice[v2].cache = NULL;
		delay += status->time_center;
		voice[v2] = voice[v1];	/* copy all parameters */
		voice[v2].velocity = (uint8)vol;
		voice[v2].delay += (int)(play_mode->rate * delay / 1000);
		recompute_amp(v2);
		apply_envelope_to_amp(v2);
		recompute_freq(v2);
		for(i=0;i<fb_loop;i++) {	/* Feedback */
			vol *= fb_ratio;
			delay += status->time_center;
			if(vol < threshold) {break;}
			if((v2 = find_free_voice()) == -1) {return;}
			orig_frequency *= bend_fine[level >> 2];
			voice[v2].orig_frequency = orig_frequency;
			voice[v2].cache = NULL;
			voice[v2] = voice[v1];	/* copy all parameters */
			voice[v2].velocity = (uint8)vol;
			voice[v2].delay += (int)(play_mode->rate * delay / 1000);
			recompute_amp(v2);
			apply_envelope_to_amp(v2);
			recompute_freq(v2);
		}
	}

	if(status->level_left) {
		vol = voice[v1].velocity * level * status->level_ratio_left;
		if (vol > threshold) {	/* First Delay */
			delay = 0;
			pan = voice[v1].panning - 64;
			if((v2 = find_free_voice()) == -1) {return;}
			orig_frequency = voice[v1].orig_frequency;
			orig_frequency *= bend_fine[level >> 2];
			voice[v2].orig_frequency = orig_frequency;
			voice[v2].cache = NULL;
			delay += status->time_left;
			voice[v2] = voice[v1];	/* copy all parameters */
			voice[v2].velocity = (uint8)vol;
			voice[v2].delay += (int)(play_mode->rate * delay / 1000);	
			voice[v2].panning = pan;
			recompute_amp(v2);
			apply_envelope_to_amp(v2);
			recompute_freq(v2);
			for(i=0;i<fb_loop;i++) {	/* Feedback */
				vol *= fb_ratio;
				delay += status->time_left;
				if(vol < threshold) {break;}
				if((v2 = find_free_voice()) == -1) {return;}
				orig_frequency *= bend_fine[level >> 2];
				voice[v2].orig_frequency = orig_frequency;
				voice[v2].cache = NULL;
				voice[v2] = voice[v1];	/* copy all parameters */
				voice[v2].velocity = (uint8)vol;
				voice[v2].delay += (int)(play_mode->rate * delay / 1000);
				voice[v2].panning = pan;
				recompute_amp(v2);
				apply_envelope_to_amp(v2);
				recompute_freq(v2);
			}
		}
	}

	if(status->level_right) {
		vol = voice[v1].velocity * level * status->level_ratio_right;
		if (vol > threshold) {	/* First Delay */
			delay = 0;
			pan = voice[v1].panning - 64;
			if((v2 = find_free_voice()) == -1) {return;}
			orig_frequency = voice[v1].orig_frequency;
			orig_frequency *= bend_fine[level >> 2];
			voice[v2].orig_frequency = orig_frequency;
			voice[v2].cache = NULL;
			delay += status->time_right;
			voice[v2] = voice[v1];	/* copy all parameters */
			voice[v2].velocity = (uint8)vol;
			voice[v2].delay += (int)(play_mode->rate * delay / 1000);	
			voice[v2].panning = pan;
			recompute_amp(v2);
			apply_envelope_to_amp(v2);
			recompute_freq(v2);
			for(i=0;i<fb_loop;i++) {	/* Feedback */
				vol *= fb_ratio;
				delay += status->time_right;
				if(vol < threshold) {break;}
				if((v2 = find_free_voice()) == -1) {return;}
				orig_frequency *= bend_fine[level >> 2];
				voice[v2].orig_frequency = orig_frequency;
				voice[v2].cache = NULL;
				voice[v2] = voice[v1];	/* copy all parameters */
				voice[v2].velocity = (uint8)vol;
				voice[v2].delay += (int)(play_mode->rate * delay / 1000);
				voice[v2].panning = pan;
				recompute_amp(v2);
				apply_envelope_to_amp(v2);
				recompute_freq(v2);
			}
		}
	}
}

static void new_chorus_voice(int v1, int level)
{
    int v2, ch;
    uint8 vol;  
    int vel;  /* sms 046.05 */
    struct chorus_status_t *status = get_chorus_status();

    if((v2 = find_free_voice()) == -1)
	return;
    ch = voice[v1].channel;
    /* sms    vol = voice[v1].velocity;  */
    vel = voice[v1].velocity;
    voice[v2] = voice[v1];	/* copy all parameters */

	/* NRPN Chorus Send Level of Drum */
	if(ISDRUMCHANNEL(ch) && channel[ch].drums[voice[v1].note] != NULL) {
		level *= (FLOAT_T)channel[ch].drums[voice[v1].note]->chorus_level / 127.0;
	}

    /* Choose lower voice index for base voice (v1) */
    if(v1 > v2)
    {
	int tmp;
	tmp = v1;
	v1 = v2;
	v2 = v1;
    }

    /* v1: Base churos voice
     * v2: Sub chorus voice (detuned)
     */
    /* sms 046.05 
    voice[v1].velocity = (uint8)(vol * CHORUS_VELOCITY_TUNING1);
    voice[v2].velocity = (uint8)(vol * CHORUS_VELOCITY_TUNING2);
    */
    vel -= CHORUS_VELOCITY_DELTA; if (vel<0) vel = 0; 
    voice[v1].velocity = voice[v2].velocity = (uint8) vel;

    /* Make doubled link v1 and v2 */
    voice[v1].chorus_link = v2;
    voice[v2].chorus_link = v1;

    level >>= 2;		     /* scale level to a "better" value */
    if(channel[ch].pitchbend + level < 0x2000)
        voice[v2].orig_frequency *= bend_fine[level];
    else
	voice[v2].orig_frequency /= bend_fine[level];

    MYCHECK(voice[v2].orig_frequency);

    voice[v2].cache = NULL;

    /* set panning & delay */
    if(!(play_mode->encoding & PE_MONO))
    {
	double delay;

	if(voice[v2].panned == PANNED_CENTER)
	{
	    voice[v2].panning = 64 + int_rand(40) - 20; /* 64 +- rand(20) */
	    delay = 0;
	}
	else
	{
	    int panning = voice[v2].panning;

	    if(panning < CHORUS_OPPOSITE_THRESHOLD)
	    {
		voice[v2].panning = 127;
		delay = DEFAULT_CHORUS_DELAY1;
	    }
	    else if(panning > 127 - CHORUS_OPPOSITE_THRESHOLD)
	    {
		voice[v2].panning = 0;
		delay = DEFAULT_CHORUS_DELAY1;
	    }
	    else
	    {
		voice[v2].panning = (panning < 64 ? 0 : 127);
		delay = DEFAULT_CHORUS_DELAY2;
	    }
	}
	voice[v2].delay += (int)(play_mode->rate * delay);
    }

    recompute_amp(v1);
    apply_envelope_to_amp(v1);
    recompute_amp(v2);
    apply_envelope_to_amp(v2);

    /* voice[v2].orig_frequency is changed.
     * Update the depened parameters.
     */
    recompute_freq(v2);
}

/* Yet another chorus implementation
 *	by Eric A. Welsh <ewelsh@gpc.wustl.edu>.
 */
static void new_chorus_voice_alternate(int v1, int level)
{
    int v2, ch, panlevel;
    uint8 vol, pan;
    int vel;  /* sms 046.05 */
    double delay;
	struct chorus_status_t *status = get_chorus_status();

    if((v2 = find_free_voice()) == -1)
	return;
    ch = voice[v1].channel;
    voice[v2] = voice[v1];

	/* NRPN Chorus Send Level of Drum */
	if(ISDRUMCHANNEL(ch) && channel[ch].drums[voice[v1].note] != NULL) {
		level *= (FLOAT_T)channel[ch].drums[voice[v1].note]->chorus_level / 127.0;
	}

    /* for our purposes, hard left will be equal to 1 instead of 0 */
    pan = voice[v1].panning;
    if (!pan) pan = 1;

    /* Choose lower voice index for base voice (v1) */
    if(v1 > v2)
    {
	int tmp;
	tmp = v1;
	v1 = v2;
	v2 = v1;
    }

    /* lower the volumes so that the two notes add to roughly the orig. vol */
    /*  sms 046.05   velocity in logarithm space, volume in amplitude  
    vol = voice[v1].velocity;
    voice[v1].velocity  = (uint8)(vol * CHORUS_VELOCITY_TUNING2);
    voice[v2].velocity  = (uint8)(vol * CHORUS_VELOCITY_TUNING2);
    */

    vel = voice[v1].velocity;
    vel -= CHORUS_VELOCITY_DELTA; if (vel<0) vel = 0; 
    voice[v1].velocity = voice[v2].velocity = (uint8) vel;

    /* Make doubled link v1 and v2 */
    voice[v1].chorus_link = v2;
    voice[v2].chorus_link = v1;

    /* detune notes for chorus effect */
    level >>= 2;		/* scale to a "better" value */
    if (level)
    {
        if(channel[ch].pitchbend + level < 0x2000)
            voice[v2].orig_frequency *= bend_fine[level];
        else
	    voice[v2].orig_frequency /= bend_fine[level];
        voice[v2].cache = NULL;
    }

    MYCHECK(voice[v2].orig_frequency);

    /* Try to keep the delayed voice from cancelling out the other voice */
    /* Don't bother with trying to figure out drum pitches... */
    /* Don't bother with mod files for the same reason... */
    /* Drums and mods could be fixed, but pitch detection is too expensive */
    delay = DEFAULT_CHORUS_DELAY2;
    if (!ISDRUMCHANNEL(voice[v1].channel) &&
    	current_file_info->file_type != IS_MOD_FILE &&
    	current_file_info->file_type != IS_S3M_FILE)
    {
    	double freq, frac;
    
    	freq = pitch_freq_table[voice[v1].note];
    	delay = DEFAULT_CHORUS_DELAY2 * freq;
    	frac = delay - floor(delay);

	/* force the delay away from 0.5 period */

⌨️ 快捷键说明

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