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

📄 mix.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    TiMidity -- Experimental MIDI to WAVE converter    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>    Suddenly, you realize that this program is free software; you get    an overwhelming urge to redistribute it and/or modify it under the    terms of the GNU General Public License as published by the Free    Software Foundation; either version 2 of the License, or (at your    option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received another copy of the GNU General Public    License along with this program; if not, write to the Free    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    I bet they'll be amazed.    mix.c */#include <math.h>#include <stdio.h>#include <stdlib.h>#include "config.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "output.h"#include "ctrlmode.h"#include "tables.h"#include "resample.h"#include "mix.h"/* Returns 1 if envelope runs out */int recompute_envelope(int v){  int stage;  stage = voice[v].envelope_stage;  if (stage>5)    {      /* Envelope ran out. */      int tmp=(voice[v].status == VOICE_DIE); /* Already displayed as dead */      voice[v].status = VOICE_FREE;      if(!tmp)	ctl->note(v);      return 1;    }  if (voice[v].sample->modes & MODES_ENVELOPE)    {      if (voice[v].status==VOICE_ON || voice[v].status==VOICE_SUSTAINED)	{	  if (stage>2)	    {	      /* Freeze envelope until note turns off. Trumpets want this. */	      voice[v].envelope_increment=0;	      return 0;	    }	}    }  voice[v].envelope_stage=stage+1;  if (voice[v].envelope_volume==voice[v].sample->envelope_offset[stage])    return recompute_envelope(v);  voice[v].envelope_target=voice[v].sample->envelope_offset[stage];  voice[v].envelope_increment = voice[v].sample->envelope_rate[stage];  if (voice[v].envelope_target<voice[v].envelope_volume)    voice[v].envelope_increment = -voice[v].envelope_increment;  return 0;}void apply_envelope_to_amp(int v){  FLOAT_T lamp=voice[v].left_amp, ramp, lramp, rramp, ceamp, lfeamp;  int32 la,ra, lra, rra, cea, lfea;  if (voice[v].panned == PANNED_MYSTERY)    {      lramp=voice[v].lr_amp;      ramp=voice[v].right_amp;      ceamp=voice[v].ce_amp;      rramp=voice[v].rr_amp;      lfeamp=voice[v].lfe_amp;      if (voice[v].tremolo_phase_increment)	{	  FLOAT_T tv = voice[v].tremolo_volume;	  lramp *= tv;	  lamp *= tv;	  ceamp *= tv;	  ramp *= tv;	  rramp *= tv;	  lfeamp *= tv;	}      if (voice[v].sample->modes & MODES_ENVELOPE)	{	  FLOAT_T ev = (FLOAT_T)vol_table[voice[v].envelope_volume>>23];	  lramp *= ev;	  lamp *= ev;	  ceamp *= ev;	  ramp *= ev;	  rramp *= ev;	  lfeamp *= ev;	}      la = (int32)FSCALE(lamp,AMP_BITS);      ra = (int32)FSCALE(ramp,AMP_BITS);      lra = (int32)FSCALE(lramp,AMP_BITS);      rra = (int32)FSCALE(rramp,AMP_BITS);      cea = (int32)FSCALE(ceamp,AMP_BITS);      lfea = (int32)FSCALE(lfeamp,AMP_BITS);            if (la>MAX_AMP_VALUE) la=MAX_AMP_VALUE;      if (ra>MAX_AMP_VALUE) ra=MAX_AMP_VALUE;      if (lra>MAX_AMP_VALUE) lra=MAX_AMP_VALUE;      if (rra>MAX_AMP_VALUE) rra=MAX_AMP_VALUE;      if (cea>MAX_AMP_VALUE) cea=MAX_AMP_VALUE;      if (lfea>MAX_AMP_VALUE) lfea=MAX_AMP_VALUE;      voice[v].lr_mix=FINAL_VOLUME(lra);      voice[v].left_mix=FINAL_VOLUME(la);      voice[v].ce_mix=FINAL_VOLUME(cea);      voice[v].right_mix=FINAL_VOLUME(ra);      voice[v].rr_mix=FINAL_VOLUME(rra);      voice[v].lfe_mix=FINAL_VOLUME(lfea);    }  else    {      if (voice[v].tremolo_phase_increment)	lamp *= voice[v].tremolo_volume;      if (voice[v].sample->modes & MODES_ENVELOPE)	lamp *= (FLOAT_T)vol_table[voice[v].envelope_volume>>23];      la = (int32)FSCALE(lamp,AMP_BITS);      if (la>MAX_AMP_VALUE)	la=MAX_AMP_VALUE;      voice[v].left_mix=FINAL_VOLUME(la);    }}static int update_envelope(int v){  voice[v].envelope_volume += voice[v].envelope_increment;  /* Why is there no ^^ operator?? */  if (((voice[v].envelope_increment < 0) &&       (voice[v].envelope_volume <= voice[v].envelope_target)) ||      ((voice[v].envelope_increment > 0) &&	   (voice[v].envelope_volume >= voice[v].envelope_target)))    {      voice[v].envelope_volume = voice[v].envelope_target;      if (recompute_envelope(v))	return 1;    }  return 0;}static void update_tremolo(int v){  int32 depth=voice[v].sample->tremolo_depth<<7;  if (voice[v].tremolo_sweep)    {      /* Update sweep position */      voice[v].tremolo_sweep_position += voice[v].tremolo_sweep;      if (voice[v].tremolo_sweep_position>=(1<<SWEEP_SHIFT))	voice[v].tremolo_sweep=0; /* Swept to max amplitude */      else	{	  /* Need to adjust depth */	  depth *= voice[v].tremolo_sweep_position;	  depth >>= SWEEP_SHIFT;	}    }  voice[v].tremolo_phase += voice[v].tremolo_phase_increment;  /* if (voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))     voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT;  */  voice[v].tremolo_volume = (FLOAT_T)     (1.0 - FSCALENEG((sine(voice[v].tremolo_phase >> RATE_SHIFT) + 1.0)		    * depth * TREMOLO_AMPLITUDE_TUNING,		    17));  /* I'm not sure about the +1.0 there -- it makes tremoloed voices'     volumes on average the lower the higher the tremolo amplitude. */}/* Returns 1 if the note died */static int update_signal(int v){  if (voice[v].envelope_increment && update_envelope(v))    return 1;  if (voice[v].tremolo_phase_increment)    update_tremolo(v);  apply_envelope_to_amp(v);  return 0;}#ifdef LOOKUP_HACK#  define MIXATION(a)	*lp++ += mixup[(a<<8) | (uint8)s];#else#  define MIXATION(a)	*lp++ += (a)*s;#endif#define MIXSKIP lp++#define MIXMAX(a,b) *lp++ += ((a>b)?a:b) * s#define MIXCENT(a,b) *lp++ += (a/2+b/2) * s#define MIXHALF(a)	*lp++ += (a>>1)*s;static void mix_mystery_signal(resample_t *sp, int32 *lp, int v, int count){  Voice *vp = voice + v;  final_volume_t     left_rear=vp->lr_mix,     left=vp->left_mix,     center=vp->ce_mix,     right=vp->right_mix,     right_rear=vp->rr_mix,     lfe=vp->lfe_mix;  int cc;  resample_t s;  if (!(cc = vp->control_counter))    {      cc = control_ratio;      if (update_signal(v))	return;	/* Envelope ran out */	left_rear = vp->lr_mix;	left = vp->left_mix;	center = vp->ce_mix;	right = vp->right_mix;	right_rear = vp->rr_mix;	lfe = vp->lfe_mix;    }    while (count)    if (cc < count)      {	count -= cc;	while (cc--)	  {	    s = *sp++;	      	MIXATION(left);	      	MIXATION(right);		if (num_ochannels >= 4) {			MIXATION(left_rear);			MIXATION(right_rear);		}		if (num_ochannels == 6) {			MIXATION(center);			MIXATION(lfe);		}	  }	cc = control_ratio;	if (update_signal(v))	  return;	/* Envelope ran out */	left_rear = vp->lr_mix;	left = vp->left_mix;	center = vp->ce_mix;	right = vp->right_mix;	right_rear = vp->rr_mix;	lfe = vp->lfe_mix;      }    else      {	vp->control_counter = cc - count;	while (count--)	  {	    s = *sp++;	      	MIXATION(left);	      	MIXATION(right);		if (num_ochannels >= 4) {			MIXATION(left_rear);			MIXATION(right_rear);		}		if (num_ochannels == 6) {			MIXATION(center);			MIXATION(lfe);		}	  }	return;      }}static void mix_center_signal(resample_t *sp, int32 *lp, int v, int count){  Voice *vp = voice + v;  final_volume_t     left=vp->left_mix;  int cc;  resample_t s;  if (!(cc = vp->control_counter))    {      cc = control_ratio;      if (update_signal(v))	return;	/* Envelope ran out */      left = vp->left_mix;    }    while (count)    if (cc < count)      {	count -= cc;	while (cc--)	  {	    s = *sp++;		if (num_ochannels == 2) {	    		MIXATION(left);	    		MIXATION(left);		}		else if (num_ochannels == 4) {			MIXATION(left);			MIXSKIP;			MIXATION(left);			MIXSKIP;		}		else if (num_ochannels == 6) {			MIXSKIP;			MIXSKIP;			MIXSKIP;			MIXSKIP;			MIXATION(left);			MIXATION(left);		}	  }	cc = control_ratio;	if (update_signal(v))	  return;	/* Envelope ran out */	left = vp->left_mix;      }    else      {	vp->control_counter = cc - count;	while (count--)	  {	    s = *sp++;		if (num_ochannels == 2) {	    		MIXATION(left);	    		MIXATION(left);		}		else if (num_ochannels == 4) {			MIXATION(left);			MIXSKIP;			MIXATION(left);			MIXSKIP;		}		else if (num_ochannels == 6) {			MIXSKIP;			MIXSKIP;			MIXSKIP;			MIXSKIP;			MIXATION(left);			MIXATION(left);		}	  }	return;      }}static void mix_single_left_signal(resample_t *sp, int32 *lp, int v, int count){  Voice *vp = voice + v;  final_volume_t     left=vp->left_mix;  int cc;  resample_t s;    if (!(cc = vp->control_counter))    {      cc = control_ratio;      if (update_signal(v))	return;	/* Envelope ran out */      left = vp->left_mix;    }    while (count)    if (cc < count)      {	count -= cc;	while (cc--)	  {	    s = *sp++;		if (num_ochannels == 2) {			MIXATION(left);	    		MIXSKIP;		}		if (num_ochannels >= 4) {			MIXHALF(left);	    		MIXSKIP;			MIXATION(left);	    		MIXSKIP;		}		if (num_ochannels == 6) {	    		MIXSKIP;			MIXATION(left);		}	  }	cc = control_ratio;	if (update_signal(v))	  return;	/* Envelope ran out */	left = vp->left_mix;      }    else      {	vp->control_counter = cc - count;	while (count--)	  {	    s = *sp++;		if (num_ochannels == 2) {			MIXATION(left);	    		MIXSKIP;		}		if (num_ochannels >= 4) {			MIXHALF(left);	    		MIXSKIP;			MIXATION(left);	    		MIXSKIP;		}		if (num_ochannels == 6) {	    		MIXSKIP;			MIXATION(left);

⌨️ 快捷键说明

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