+2004-02-18 Saito <saito2@digitalme.com>
+
+ * timidity/reverb.[ch], timidity/playmidi.c, timidity/readmidi.c:
+ Clean up around chorus effect.
+
2004-02-18 TAMUKI Shoichi <tamuki@linet.gr.jp>
* doc/C/timidity.cfg.5, doc/ja_JP.ujis/timidity.cfg.5: Update
case 0x0E: /* Chorus Pre-LPF */
if (val > 7) {val = 7;}
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Pre-LPF (%d)",val);
- chorus_param.chorus_pre_lpf = val;
+ chorus_status.pre_lpf = val;
recompute_chorus_status_gs();
break;
case 0x0F: /* Chorus Level */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Level (%d)",val);
- chorus_param.chorus_level = val;
+ chorus_status.level = val;
recompute_chorus_status_gs();
break;
case 0x10: /* Chorus Feedback */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Feedback (%d)",val);
- chorus_param.chorus_feedback = val;
+ chorus_status.feedback = val;
recompute_chorus_status_gs();
break;
case 0x11: /* Chorus Delay */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Delay (%d)",val);
- chorus_param.chorus_delay = val;
+ chorus_status.delay = val;
init_ch_chorus();
recompute_chorus_status_gs();
init_chorus_lfo();
break;
case 0x12: /* Chorus Rate */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Rate (%d)",val);
- chorus_param.chorus_rate = val;
+ chorus_status.rate = val;
recompute_chorus_status_gs();
init_chorus_lfo();
break;
case 0x13: /* Chorus Depth */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Depth (%d)",val);
- chorus_param.chorus_depth = val;
+ chorus_status.depth = val;
recompute_chorus_status_gs();
init_chorus_lfo();
break;
case 0x14: /* Chorus Send Level to Reverb */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Send Level to Reverb (%d)",val);
- chorus_param.chorus_send_level_to_reverb = val;
+ chorus_status.send_reverb = val;
recompute_chorus_status_gs();
break;
case 0x15: /* Chorus Send Level to Delay */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Send Level to Delay (%d)",val);
- chorus_param.chorus_send_level_to_delay = val;
+ chorus_status.send_delay = val;
recompute_chorus_status_gs();
break;
case 0x16: /* Delay Macro */
break;
case 0x01: /* Chorus Return */
ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Return (%d)", val);
- chorus_param.chorus_level = val;
+ chorus_status.level = val;
recompute_chorus_status_gs();
break;
case 0x50: /* EQ type */
static void check_chorus_text_start(void)
{
- if(chorus_status.status != CHORUS_ST_OK &&
- chorus_status.voice_reserve[17] &&
- chorus_status.macro[2] &&
- chorus_status.pre_lpf[2] &&
- chorus_status.level[2] &&
- chorus_status.feed_back[2] &&
- chorus_status.delay[2] &&
- chorus_status.rate[2] &&
- chorus_status.depth[2] &&
- chorus_status.send_level[2])
+ struct chorus_text_t *p = &(chorus_status.text);
+ if(p->status != CHORUS_ST_OK && p->voice_reserve[17] &&
+ p->macro[2] && p->pre_lpf[2] && p->level[2] &&
+ p->feed_back[2] && p->delay[2] && p->rate[2] &&
+ p->depth[2] && p->send_level[2])
{
ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Chorus text start");
- chorus_status.status = CHORUS_ST_OK;
+ p->status = CHORUS_ST_OK;
}
}
if((addr & 0xFFFFF0) == 0x400130) /* Changing Effects */
{
+ struct chorus_text_t *chorus_text = &(chorus_status.text);
switch(addr & 0xF)
{
case 0x8: /* macro */
- memcpy(chorus_status.macro, body, 3);
+ memcpy(chorus_text->macro, body, 3);
break;
case 0x9: /* PRE-LPF */
- memcpy(chorus_status.pre_lpf, body, 3);
+ memcpy(chorus_text->pre_lpf, body, 3);
break;
case 0xa: /* level */
- memcpy(chorus_status.level, body, 3);
+ memcpy(chorus_text->level, body, 3);
break;
case 0xb: /* feed back */
- memcpy(chorus_status.feed_back, body, 3);
+ memcpy(chorus_text->feed_back, body, 3);
break;
case 0xc: /* delay */
- memcpy(chorus_status.delay, body, 3);
+ memcpy(chorus_text->delay, body, 3);
break;
case 0xd: /* rate */
- memcpy(chorus_status.rate, body, 3);
+ memcpy(chorus_text->rate, body, 3);
break;
case 0xe: /* depth */
- memcpy(chorus_status.depth, body, 3);
+ memcpy(chorus_text->depth, body, 3);
break;
case 0xf: /* send level */
- memcpy(chorus_status.send_level, body, 3);
+ memcpy(chorus_text->send_level, body, 3);
break;
default: break;
}
if(addr == 0x400110) /* Voice Reserve */
{
if(len >= 25)
- memcpy(chorus_status.voice_reserve, body, 18);
+ memcpy(chorus_status.text.voice_reserve, body, 18);
check_chorus_text_start();
return 0;
}
if(type == 5 || /* Lyric */
(type == 1 && (opt_trace_text_meta_event ||
karaoke_format == 2 ||
- chorus_status.status == CHORUS_ST_OK)) ||
+ chorus_status.text.status == CHORUS_ST_OK)) ||
(type == 6 && (current_file_info->format == 0 ||
(current_file_info->format == 1 &&
current_read_track == 0))))
readmidi_add_event(&ev);
continue;
}
- if(chorus_status.status == CHORUS_ST_OK)
+ if(chorus_status.text.status == CHORUS_ST_OK)
{
*text = ME_CHORUS_TEXT;
ev.type = ME_CHORUS_TEXT;
/*! initialize Chorus Effect (GS) */
void init_chorus_status_gs(void)
{
- struct chorus_param_t *p = &chorus_param;
- p->chorus_macro = 0;
- p->chorus_pre_lpf = 0;
- p->chorus_level = 0x40;
- p->chorus_feedback = 0x08;
- p->chorus_delay = 0x50;
- p->chorus_rate = 0x03;
- p->chorus_depth = 0x13;
- p->chorus_send_level_to_reverb = 0;
- p->chorus_send_level_to_delay = 0;
+ struct chorus_status_t *p = &chorus_status;
+ p->macro = 0;
+ p->pre_lpf = 0;
+ p->level = 0x40;
+ p->feedback = 0x08;
+ p->delay = 0x50;
+ p->rate = 0x03;
+ p->depth = 0x13;
+ p->send_reverb = 0;
+ p->send_delay = 0;
recompute_chorus_status_gs();
init_chorus_lfo();
}
/*! recompute Chorus Effect (GS) */
void recompute_chorus_status_gs()
{
- struct chorus_param_t *p = &chorus_param;
- p->delay_in_sample = chorus_delay_time_table[p->chorus_delay] * (double)play_mode->rate / 1000.0;
- p->depth_in_sample = (double)(p->chorus_depth + 1) / 3.2f * (double)play_mode->rate / 1000.0;
+ struct chorus_status_t *p = &chorus_status;
+ p->delay_in_sample = chorus_delay_time_table[p->delay] * (double)play_mode->rate / 1000.0;
+ p->depth_in_sample = (double)(p->depth + 1) / 3.2f * (double)play_mode->rate / 1000.0;
p->delay_in_sample -= p->depth_in_sample / 2; /* NOMINAL_DELAY to delay */
if (p->delay_in_sample < 1) {p->delay_in_sample = 1;}
- p->cycle_in_sample = play_mode->rate / ((double)p->chorus_rate * 0.122f);
- if (p->chorus_rate < 1) {p->cycle_in_sample = 0x7fffffff;}
- p->feedback_ratio = (double)p->chorus_feedback * 0.763f / 100.0f;
- p->level_ratio = (double)p->chorus_level / 127.0f;
- p->send_reverb_ratio = (double)p->chorus_send_level_to_reverb * 0.787f / 100.0f;
- p->send_delay_ratio = (double)p->chorus_send_level_to_delay * 0.787f / 100.0f;
-
- if(p->chorus_pre_lpf) {
- p->lpf.a = (double)(7 - p->chorus_pre_lpf) / 7.0 * 0.9 + 0.05;
+ p->cycle_in_sample = play_mode->rate / ((double)p->rate * 0.122f);
+ if (p->rate < 1) {p->cycle_in_sample = 0x7fffffff;}
+ p->feedback_ratio = (double)p->feedback * 0.763f / 100.0f;
+ p->level_ratio = (double)p->level / 127.0f;
+ p->send_reverb_ratio = (double)p->send_reverb * 0.787f / 100.0f;
+ p->send_delay_ratio = (double)p->send_delay * 0.787f / 100.0f;
+
+ if(p->pre_lpf) {
+ p->lpf.a = (double)(7 - p->pre_lpf) / 7.0 * 0.9 + 0.05;
init_filter_lowpass1(&(p->lpf));
}
}
/*! Chorus Macro (GS), Chorus Type (GM2) */
void set_chorus_macro_gs(int macro)
{
- struct chorus_param_t *p = &chorus_param;
+ struct chorus_status_t *p = &chorus_status;
macro *= 8;
- p->chorus_pre_lpf = chorus_macro_presets[macro];
- p->chorus_level = chorus_macro_presets[macro + 1];
- p->chorus_feedback = chorus_macro_presets[macro + 2];
- p->chorus_delay = chorus_macro_presets[macro + 3];
- p->chorus_rate = chorus_macro_presets[macro + 4];
- p->chorus_depth = chorus_macro_presets[macro + 5];
- p->chorus_send_level_to_reverb = chorus_macro_presets[macro + 6];
- p->chorus_send_level_to_delay = chorus_macro_presets[macro + 7];
+ p->pre_lpf = chorus_macro_presets[macro];
+ p->level = chorus_macro_presets[macro + 1];
+ p->feedback = chorus_macro_presets[macro + 2];
+ p->delay = chorus_macro_presets[macro + 3];
+ p->rate = chorus_macro_presets[macro + 4];
+ p->depth = chorus_macro_presets[macro + 5];
+ p->send_reverb = chorus_macro_presets[macro + 6];
+ p->send_delay = chorus_macro_presets[macro + 7];
}
/*! initialize EQ (GS) */
#ifdef USE_DSP_EFFECT
int32 i;
- chorus_cyc0 = chorus_param.cycle_in_sample;
+ chorus_cyc0 = chorus_status.cycle_in_sample;
if(chorus_cyc0 == 0) {chorus_cyc0 = 1;}
for(i=0;i<SINE_CYCLE_LENGTH;i++) {
memset(chorus_buf0_R, 0, sizeof(chorus_buf0_R));
memset(chorus_effect_buffer, 0, sizeof(chorus_effect_buffer));
/* clear delay-line of LPF */
- init_filter_lowpass1(&(chorus_param.lpf));
+ init_filter_lowpass1(&(chorus_status.lpf));
chorus_cnt0 = chorus_wpt0 = chorus_wpt1 = 0;
chorus_spt0 = chorus_spt1 = chorus_hist0 = chorus_hist1 = 0;
int32 i, level, feedback, send_reverb, send_delay, pdelay,
depth, output, icycle, hist0, hist1, f0, f1, v0, v1;
- level = TIM_FSCALE(chorus_param.level_ratio * MASTER_CHORUS_LEVEL, 24);
- feedback = TIM_FSCALE(chorus_param.feedback_ratio, 24);
- send_reverb = TIM_FSCALE(chorus_param.send_reverb_ratio * REV_INP_LEV, 24);
- send_delay = TIM_FSCALE(chorus_param.send_delay_ratio, 24);
- depth = chorus_param.depth_in_sample;
- pdelay = chorus_param.delay_in_sample;
+ level = TIM_FSCALE(chorus_status.level_ratio * MASTER_CHORUS_LEVEL, 24);
+ feedback = TIM_FSCALE(chorus_status.feedback_ratio, 24);
+ send_reverb = TIM_FSCALE(chorus_status.send_reverb_ratio * REV_INP_LEV, 24);
+ send_delay = TIM_FSCALE(chorus_status.send_delay_ratio, 24);
+ depth = chorus_status.depth_in_sample;
+ pdelay = chorus_status.delay_in_sample;
icycle = TIM_FSCALE((SINE_CYCLE_LENGTH - 1) / (double)chorus_cyc0, 24) - 0.5;
hist0 = chorus_hist0, hist1 = chorus_hist1;
#endif /* OPT_MODE != 0 */
}
+#if 0
+/*! Stereo Chorus; this implementation is specialized for system effect. */
+static void do_ch_stereo_chorus(int32 *buf, int32 count, InfoStereoChorus *info)
+{
+ int32 i;
+
+ if(count == MAGIC_INIT_EFFECT_INFO) {
+ init_lfo(lfoL, /*Hz*/, LFO_SINE);
+ init_lfo(lfoR, /*Hz*/, LFO_COSINE);
+ return;
+ } else if(count == MAGIC_FREE_EFFECT_INFO) {
+ return;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ outr = outl = 0;
+ x = (reverb_effect_buffer[i] + reverb_effect_buffer[i + 1]) >> 1;
+ reverb_effect_buffer[i] = reverb_effect_buffer[i + 1] = 0;
+
+ buf[i] += outl;
+ buf[i + 1] += outr;
+
+ ++i;
+ }
+ info->t1 = t1, info->t1d = t1d;
+}
+#endif
+
#if OPT_MODE != 0 /* fixed-point implementation */
#if _MSC_VER
void set_ch_chorus(int32 *buf, int32 count, int32 level)
{
#ifdef SYS_EFFECT_PRE_LPF
if ((opt_reverb_control == 3 || opt_reverb_control == 4
- || (opt_reverb_control < 0 && ! (opt_reverb_control & 0x100))) && chorus_param.chorus_pre_lpf)
- do_filter_lowpass1_stereo(chorus_effect_buffer, count, &(chorus_param.lpf));
+ || (opt_reverb_control < 0 && ! (opt_reverb_control & 0x100))) && chorus_status.pre_lpf)
+ do_filter_lowpass1_stereo(chorus_effect_buffer, count, &(chorus_status.lpf));
#endif /* SYS_EFFECT_PRE_LPF */
do_stereo_chorus(buf, count);
int32 leveli[3], feedbacki, send_reverbi;
} InfoDelay3;
+/*! Stereo Chorus Effect */
+typedef struct {
+ delay delayL, delayR;
+ lfo lfoL, lfoR;
+ int32 wpt0, wpt1, spt0, spt1, hist0, hist1;
+ int32 rpt0, depth, pdelay;
+ double level, feedback, send_reverb, send_delay;
+ int32 leveli, feedbacki, send_reverbi, send_delayi;
+} InfoStereoChorus;
+
/* */
/* System Effect */
/* */
filter_lowpass1 lpf;
} reverb_status;
+struct chorus_text_t
+{
+ int status;
+ uint8 voice_reserve[18], macro[3], pre_lpf[3], level[3], feed_back[3],
+ delay[3], rate[3], depth[3], send_level[3];
+};
+
/* GS parameters of chorus effect */
-struct chorus_param_t
+struct chorus_status_t
{
/* GS parameters */
- int8 chorus_macro, chorus_pre_lpf, chorus_level, chorus_feedback,
- chorus_delay, chorus_rate, chorus_depth, chorus_send_level_to_reverb,
- chorus_send_level_to_delay;
+ int8 macro, pre_lpf, level, feedback, delay, rate, depth, send_reverb, send_delay;
/* for pre-calculation */
double level_ratio, feedback_ratio, send_reverb_ratio, send_delay_ratio;
int32 cycle_in_sample, depth_in_sample, delay_in_sample;
- filter_lowpass1 lpf;
-} chorus_param;
+ struct chorus_text_t text;
-/* dummy. see also readmidi.c */
-struct chorus_status_t
-{
- int status;
- uint8 voice_reserve[18], macro[3], pre_lpf[3], level[3], feed_back[3],
- delay[3], rate[3], depth[3], send_level[3];
+ InfoStereoChorus info_stereo_chorus;
+ filter_lowpass1 lpf;
} chorus_status;
/* GS parameters of delay effect */