gzdoom-gles/libraries/timidityplus/playmidi.cpp
Christoph Oelckers 5d73f09ebf - first state of music configuration refactor.
# Conflicts:
#	src/sound/music/midi_cvars.cpp
2020-01-05 12:56:28 +01:00

6148 lines
185 KiB
C++

/*
TiMidity++ -- MIDI to WAVE converter and player
Copyright (C) 1999-2009 Masanao Izumo <iz@onicos.co.jp>
Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
This program is free software; you can 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 a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
playmidi.c -- random stuff in need of rearrangement
*/
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include "timidity.h"
#include "common.h"
#include "instrum.h"
#include "playmidi.h"
#include "mix.h"
#include "recache.h"
#include "reverb.h"
#include "freq.h"
#include "quantity.h"
#include "tables.h"
#include "effect.h"
namespace TimidityPlus
{
std::mutex ConfigMutex;
int timidity_modulation_wheel = true;
int timidity_portamento = false;
int timidity_reverb = 0;
int timidity_chorus = 0;
int timidity_surround_chorus = false; // requires restart!
int timidity_channel_pressure = false;
int timidity_lpf_def = true;
int timidity_temper_control = true;
int timidity_modulation_envelope = true;
int timidity_overlap_voice_allow = true;
int timidity_drum_effect = false;
int timidity_pan_delay = false;
float timidity_drum_power = 1.f;
int timidity_key_adjust = 0;
float timidity_tempo_adjust = 1.f;
float min_sustain_time = 5000;
// The following options have no generic use and are only meaningful for some SYSEX events not normally found in common MIDIs.
// For now they are kept as unchanging global variables
static bool opt_eq_control = false;
static bool op_nrpn_vibrato = true;
static bool opt_tva_attack = false;
static bool opt_tva_decay = false;
static bool opt_tva_release = false;
static bool opt_insertion_effect = false;
static bool opt_delay_control = false;
// These two variables need to remain global or things will get messy because they get accessed from non-class code.
int32_t control_ratio = 22;
int32_t playback_rate = 22050;
#define PLAY_INTERLEAVE_SEC 1.0
#define PORTAMENTO_TIME_TUNING (1.0 / 5000.0)
#define PORTAMENTO_CONTROL_RATIO 256 /* controls per sec */
#define DEFAULT_CHORUS_DELAY1 0.02
#define DEFAULT_CHORUS_DELAY2 0.003
#define CHORUS_OPPOSITE_THRESHOLD 32
#define EOT_PRESEARCH_LEN 32
#define SPEED_CHANGE_RATE 1.0594630943592953 /* 2^(1/12) */
#define DEFAULT_AMPLIFICATION 70
#define VIBRATO_DEPTH_MAX 384 /* 600 cent */
void set_playback_rate(int freq)
{
const int CONTROLS_PER_SECOND = 1000;
const int MAX_CONTROL_RATIO = 255;
playback_rate = freq;
control_ratio = playback_rate / CONTROLS_PER_SECOND;
if (control_ratio < 1)
control_ratio = 1;
else if (control_ratio > MAX_CONTROL_RATIO)
control_ratio = MAX_CONTROL_RATIO;
}
Player::Player(Instruments *instr)
{
last_reverb_setting = timidity_reverb;
memset(this, 0, sizeof(*this));
// init one-time global stuff - this should go to the device class once it exists.
instruments = instr;
initialize_resampler_coeffs();
init_tables();
new_midi_file_info();
init_mblock(&playmidi_pool);
reverb = new Reverb;
reverb->init_effect_status(play_system_mode);
effect = new Effect(reverb);
mixer = new Mixer(this);
recache = new Recache(this);
for (int i = 0; i < MAX_CHANNELS; i++)
init_channel_layer(i);
instruments->init_userdrum();
instruments->init_userinst();
master_volume_ratio = 0xFFFF;
vol_table = def_vol_table;
play_system_mode = DEFAULT_SYSTEM_MODE;
midi_streaming = 0;
stream_max_compute = 500; /* compute time limit (in msec) when streaming */
current_keysig = 0;
current_temper_keysig = 0;
temper_adj = 0;
current_play_tempo = 500000;
opt_realtime_playing = 0;
check_eot_flag = 0;
playmidi_seek_flag = 0;
opt_pure_intonation = 0;
current_freq_table = 0;
current_temper_freq_table = 0;
master_tuning = 0;
make_rvid_flag = 0; /* For reverb optimization */
voices = DEFAULT_VOICES;
amplification = DEFAULT_AMPLIFICATION;
static const int drums[] = { 10, -1 };
CLEAR_CHANNELMASK(default_drumchannels);
for (int i = 0; drums[i] > 0; i++)
{
SET_CHANNELMASK(default_drumchannels, drums[i] - 1);
}
for (int i = 16; i < MAX_CHANNELS; i++)
{
if (IS_SET_CHANNELMASK(default_drumchannels, i & 0xF))
SET_CHANNELMASK(default_drumchannels, i);
}
COPY_CHANNELMASK(drumchannels, default_drumchannels);
COPY_CHANNELMASK(drumchannel_mask, default_drumchannel_mask);
}
Player::~Player()
{
reuse_mblock(&playmidi_pool);
if (reverb_buffer != nullptr) free(reverb_buffer);
for (int i = 0; i < MAX_CHANNELS; i++) free_drum_effect(i);
delete mixer;
delete recache;
delete effect;
delete reverb;
}
bool Player::IS_SYSEX_EVENT_TYPE(MidiEvent *event)
{
return ((event)->type == ME_NONE || (event)->type >= ME_RANDOM_PAN || (event)->b == SYSEX_TAG);
}
void Player::init_freq_table_user(void)
{
int p, i, j, k, l;
double f;
for (p = 0; p < 4; p++)
for (i = 0; i < 12; i++)
for (j = -1; j < 11; j++) {
f = 440 * pow(2.0, (i - 9) / 12.0 + j - 5);
for (k = 0; k < 12; k++) {
l = i + j * 12 + k;
if (l < 0 || l >= 128)
continue;
freq_table_user[p][i][l] = f * 1000 + 0.5;
freq_table_user[p][i + 12][l] = f * 1000 + 0.5;
freq_table_user[p][i + 24][l] = f * 1000 + 0.5;
freq_table_user[p][i + 36][l] = f * 1000 + 0.5;
}
}
}
/*! convert Hz to internal vibrato control ratio. */
double Player::cnv_Hz_to_vib_ratio(double freq)
{
return ((double)(playback_rate) / (freq * 2.0f * VIBRATO_SAMPLE_INCREMENTS));
}
void Player::adjust_amplification(void)
{
static const double compensation_ratio = 1.0;
/* compensate master volume */
master_volume = (double)(amplification) / 100.0 *
((double)master_volume_ratio * (compensation_ratio/0xFFFF));
}
int Player::new_vidq(int ch, int note)
{
int i;
if(timidity_overlap_voice_allow)
{
i = ch * 128 + note;
return vidq_head[i]++;
}
return 0;
}
int Player::last_vidq(int ch, int note)
{
int i;
if(timidity_overlap_voice_allow)
{
i = ch * 128 + note;
if(vidq_head[i] == vidq_tail[i])
{
return -1;
}
return vidq_tail[i]++;
}
return 0;
}
void Player::reset_voices(void)
{
int i;
for(i = 0; i < max_voices; i++)
{
voice[i].status = VOICE_FREE;
voice[i].temper_instant = 0;
voice[i].chorus_link = i;
}
upper_voices = 0;
memset(vidq_head, 0, sizeof(vidq_head));
memset(vidq_tail, 0, sizeof(vidq_tail));
}
void Player::kill_note(int i)
{
voice[i].status = VOICE_DIE;
}
void Player::kill_all_voices(void)
{
int i, uv = upper_voices;
for(i = 0; i < uv; i++)
if(voice[i].status & ~(VOICE_FREE | VOICE_DIE))
kill_note(i);
memset(vidq_head, 0, sizeof(vidq_head));
memset(vidq_tail, 0, sizeof(vidq_tail));
}
void Player::reset_drum_controllers(struct DrumParts *d[], int note)
{
int i, j;
if (note == -1)
{
for (i = 0; i < 128; i++)
if (d[i] != NULL)
{
d[i]->drum_panning = NO_PANNING;
for (j = 0; j < 6; j++) { d[i]->drum_envelope_rate[j] = -1; }
d[i]->pan_random = 0;
d[i]->drum_level = 1.0f;
d[i]->coarse = 0;
d[i]->fine = 0;
d[i]->delay_level = -1;
d[i]->chorus_level = -1;
d[i]->reverb_level = -1;
d[i]->play_note = -1;
d[i]->drum_cutoff_freq = 0;
d[i]->drum_resonance = 0;
init_rx_drum(d[i]);
}
}
else
{
d[note]->drum_panning = NO_PANNING;
for (j = 0; j < 6; j++) { d[note]->drum_envelope_rate[j] = -1; }
d[note]->pan_random = 0;
d[note]->drum_level = 1.0f;
d[note]->coarse = 0;
d[note]->fine = 0;
d[note]->delay_level = -1;
d[note]->chorus_level = -1;
d[note]->reverb_level = -1;
d[note]->play_note = -1;
d[note]->drum_cutoff_freq = 0;
d[note]->drum_resonance = 0;
init_rx_drum(d[note]);
}
}
void Player::reset_nrpn_controllers(int c)
{
int i;
/* NRPN */
reset_drum_controllers(channel[c].drums, -1);
channel[c].vibrato_ratio = 1.0;
channel[c].vibrato_depth = 0;
channel[c].vibrato_delay = 0;
channel[c].param_cutoff_freq = 0;
channel[c].param_resonance = 0;
channel[c].cutoff_freq_coef = 1.0;
channel[c].resonance_dB = 0;
/* System Exclusive */
channel[c].dry_level = 127;
channel[c].eq_gs = 1;
channel[c].insertion_effect = 0;
channel[c].velocity_sense_depth = 0x40;
channel[c].velocity_sense_offset = 0x40;
channel[c].pitch_offset_fine = 0;
if (play_system_mode == GS_SYSTEM_MODE) { channel[c].assign_mode = 1; }
else {
if (ISDRUMCHANNEL(c)) { channel[c].assign_mode = 1; }
else { channel[c].assign_mode = 2; }
}
for (i = 0; i < 12; i++)
channel[c].scale_tuning[i] = 0;
channel[c].prev_scale_tuning = 0;
channel[c].temper_type = 0;
init_channel_layer(c);
init_part_eq_xg(&(channel[c].eq_xg));
/* channel pressure & polyphonic key pressure control */
init_midi_controller(&(channel[c].mod));
init_midi_controller(&(channel[c].bend));
init_midi_controller(&(channel[c].caf));
init_midi_controller(&(channel[c].paf));
init_midi_controller(&(channel[c].cc1));
init_midi_controller(&(channel[c].cc2));
channel[c].bend.pitch = 2;
init_rx(c);
channel[c].note_limit_high = 127;
channel[c].note_limit_low = 0;
channel[c].vel_limit_high = 127;
channel[c].vel_limit_low = 0;
free_drum_effect(c);
channel[c].legato = 0;
channel[c].damper_mode = 0;
channel[c].loop_timeout = 0;
channel[c].sysex_gs_msb_addr = channel[c].sysex_gs_msb_val =
channel[c].sysex_xg_msb_addr = channel[c].sysex_xg_msb_val =
channel[c].sysex_msb_addr = channel[c].sysex_msb_val = 0;
}
/* Process the Reset All Controllers event */
void Player::reset_controllers(int c)
{
int j;
/* Some standard says, although the SCC docs say 0. */
if (play_system_mode == XG_SYSTEM_MODE)
channel[c].volume = 100;
else
channel[c].volume = 90;
channel[c].expression = 127; /* SCC-1 does this. */
channel[c].sustain = 0;
channel[c].sostenuto = 0;
channel[c].pitchbend = 0x2000;
channel[c].pitchfactor = 0; /* to be computed */
channel[c].mod.val = 0;
channel[c].bend.val = 0;
channel[c].caf.val = 0;
channel[c].paf.val = 0;
channel[c].cc1.val = 0;
channel[c].cc2.val = 0;
channel[c].portamento_time_lsb = 0;
channel[c].portamento_time_msb = 0;
channel[c].porta_control_ratio = 0;
channel[c].portamento = 0;
channel[c].last_note_fine = -1;
for (j = 0; j < 6; j++) { channel[c].envelope_rate[j] = -1; }
update_portamento_controls(c);
set_reverb_level(c, -1);
if (timidity_chorus == 1)
channel[c].chorus_level = 0;
else
channel[c].chorus_level = -timidity_chorus;
channel[c].mono = 0;
channel[c].delay_level = 0;
}
int Player::get_default_mapID(int ch)
{
if (play_system_mode == XG_SYSTEM_MODE)
return ISDRUMCHANNEL(ch) ? XG_DRUM_MAP : XG_NORMAL_MAP;
return INST_NO_MAP;
}
void Player::reset_midi(int playing)
{
int i;
for (i = 0; i < MAX_CHANNELS; i++) {
reset_controllers(i);
reset_nrpn_controllers(i);
channel[i].tone_map0_number = 0;
channel[i].mod.lfo1_pitch_depth = 50;
/* The rest of these are unaffected
* by the Reset All Controllers event
*/
channel[i].program = instruments->defaultProgram(i);
channel[i].panning = NO_PANNING;
channel[i].pan_random = 0;
/* tone bank or drum set */
if (ISDRUMCHANNEL(i)) {
channel[i].bank = 0;
channel[i].altassign = instruments->drumSet(0)->alt;
} else {
if (special_tonebank >= 0)
channel[i].bank = special_tonebank;
else
channel[i].bank = default_tonebank;
}
channel[i].bank_lsb = channel[i].bank_msb = 0;
if (play_system_mode == XG_SYSTEM_MODE && i % 16 == 9)
channel[i].bank_msb = 127; /* Use MSB=127 for XG */
update_rpn_map(i, RPN_ADDR_FFFF, 0);
channel[i].special_sample = 0;
channel[i].key_shift = 0;
channel[i].mapID = get_default_mapID(i);
channel[i].lasttime = 0;
}
if (playing) {
kill_all_voices();
if (temper_type_mute) {
if (temper_type_mute & 1)
FILL_CHANNELMASK(channel_mute);
else
CLEAR_CHANNELMASK(channel_mute);
}
} else
reset_voices();
master_volume_ratio = 0xffff;
adjust_amplification();
master_tuning = 0;
if (current_file_info) {
COPY_CHANNELMASK(drumchannels, current_file_info->drumchannels);
COPY_CHANNELMASK(drumchannel_mask,
current_file_info->drumchannel_mask);
} else {
COPY_CHANNELMASK(drumchannels, default_drumchannels);
COPY_CHANNELMASK(drumchannel_mask, default_drumchannel_mask);
}
}
void Player::recompute_freq(int v)
{
int i;
int ch = voice[v].channel;
int note = voice[v].note;
int32_t tuning = 0;
int8_t st = channel[ch].scale_tuning[note % 12];
int8_t tt = channel[ch].temper_type;
uint8_t tp = channel[ch].rpnmap[RPN_ADDR_0003];
int32_t f;
int pb = channel[ch].pitchbend;
int32_t tmp;
double pf, root_freq;
int32_t a;
Voice *vp = &(voice[v]);
if (! voice[v].sample->sample_rate)
return;
if (! timidity_modulation_wheel)
channel[ch].mod.val = 0;
if (! timidity_portamento)
voice[v].porta_control_ratio = 0;
voice[v].vibrato_control_ratio = voice[v].orig_vibrato_control_ratio;
if (voice[v].vibrato_control_ratio || channel[ch].mod.val > 0) {
/* This instrument has vibrato. Invalidate any precomputed
* sample_increments.
*/
/* MIDI controllers LFO pitch depth */
if (timidity_channel_pressure || timidity_modulation_wheel) {
vp->vibrato_depth = vp->sample->vibrato_depth + channel[ch].vibrato_depth;
vp->vibrato_depth += get_midi_controller_pitch_depth(&(channel[ch].mod))
+ get_midi_controller_pitch_depth(&(channel[ch].bend))
+ get_midi_controller_pitch_depth(&(channel[ch].caf))
+ get_midi_controller_pitch_depth(&(channel[ch].paf))
+ get_midi_controller_pitch_depth(&(channel[ch].cc1))
+ get_midi_controller_pitch_depth(&(channel[ch].cc2));
if (vp->vibrato_depth > VIBRATO_DEPTH_MAX) {vp->vibrato_depth = VIBRATO_DEPTH_MAX;}
else if (vp->vibrato_depth < 1) {vp->vibrato_depth = 1;}
if (vp->sample->vibrato_depth < 0) { /* in opposite phase */
vp->vibrato_depth = -vp->vibrato_depth;
}
}
/* fill parameters for modulation wheel */
if (channel[ch].mod.val > 0) {
if(vp->vibrato_control_ratio == 0) {
vp->vibrato_control_ratio =
vp->orig_vibrato_control_ratio = (int)(cnv_Hz_to_vib_ratio(5.0) * channel[ch].vibrato_ratio);
}
vp->vibrato_delay = 0;
}
for (i = 0; i < VIBRATO_SAMPLE_INCREMENTS; i++)
vp->vibrato_sample_increment[i] = 0;
vp->cache = NULL;
}
/* At least for GM2, it's recommended not to apply master_tuning for drum channels */
tuning = ISDRUMCHANNEL(ch) ? 0 : master_tuning;
/* fine: [0..128] => [-256..256]
* 1 coarse = 256 fine (= 1 note)
* 1 fine = 2^5 tuning
*/
tuning += (channel[ch].rpnmap[RPN_ADDR_0001] - 0x40
+ (channel[ch].rpnmap[RPN_ADDR_0002] - 0x40) * 64) << 7;
/* for NRPN Coarse Pitch of Drum (GS) & Fine Pitch of Drum (XG) */
if (ISDRUMCHANNEL(ch) && channel[ch].drums[note] != NULL
&& (channel[ch].drums[note]->fine
|| channel[ch].drums[note]->coarse)) {
tuning += (channel[ch].drums[note]->fine
+ channel[ch].drums[note]->coarse * 64) << 7;
}
/* MIDI controllers pitch control */
if (timidity_channel_pressure) {
tuning += get_midi_controller_pitch(&(channel[ch].mod))
+ get_midi_controller_pitch(&(channel[ch].bend))
+ get_midi_controller_pitch(&(channel[ch].caf))
+ get_midi_controller_pitch(&(channel[ch].paf))
+ get_midi_controller_pitch(&(channel[ch].cc1))
+ get_midi_controller_pitch(&(channel[ch].cc2));
}
if (timidity_modulation_envelope) {
if (voice[v].sample->tremolo_to_pitch) {
tuning += lookup_triangular(voice[v].tremolo_phase >> RATE_SHIFT)
* (voice[v].sample->tremolo_to_pitch << 13) / 100.0 + 0.5;
channel[ch].pitchfactor = 0;
}
if (voice[v].sample->modenv_to_pitch) {
tuning += voice[v].last_modenv_volume
* (voice[v].sample->modenv_to_pitch << 13) / 100.0 + 0.5;
channel[ch].pitchfactor = 0;
}
}
/* GS/XG - Scale Tuning */
if (! ISDRUMCHANNEL(ch)) {
tuning += ((st << 13) + 50) / 100;
if (st != channel[ch].prev_scale_tuning) {
channel[ch].pitchfactor = 0;
channel[ch].prev_scale_tuning = st;
}
}
if (! opt_pure_intonation
&& timidity_temper_control && voice[v].temper_instant) {
switch (tt) {
case 0:
f = freq_table_tuning[tp][note];
break;
case 1:
if (current_temper_keysig < 8)
f = freq_table_pytha[current_temper_freq_table][note];
else
f = freq_table_pytha[current_temper_freq_table + 12][note];
break;
case 2:
if (current_temper_keysig < 8)
f = freq_table_meantone[current_temper_freq_table
+ ((temper_adj) ? 36 : 0)][note];
else
f = freq_table_meantone[current_temper_freq_table
+ ((temper_adj) ? 24 : 12)][note];
break;
case 3:
if (current_temper_keysig < 8)
f = freq_table_pureint[current_temper_freq_table
+ ((temper_adj) ? 36 : 0)][note];
else
f = freq_table_pureint[current_temper_freq_table
+ ((temper_adj) ? 24 : 12)][note];
break;
default: /* user-defined temperament */
if ((tt -= 0x40) >= 0 && tt < 4) {
if (current_temper_keysig < 8)
f = freq_table_user[tt][current_temper_freq_table
+ ((temper_adj) ? 36 : 0)][note];
else
f = freq_table_user[tt][current_temper_freq_table
+ ((temper_adj) ? 24 : 12)][note];
} else
f = freq_table[note];
break;
}
voice[v].orig_frequency = f;
}
if (! voice[v].porta_control_ratio) {
if (tuning == 0 && pb == 0x2000)
voice[v].frequency = voice[v].orig_frequency;
else {
pb -= 0x2000;
if (! channel[ch].pitchfactor) {
/* Damn. Somebody bent the pitch. */
tmp = pb * channel[ch].rpnmap[RPN_ADDR_0000] + tuning;
if (tmp >= 0)
channel[ch].pitchfactor = bend_fine[tmp >> 5 & 0xff]
* bend_coarse[tmp >> 13 & 0x7f];
else
channel[ch].pitchfactor = 1.0 /
(bend_fine[-tmp >> 5 & 0xff]
* bend_coarse[-tmp >> 13 & 0x7f]);
}
voice[v].frequency =
voice[v].orig_frequency * channel[ch].pitchfactor;
if (voice[v].frequency != voice[v].orig_frequency)
voice[v].cache = NULL;
}
} else { /* Portamento */
pb -= 0x2000;
tmp = pb * channel[ch].rpnmap[RPN_ADDR_0000]
+ (voice[v].porta_pb << 5) + tuning;
if (tmp >= 0)
pf = bend_fine[tmp >> 5 & 0xff]
* bend_coarse[tmp >> 13 & 0x7f];
else
pf = 1.0 / (bend_fine[-tmp >> 5 & 0xff]
* bend_coarse[-tmp >> 13 & 0x7f]);
voice[v].frequency = voice[v].orig_frequency * pf;
voice[v].cache = NULL;
}
root_freq = voice[v].sample->root_freq;
a = TIM_FSCALE(((double) voice[v].sample->sample_rate
* ((double)voice[v].frequency + channel[ch].pitch_offset_fine))
/ (root_freq * playback_rate), FRACTION_BITS) + 0.5;
/* need to preserve the loop direction */
voice[v].sample_increment = (voice[v].sample_increment >= 0) ? a : -a;
}
int32_t Player::calc_velocity(int32_t ch,int32_t vel)
{
int32_t velocity;
velocity = channel[ch].velocity_sense_depth * vel / 64 + (channel[ch].velocity_sense_offset - 64) * 2;
if(velocity > 127) {velocity = 127;}
return velocity;
}
void Player::recompute_voice_tremolo(int v)
{
Voice *vp = &(voice[v]);
int ch = vp->channel;
int32_t depth = vp->sample->tremolo_depth;
depth += get_midi_controller_amp_depth(&(channel[ch].mod))
+ get_midi_controller_amp_depth(&(channel[ch].bend))
+ get_midi_controller_amp_depth(&(channel[ch].caf))
+ get_midi_controller_amp_depth(&(channel[ch].paf))
+ get_midi_controller_amp_depth(&(channel[ch].cc1))
+ get_midi_controller_amp_depth(&(channel[ch].cc2));
if(depth > 256) {depth = 256;}
vp->tremolo_depth = depth;
}
void Player::recompute_amp(int v)
{
double tempamp;
int ch = voice[v].channel;
/* master_volume and sample->volume are percentages, used to scale
* amplitude directly, NOT perceived volume
*
* all other MIDI volumes are linear in perceived volume, 0-127
* use a lookup table for the non-linear scalings
*/
if (play_system_mode == GM2_SYSTEM_MODE) {
tempamp = master_volume *
voice[v].sample->volume *
gm2_vol_table[calc_velocity(ch, voice[v].velocity)] * /* velocity: not in GM2 standard */
gm2_vol_table[channel[ch].volume] *
gm2_vol_table[channel[ch].expression]; /* 21 bits */
}
else if (play_system_mode == GS_SYSTEM_MODE) { /* use measured curve */
tempamp = master_volume *
voice[v].sample->volume *
sc_vel_table[calc_velocity(ch, voice[v].velocity)] *
sc_vol_table[channel[ch].volume] *
sc_vol_table[channel[ch].expression]; /* 21 bits */
}
else { /* use generic exponential curve */
tempamp = master_volume *
voice[v].sample->volume *
perceived_vol_table[calc_velocity(ch, voice[v].velocity)] *
perceived_vol_table[channel[ch].volume] *
perceived_vol_table[channel[ch].expression]; /* 21 bits */
}
/* every digital effect increases amplitude,
* so that it must be reduced in advance.
*/
if (
(timidity_reverb || timidity_chorus || opt_delay_control
|| (opt_eq_control && (reverb->eq_status_gs.low_gain != 0x40
|| reverb->eq_status_gs.high_gain != 0x40))
|| opt_insertion_effect))
tempamp *= 1.35f * 0.55f;
else
tempamp *= 1.35f;
/* Reduce amplitude for chorus partners.
* 2x voices -> 2x power -> sqrt(2)x amplitude.
* 1 / sqrt(2) = ~0.7071, which is very close to the old
* CHORUS_VELOCITY_TUNING1 value of 0.7.
*
* The previous amp scaling for the various digital effects should
* really be redone to split them into separate scalings for each
* effect, rather than a single scaling if any one of them is used
* (which is NOT correct). As it is now, if partner chorus is the
* only effect in use, then it is reduced in volume twice and winds
* up too quiet. Compare the output of "-EFreverb=0 -EFchorus=0",
* "-EFreverb=0 -EFchorus=2", "-EFreverb=4 -EFchorus=2", and
* "-EFreverb=4 -EFchorus=0" to see how the digital effect volumes
* are not scaled properly. Idealy, all the resulting output should
* have the same volume, regardless of effects used. This will
* require empirically determining the amount to scale for each
* individual effect.
*/
if (voice[v].chorus_link != v)
tempamp *= 0.7071067811865f;
/* NRPN - drum instrument tva level */
if (ISDRUMCHANNEL(ch)) {
if (channel[ch].drums[voice[v].note] != NULL) {
tempamp *= channel[ch].drums[voice[v].note]->drum_level;
}
tempamp *= (double)timidity_drum_power; /* global drum power */
}
/* MIDI controllers amplitude control */
if (timidity_channel_pressure) {
tempamp *= get_midi_controller_amp(&(channel[ch].mod))
* get_midi_controller_amp(&(channel[ch].bend))
* get_midi_controller_amp(&(channel[ch].caf))
* get_midi_controller_amp(&(channel[ch].paf))
* get_midi_controller_amp(&(channel[ch].cc1))
* get_midi_controller_amp(&(channel[ch].cc2));
recompute_voice_tremolo(v);
}
if (voice[v].fc.type != 0) {
tempamp *= voice[v].fc.gain; /* filter gain */
}
/* applying panning to amplitude */
if (true)
{
if (voice[v].panning == 64)
{
voice[v].panned = PANNED_CENTER;
voice[v].left_amp = voice[v].right_amp = TIM_FSCALENEG(tempamp * pan_table[64], 27);
}
else if (voice[v].panning < 2)
{
voice[v].panned = PANNED_LEFT;
voice[v].left_amp = TIM_FSCALENEG(tempamp, 20);
voice[v].right_amp = 0;
}
else if (voice[v].panning == 127)
{
if (voice[v].panned == PANNED_MYSTERY) {
voice[v].old_left_mix = voice[v].old_right_mix;
voice[v].old_right_mix = 0;
}
voice[v].panned = PANNED_RIGHT;
voice[v].left_amp = TIM_FSCALENEG(tempamp, 20);
voice[v].right_amp = 0;
}
else
{
if (voice[v].panned == PANNED_RIGHT) {
voice[v].old_right_mix = voice[v].old_left_mix;
voice[v].old_left_mix = 0;
}
voice[v].panned = PANNED_MYSTERY;
voice[v].left_amp = TIM_FSCALENEG(tempamp * pan_table[128 - voice[v].panning], 27);
voice[v].right_amp = TIM_FSCALENEG(tempamp * pan_table[voice[v].panning], 27);
}
}
else
{
voice[v].panned = PANNED_CENTER;
voice[v].left_amp = TIM_FSCALENEG(tempamp, 21);
}
}
#define RESONANCE_COEFF 0.2393
void Player::recompute_channel_filter(int ch, int note)
{
double coef = 1.0f, reso = 0;
if(channel[ch].special_sample > 0) {return;}
/* Soft Pedal */
if(channel[ch].soft_pedal != 0) {
if(note > 49) { /* tre corde */
coef *= 1.0 - 0.20 * ((double)channel[ch].soft_pedal) / 127.0f;
} else { /* una corda (due corde) */
coef *= 1.0 - 0.25 * ((double)channel[ch].soft_pedal) / 127.0f;
}
}
if(!ISDRUMCHANNEL(ch)) {
/* NRPN Filter Cutoff */
coef *= pow(1.26, (double)(channel[ch].param_cutoff_freq) / 8.0f);
/* NRPN Resonance */
reso = (double)channel[ch].param_resonance * RESONANCE_COEFF;
}
channel[ch].cutoff_freq_coef = coef;
channel[ch].resonance_dB = reso;
}
void Player::init_voice_filter(int i)
{
memset(&(voice[i].fc), 0, sizeof(FilterCoefficients));
if(timidity_lpf_def && voice[i].sample->cutoff_freq) {
voice[i].fc.orig_freq = voice[i].sample->cutoff_freq;
voice[i].fc.orig_reso_dB = (double)voice[i].sample->resonance / 10.0f - 3.01f;
if (voice[i].fc.orig_reso_dB < 0.0f) {voice[i].fc.orig_reso_dB = 0.0f;}
if (timidity_lpf_def == 2) {
voice[i].fc.gain = 1.0;
voice[i].fc.type = 2;
} else if(timidity_lpf_def == 1) {
voice[i].fc.gain = pow(10.0f, -voice[i].fc.orig_reso_dB / 2.0f / 20.0f);
voice[i].fc.type = 1;
}
voice[i].fc.start_flag = 0;
} else {
voice[i].fc.type = 0;
}
}
#define CHAMBERLIN_RESONANCE_MAX 24.0
void Player::recompute_voice_filter(int v)
{
int ch = voice[v].channel, note = voice[v].note;
double coef = 1.0, reso = 0, cent = 0, depth_cent = 0, freq;
FilterCoefficients *fc = &(voice[v].fc);
Sample *sp = (Sample *) &voice[v].sample;
if(fc->type == 0) {return;}
coef = channel[ch].cutoff_freq_coef;
if(ISDRUMCHANNEL(ch) && channel[ch].drums[note] != NULL) {
/* NRPN Drum Instrument Filter Cutoff */
coef *= pow(1.26, (double)(channel[ch].drums[note]->drum_cutoff_freq) / 8.0f);
/* NRPN Drum Instrument Filter Resonance */
reso += (double)channel[ch].drums[note]->drum_resonance * RESONANCE_COEFF;
}
/* MIDI controllers filter cutoff control and LFO filter depth */
if(timidity_channel_pressure) {
cent += get_midi_controller_filter_cutoff(&(channel[ch].mod))
+ get_midi_controller_filter_cutoff(&(channel[ch].bend))
+ get_midi_controller_filter_cutoff(&(channel[ch].caf))
+ get_midi_controller_filter_cutoff(&(channel[ch].paf))
+ get_midi_controller_filter_cutoff(&(channel[ch].cc1))
+ get_midi_controller_filter_cutoff(&(channel[ch].cc2));
depth_cent += get_midi_controller_filter_depth(&(channel[ch].mod))
+ get_midi_controller_filter_depth(&(channel[ch].bend))
+ get_midi_controller_filter_depth(&(channel[ch].caf))
+ get_midi_controller_filter_depth(&(channel[ch].paf))
+ get_midi_controller_filter_depth(&(channel[ch].cc1))
+ get_midi_controller_filter_depth(&(channel[ch].cc2));
}
if(sp->vel_to_fc) { /* velocity to filter cutoff frequency */
if(voice[v].velocity > sp->vel_to_fc_threshold)
cent += sp->vel_to_fc * (double)(127 - voice[v].velocity) / 127.0f;
else
coef += sp->vel_to_fc * (double)(127 - sp->vel_to_fc_threshold) / 127.0f;
}
if(sp->vel_to_resonance) { /* velocity to filter resonance */
reso += (double)voice[v].velocity * sp->vel_to_resonance / 127.0f / 10.0f;
}
if(sp->key_to_fc) { /* filter cutoff key-follow */
cent += sp->key_to_fc * (double)(voice[v].note - sp->key_to_fc_bpo);
}
if(timidity_modulation_envelope) {
if(voice[v].sample->tremolo_to_fc + (int16_t)depth_cent) {
cent += ((double)voice[v].sample->tremolo_to_fc + depth_cent) * lookup_triangular(voice[v].tremolo_phase >> RATE_SHIFT);
}
if(voice[v].sample->modenv_to_fc) {
cent += (double)voice[v].sample->modenv_to_fc * voice[v].last_modenv_volume;
}
}
if(cent != 0) {coef *= pow(2.0, cent / 1200.0f);}
freq = (double)fc->orig_freq * coef;
if (freq > playback_rate / 2) {freq = playback_rate / 2;}
else if(freq < 5) {freq = 5;}
fc->freq = (int32_t)freq;
fc->reso_dB = fc->orig_reso_dB + channel[ch].resonance_dB + reso;
if(fc->reso_dB < 0.0f) {fc->reso_dB = 0.0f;}
else if(fc->reso_dB > 96.0f) {fc->reso_dB = 96.0f;}
if(fc->type == 1) { /* Chamberlin filter */
if(fc->freq > playback_rate / 6) {
if (fc->start_flag == 0) {fc->type = 0;} /* turn off. */
else {fc->freq = playback_rate / 6;}
}
if(fc->reso_dB > CHAMBERLIN_RESONANCE_MAX) {fc->reso_dB = CHAMBERLIN_RESONANCE_MAX;}
} else if(fc->type == 2) { /* Moog VCF */
if(fc->reso_dB > fc->orig_reso_dB / 2) {
fc->gain = pow(10.0f, (fc->reso_dB - fc->orig_reso_dB / 2) / 20.0f);
}
}
fc->start_flag = 1; /* filter is started. */
}
float Player::calc_drum_tva_level(int ch, int note, int level)
{
int def_level, nbank, nprog;
const ToneBank *bank;
if(channel[ch].special_sample > 0) {return 1.0;}
nbank = channel[ch].bank;
nprog = note;
instruments->instrument_map(channel[ch].mapID, &nbank, &nprog);
if(ISDRUMCHANNEL(ch)) {
bank = instruments->drumSet(nbank);
if(bank == NULL) {bank = instruments->drumSet(0);}
} else {
return 1.0;
}
def_level = bank->tone[nprog].tva_level;
if(def_level == -1 || def_level == 0) {def_level = 127;}
else if(def_level > 127) {def_level = 127;}
return (sc_drum_level_table[level] / sc_drum_level_table[def_level]);
}
int32_t Player::calc_random_delay(int ch, int note)
{
int nbank, nprog;
const ToneBank *bank;
if(channel[ch].special_sample > 0) {return 0;}
nbank = channel[ch].bank;
if(ISDRUMCHANNEL(ch)) {
nprog = note;
instruments->instrument_map(channel[ch].mapID, &nbank, &nprog);
bank = instruments->drumSet(nbank);
if (bank == NULL) {bank = instruments->drumSet(0);}
} else {
nprog = channel[ch].program;
if(nprog == SPECIAL_PROGRAM) {return 0;}
instruments->instrument_map(channel[ch].mapID, &nbank, &nprog);
bank = instruments->toneBank(nbank);
if(bank == NULL) {bank = instruments->toneBank(0);}
}
if (bank->tone[nprog].rnddelay == 0) {return 0;}
else {return (int32_t)((double)bank->tone[nprog].rnddelay * playback_rate / 1000.0
* (reverb->get_pink_noise_light(&reverb->global_pink_noise_light) + 1.0f) * 0.5);}
}
void Player::recompute_bank_parameter(int ch, int note)
{
int nbank, nprog;
const ToneBank *bank;
struct DrumParts *drum;
if(channel[ch].special_sample > 0) {return;}
nbank = channel[ch].bank;
if(ISDRUMCHANNEL(ch)) {
nprog = note;
instruments->instrument_map(channel[ch].mapID, &nbank, &nprog);
bank = instruments->drumSet(nbank);
if (bank == NULL) {bank = instruments->drumSet(0);}
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
drum = channel[ch].drums[note];
if (drum->reverb_level == -1 && bank->tone[nprog].reverb_send != -1) {
drum->reverb_level = bank->tone[nprog].reverb_send;
}
if (drum->chorus_level == -1 && bank->tone[nprog].chorus_send != -1) {
drum->chorus_level = bank->tone[nprog].chorus_send;
}
if (drum->delay_level == -1 && bank->tone[nprog].delay_send != -1) {
drum->delay_level = bank->tone[nprog].delay_send;
}
} else {
nprog = channel[ch].program;
if (nprog == SPECIAL_PROGRAM) {return;}
instruments->instrument_map(channel[ch].mapID, &nbank, &nprog);
bank = instruments->toneBank(nbank);
if (bank == NULL) {bank = instruments->toneBank(0);}
channel[ch].legato = bank->tone[nprog].legato;
channel[ch].damper_mode = bank->tone[nprog].damper_mode;
channel[ch].loop_timeout = bank->tone[nprog].loop_timeout;
}
}
/* this reduces voices while maintaining sound quality */
int Player::reduce_voice(void)
{
int32_t lv, v;
int i, j, lowest=-0x7FFFFFFF;
i = upper_voices;
lv = 0x7FFFFFFF;
/* Look for the decaying note with the smallest volume */
/* Protect drum decays. Truncating them early sounds bad, especially on
snares and cymbals */
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE ||
(voice[j].sample->note_to_use && ISDRUMCHANNEL(voice[j].channel)))
continue;
if(voice[j].status & ~(VOICE_ON | VOICE_DIE | VOICE_SUSTAINED))
{
/* find lowest volume */
v = voice[j].left_mix;
if(voice[j].panned == PANNED_MYSTERY && voice[j].right_mix > v)
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
}
if(lowest != -0x7FFFFFFF)
{
/* This can still cause a click, but if we had a free voice to
spare for ramping down this note, we wouldn't need to kill it
in the first place... Still, this needs to be fixed. Perhaps
we could use a reserve of voices to play dying notes only. */
cut_notes++;
free_voice(lowest);
return lowest;
}
/* try to remove VOICE_DIE before VOICE_ON */
lv = 0x7FFFFFFF;
lowest = -1;
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE)
continue;
if(voice[j].status & ~(VOICE_ON | VOICE_SUSTAINED))
{
/* continue protecting drum decays */
if (voice[j].status & ~(VOICE_DIE) &&
(voice[j].sample->note_to_use && ISDRUMCHANNEL(voice[j].channel)))
continue;
/* find lowest volume */
v = voice[j].left_mix;
if(voice[j].panned == PANNED_MYSTERY && voice[j].right_mix > v)
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
}
if(lowest != -1)
{
cut_notes++;
free_voice(lowest);
return lowest;
}
/* try to remove VOICE_SUSTAINED before VOICE_ON */
lv = 0x7FFFFFFF;
lowest = -0x7FFFFFFF;
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE)
continue;
if(voice[j].status & VOICE_SUSTAINED)
{
/* find lowest volume */
v = voice[j].left_mix;
if(voice[j].panned == PANNED_MYSTERY && voice[j].right_mix > v)
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
}
if(lowest != -0x7FFFFFFF)
{
cut_notes++;
free_voice(lowest);
return lowest;
}
/* try to remove chorus before VOICE_ON */
lv = 0x7FFFFFFF;
lowest = -0x7FFFFFFF;
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE)
continue;
if(voice[j].chorus_link < j)
{
/* find lowest volume */
v = voice[j].left_mix;
if(voice[j].panned == PANNED_MYSTERY && voice[j].right_mix > v)
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
}
if(lowest != -0x7FFFFFFF)
{
cut_notes++;
/* fix pan */
j = voice[lowest].chorus_link;
voice[j].panning = channel[voice[lowest].channel].panning;
recompute_amp(j);
mixer->apply_envelope_to_amp(j);
free_voice(lowest);
return lowest;
}
lost_notes++;
/* remove non-drum VOICE_ON */
lv = 0x7FFFFFFF;
lowest = -0x7FFFFFFF;
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE ||
(voice[j].sample->note_to_use && ISDRUMCHANNEL(voice[j].channel)))
continue;
/* find lowest volume */
v = voice[j].left_mix;
if(voice[j].panned == PANNED_MYSTERY && voice[j].right_mix > v)
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
if(lowest != -0x7FFFFFFF)
{
free_voice(lowest);
return lowest;
}
/* remove all other types of notes */
lv = 0x7FFFFFFF;
lowest = 0;
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE)
continue;
/* find lowest volume */
v = voice[j].left_mix;
if(voice[j].panned == PANNED_MYSTERY && voice[j].right_mix > v)
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
free_voice(lowest);
return lowest;
}
void Player::free_voice(int v1)
{
int v2;
#ifdef ENABLE_PAN_DELAY
if (voice[v1].pan_delay_buf != NULL) {
free(voice[v1].pan_delay_buf);
voice[v1].pan_delay_buf = NULL;
}
#endif /* ENABLE_PAN_DELAY */
v2 = voice[v1].chorus_link;
if(v1 != v2)
{
/* Unlink chorus link */
voice[v1].chorus_link = v1;
voice[v2].chorus_link = v2;
}
voice[v1].status = VOICE_FREE;
voice[v1].temper_instant = 0;
}
int Player::find_free_voice(void)
{
int i, nv = voices, lowest;
int32_t lv, v;
for(i = 0; i < nv; i++)
if(voice[i].status == VOICE_FREE)
{
if(upper_voices <= i)
upper_voices = i + 1;
return i;
}
upper_voices = voices;
/* Look for the decaying note with the lowest volume */
lv = 0x7FFFFFFF;
lowest = -1;
for(i = 0; i < nv; i++)
{
if(voice[i].status & ~(VOICE_ON | VOICE_DIE) &&
!(voice[i].sample && voice[i].sample->note_to_use && ISDRUMCHANNEL(voice[i].channel)))
{
v = voice[i].left_mix;
if((voice[i].panned==PANNED_MYSTERY) && (voice[i].right_mix>v))
v = voice[i].right_mix;
if(v<lv)
{
lv = v;
lowest = i;
}
}
}
return lowest;
}
int Player::find_samples(MidiEvent *e, int *vlist)
{
int i, j, ch, bank, prog, note, nv;
const SpecialPatch *s;
Instrument *ip;
ch = e->channel;
if (channel[ch].special_sample > 0) {
if ((s = instruments->specialPatch(channel[ch].special_sample)) == NULL) {
return 0;
}
note = e->a + channel[ch].key_shift + note_key_offset;
note = (note < 0) ? 0 : ((note > 127) ? 127 : note);
return select_play_sample(s->sample, s->samples, &note, vlist, e);
}
bank = channel[ch].bank;
if (ISDRUMCHANNEL(ch)) {
note = e->a & 0x7f;
instruments->instrument_map(channel[ch].mapID, &bank, &note);
if (! (ip = play_midi_load_instrument(1, bank, note)))
return 0; /* No instrument? Then we can't play. */
/* "keynum" of SF2, and patch option "note=" */
if (ip->sample->note_to_use)
note = ip->sample->note_to_use;
} else {
if ((prog = channel[ch].program) == SPECIAL_PROGRAM)
ip = instruments->defaultInstrument();
else {
instruments->instrument_map(channel[ch].mapID, &bank, &prog);
if (! (ip = play_midi_load_instrument(0, bank, prog)))
return 0; /* No instrument? Then we can't play. */
}
note = ((ip->sample->note_to_use) ? ip->sample->note_to_use : e->a)
+ channel[ch].key_shift + note_key_offset;
note = (note < 0) ? 0 : ((note > 127) ? 127 : note);
}
nv = select_play_sample(ip->sample, ip->samples, &note, vlist, e);
/* Replace the sample if the sample is cached. */
if (ip->sample->note_to_use)
note = MIDI_EVENT_NOTE(e);
for (i = 0; i < nv; i++) {
j = vlist[i];
if (! opt_realtime_playing && allocate_cache_size > 0
&& ! channel[ch].portamento) {
voice[j].cache = recache->resamp_cache_fetch(voice[j].sample, note);
if (voice[j].cache) /* cache hit */
voice[j].sample = voice[j].cache->resampled;
} else
voice[j].cache = NULL;
}
return nv;
}
int Player::select_play_sample(Sample *splist, int nsp, int *note, int *vlist, MidiEvent *e)
{
int ch = e->channel, kn = e->a & 0x7f, vel = e->b;
int32_t f, fs, ft, fst, fc, fr, cdiff, diff, sample_link;
int8_t tt = channel[ch].temper_type;
uint8_t tp = channel[ch].rpnmap[RPN_ADDR_0003];
Sample *sp, *spc, *spr;
int16_t sf, sn;
double ratio;
int i, j, k, nv, nvc;
if (ISDRUMCHANNEL(ch))
f = fs = freq_table[*note];
else {
if (opt_pure_intonation) {
if (current_keysig < 8)
f = freq_table_pureint[current_freq_table][*note];
else
f = freq_table_pureint[current_freq_table + 12][*note];
} else if (timidity_temper_control)
switch (tt) {
case 0:
f = freq_table_tuning[tp][*note];
break;
case 1:
if (current_temper_keysig < 8)
f = freq_table_pytha[
current_temper_freq_table][*note];
else
f = freq_table_pytha[
current_temper_freq_table + 12][*note];
break;
case 2:
if (current_temper_keysig < 8)
f = freq_table_meantone[current_temper_freq_table
+ ((temper_adj) ? 36 : 0)][*note];
else
f = freq_table_meantone[current_temper_freq_table
+ ((temper_adj) ? 24 : 12)][*note];
break;
case 3:
if (current_temper_keysig < 8)
f = freq_table_pureint[current_temper_freq_table
+ ((temper_adj) ? 36 : 0)][*note];
else
f = freq_table_pureint[current_temper_freq_table
+ ((temper_adj) ? 24 : 12)][*note];
break;
default: /* user-defined temperament */
if ((tt -= 0x40) >= 0 && tt < 4) {
if (current_temper_keysig < 8)
f = freq_table_user[tt][current_temper_freq_table
+ ((temper_adj) ? 36 : 0)][*note];
else
f = freq_table_user[tt][current_temper_freq_table
+ ((temper_adj) ? 24 : 12)][*note];
} else
f = freq_table[*note];
break;
}
else
f = freq_table[*note];
if (! opt_pure_intonation && timidity_temper_control
&& tt == 0 && f != freq_table[*note]) {
*note = log(f / 440000.0) / log(2) * 12 + 69.5;
*note = (*note < 0) ? 0 : ((*note > 127) ? 127 : *note);
fs = freq_table[*note];
} else
fs = freq_table[*note];
}
nv = 0;
for (i = 0, sp = splist; i < nsp; i++, sp++) {
/* GUS/SF2 - Scale Tuning */
if ((sf = sp->scale_factor) != 1024) {
sn = sp->scale_freq;
ratio = pow(2.0, (*note - sn) * (sf - 1024) / 12288.0);
ft = f * ratio + 0.5, fst = fs * ratio + 0.5;
} else
ft = f, fst = fs;
if (ISDRUMCHANNEL(ch) && channel[ch].drums[kn] != NULL)
if ((ratio = get_play_note_ratio(ch, kn)) != 1.0)
ft = ft * ratio + 0.5, fst = fst * ratio + 0.5;
if (sp->low_freq <= fst && sp->high_freq >= fst
&& sp->low_vel <= vel && sp->high_vel >= vel
&& ! (sp->inst_type == INST_SF2
&& sp->sample_type == SF_SAMPLETYPE_RIGHT)) {
j = vlist[nv] = find_voice(e);
voice[j].orig_frequency = ft;
voice[j].sample = sp;
voice[j].status = VOICE_ON;
nv++;
}
}
if (nv == 0) { /* we must select at least one sample. */
fr = fc = 0;
spc = spr = NULL;
cdiff = 0x7fffffff;
for (i = 0, sp = splist; i < nsp; i++, sp++) {
/* GUS/SF2 - Scale Tuning */
if ((sf = sp->scale_factor) != 1024) {
sn = sp->scale_freq;
ratio = pow(2.0, (*note - sn) * (sf - 1024) / 12288.0);
ft = f * ratio + 0.5, fst = fs * ratio + 0.5;
} else
ft = f, fst = fs;
if (ISDRUMCHANNEL(ch) && channel[ch].drums[kn] != NULL)
if ((ratio = get_play_note_ratio(ch, kn)) != 1.0)
ft = ft * ratio + 0.5, fst = fst * ratio + 0.5;
diff = abs(sp->root_freq - fst);
if (diff < cdiff) {
if (sp->inst_type == INST_SF2
&& sp->sample_type == SF_SAMPLETYPE_RIGHT) {
fr = ft; /* reserve */
spr = sp; /* reserve */
} else {
fc = ft;
spc = sp;
cdiff = diff;
}
}
}
/* If spc is not NULL, a makeshift sample is found. */
/* Otherwise, it's a lonely right sample, but better than nothing. */
j = vlist[nv] = find_voice(e);
voice[j].orig_frequency = (spc) ? fc : fr;
voice[j].sample = (spc) ? spc : spr;
voice[j].status = VOICE_ON;
nv++;
}
nvc = nv;
for (i = 0; i < nvc; i++) {
spc = voice[vlist[i]].sample;
/* If it's left sample, there must be right sample. */
if (spc->inst_type == INST_SF2
&& spc->sample_type == SF_SAMPLETYPE_LEFT) {
sample_link = spc->sf_sample_link;
for (j = 0, sp = splist; j < nsp; j++, sp++)
if (sp->inst_type == INST_SF2
&& sp->sample_type == SF_SAMPLETYPE_RIGHT
&& sp->sf_sample_index == sample_link) {
/* right sample is found. */
/* GUS/SF2 - Scale Tuning */
if ((sf = sp->scale_factor) != 1024) {
sn = sp->scale_freq;
ratio = pow(2.0, (*note - sn) * (sf - 1024) / 12288.0);
ft = f * ratio + 0.5;
} else
ft = f;
if (ISDRUMCHANNEL(ch) && channel[ch].drums[kn] != NULL)
if ((ratio = get_play_note_ratio(ch, kn)) != 1.0)
ft = ft * ratio + 0.5;
k = vlist[nv] = find_voice(e);
voice[k].orig_frequency = ft;
voice[k].sample = sp;
voice[k].status = VOICE_ON;
nv++;
break;
}
}
}
return nv;
}
double Player::get_play_note_ratio(int ch, int note)
{
int play_note = channel[ch].drums[note]->play_note;
int bank = channel[ch].bank;
const ToneBank *dbank;
int def_play_note;
if (play_note == -1)
return 1.0;
instruments->instrument_map(channel[ch].mapID, &bank, &note);
dbank = (instruments->drumSet(bank)) ? instruments->drumSet(bank) : instruments->drumSet(0);
if ((def_play_note = dbank->tone[note].play_note) == -1)
return 1.0;
if (play_note >= def_play_note)
return bend_coarse[(play_note - def_play_note) & 0x7f];
else
return 1 / bend_coarse[(def_play_note - play_note) & 0x7f];
}
/* Only one instance of a note can be playing on a single channel. */
int Player::find_voice(MidiEvent *e)
{
int ch = e->channel;
int note = MIDI_EVENT_NOTE(e);
int status_check, mono_check;
AlternateAssign *altassign;
int i, lowest = -1;
status_check = (timidity_overlap_voice_allow)
? (VOICE_OFF | VOICE_SUSTAINED) : 0xff;
mono_check = channel[ch].mono;
altassign = instruments->find_altassign(channel[ch].altassign, note);
for (i = 0; i < upper_voices; i++)
if (voice[i].status == VOICE_FREE) {
lowest = i; /* lower volume */
break;
}
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE && voice[i].channel == ch) {
if (voice[i].note == note && (voice[i].status & status_check))
kill_note(i);
else if (mono_check)
kill_note(i);
else if (altassign && instruments->find_altassign(altassign, voice[i].note))
kill_note(i);
else if (voice[i].note == note && (channel[ch].assign_mode == 0
|| (channel[ch].assign_mode == 1 &&
voice[i].proximate_flag == 0)))
kill_note(i);
}
for (i = 0; i < upper_voices; i++)
if (voice[i].channel == ch && voice[i].note == note)
voice[i].proximate_flag = 0;
if (lowest != -1) /* Found a free voice. */
return lowest;
if (upper_voices < voices)
return upper_voices++;
return reduce_voice();
}
int Player::get_panning(int ch, int note,int v)
{
int pan;
if(channel[ch].panning != NO_PANNING) {pan = (int)channel[ch].panning - 64;}
else {pan = 0;}
if(ISDRUMCHANNEL(ch) &&
channel[ch].drums[note] != NULL &&
channel[ch].drums[note]->drum_panning != NO_PANNING) {
pan += channel[ch].drums[note]->drum_panning;
} else {
pan += voice[v].sample->panning;
}
if (pan > 127) pan = 127;
else if (pan < 0) pan = 0;
return pan;
}
/*! initialize vibrato parameters for a voice. */
void Player::init_voice_vibrato(int v)
{
Voice *vp = &(voice[v]);
int ch = vp->channel, j, nrpn_vib_flag;
double ratio;
/* if NRPN vibrato is set, it's believed that there must be vibrato. */
nrpn_vib_flag = op_nrpn_vibrato
&& (channel[ch].vibrato_ratio != 1.0 || channel[ch].vibrato_depth != 0);
/* vibrato sweep */
vp->vibrato_sweep = vp->sample->vibrato_sweep_increment;
vp->vibrato_sweep_position = 0;
/* vibrato rate */
if (nrpn_vib_flag) {
if(vp->sample->vibrato_control_ratio == 0) {
ratio = cnv_Hz_to_vib_ratio(5.0) * channel[ch].vibrato_ratio;
} else {
ratio = (double)vp->sample->vibrato_control_ratio * channel[ch].vibrato_ratio;
}
if (ratio < 0) {ratio = 0;}
vp->vibrato_control_ratio = (int)ratio;
} else {
vp->vibrato_control_ratio = vp->sample->vibrato_control_ratio;
}
/* vibrato depth */
if (nrpn_vib_flag) {
vp->vibrato_depth = vp->sample->vibrato_depth + channel[ch].vibrato_depth;
if (vp->vibrato_depth > VIBRATO_DEPTH_MAX) {vp->vibrato_depth = VIBRATO_DEPTH_MAX;}
else if (vp->vibrato_depth < 1) {vp->vibrato_depth = 1;}
if (vp->sample->vibrato_depth < 0) { /* in opposite phase */
vp->vibrato_depth = -vp->vibrato_depth;
}
} else {
vp->vibrato_depth = vp->sample->vibrato_depth;
}
/* vibrato delay */
vp->vibrato_delay = vp->sample->vibrato_delay + channel[ch].vibrato_delay;
/* internal parameters */
vp->orig_vibrato_control_ratio = vp->vibrato_control_ratio;
vp->vibrato_control_counter = vp->vibrato_phase = 0;
for (j = 0; j < VIBRATO_SAMPLE_INCREMENTS; j++) {
vp->vibrato_sample_increment[j] = 0;
}
}
/*! initialize panning-delay for a voice. */
void Player::init_voice_pan_delay(int v)
{
#ifdef ENABLE_PAN_DELAY
Voice *vp = &(voice[v]);
int ch = vp->channel;
double pan_delay_diff;
if (vp->pan_delay_buf != NULL) {
free(vp->pan_delay_buf);
vp->pan_delay_buf = NULL;
}
vp->pan_delay_rpt = 0;
if (timidity_pan_delay && channel[ch].insertion_effect == 0 && !timidity_surround_chorus) {
if (vp->panning == 64) {vp->delay += pan_delay_table[64] * playback_rate / 1000;}
else {
if(pan_delay_table[vp->panning] > pan_delay_table[127 - vp->panning]) {
pan_delay_diff = pan_delay_table[vp->panning] - pan_delay_table[127 - vp->panning];
vp->delay += (pan_delay_table[vp->panning] - pan_delay_diff) * playback_rate / 1000;
} else {
pan_delay_diff = pan_delay_table[127 - vp->panning] - pan_delay_table[vp->panning];
vp->delay += (pan_delay_table[127 - vp->panning] - pan_delay_diff) * playback_rate / 1000;
}
vp->pan_delay_rpt = pan_delay_diff * playback_rate / 1000;
}
if(vp->pan_delay_rpt < 1) {vp->pan_delay_rpt = 0;}
vp->pan_delay_wpt = 0;
vp->pan_delay_spt = vp->pan_delay_wpt - vp->pan_delay_rpt;
if (vp->pan_delay_spt < 0) {vp->pan_delay_spt += PAN_DELAY_BUF_MAX;}
vp->pan_delay_buf = (int32_t *)safe_malloc(sizeof(int32_t) * PAN_DELAY_BUF_MAX);
memset(vp->pan_delay_buf, 0, sizeof(int32_t) * PAN_DELAY_BUF_MAX);
}
#endif /* ENABLE_PAN_DELAY */
}
/*! initialize portamento or legato for a voice. */
void Player::init_voice_portamento(int v)
{
Voice *vp = &(voice[v]);
int ch = vp->channel;
vp->porta_control_counter = 0;
if (channel[ch].legato && channel[ch].legato_flag) {
update_legato_controls(ch);
}
else if (channel[ch].portamento && !channel[ch].porta_control_ratio) {
update_portamento_controls(ch);
}
vp->porta_control_ratio = 0;
if (channel[ch].porta_control_ratio)
{
if (channel[ch].last_note_fine == -1) {
/* first on */
channel[ch].last_note_fine = vp->note * 256;
channel[ch].porta_control_ratio = 0;
}
else {
vp->porta_control_ratio = channel[ch].porta_control_ratio;
vp->porta_dpb = channel[ch].porta_dpb;
vp->porta_pb = channel[ch].last_note_fine -
vp->note * 256;
if (vp->porta_pb == 0) { vp->porta_control_ratio = 0; }
}
}
}
/*! initialize tremolo for a voice. */
void Player::init_voice_tremolo(int v)
{
Voice *vp = &(voice[v]);
vp->tremolo_delay = vp->sample->tremolo_delay;
vp->tremolo_phase = 0;
vp->tremolo_phase_increment = vp->sample->tremolo_phase_increment;
vp->tremolo_sweep = vp->sample->tremolo_sweep_increment;
vp->tremolo_sweep_position = 0;
vp->tremolo_depth = vp->sample->tremolo_depth;
}
void Player::start_note(MidiEvent *e, int i, int vid, int cnt)
{
int j, ch, note;
ch = e->channel;
note = MIDI_EVENT_NOTE(e);
voice[i].status = VOICE_ON;
voice[i].channel = ch;
voice[i].note = note;
voice[i].velocity = e->b;
voice[i].chorus_link = i; /* No link */
voice[i].proximate_flag = 1;
j = channel[ch].special_sample;
if (j == 0 || instruments->specialPatch(j) == NULL)
voice[i].sample_offset = 0;
else
{
voice[i].sample_offset = instruments->specialPatch(j)->sample_offset << FRACTION_BITS;
if (voice[i].sample->modes & MODES_LOOPING)
{
if (voice[i].sample_offset > voice[i].sample->loop_end)
voice[i].sample_offset = voice[i].sample->loop_start;
}
else if (voice[i].sample_offset > voice[i].sample->data_length)
{
free_voice(i);
return;
}
}
voice[i].sample_increment = 0; /* make sure it isn't negative */
voice[i].vid = vid;
voice[i].delay = voice[i].sample->envelope_delay;
voice[i].modenv_delay = voice[i].sample->modenv_delay;
voice[i].delay_counter = 0;
init_voice_tremolo(i); /* tremolo */
init_voice_filter(i); /* resonant lowpass filter */
init_voice_vibrato(i); /* vibrato */
voice[i].panning = get_panning(ch, note, i); /* pan */
init_voice_pan_delay(i); /* panning-delay */
init_voice_portamento(i); /* portamento or legato */
if (cnt == 0)
channel[ch].last_note_fine = voice[i].note * 256;
/* initialize modulation envelope */
if (voice[i].sample->modes & MODES_ENVELOPE)
{
voice[i].modenv_stage = EG_GUS_ATTACK;
voice[i].modenv_volume = 0;
mixer->recompute_modulation_envelope(i);
mixer->apply_modulation_envelope(i);
}
else
{
voice[i].modenv_increment = 0;
mixer->apply_modulation_envelope(i);
}
recompute_freq(i);
recompute_voice_filter(i);
recompute_amp(i);
/* initialize volume envelope */
if (voice[i].sample->modes & MODES_ENVELOPE)
{
/* Ramp up from 0 */
voice[i].envelope_stage = EG_GUS_ATTACK;
voice[i].envelope_volume = 0;
voice[i].control_counter = 0;
mixer->recompute_envelope(i);
mixer->apply_envelope_to_amp(i);
}
else
{
voice[i].envelope_increment = 0;
mixer->apply_envelope_to_amp(i);
}
voice[i].timeout = -1;
}
void Player::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 < EG_GUS_RELEASE1 */
voice[i].status = VOICE_OFF;
voice[i].envelope_stage = EG_GUS_RELEASE1;
mixer->recompute_envelope(i);
voice[i].modenv_stage = EG_GUS_RELEASE1;
mixer->recompute_modulation_envelope(i);
mixer->apply_modulation_envelope(i);
mixer->apply_envelope_to_amp(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;
}
}
}
void Player::set_envelope_time(int ch, int val, int stage)
{
val = val & 0x7F;
#if 0
switch(stage) {
case EG_ATTACK: /* Attack */
//printMessage(CMSG_INFO,VERB_NOISY,"Attack Time (CH:%d VALUE:%d)", ch, val);
break;
case EG_DECAY: /* Decay */
//printMessage(CMSG_INFO,VERB_NOISY,"Decay Time (CH:%d VALUE:%d)", ch, val);
break;
case EG_RELEASE: /* Release */
//printMessage(CMSG_INFO,VERB_NOISY,"Release Time (CH:%d VALUE:%d)", ch, val);
break;
default:
//printMessage(CMSG_INFO,VERB_NOISY,"? Time (CH:%d VALUE:%d)", ch, val);
}
#endif
channel[ch].envelope_rate[stage] = val;
}
/* Yet another chorus implementation
* by Eric A. Welsh <ewelsh@gpc.wustl.edu>.
*/
void Player::new_chorus_voice_alternate(int v1, int level)
{
int v2, ch, panlevel;
uint8_t pan;
double delay;
double freq, frac;
int note_adjusted;
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 *= (double)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)
{
v1 ^= v2;
v2 ^= v1;
v1 ^= v2;
}
/* 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;
}
delay = 0.003;
/* Try to keep the delayed voice from cancelling out the other voice */
/* Pitch detection is used to find the real pitches for drums and MODs */
note_adjusted = voice[v1].note + voice[v1].sample->transpose_detected;
if (note_adjusted > 127) note_adjusted = 127;
else if (note_adjusted < 0) note_adjusted = 0;
freq = pitch_freq_table[note_adjusted];
delay *= freq;
frac = delay - floor(delay);
/* force the delay away from 0.5 period */
if (frac < 0.5 && frac > 0.40)
{
delay = (floor(delay) + 0.40) / freq;
delay += (0.5 - frac) * (1.0 - labs(64 - pan) / 63.0) / freq;
}
else if (frac >= 0.5 && frac < 0.60)
{
delay = (floor(delay) + 0.60) / freq;
delay += (0.5 - frac) * (1.0 - labs(64 - pan) / 63.0) / freq;
}
else
delay = 0.003;
/* set panning & delay for pseudo-surround effect */
{
panlevel = 63;
if (pan - panlevel < 1) panlevel = pan - 1;
if (pan + panlevel > 127) panlevel = 127 - pan;
voice[v1].panning -= panlevel;
voice[v2].panning += panlevel;
/* choose which voice is delayed based on panning */
if (voice[v1].panned == PANNED_CENTER) {
/* randomly choose which voice is delayed */
if (int_rand(2))
voice[v1].delay += (int)(playback_rate * delay);
else
voice[v2].delay += (int)(playback_rate * delay);
}
else if (pan - 64 < 0) {
voice[v2].delay += (int)(playback_rate * delay);
}
else {
voice[v1].delay += (int)(playback_rate * delay);
}
}
/* check for similar drums playing simultaneously with center pans */
if (ISDRUMCHANNEL(ch) && voice[v1].panned == PANNED_CENTER)
{
int i, j;
/* force Rimshot (37), Snare1 (38), Snare2 (40), and XG #34 to have
* the same delay, otherwise there will be bad voice cancellation.
*/
if (voice[v1].note == 37 ||
voice[v1].note == 38 ||
voice[v1].note == 40 ||
(voice[v1].note == 34 && play_system_mode == XG_SYSTEM_MODE))
{
for (i = 0; i < upper_voices; i++)
{
if (voice[i].status & (VOICE_DIE | VOICE_FREE))
continue;
if (!ISDRUMCHANNEL(voice[i].channel))
continue;
if (i == v1 || i == v2)
continue;
if (voice[i].note == 37 ||
voice[i].note == 38 ||
voice[i].note == 40 ||
(voice[i].note == 34 &&
play_system_mode == XG_SYSTEM_MODE))
{
j = voice[i].chorus_link;
if (voice[i].panned == PANNED_LEFT &&
voice[j].panned == PANNED_RIGHT)
{
voice[v1].delay = voice[i].delay;
voice[v2].delay = voice[j].delay;
break;
}
}
}
}
/* force Kick1 (35), Kick2 (36), and XG Kick #33 to have the same
* delay, otherwise there will be bad voice cancellation.
*/
if (voice[v1].note == 35 ||
voice[v1].note == 36 ||
(voice[v1].note == 33 && play_system_mode == XG_SYSTEM_MODE))
{
for (i = 0; i < upper_voices; i++)
{
if (voice[i].status & (VOICE_DIE | VOICE_FREE))
continue;
if (!ISDRUMCHANNEL(voice[i].channel))
continue;
if (i == v1 || i == v2)
continue;
if (voice[i].note == 35 ||
voice[i].note == 36 ||
(voice[i].note == 33 &&
play_system_mode == XG_SYSTEM_MODE))
{
j = voice[i].chorus_link;
if (voice[i].panned == PANNED_LEFT &&
voice[j].panned == PANNED_RIGHT)
{
voice[v1].delay = voice[i].delay;
voice[v2].delay = voice[j].delay;
break;
}
}
}
}
}
init_voice_pan_delay(v1);
init_voice_pan_delay(v2);
recompute_amp(v1);
mixer->apply_envelope_to_amp(v1);
recompute_amp(v2);
mixer->apply_envelope_to_amp(v2);
if (level) recompute_freq(v2);
}
void Player::note_on(MidiEvent *e)
{
int i, nv, v, ch, note;
int vlist[32];
int vid;
int32_t random_delay = 0;
ch = e->channel;
note = MIDI_EVENT_NOTE(e);
if(ISDRUMCHANNEL(ch) &&
channel[ch].drums[note] != NULL &&
!get_rx_drum(channel[ch].drums[note], RX_NOTE_ON)) { /* Rx. Note On */
return;
}
if(channel[ch].note_limit_low > note ||
channel[ch].note_limit_high < note ||
channel[ch].vel_limit_low > e->b ||
channel[ch].vel_limit_high < e->b) {
return;
}
if((nv = find_samples(e, vlist)) == 0)
return;
vid = new_vidq(e->channel, note);
recompute_bank_parameter(ch, note);
recompute_channel_filter(ch, note);
random_delay = calc_random_delay(ch, note);
for(i = 0; i < nv; i++)
{
v = vlist[i];
if(ISDRUMCHANNEL(ch) &&
channel[ch].drums[note] != NULL &&
channel[ch].drums[note]->pan_random)
channel[ch].drums[note]->drum_panning = int_rand(128);
else if(channel[ch].pan_random)
{
channel[ch].panning = int_rand(128);
}
start_note(e, v, vid, nv - i - 1);
voice[v].delay += random_delay;
voice[v].modenv_delay += random_delay;
voice[v].old_left_mix = voice[v].old_right_mix =
voice[v].left_mix_inc = voice[v].left_mix_offset =
voice[v].right_mix_inc = voice[v].right_mix_offset = 0;
if(timidity_surround_chorus)
new_chorus_voice_alternate(v, 0);
}
channel[ch].legato_flag = 1;
}
/*! sostenuto is now implemented as an instant sustain */
void Player::update_sostenuto_controls(int ch)
{
int uv = upper_voices, i;
if(ISDRUMCHANNEL(ch) || channel[ch].sostenuto == 0) {return;}
for(i = 0; i < uv; i++)
{
if ((voice[i].status & (VOICE_ON | VOICE_OFF))
&& voice[i].channel == ch)
{
voice[i].status = VOICE_SUSTAINED;
voice[i].envelope_stage = EG_GUS_RELEASE1;
mixer->recompute_envelope(i);
}
}
}
/*! redamper effect for piano instruments */
void Player::update_redamper_controls(int ch)
{
int uv = upper_voices, i;
if(ISDRUMCHANNEL(ch) || channel[ch].damper_mode == 0) {return;}
for(i = 0; i < uv; i++)
{
if ((voice[i].status & (VOICE_ON | VOICE_OFF))
&& voice[i].channel == ch)
{
voice[i].status = VOICE_SUSTAINED;
voice[i].envelope_stage = EG_GUS_RELEASE1;
mixer->recompute_envelope(i);
}
}
}
void Player::note_off(MidiEvent *e)
{
int uv = upper_voices, i;
int ch, note, vid, sustain;
ch = e->channel;
note = MIDI_EVENT_NOTE(e);
if(ISDRUMCHANNEL(ch))
{
int nbank, nprog;
nbank = channel[ch].bank;
nprog = note;
instruments->instrument_map(channel[ch].mapID, &nbank, &nprog);
if (channel[ch].drums[nprog] != NULL &&
get_rx_drum(channel[ch].drums[nprog], RX_NOTE_OFF))
{
auto bank = instruments->drumSet(nbank);
if(bank == NULL) bank = instruments->drumSet(0);
/* uh oh, this drum doesn't have an instrument loaded yet */
if (bank->tone[nprog].instrument == NULL)
return;
/* this drum is not loaded for some reason (error occured?) */
if (IS_MAGIC_INSTRUMENT(bank->tone[nprog].instrument))
return;
/* only disallow Note Off if the drum sample is not looped */
if (!(bank->tone[nprog].instrument->sample->modes & MODES_LOOPING))
return; /* Note Off is not allowed. */
}
}
if ((vid = last_vidq(ch, note)) == -1)
return;
sustain = channel[ch].sustain;
for (i = 0; i < uv; i++)
{
if(voice[i].status == VOICE_ON &&
voice[i].channel == ch &&
voice[i].note == note &&
voice[i].vid == vid)
{
if(sustain)
{
voice[i].status = VOICE_SUSTAINED;
}
else
finish_note(i);
}
}
channel[ch].legato_flag = 0;
}
/* Process the All Notes Off event */
void Player::all_notes_off(int c)
{
int i, uv = upper_voices;
printMessage(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c);
for(i = 0; i < uv; i++)
if (voice[i].status==VOICE_ON &&
voice[i].channel==c)
{
if (channel[c].sustain)
{
voice[i].status=VOICE_SUSTAINED;
}
else
finish_note(i);
}
for(i = 0; i < 128; i++)
vidq_head[c * 128 + i] = vidq_tail[c * 128 + i] = 0;
}
/* Process the All Sounds Off event */
void Player::all_sounds_off(int c)
{
int i, uv = upper_voices;
for(i = 0; i < uv; i++)
if (voice[i].channel==c &&
(voice[i].status & ~(VOICE_FREE | VOICE_DIE)))
{
kill_note(i);
}
for(i = 0; i < 128; i++)
vidq_head[c * 128 + i] = vidq_tail[c * 128 + i] = 0;
}
/*! adjust polyphonic key pressure (PAf, PAT) */
void Player::adjust_pressure(MidiEvent *e)
{
int i, uv = upper_voices;
int note, ch;
if(timidity_channel_pressure)
{
ch = e->channel;
note = MIDI_EVENT_NOTE(e);
channel[ch].paf.val = e->b;
if(channel[ch].paf.pitch != 0) {channel[ch].pitchfactor = 0;}
for(i = 0; i < uv; i++)
if(voice[i].status == VOICE_ON &&
voice[i].channel == ch &&
voice[i].note == note)
{
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
recompute_freq(i);
recompute_voice_filter(i);
}
}
}
/*! adjust channel pressure (channel aftertouch, CAf, CAT) */
void Player::adjust_channel_pressure(MidiEvent *e)
{
if(timidity_channel_pressure)
{
int i, uv = upper_voices;
int ch;
ch = e->channel;
channel[ch].caf.val = e->a;
if(channel[ch].caf.pitch != 0) {channel[ch].pitchfactor = 0;}
for(i = 0; i < uv; i++)
{
if(voice[i].status == VOICE_ON && voice[i].channel == ch)
{
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
recompute_freq(i);
recompute_voice_filter(i);
}
}
}
}
void Player::adjust_panning(int c)
{
int i, uv = upper_voices, pan = channel[c].panning;
for(i = 0; i < uv; i++)
{
if ((voice[i].channel==c) &&
(voice[i].status & (VOICE_ON | VOICE_SUSTAINED)))
{
/* adjust pan to include drum/sample pan offsets */
pan = get_panning(c, voice[i].note, i);
/* Hack to handle -EFchorus=2 in a "reasonable" way */
if(timidity_surround_chorus && voice[i].chorus_link != i)
{
int v1, v2;
if(i >= voice[i].chorus_link)
/* `i' is not base chorus voice.
* This sub voice is already updated.
*/
continue;
v1 = i; /* base voice */
v2 = voice[i].chorus_link; /* sub voice (detuned) */
if(timidity_surround_chorus) /* Surround chorus mode by Eric. */
{
int panlevel;
if (!pan) pan = 1; /* make hard left be 1 instead of 0 */
panlevel = 63;
if (pan - panlevel < 1) panlevel = pan - 1;
if (pan + panlevel > 127) panlevel = 127 - pan;
voice[v1].panning = pan - panlevel;
voice[v2].panning = pan + panlevel;
}
else
{
voice[v1].panning = pan;
if(pan > 60 && pan < 68) /* PANNED_CENTER */
voice[v2].panning =
64 + int_rand(40) - 20; /* 64 +- rand(20) */
else if(pan < CHORUS_OPPOSITE_THRESHOLD)
voice[v2].panning = 127;
else if(pan > 127 - CHORUS_OPPOSITE_THRESHOLD)
voice[v2].panning = 0;
else
voice[v2].panning = (pan < 64 ? 0 : 127);
}
recompute_amp(v2);
mixer->apply_envelope_to_amp(v2);
/* v1 == i, so v1 will be updated next */
}
else
voice[i].panning = pan;
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
}
}
}
void Player::play_midi_setup_drums(int ch, int note)
{
channel[ch].drums[note] = (struct DrumParts *)
new_segment(&playmidi_pool, sizeof(struct DrumParts));
reset_drum_controllers(channel[ch].drums, note);
}
void Player::adjust_drum_panning(int ch, int note)
{
int i, uv = upper_voices;
for(i = 0; i < uv; i++) {
if(voice[i].channel == ch &&
voice[i].note == note &&
(voice[i].status & (VOICE_ON | VOICE_SUSTAINED)))
{
voice[i].panning = get_panning(ch, note, i);
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
}
}
}
void Player::drop_sustain(int c)
{
int i, uv = upper_voices;
for(i = 0; i < uv; i++)
if (voice[i].status == VOICE_SUSTAINED && voice[i].channel == c)
finish_note(i);
}
void Player::adjust_all_pitch(void)
{
int ch, i, uv = upper_voices;
for (ch = 0; ch < MAX_CHANNELS; ch++)
channel[ch].pitchfactor = 0;
for (i = 0; i < uv; i++)
if (voice[i].status != VOICE_FREE)
recompute_freq(i);
}
void Player::adjust_pitch(int c)
{
int i, uv = upper_voices;
for(i = 0; i < uv; i++)
if (voice[i].status != VOICE_FREE && voice[i].channel == c)
recompute_freq(i);
}
void Player::adjust_volume(int c)
{
int i, uv = upper_voices;
for(i = 0; i < uv; i++)
if (voice[i].channel == c &&
(voice[i].status & (VOICE_ON | VOICE_SUSTAINED)))
{
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
}
}
void Player::set_reverb_level(int ch, int level)
{
if (level == -1) {
channel[ch].reverb_level = channel[ch].reverb_id =
(timidity_reverb < 0)
? -timidity_reverb & 0x7f : DEFAULT_REVERB_SEND_LEVEL;
make_rvid_flag = 1;
return;
}
channel[ch].reverb_level = level;
make_rvid_flag = 0; /* to update reverb_id */
}
int Player::get_reverb_level(int ch)
{
if (channel[ch].reverb_level == -1)
return (timidity_reverb < 0)
? -timidity_reverb & 0x7f : DEFAULT_REVERB_SEND_LEVEL;
return channel[ch].reverb_level;
}
int Player::get_chorus_level(int ch)
{
#ifdef DISALLOW_DRUM_BENDS
if(ISDRUMCHANNEL(ch))
return 0; /* Not supported drum channel chorus */
#endif
if(timidity_chorus == 1)
return channel[ch].chorus_level;
return -timidity_chorus;
}
void Player::free_drum_effect(int ch)
{
int i;
if (channel[ch].drum_effect != NULL) {
for (i = 0; i < channel[ch].drum_effect_num; i++) {
if (channel[ch].drum_effect[i].buf != NULL) {
free(channel[ch].drum_effect[i].buf);
channel[ch].drum_effect[i].buf = NULL;
}
}
free(channel[ch].drum_effect);
channel[ch].drum_effect = NULL;
}
channel[ch].drum_effect_num = 0;
channel[ch].drum_effect_flag = 0;
}
void Player::make_drum_effect(int ch)
{
int i, note, num = 0;
int8_t note_table[128];
struct DrumParts *drum;
struct DrumPartEffect *de;
if (channel[ch].drum_effect_flag == 0) {
free_drum_effect(ch);
memset(note_table, 0, sizeof(int8_t) * 128);
for(i = 0; i < 128; i++) {
if ((drum = channel[ch].drums[i]) != NULL)
{
if (drum->reverb_level != -1
|| drum->chorus_level != -1 || drum->delay_level != -1) {
note_table[num++] = i;
}
}
}
channel[ch].drum_effect = (struct DrumPartEffect *)safe_malloc(sizeof(struct DrumPartEffect) * num);
for(i = 0; i < num; i++) {
de = &(channel[ch].drum_effect[i]);
de->note = note = note_table[i];
drum = channel[ch].drums[note];
de->reverb_send = (int32_t)drum->reverb_level * (int32_t)get_reverb_level(ch) / 127;
de->chorus_send = (int32_t)drum->chorus_level * (int32_t)channel[ch].chorus_level / 127;
de->delay_send = (int32_t)drum->delay_level * (int32_t)channel[ch].delay_level / 127;
de->buf = (int32_t *)safe_malloc(AUDIO_BUFFER_SIZE * 8);
memset(de->buf, 0, AUDIO_BUFFER_SIZE * 8);
}
channel[ch].drum_effect_num = num;
channel[ch].drum_effect_flag = 1;
}
}
void Player::adjust_master_volume(void)
{
int i, uv = upper_voices;
adjust_amplification();
for(i = 0; i < uv; i++)
if(voice[i].status & (VOICE_ON | VOICE_SUSTAINED))
{
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
}
}
int Player::midi_drumpart_change(int ch, int isdrum)
{
if (IS_SET_CHANNELMASK(drumchannel_mask, ch))
return 0;
if (isdrum) {
SET_CHANNELMASK(drumchannels, ch);
SET_CHANNELMASK(current_file_info->drumchannels, ch);
} else {
UNSET_CHANNELMASK(drumchannels, ch);
UNSET_CHANNELMASK(current_file_info->drumchannels, ch);
}
return 1;
}
void Player::midi_program_change(int ch, int prog)
{
int dr = ISDRUMCHANNEL(ch);
int newbank, b, p, map;
switch (play_system_mode) {
case GS_SYSTEM_MODE: /* GS */
if ((map = channel[ch].bank_lsb) == 0) {
map = channel[ch].tone_map0_number;
}
switch (map) {
case 0: /* No change */
break;
case 1:
channel[ch].mapID = (dr) ? SC_55_DRUM_MAP : SC_55_TONE_MAP;
break;
case 2:
channel[ch].mapID = (dr) ? SC_88_DRUM_MAP : SC_88_TONE_MAP;
break;
case 3:
channel[ch].mapID = (dr) ? SC_88PRO_DRUM_MAP : SC_88PRO_TONE_MAP;
break;
case 4:
channel[ch].mapID = (dr) ? SC_8850_DRUM_MAP : SC_8850_TONE_MAP;
break;
default:
break;
}
newbank = channel[ch].bank_msb;
break;
case XG_SYSTEM_MODE: /* XG */
switch (channel[ch].bank_msb) {
case 0: /* Normal */
#if 0
if (ch == 9 && channel[ch].bank_lsb == 127
&& channel[ch].mapID == XG_DRUM_MAP)
/* FIXME: Why this part is drum? Is this correct? */
break;
#endif
/* Eric's explanation for the FIXME (March 2004):
*
* I don't have the original email from my archived inbox, but I found a
* reply I made in my archived sent-mail from 1999. A September 5th message
* to Masanao Izumo is discussing a problem with a "reapxg.mid", a file which
* I still have, and how it issues an MSB=0 with a program change on ch 9,
* thus turning it into a melodic channel. The strange thing is, this doesn't
* happen on XG hardware, nor on the XG softsynth. It continues to play as a
* normal drum. The author of the midi file obviously intended it to be
* drumset 16 too. The original fix was to detect LSB == -1, then break so
* as to not set it to a melodic channel. I'm guessing that this somehow got
* mutated into checking for 127 instead, and the current FIXME is related to
* the original hack from Sept 1999. The Sept 5th email discusses patches
* being applied to version 2.5.1 to get XG drums to work properly, and a
* Sept 7th email to someone else discusses the fixes being part of the
* latest 2.6.0-beta3. A September 23rd email to Masanao Izumo specifically
* mentions the LSB == -1 hack (and reapxg.mid not playing "correctly"
* anymore), as well as new changes in 2.6.0 that broke a lot of other XG
* files (XG drum support was extremely buggy in 1999 and we were still trying
* to figure out how to initialize things to reproduce hardware behavior). An
* October 5th email says that 2.5.1 was correct, 2.6.0 had very broken XG
* drum changes, and 2.6.1 still has problems. Further discussions ensued
* over what was "correct": to follow the XG spec, or to reproduce
* "features" / bugs in the hardware. I can't find the rest of the
* discussions, but I think it ended with us agreeing to just follow the spec
* and not try to reproduce the hardware strangeness. I don't know how the
* current FIXME wound up the way it is now. I'm still going to guess it is
* related to the old reapxg.mid hack.
*
* Now that reset_midi() initializes channel[ch].bank_lsb to 0 instead of -1,
* checking for LSB == -1 won't do anything anymore, so changing the above
* FIXME to the original == -1 won't do any good. It is best to just #if 0
* it out and leave it here as a reminder that there is at least one XG
* hardware / softsynth "bug" that is not reproduced by timidity at the
* moment.
*
* If the current FIXME actually reproduces some other XG hadware bug that
* I don't know about, then it may have a valid purpose. I just don't know
* what that purpose is at the moment. Perhaps someone else does? I still
* have src going back to 2.10.4, and the FIXME comment was already there by
* then. I don't see any entries in the Changelog that could explain it
* either. If someone has src from 2.5.1 through 2.10.3 and wants to
* investigate this further, go for it :)
*/
midi_drumpart_change(ch, 0);
channel[ch].mapID = XG_NORMAL_MAP;
dr = ISDRUMCHANNEL(ch);
break;
case 64: /* SFX voice */
midi_drumpart_change(ch, 0);
channel[ch].mapID = XG_SFX64_MAP;
dr = ISDRUMCHANNEL(ch);
break;
case 126: /* SFX kit */
midi_drumpart_change(ch, 1);
channel[ch].mapID = XG_SFX126_MAP;
dr = ISDRUMCHANNEL(ch);
break;
case 127: /* Drum kit */
midi_drumpart_change(ch, 1);
channel[ch].mapID = XG_DRUM_MAP;
dr = ISDRUMCHANNEL(ch);
break;
default:
break;
}
newbank = channel[ch].bank_lsb;
break;
case GM2_SYSTEM_MODE: /* GM2 */
if ((channel[ch].bank_msb & 0xfe) == 0x78) { /* 0x78/0x79 */
midi_drumpart_change(ch, channel[ch].bank_msb == 0x78);
dr = ISDRUMCHANNEL(ch);
}
channel[ch].mapID = (dr) ? GM2_DRUM_MAP : GM2_TONE_MAP;
newbank = channel[ch].bank_lsb;
break;
default:
newbank = channel[ch].bank_msb;
break;
}
if (dr) {
channel[ch].bank = prog; /* newbank is ignored */
channel[ch].program = prog;
if (instruments->drumSet(prog) == NULL || instruments->drumSet(prog)->alt == NULL)
channel[ch].altassign = instruments->drumSet(0)->alt;
else
channel[ch].altassign = instruments->drumSet(prog)->alt;
} else {
channel[ch].bank = (special_tonebank >= 0)
? special_tonebank : newbank;
channel[ch].program = (instruments->defaultProgram(ch) == SPECIAL_PROGRAM)
? SPECIAL_PROGRAM : prog;
channel[ch].altassign = NULL;
if (opt_realtime_playing)
{
b = channel[ch].bank, p = prog;
instruments->instrument_map(channel[ch].mapID, &b, &p);
play_midi_load_instrument(0, b, p);
}
}
}
/*! add a new layer. */
void Player::add_channel_layer(int to_ch, int from_ch)
{
if (to_ch >= MAX_CHANNELS || from_ch >= MAX_CHANNELS)
return;
/* add a channel layer */
UNSET_CHANNELMASK(channel[to_ch].channel_layer, to_ch);
SET_CHANNELMASK(channel[to_ch].channel_layer, from_ch);
//printMessage(CMSG_INFO,VERB_NOISY,"Channel Layer (CH:%d -> CH:%d)", from_ch, to_ch);
}
/*! remove all layers for this channel. */
void Player::remove_channel_layer(int ch)
{
int i, offset;
if (ch >= MAX_CHANNELS)
return;
/* remove channel layers */
offset = ch & ~0xf;
for (i = offset; i < offset + REDUCE_CHANNELS; i++)
UNSET_CHANNELMASK(channel[i].channel_layer, ch);
SET_CHANNELMASK(channel[ch].channel_layer, ch);
}
/*! process system exclusive sent from parse_sysex_event_multi(). */
void Player::process_sysex_event(int ev, int ch, int val, int b)
{
int temp, msb, note;
if (ch >= MAX_CHANNELS)
return;
if (ev == ME_SYSEX_MSB) {
channel[ch].sysex_msb_addr = b;
channel[ch].sysex_msb_val = val;
} else if(ev == ME_SYSEX_GS_MSB) {
channel[ch].sysex_gs_msb_addr = b;
channel[ch].sysex_gs_msb_val = val;
} else if(ev == ME_SYSEX_XG_MSB) {
channel[ch].sysex_xg_msb_addr = b;
channel[ch].sysex_xg_msb_val = val;
} else if(ev == ME_SYSEX_LSB) { /* Universal system exclusive message */
msb = channel[ch].sysex_msb_addr;
note = channel[ch].sysex_msb_val;
channel[ch].sysex_msb_addr = channel[ch].sysex_msb_val = 0;
switch(b)
{
case 0x00: /* CAf Pitch Control */
if(val > 0x58) {val = 0x58;}
else if(val < 0x28) {val = 0x28;}
channel[ch].caf.pitch = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf Pitch Control (CH:%d %d semitones)", ch, channel[ch].caf.pitch);
break;
case 0x01: /* CAf Filter Cutoff Control */
channel[ch].caf.cutoff = (val - 64) * 150;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf Filter Cutoff Control (CH:%d %d cents)", ch, channel[ch].caf.cutoff);
break;
case 0x02: /* CAf Amplitude Control */
channel[ch].caf.amp = (float)val / 64.0f - 1.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf Amplitude Control (CH:%d %.2f)", ch, channel[ch].caf.amp);
break;
case 0x03: /* CAf LFO1 Rate Control */
channel[ch].caf.lfo1_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO1 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].caf.lfo1_rate);
break;
case 0x04: /* CAf LFO1 Pitch Depth */
channel[ch].caf.lfo1_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO1 Pitch Depth (CH:%d %d cents)", ch, channel[ch].caf.lfo1_pitch_depth);
break;
case 0x05: /* CAf LFO1 Filter Depth */
channel[ch].caf.lfo1_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO1 Filter Depth (CH:%d %d cents)", ch, channel[ch].caf.lfo1_tvf_depth);
break;
case 0x06: /* CAf LFO1 Amplitude Depth */
channel[ch].caf.lfo1_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO1 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].caf.lfo1_tva_depth);
break;
case 0x07: /* CAf LFO2 Rate Control */
channel[ch].caf.lfo2_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO2 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].caf.lfo2_rate);
break;
case 0x08: /* CAf LFO2 Pitch Depth */
channel[ch].caf.lfo2_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO2 Pitch Depth (CH:%d %d cents)", ch, channel[ch].caf.lfo2_pitch_depth);
break;
case 0x09: /* CAf LFO2 Filter Depth */
channel[ch].caf.lfo2_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO2 Filter Depth (CH:%d %d cents)", ch, channel[ch].caf.lfo2_tvf_depth);
break;
case 0x0A: /* CAf LFO2 Amplitude Depth */
channel[ch].caf.lfo2_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CAf LFO2 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].caf.lfo2_tva_depth);
break;
case 0x0B: /* PAf Pitch Control */
if(val > 0x58) {val = 0x58;}
else if(val < 0x28) {val = 0x28;}
channel[ch].paf.pitch = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf Pitch Control (CH:%d %d semitones)", ch, channel[ch].paf.pitch);
break;
case 0x0C: /* PAf Filter Cutoff Control */
channel[ch].paf.cutoff = (val - 64) * 150;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf Filter Cutoff Control (CH:%d %d cents)", ch, channel[ch].paf.cutoff);
break;
case 0x0D: /* PAf Amplitude Control */
channel[ch].paf.amp = (float)val / 64.0f - 1.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf Amplitude Control (CH:%d %.2f)", ch, channel[ch].paf.amp);
break;
case 0x0E: /* PAf LFO1 Rate Control */
channel[ch].paf.lfo1_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO1 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].paf.lfo1_rate);
break;
case 0x0F: /* PAf LFO1 Pitch Depth */
channel[ch].paf.lfo1_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO1 Pitch Depth (CH:%d %d cents)", ch, channel[ch].paf.lfo1_pitch_depth);
break;
case 0x10: /* PAf LFO1 Filter Depth */
channel[ch].paf.lfo1_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO1 Filter Depth (CH:%d %d cents)", ch, channel[ch].paf.lfo1_tvf_depth);
break;
case 0x11: /* PAf LFO1 Amplitude Depth */
channel[ch].paf.lfo1_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO1 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].paf.lfo1_tva_depth);
break;
case 0x12: /* PAf LFO2 Rate Control */
channel[ch].paf.lfo2_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO2 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].paf.lfo2_rate);
break;
case 0x13: /* PAf LFO2 Pitch Depth */
channel[ch].paf.lfo2_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO2 Pitch Depth (CH:%d %d cents)", ch, channel[ch].paf.lfo2_pitch_depth);
break;
case 0x14: /* PAf LFO2 Filter Depth */
channel[ch].paf.lfo2_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO2 Filter Depth (CH:%d %d cents)", ch, channel[ch].paf.lfo2_tvf_depth);
break;
case 0x15: /* PAf LFO2 Amplitude Depth */
channel[ch].paf.lfo2_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"PAf LFO2 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].paf.lfo2_tva_depth);
break;
case 0x16: /* MOD Pitch Control */
if(val > 0x58) {val = 0x58;}
else if(val < 0x28) {val = 0x28;}
channel[ch].mod.pitch = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD Pitch Control (CH:%d %d semitones)", ch, channel[ch].mod.pitch);
break;
case 0x17: /* MOD Filter Cutoff Control */
channel[ch].mod.cutoff = (val - 64) * 150;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD Filter Cutoff Control (CH:%d %d cents)", ch, channel[ch].mod.cutoff);
break;
case 0x18: /* MOD Amplitude Control */
channel[ch].mod.amp = (float)val / 64.0f - 1.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD Amplitude Control (CH:%d %.2f)", ch, channel[ch].mod.amp);
break;
case 0x19: /* MOD LFO1 Rate Control */
channel[ch].mod.lfo1_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO1 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].mod.lfo1_rate);
break;
case 0x1A: /* MOD LFO1 Pitch Depth */
channel[ch].mod.lfo1_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO1 Pitch Depth (CH:%d %d cents)", ch, channel[ch].mod.lfo1_pitch_depth);
break;
case 0x1B: /* MOD LFO1 Filter Depth */
channel[ch].mod.lfo1_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO1 Filter Depth (CH:%d %d cents)", ch, channel[ch].mod.lfo1_tvf_depth);
break;
case 0x1C: /* MOD LFO1 Amplitude Depth */
channel[ch].mod.lfo1_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO1 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].mod.lfo1_tva_depth);
break;
case 0x1D: /* MOD LFO2 Rate Control */
channel[ch].mod.lfo2_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO2 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].mod.lfo2_rate);
break;
case 0x1E: /* MOD LFO2 Pitch Depth */
channel[ch].mod.lfo2_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO2 Pitch Depth (CH:%d %d cents)", ch, channel[ch].mod.lfo2_pitch_depth);
break;
case 0x1F: /* MOD LFO2 Filter Depth */
channel[ch].mod.lfo2_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO2 Filter Depth (CH:%d %d cents)", ch, channel[ch].mod.lfo2_tvf_depth);
break;
case 0x20: /* MOD LFO2 Amplitude Depth */
channel[ch].mod.lfo2_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"MOD LFO2 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].mod.lfo2_tva_depth);
break;
case 0x21: /* BEND Pitch Control */
if(val > 0x58) {val = 0x58;}
else if(val < 0x28) {val = 0x28;}
channel[ch].bend.pitch = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND Pitch Control (CH:%d %d semitones)", ch, channel[ch].bend.pitch);
break;
case 0x22: /* BEND Filter Cutoff Control */
channel[ch].bend.cutoff = (val - 64) * 150;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND Filter Cutoff Control (CH:%d %d cents)", ch, channel[ch].bend.cutoff);
break;
case 0x23: /* BEND Amplitude Control */
channel[ch].bend.amp = (float)val / 64.0f - 1.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND Amplitude Control (CH:%d %.2f)", ch, channel[ch].bend.amp);
break;
case 0x24: /* BEND LFO1 Rate Control */
channel[ch].bend.lfo1_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO1 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].bend.lfo1_rate);
break;
case 0x25: /* BEND LFO1 Pitch Depth */
channel[ch].bend.lfo1_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO1 Pitch Depth (CH:%d %d cents)", ch, channel[ch].bend.lfo1_pitch_depth);
break;
case 0x26: /* BEND LFO1 Filter Depth */
channel[ch].bend.lfo1_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO1 Filter Depth (CH:%d %d cents)", ch, channel[ch].bend.lfo1_tvf_depth);
break;
case 0x27: /* BEND LFO1 Amplitude Depth */
channel[ch].bend.lfo1_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO1 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].bend.lfo1_tva_depth);
break;
case 0x28: /* BEND LFO2 Rate Control */
channel[ch].bend.lfo2_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO2 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].bend.lfo2_rate);
break;
case 0x29: /* BEND LFO2 Pitch Depth */
channel[ch].bend.lfo2_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO2 Pitch Depth (CH:%d %d cents)", ch, channel[ch].bend.lfo2_pitch_depth);
break;
case 0x2A: /* BEND LFO2 Filter Depth */
channel[ch].bend.lfo2_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO2 Filter Depth (CH:%d %d cents)", ch, channel[ch].bend.lfo2_tvf_depth);
break;
case 0x2B: /* BEND LFO2 Amplitude Depth */
channel[ch].bend.lfo2_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"BEND LFO2 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].bend.lfo2_tva_depth);
break;
case 0x2C: /* CC1 Pitch Control */
if(val > 0x58) {val = 0x58;}
else if(val < 0x28) {val = 0x28;}
channel[ch].cc1.pitch = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 Pitch Control (CH:%d %d semitones)", ch, channel[ch].cc1.pitch);
break;
case 0x2D: /* CC1 Filter Cutoff Control */
channel[ch].cc1.cutoff = (val - 64) * 150;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 Filter Cutoff Control (CH:%d %d cents)", ch, channel[ch].cc1.cutoff);
break;
case 0x2E: /* CC1 Amplitude Control */
channel[ch].cc1.amp = (float)val / 64.0f - 1.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 Amplitude Control (CH:%d %.2f)", ch, channel[ch].cc1.amp);
break;
case 0x2F: /* CC1 LFO1 Rate Control */
channel[ch].cc1.lfo1_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO1 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].cc1.lfo1_rate);
break;
case 0x30: /* CC1 LFO1 Pitch Depth */
channel[ch].cc1.lfo1_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO1 Pitch Depth (CH:%d %d cents)", ch, channel[ch].cc1.lfo1_pitch_depth);
break;
case 0x31: /* CC1 LFO1 Filter Depth */
channel[ch].cc1.lfo1_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO1 Filter Depth (CH:%d %d cents)", ch, channel[ch].cc1.lfo1_tvf_depth);
break;
case 0x32: /* CC1 LFO1 Amplitude Depth */
channel[ch].cc1.lfo1_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO1 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].cc1.lfo1_tva_depth);
break;
case 0x33: /* CC1 LFO2 Rate Control */
channel[ch].cc1.lfo2_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO2 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].cc1.lfo2_rate);
break;
case 0x34: /* CC1 LFO2 Pitch Depth */
channel[ch].cc1.lfo2_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO2 Pitch Depth (CH:%d %d cents)", ch, channel[ch].cc1.lfo2_pitch_depth);
break;
case 0x35: /* CC1 LFO2 Filter Depth */
channel[ch].cc1.lfo2_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO2 Filter Depth (CH:%d %d cents)", ch, channel[ch].cc1.lfo2_tvf_depth);
break;
case 0x36: /* CC1 LFO2 Amplitude Depth */
channel[ch].cc1.lfo2_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 LFO2 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].cc1.lfo2_tva_depth);
break;
case 0x37: /* CC2 Pitch Control */
if(val > 0x58) {val = 0x58;}
else if(val < 0x28) {val = 0x28;}
channel[ch].cc2.pitch = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 Pitch Control (CH:%d %d semitones)", ch, channel[ch].cc2.pitch);
break;
case 0x38: /* CC2 Filter Cutoff Control */
channel[ch].cc2.cutoff = (val - 64) * 150;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 Filter Cutoff Control (CH:%d %d cents)", ch, channel[ch].cc2.cutoff);
break;
case 0x39: /* CC2 Amplitude Control */
channel[ch].cc2.amp = (float)val / 64.0f - 1.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 Amplitude Control (CH:%d %.2f)", ch, channel[ch].cc2.amp);
break;
case 0x3A: /* CC2 LFO1 Rate Control */
channel[ch].cc2.lfo1_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO1 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].cc2.lfo1_rate);
break;
case 0x3B: /* CC2 LFO1 Pitch Depth */
channel[ch].cc2.lfo1_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO1 Pitch Depth (CH:%d %d cents)", ch, channel[ch].cc2.lfo1_pitch_depth);
break;
case 0x3C: /* CC2 LFO1 Filter Depth */
channel[ch].cc2.lfo1_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO1 Filter Depth (CH:%d %d cents)", ch, channel[ch].cc2.lfo1_tvf_depth);
break;
case 0x3D: /* CC2 LFO1 Amplitude Depth */
channel[ch].cc2.lfo1_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO1 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].cc2.lfo1_tva_depth);
break;
case 0x3E: /* CC2 LFO2 Rate Control */
channel[ch].cc2.lfo2_rate = (float)(val - 64) / 6.4f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO2 Rate Control (CH:%d %.1f Hz)", ch, channel[ch].cc2.lfo2_rate);
break;
case 0x3F: /* CC2 LFO2 Pitch Depth */
channel[ch].cc2.lfo2_pitch_depth = conv_lfo_pitch_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO2 Pitch Depth (CH:%d %d cents)", ch, channel[ch].cc2.lfo2_pitch_depth);
break;
case 0x40: /* CC2 LFO2 Filter Depth */
channel[ch].cc2.lfo2_tvf_depth = conv_lfo_filter_depth(val);
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO2 Filter Depth (CH:%d %d cents)", ch, channel[ch].cc2.lfo2_tvf_depth);
break;
case 0x41: /* CC2 LFO2 Amplitude Depth */
channel[ch].cc2.lfo2_tva_depth = (float)val / 127.0f;
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 LFO2 Amplitude Depth (CH:%d %.2f)", ch, channel[ch].cc2.lfo2_tva_depth);
break;
case 0x42: /* Note Limit Low */
channel[ch].note_limit_low = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Note Limit Low (CH:%d VAL:%d)", ch, val);
break;
case 0x43: /* Note Limit High */
channel[ch].note_limit_high = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Note Limit High (CH:%d VAL:%d)", ch, val);
break;
case 0x44: /* Velocity Limit Low */
channel[ch].vel_limit_low = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Velocity Limit Low (CH:%d VAL:%d)", ch, val);
break;
case 0x45: /* Velocity Limit High */
channel[ch].vel_limit_high = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Velocity Limit High (CH:%d VAL:%d)", ch, val);
break;
case 0x46: /* Rx. Note Off */
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
set_rx_drum(channel[ch].drums[note], RX_NOTE_OFF, val);
printMessage(CMSG_INFO, VERB_NOISY,
"Drum Instrument Rx. Note Off (CH:%d NOTE:%d VAL:%d)",
ch, note, val);
break;
case 0x47: /* Rx. Note On */
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
set_rx_drum(channel[ch].drums[note], RX_NOTE_ON, val);
printMessage(CMSG_INFO, VERB_NOISY,
"Drum Instrument Rx. Note On (CH:%d NOTE:%d VAL:%d)",
ch, note, val);
break;
case 0x48: /* Rx. Pitch Bend */
set_rx(ch, RX_PITCH_BEND, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Pitch Bend (CH:%d VAL:%d)", ch, val);
break;
case 0x49: /* Rx. Channel Pressure */
set_rx(ch, RX_CH_PRESSURE, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Channel Pressure (CH:%d VAL:%d)", ch, val);
break;
case 0x4A: /* Rx. Program Change */
set_rx(ch, RX_PROGRAM_CHANGE, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Program Change (CH:%d VAL:%d)", ch, val);
break;
case 0x4B: /* Rx. Control Change */
set_rx(ch, RX_CONTROL_CHANGE, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Control Change (CH:%d VAL:%d)", ch, val);
break;
case 0x4C: /* Rx. Poly Pressure */
set_rx(ch, RX_POLY_PRESSURE, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Poly Pressure (CH:%d VAL:%d)", ch, val);
break;
case 0x4D: /* Rx. Note Message */
set_rx(ch, RX_NOTE_MESSAGE, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Note Message (CH:%d VAL:%d)", ch, val);
break;
case 0x4E: /* Rx. RPN */
set_rx(ch, RX_RPN, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. RPN (CH:%d VAL:%d)", ch, val);
break;
case 0x4F: /* Rx. NRPN */
set_rx(ch, RX_NRPN, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. NRPN (CH:%d VAL:%d)", ch, val);
break;
case 0x50: /* Rx. Modulation */
set_rx(ch, RX_MODULATION, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Modulation (CH:%d VAL:%d)", ch, val);
break;
case 0x51: /* Rx. Volume */
set_rx(ch, RX_VOLUME, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Volume (CH:%d VAL:%d)", ch, val);
break;
case 0x52: /* Rx. Panpot */
set_rx(ch, RX_PANPOT, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Panpot (CH:%d VAL:%d)", ch, val);
break;
case 0x53: /* Rx. Expression */
set_rx(ch, RX_EXPRESSION, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Expression (CH:%d VAL:%d)", ch, val);
break;
case 0x54: /* Rx. Hold1 */
set_rx(ch, RX_HOLD1, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Hold1 (CH:%d VAL:%d)", ch, val);
break;
case 0x55: /* Rx. Portamento */
set_rx(ch, RX_PORTAMENTO, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Portamento (CH:%d VAL:%d)", ch, val);
break;
case 0x56: /* Rx. Sostenuto */
set_rx(ch, RX_SOSTENUTO, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Sostenuto (CH:%d VAL:%d)", ch, val);
break;
case 0x57: /* Rx. Soft */
set_rx(ch, RX_SOFT, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Soft (CH:%d VAL:%d)", ch, val);
break;
case 0x58: /* Rx. Bank Select */
set_rx(ch, RX_BANK_SELECT, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Bank Select (CH:%d VAL:%d)", ch, val);
break;
case 0x59: /* Rx. Bank Select LSB */
set_rx(ch, RX_BANK_SELECT_LSB, val);
//printMessage(CMSG_INFO,VERB_NOISY,"Rx. Bank Select LSB (CH:%d VAL:%d)", ch, val);
break;
case 0x60: /* Reverb Type (GM2) */
if (val > 8) {val = 8;}
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Type (%d)", val);
reverb->set_reverb_macro_gm2(val);
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
break;
case 0x61: /* Chorus Type (GM2) */
if (val > 5) {val = 5;}
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Type (%d)", val);
reverb->set_chorus_macro_gs(val);
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
break;
default:
break;
}
return;
} else if(ev == ME_SYSEX_GS_LSB) { /* GS system exclusive message */
msb = channel[ch].sysex_gs_msb_addr;
note = channel[ch].sysex_gs_msb_val;
channel[ch].sysex_gs_msb_addr = channel[ch].sysex_gs_msb_val = 0;
switch(b)
{
case 0x00: /* EQ ON/OFF */
if(!opt_eq_control) {break;}
channel[ch].eq_gs = val;
break;
case 0x01: /* EQ LOW FREQ */
if(!opt_eq_control) {break;}
reverb->eq_status_gs.low_freq = val;
reverb->recompute_eq_status_gs();
break;
case 0x02: /* EQ LOW GAIN */
if(!opt_eq_control) {break;}
reverb->eq_status_gs.low_gain = val;
reverb->recompute_eq_status_gs();
break;
case 0x03: /* EQ HIGH FREQ */
if(!opt_eq_control) {break;}
reverb->eq_status_gs.high_freq = val;
reverb->recompute_eq_status_gs();
break;
case 0x04: /* EQ HIGH GAIN */
if(!opt_eq_control) {break;}
reverb->eq_status_gs.high_gain = val;
reverb->recompute_eq_status_gs();
break;
case 0x05: /* Reverb Macro */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Macro (%d)",val);
reverb->set_reverb_macro_gs(val);
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
break;
case 0x06: /* Reverb Character */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Character (%d)",val);
if (reverb->reverb_status_gs.character != val) {
reverb->reverb_status_gs.character = val;
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
}
break;
case 0x07: /* Reverb Pre-LPF */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Pre-LPF (%d)",val);
if(reverb->reverb_status_gs.pre_lpf != val) {
reverb->reverb_status_gs.pre_lpf = val;
reverb->recompute_reverb_status_gs();
}
break;
case 0x08: /* Reverb Level */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Level (%d)",val);
if(reverb->reverb_status_gs.level != val) {
reverb->reverb_status_gs.level = val;
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
}
break;
case 0x09: /* Reverb Time */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Time (%d)",val);
if(reverb->reverb_status_gs.time != val) {
reverb->reverb_status_gs.time = val;
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
}
break;
case 0x0A: /* Reverb Delay Feedback */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Delay Feedback (%d)",val);
if(reverb->reverb_status_gs.delay_feedback != val) {
reverb->reverb_status_gs.delay_feedback = val;
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
}
break;
case 0x0C: /* Reverb Predelay Time */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Predelay Time (%d)",val);
if(reverb->reverb_status_gs.pre_delay_time != val) {
reverb->reverb_status_gs.pre_delay_time = val;
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
}
break;
case 0x0D: /* Chorus Macro */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Macro (%d)",val);
reverb->set_chorus_macro_gs(val);
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
break;
case 0x0E: /* Chorus Pre-LPF */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Pre-LPF (%d)",val);
if (reverb->chorus_status_gs.pre_lpf != val) {
reverb->chorus_status_gs.pre_lpf = val;
reverb->recompute_chorus_status_gs();
}
break;
case 0x0F: /* Chorus Level */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Level (%d)",val);
if (reverb->chorus_status_gs.level != val) {
reverb->chorus_status_gs.level = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x10: /* Chorus Feedback */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Feedback (%d)",val);
if (reverb->chorus_status_gs.feedback != val) {
reverb->chorus_status_gs.feedback = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x11: /* Chorus Delay */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Delay (%d)",val);
if (reverb->chorus_status_gs.delay != val) {
reverb->chorus_status_gs.delay = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x12: /* Chorus Rate */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Rate (%d)",val);
if (reverb->chorus_status_gs.rate != val) {
reverb->chorus_status_gs.rate = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x13: /* Chorus Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Depth (%d)",val);
if (reverb->chorus_status_gs.depth != val) {
reverb->chorus_status_gs.depth = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x14: /* Chorus Send Level to Reverb */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Send Level to Reverb (%d)",val);
if (reverb->chorus_status_gs.send_reverb != val) {
reverb->chorus_status_gs.send_reverb = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x15: /* Chorus Send Level to Delay */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Send Level to Delay (%d)",val);
if (reverb->chorus_status_gs.send_delay != val) {
reverb->chorus_status_gs.send_delay = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
break;
case 0x16: /* Delay Macro */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Macro (%d)",val);
reverb->set_delay_macro_gs(val);
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
break;
case 0x17: /* Delay Pre-LPF */
if (val > 7) {val = 7;}
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Pre-LPF (%d)",val);
val &= 0x7;
if (reverb->delay_status_gs.pre_lpf != val) {
reverb->delay_status_gs.pre_lpf = val;
reverb->recompute_delay_status_gs();
}
break;
case 0x18: /* Delay Time Center */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Time Center (%d)",val);
if (reverb->delay_status_gs.time_c != val) {
reverb->delay_status_gs.time_c = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x19: /* Delay Time Ratio Left */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Time Ratio Left (%d)",val);
if (val == 0) {val = 1;}
if (reverb->delay_status_gs.time_l != val) {
reverb->delay_status_gs.time_l = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x1A: /* Delay Time Ratio Right */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Time Ratio Right (%d)",val);
if (val == 0) {val = 1;}
if (reverb->delay_status_gs.time_r != val) {
reverb->delay_status_gs.time_r = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x1B: /* Delay Level Center */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Level Center (%d)",val);
if (reverb->delay_status_gs.level_center != val) {
reverb->delay_status_gs.level_center = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x1C: /* Delay Level Left */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Level Left (%d)",val);
if (reverb->delay_status_gs.level_left != val) {
reverb->delay_status_gs.level_left = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x1D: /* Delay Level Right */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Level Right (%d)",val);
if (reverb->delay_status_gs.level_right != val) {
reverb->delay_status_gs.level_right = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x1E: /* Delay Level */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Level (%d)",val);
if (reverb->delay_status_gs.level != val) {
reverb->delay_status_gs.level = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x1F: /* Delay Feedback */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Feedback (%d)",val);
if (reverb->delay_status_gs.feedback != val) {
reverb->delay_status_gs.feedback = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x20: /* Delay Send Level to Reverb */
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Send Level to Reverb (%d)",val);
if (reverb->delay_status_gs.send_reverb != val) {
reverb->delay_status_gs.send_reverb = val;
reverb->recompute_delay_status_gs();
reverb->init_ch_delay();
}
break;
case 0x21: /* Velocity Sense Depth */
channel[ch].velocity_sense_depth = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Velocity Sense Depth (CH:%d VAL:%d)",ch,val);
break;
case 0x22: /* Velocity Sense Offset */
channel[ch].velocity_sense_offset = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Velocity Sense Offset (CH:%d VAL:%d)",ch,val);
break;
case 0x23: /* Insertion Effect ON/OFF */
if(!opt_insertion_effect) {break;}
if(channel[ch].insertion_effect != val) {
//if(val) {//printMessage(CMSG_INFO,VERB_NOISY,"EFX ON (CH:%d)",ch);}
//else {//printMessage(CMSG_INFO,VERB_NOISY,"EFX OFF (CH:%d)",ch);}
}
channel[ch].insertion_effect = val;
break;
case 0x24: /* Assign Mode */
channel[ch].assign_mode = val;
if(val == 0) {
//printMessage(CMSG_INFO,VERB_NOISY,"Assign Mode: Single (CH:%d)",ch);
} else if(val == 1) {
//printMessage(CMSG_INFO,VERB_NOISY,"Assign Mode: Limited-Multi (CH:%d)",ch);
} else if(val == 2) {
//printMessage(CMSG_INFO,VERB_NOISY,"Assign Mode: Full-Multi (CH:%d)",ch);
}
break;
case 0x25: /* TONE MAP-0 NUMBER */
channel[ch].tone_map0_number = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Tone Map-0 Number (CH:%d VAL:%d)",ch,val);
break;
case 0x26: /* Pitch Offset Fine */
channel[ch].pitch_offset_fine = (double)((((int32_t)val << 4) | (int32_t)val) - 0x80) / 10.0;
//printMessage(CMSG_INFO,VERB_NOISY,"Pitch Offset Fine (CH:%d %3fHz)",ch,channel[ch].pitch_offset_fine);
break;
case 0x27: /* Insertion Effect Parameter */
if(!opt_insertion_effect) {break;}
temp = reverb->insertion_effect_gs.type;
reverb->insertion_effect_gs.type_msb = val;
reverb->insertion_effect_gs.type = ((int32_t)reverb->insertion_effect_gs.type_msb << 8) | (int32_t)reverb->insertion_effect_gs.type_lsb;
if(temp == reverb->insertion_effect_gs.type) {
reverb->recompute_insertion_effect_gs();
} else {
reverb->realloc_insertion_effect_gs();
}
break;
case 0x28: /* Insertion Effect Parameter */
if(!opt_insertion_effect) {break;}
temp = reverb->insertion_effect_gs.type;
reverb->insertion_effect_gs.type_lsb = val;
reverb->insertion_effect_gs.type = ((int32_t)reverb->insertion_effect_gs.type_msb << 8) | (int32_t)reverb->insertion_effect_gs.type_lsb;
if(temp == reverb->insertion_effect_gs.type) {
reverb->recompute_insertion_effect_gs();
} else {
reverb->realloc_insertion_effect_gs();
}
break;
case 0x29:
reverb->insertion_effect_gs.parameter[0] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x2A:
reverb->insertion_effect_gs.parameter[1] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x2B:
reverb->insertion_effect_gs.parameter[2] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x2C:
reverb->insertion_effect_gs.parameter[3] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x2D:
reverb->insertion_effect_gs.parameter[4] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x2E:
reverb->insertion_effect_gs.parameter[5] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x2F:
reverb->insertion_effect_gs.parameter[6] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x30:
reverb->insertion_effect_gs.parameter[7] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x31:
reverb->insertion_effect_gs.parameter[8] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x32:
reverb->insertion_effect_gs.parameter[9] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x33:
reverb->insertion_effect_gs.parameter[10] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x34:
reverb->insertion_effect_gs.parameter[11] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x35:
reverb->insertion_effect_gs.parameter[12] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x36:
reverb->insertion_effect_gs.parameter[13] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x37:
reverb->insertion_effect_gs.parameter[14] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x38:
reverb->insertion_effect_gs.parameter[15] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x39:
reverb->insertion_effect_gs.parameter[16] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x3A:
reverb->insertion_effect_gs.parameter[17] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x3B:
reverb->insertion_effect_gs.parameter[18] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x3C:
reverb->insertion_effect_gs.parameter[19] = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x3D:
reverb->insertion_effect_gs.send_reverb = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x3E:
reverb->insertion_effect_gs.send_chorus = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x3F:
reverb->insertion_effect_gs.send_delay = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x40:
reverb->insertion_effect_gs.control_source1 = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x41:
reverb->insertion_effect_gs.control_depth1 = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x42:
reverb->insertion_effect_gs.control_source2 = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x43:
reverb->insertion_effect_gs.control_depth2 = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x44:
reverb->insertion_effect_gs.send_eq_switch = val;
reverb->recompute_insertion_effect_gs();
break;
case 0x45: /* Rx. Channel */
reset_controllers(ch);
all_notes_off(ch);
if (val == 0x80)
remove_channel_layer(ch);
else
add_channel_layer(ch, val);
break;
case 0x46: /* Channel Msg Rx Port */
reset_controllers(ch);
all_notes_off(ch);
channel[ch].port_select = val;
break;
case 0x47: /* Play Note Number */
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
channel[ch].drums[note]->play_note = val;
printMessage(CMSG_INFO, VERB_NOISY,
"Drum Instrument Play Note (CH:%d NOTE:%d VAL:%d)",
ch, note, channel[ch].drums[note]->play_note);
channel[ch].pitchfactor = 0;
break;
default:
break;
}
return;
} else if(ev == ME_SYSEX_XG_LSB) { /* XG system exclusive message */
msb = channel[ch].sysex_xg_msb_addr;
note = channel[ch].sysex_xg_msb_val;
if (note == 3 && msb == 0) { /* Effect 2 */
note = 0; /* force insertion effect num 0 ?? */
if (note >= XG_INSERTION_EFFECT_NUM || note < 0) {return;}
switch(b)
{
case 0x00: /* Insertion Effect Type MSB */
if (reverb->insertion_effect_xg[note].type_msb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Type MSB (%d %02X)", note, val);
reverb->insertion_effect_xg[note].type_msb = val;
reverb->realloc_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x01: /* Insertion Effect Type LSB */
if (reverb->insertion_effect_xg[note].type_lsb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Type LSB (%d %02X)", note, val);
reverb->insertion_effect_xg[note].type_lsb = val;
reverb->realloc_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x02: /* Insertion Effect Parameter 1 - 10 */
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0A:
case 0x0B:
if (reverb->insertion_effect_xg[note].use_msb) {break;}
temp = b - 0x02;
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Parameter %d (%d %d)", temp + 1, note, val);
if (reverb->insertion_effect_xg[note].param_lsb[temp] != val) {
reverb->insertion_effect_xg[note].param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x0C: /* Insertion Effect Part */
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Part (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].part != val) {
reverb->insertion_effect_xg[note].part = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x0D: /* MW Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"MW Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].mw_depth != val) {
reverb->insertion_effect_xg[note].mw_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x0E: /* BEND Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"BEND Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].bend_depth != val) {
reverb->insertion_effect_xg[note].bend_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x0F: /* CAT Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"CAT Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].cat_depth != val) {
reverb->insertion_effect_xg[note].cat_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x10: /* AC1 Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"AC1 Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].ac1_depth != val) {
reverb->insertion_effect_xg[note].ac1_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x11: /* AC2 Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"AC2 Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].ac2_depth != val) {
reverb->insertion_effect_xg[note].ac2_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x12: /* CBC1 Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"CBC1 Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].cbc1_depth != val) {
reverb->insertion_effect_xg[note].cbc1_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x13: /* CBC2 Insertion Control Depth */
//printMessage(CMSG_INFO,VERB_NOISY,"CBC2 Insertion Control Depth (%d %d)", note, val);
if (reverb->insertion_effect_xg[note].cbc2_depth != val) {
reverb->insertion_effect_xg[note].cbc2_depth = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x20: /* Insertion Effect Parameter 11 - 16 */
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
temp = b - 0x20 + 10;
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Parameter %d (%d %d)", temp + 1, note, val);
if (reverb->insertion_effect_xg[note].param_lsb[temp] != val) {
reverb->insertion_effect_xg[note].param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x30: /* Insertion Effect Parameter 1 - 10 MSB */
case 0x32:
case 0x34:
case 0x36:
case 0x38:
case 0x3A:
case 0x3C:
case 0x3E:
case 0x40:
case 0x42:
if (!reverb->insertion_effect_xg[note].use_msb) {break;}
temp = (b - 0x30) / 2;
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Parameter %d MSB (%d %d)", temp + 1, note, val);
if (reverb->insertion_effect_xg[note].param_msb[temp] != val) {
reverb->insertion_effect_xg[note].param_msb[temp] = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
case 0x31: /* Insertion Effect Parameter 1 - 10 LSB */
case 0x33:
case 0x35:
case 0x37:
case 0x39:
case 0x3B:
case 0x3D:
case 0x3F:
case 0x41:
case 0x43:
if (!reverb->insertion_effect_xg[note].use_msb) {break;}
temp = (b - 0x31) / 2;
//printMessage(CMSG_INFO,VERB_NOISY,"Insertion Effect Parameter %d LSB (%d %d)", temp + 1, note, val);
if (reverb->insertion_effect_xg[note].param_lsb[temp] != val) {
reverb->insertion_effect_xg[note].param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->insertion_effect_xg[note]);
}
break;
default:
break;
}
} else if (note == 2 && msb == 1) { /* Effect 1 */
note = 0; /* force variation effect num 0 ?? */
switch(b)
{
case 0x00: /* Reverb Type MSB */
if (reverb->reverb_status_xg.type_msb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Type MSB (%02X)", val);
reverb->reverb_status_xg.type_msb = val;
reverb->realloc_effect_xg(&reverb->reverb_status_xg);
}
break;
case 0x01: /* Reverb Type LSB */
if (reverb->reverb_status_xg.type_lsb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Type LSB (%02X)", val);
reverb->reverb_status_xg.type_lsb = val;
reverb->realloc_effect_xg(&reverb->reverb_status_xg);
}
break;
case 0x02: /* Reverb Parameter 1 - 10 */
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0A:
case 0x0B:
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Parameter %d (%d)", b - 0x02 + 1, val);
if (reverb->reverb_status_xg.param_lsb[b - 0x02] != val) {
reverb->reverb_status_xg.param_lsb[b - 0x02] = val;
reverb->recompute_effect_xg(&reverb->reverb_status_xg);
}
break;
case 0x0C: /* Reverb Return */
#if 0 /* XG specific reverb is not currently implemented */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Return (%d)", val);
if (reverb->reverb_status_xg.ret != val) {
reverb->reverb_status_xg.ret = val;
reverb->recompute_effect_xg(&reverb->reverb_status_xg);
}
#else /* use GS reverb instead */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Return (%d)", val);
if (reverb->reverb_status_gs.level != val) {
reverb->reverb_status_gs.level = val;
reverb->recompute_reverb_status_gs();
reverb->init_reverb();
}
#endif
break;
case 0x0D: /* Reverb Pan */
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Pan (%d)", val);
if (reverb->reverb_status_xg.pan != val) {
reverb->reverb_status_xg.pan = val;
reverb->recompute_effect_xg(&reverb->reverb_status_xg);
}
break;
case 0x10: /* Reverb Parameter 11 - 16 */
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
temp = b - 0x10 + 10;
//printMessage(CMSG_INFO,VERB_NOISY,"Reverb Parameter %d (%d)", temp + 1, val);
if (reverb->reverb_status_xg.param_lsb[temp] != val) {
reverb->reverb_status_xg.param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->reverb_status_xg);
}
break;
case 0x20: /* Chorus Type MSB */
if (reverb->chorus_status_xg.type_msb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Type MSB (%02X)", val);
reverb->chorus_status_xg.type_msb = val;
reverb->realloc_effect_xg(&reverb->chorus_status_xg);
}
break;
case 0x21: /* Chorus Type LSB */
if (reverb->chorus_status_xg.type_lsb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Type LSB (%02X)", val);
reverb->chorus_status_xg.type_lsb = val;
reverb->realloc_effect_xg(&reverb->chorus_status_xg);
}
break;
case 0x22: /* Chorus Parameter 1 - 10 */
case 0x23:
case 0x24:
case 0x25:
case 0x26:
case 0x27:
case 0x28:
case 0x29:
case 0x2A:
case 0x2B:
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Parameter %d (%d)", b - 0x22 + 1, val);
if (reverb->chorus_status_xg.param_lsb[b - 0x22] != val) {
reverb->chorus_status_xg.param_lsb[b - 0x22] = val;
reverb->recompute_effect_xg(&reverb->chorus_status_xg);
}
break;
case 0x2C: /* Chorus Return */
#if 0 /* XG specific chorus is not currently implemented */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Return (%d)", val);
if (reverb->chorus_status_xg.ret != val) {
reverb->chorus_status_xg.ret = val;
reverb->recompute_effect_xg(&reverb->chorus_status_xg);
}
#else /* use GS chorus instead */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Return (%d)", val);
if (reverb->chorus_status_gs.level != val) {
reverb->chorus_status_gs.level = val;
reverb->recompute_chorus_status_gs();
reverb->init_ch_chorus();
}
#endif
break;
case 0x2D: /* Chorus Pan */
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Pan (%d)", val);
if (reverb->chorus_status_xg.pan != val) {
reverb->chorus_status_xg.pan = val;
reverb->recompute_effect_xg(&reverb->chorus_status_xg);
}
break;
case 0x2E: /* Send Chorus To Reverb */
//printMessage(CMSG_INFO,VERB_NOISY,"Send Chorus To Reverb (%d)", val);
if (reverb->chorus_status_xg.send_reverb != val) {
reverb->chorus_status_xg.send_reverb = val;
reverb->recompute_effect_xg(&reverb->chorus_status_xg);
}
break;
case 0x30: /* Chorus Parameter 11 - 16 */
case 0x31:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
temp = b - 0x30 + 10;
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Parameter %d (%d)", temp + 1, val);
if (reverb->chorus_status_xg.param_lsb[temp] != val) {
reverb->chorus_status_xg.param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->chorus_status_xg);
}
break;
case 0x40: /* Variation Type MSB */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
if (reverb->variation_effect_xg[note].type_msb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Type MSB (%02X)", val);
reverb->variation_effect_xg[note].type_msb = val;
reverb->realloc_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x41: /* Variation Type LSB */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
if (reverb->variation_effect_xg[note].type_lsb != val) {
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Type LSB (%02X)", val);
reverb->variation_effect_xg[note].type_lsb = val;
reverb->realloc_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x42: /* Variation Parameter 1 - 10 MSB */
case 0x44:
case 0x46:
case 0x48:
case 0x4A:
case 0x4C:
case 0x4E:
case 0x50:
case 0x52:
case 0x54:
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
temp = (b - 0x42) / 2;
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Parameter %d MSB (%d)", temp, val);
if (reverb->variation_effect_xg[note].param_msb[temp] != val) {
reverb->variation_effect_xg[note].param_msb[temp] = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x43: /* Variation Parameter 1 - 10 LSB */
case 0x45:
case 0x47:
case 0x49:
case 0x4B:
case 0x4D:
case 0x4F:
case 0x51:
case 0x53:
case 0x55:
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
temp = (b - 0x43) / 2;
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Parameter %d LSB (%d)", temp, val);
if (reverb->variation_effect_xg[note].param_lsb[temp] != val) {
reverb->variation_effect_xg[note].param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x56: /* Variation Return */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Return (%d)", val);
if (reverb->variation_effect_xg[note].ret != val) {
reverb->variation_effect_xg[note].ret = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x57: /* Variation Pan */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Pan (%d)", val);
if (reverb->variation_effect_xg[note].pan != val) {
reverb->variation_effect_xg[note].pan = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x58: /* Send Variation To Reverb */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Send Variation To Reverb (%d)", val);
if (reverb->variation_effect_xg[note].send_reverb != val) {
reverb->variation_effect_xg[note].send_reverb = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x59: /* Send Variation To Chorus */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Send Variation To Chorus (%d)", val);
if (reverb->variation_effect_xg[note].send_chorus != val) {
reverb->variation_effect_xg[note].send_chorus = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x5A: /* Variation Connection */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Connection (%d)", val);
if (reverb->variation_effect_xg[note].connection != val) {
reverb->variation_effect_xg[note].connection = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x5B: /* Variation Part */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Part (%d)", val);
if (reverb->variation_effect_xg[note].part != val) {
reverb->variation_effect_xg[note].part = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x5C: /* MW Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"MW Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].mw_depth != val) {
reverb->variation_effect_xg[note].mw_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x5D: /* BEND Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"BEND Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].bend_depth != val) {
reverb->variation_effect_xg[note].bend_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x5E: /* CAT Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"CAT Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].cat_depth != val) {
reverb->variation_effect_xg[note].cat_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x5F: /* AC1 Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"AC1 Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].ac1_depth != val) {
reverb->variation_effect_xg[note].ac1_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x60: /* AC2 Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"AC2 Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].ac2_depth != val) {
reverb->variation_effect_xg[note].ac2_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x61: /* CBC1 Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"CBC1 Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].cbc1_depth != val) {
reverb->variation_effect_xg[note].cbc1_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x62: /* CBC2 Variation Control Depth */
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"CBC2 Variation Control Depth (%d)", val);
if (reverb->variation_effect_xg[note].cbc2_depth != val) {
reverb->variation_effect_xg[note].cbc2_depth = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
case 0x70: /* Variation Parameter 11 - 16 */
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
temp = b - 0x70 + 10;
if (note >= XG_VARIATION_EFFECT_NUM || note < 0) {break;}
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Parameter %d (%d)", temp + 1, val);
if (reverb->variation_effect_xg[note].param_lsb[temp] != val) {
reverb->variation_effect_xg[note].param_lsb[temp] = val;
reverb->recompute_effect_xg(&reverb->variation_effect_xg[note]);
}
break;
default:
break;
}
} else if (note == 2 && msb == 40) { /* Multi EQ */
switch(b)
{
case 0x00: /* EQ type */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ type (%d)", val);
reverb->multi_eq_xg.type = val;
reverb->set_multi_eq_type_xg(val);
reverb->recompute_multi_eq_xg();
}
break;
case 0x01: /* EQ gain1 */
if(opt_eq_control) {
if(val > 0x4C) {val = 0x4C;}
else if(val < 0x34) {val = 0x34;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ gain1 (%d dB)", val - 0x40);
reverb->multi_eq_xg.gain1 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x02: /* EQ frequency1 */
if(opt_eq_control) {
if(val > 60) {val = 60;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ frequency1 (%d Hz)", (int32_t)eq_freq_table_xg[val]);
reverb->multi_eq_xg.freq1 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x03: /* EQ Q1 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ Q1 (%f)", (double)val / 10.0);
reverb->multi_eq_xg.q1 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x04: /* EQ shape1 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ shape1 (%d)", val);
reverb->multi_eq_xg.shape1 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x05: /* EQ gain2 */
if(opt_eq_control) {
if(val > 0x4C) {val = 0x4C;}
else if(val < 0x34) {val = 0x34;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ gain2 (%d dB)", val - 0x40);
reverb->multi_eq_xg.gain2 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x06: /* EQ frequency2 */
if(opt_eq_control) {
if(val > 60) {val = 60;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ frequency2 (%d Hz)", (int32_t)eq_freq_table_xg[val]);
reverb->multi_eq_xg.freq2 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x07: /* EQ Q2 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ Q2 (%f)", (double)val / 10.0);
reverb->multi_eq_xg.q2 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x09: /* EQ gain3 */
if(opt_eq_control) {
if(val > 0x4C) {val = 0x4C;}
else if(val < 0x34) {val = 0x34;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ gain3 (%d dB)", val - 0x40);
reverb->multi_eq_xg.gain3 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x0A: /* EQ frequency3 */
if(opt_eq_control) {
if(val > 60) {val = 60;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ frequency3 (%d Hz)", (int32_t)eq_freq_table_xg[val]);
reverb->multi_eq_xg.freq3 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x0B: /* EQ Q3 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ Q3 (%f)", (double)val / 10.0);
reverb->multi_eq_xg.q3 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x0D: /* EQ gain4 */
if(opt_eq_control) {
if(val > 0x4C) {val = 0x4C;}
else if(val < 0x34) {val = 0x34;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ gain4 (%d dB)", val - 0x40);
reverb->multi_eq_xg.gain4 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x0E: /* EQ frequency4 */
if(opt_eq_control) {
if(val > 60) {val = 60;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ frequency4 (%d Hz)", (int32_t)eq_freq_table_xg[val]);
reverb->multi_eq_xg.freq4 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x0F: /* EQ Q4 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ Q4 (%f)", (double)val / 10.0);
reverb->multi_eq_xg.q4 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x11: /* EQ gain5 */
if(opt_eq_control) {
if(val > 0x4C) {val = 0x4C;}
else if(val < 0x34) {val = 0x34;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ gain5 (%d dB)", val - 0x40);
reverb->multi_eq_xg.gain5 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x12: /* EQ frequency5 */
if(opt_eq_control) {
if(val > 60) {val = 60;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ frequency5 (%d Hz)", (int32_t)eq_freq_table_xg[val]);
reverb->multi_eq_xg.freq5 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x13: /* EQ Q5 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ Q5 (%f)", (double)val / 10.0);
reverb->multi_eq_xg.q5 = val;
reverb->recompute_multi_eq_xg();
}
break;
case 0x14: /* EQ shape5 */
if(opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ shape5 (%d)", val);
reverb->multi_eq_xg.shape5 = val;
reverb->recompute_multi_eq_xg();
}
break;
}
} else if (note == 8 && msb == 0) { /* Multi Part */
switch(b)
{
case 0x99: /* Rcv CHANNEL, remapped from 0x04 */
reset_controllers(ch);
all_notes_off(ch);
if (val == 0x7f)
remove_channel_layer(ch);
else {
if((ch < REDUCE_CHANNELS) != (val < REDUCE_CHANNELS)) {
channel[ch].port_select = ch < REDUCE_CHANNELS ? 1 : 0;
}
if((ch % REDUCE_CHANNELS) != (val % REDUCE_CHANNELS)) {
add_channel_layer(ch, val);
}
}
break;
case 0x06: /* Same Note Number Key On Assign */
if(val == 0) {
channel[ch].assign_mode = 0;
//printMessage(CMSG_INFO,VERB_NOISY,"Same Note Number Key On Assign: Single (CH:%d)",ch);
} else if(val == 1) {
channel[ch].assign_mode = 2;
//printMessage(CMSG_INFO,VERB_NOISY,"Same Note Number Key On Assign: Multi (CH:%d)",ch);
} else if(val == 2) {
//printMessage(CMSG_INFO,VERB_NOISY,"Same Note Number Key On Assign: Inst is not supported. (CH:%d)",ch);
}
break;
case 0x11: /* Dry Level */
channel[ch].dry_level = val;
//printMessage(CMSG_INFO,VERB_NOISY,"Dry Level (CH:%d VAL:%d)", ch, val);
break;
}
} else if ((note & 0xF0) == 0x30) { /* Drum Setup */
note = msb;
switch(b)
{
case 0x0E: /* EG Decay1 */
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument EG Decay1 (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_envelope_rate[EG_DECAY1] = val;
break;
case 0x0F: /* EG Decay2 */
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument EG Decay2 (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_envelope_rate[EG_DECAY2] = val;
break;
default:
break;
}
}
return;
}
}
/*! convert GS NRPN to vibrato rate ratio. */
/* from 0 to 3.0. */
double Player::gs_cnv_vib_rate(int rate)
{
double ratio;
if(rate == 0) {
ratio = 1.6 / 100.0;
} else if(rate == 64) {
ratio = 1.0;
} else if(rate <= 100) {
ratio = (double)rate * 1.6 / 100.0;
} else {
ratio = (double)(rate - 101) * 1.33 / 26.0 + 1.67;
}
return (1.0 / ratio);
}
/*! convert GS NRPN to vibrato depth. */
/* from -9.6 cents to +9.45 cents. */
int32_t Player::gs_cnv_vib_depth(int depth)
{
double cent;
cent = (double)(depth - 64) * 0.15;
return (int32_t)(cent * 256.0 / 400.0);
}
/*! convert GS NRPN to vibrato delay. */
/* from 0 ms to 5074 ms. */
int32_t Player::gs_cnv_vib_delay(int delay)
{
double ms;
ms = 0.2092 * exp(0.0795 * (double)delay);
if(delay == 0) {ms = 0;}
return (int32_t)((double)playback_rate * ms * 0.001);
}
int Player::last_rpn_addr(int ch)
{
int lsb, msb, addr, i;
const struct rpn_tag_map_t *addrmap;
struct rpn_tag_map_t {
int addr, mask, tag;
};
static const struct rpn_tag_map_t nrpn_addr_map[] = {
{0x0108, 0xffff, NRPN_ADDR_0108},
{0x0109, 0xffff, NRPN_ADDR_0109},
{0x010a, 0xffff, NRPN_ADDR_010A},
{0x0120, 0xffff, NRPN_ADDR_0120},
{0x0121, 0xffff, NRPN_ADDR_0121},
{0x0130, 0xffff, NRPN_ADDR_0130},
{0x0131, 0xffff, NRPN_ADDR_0131},
{0x0134, 0xffff, NRPN_ADDR_0134},
{0x0135, 0xffff, NRPN_ADDR_0135},
{0x0163, 0xffff, NRPN_ADDR_0163},
{0x0164, 0xffff, NRPN_ADDR_0164},
{0x0166, 0xffff, NRPN_ADDR_0166},
{0x1400, 0xff00, NRPN_ADDR_1400},
{0x1500, 0xff00, NRPN_ADDR_1500},
{0x1600, 0xff00, NRPN_ADDR_1600},
{0x1700, 0xff00, NRPN_ADDR_1700},
{0x1800, 0xff00, NRPN_ADDR_1800},
{0x1900, 0xff00, NRPN_ADDR_1900},
{0x1a00, 0xff00, NRPN_ADDR_1A00},
{0x1c00, 0xff00, NRPN_ADDR_1C00},
{0x1d00, 0xff00, NRPN_ADDR_1D00},
{0x1e00, 0xff00, NRPN_ADDR_1E00},
{0x1f00, 0xff00, NRPN_ADDR_1F00},
{0x3000, 0xff00, NRPN_ADDR_3000},
{0x3100, 0xff00, NRPN_ADDR_3100},
{0x3400, 0xff00, NRPN_ADDR_3400},
{0x3500, 0xff00, NRPN_ADDR_3500},
{-1, -1, 0}
};
static const struct rpn_tag_map_t rpn_addr_map[] = {
{0x0000, 0xffff, RPN_ADDR_0000},
{0x0001, 0xffff, RPN_ADDR_0001},
{0x0002, 0xffff, RPN_ADDR_0002},
{0x0003, 0xffff, RPN_ADDR_0003},
{0x0004, 0xffff, RPN_ADDR_0004},
{0x0005, 0xffff, RPN_ADDR_0005},
{0x7f7f, 0xffff, RPN_ADDR_7F7F},
{0xffff, 0xffff, RPN_ADDR_FFFF},
{-1, -1}
};
if (channel[ch].nrpn == -1)
return -1;
lsb = channel[ch].lastlrpn;
msb = channel[ch].lastmrpn;
if (lsb == 0xff || msb == 0xff)
return -1;
addr = (msb << 8 | lsb);
if (channel[ch].nrpn)
addrmap = nrpn_addr_map;
else
addrmap = rpn_addr_map;
for (i = 0; addrmap[i].addr != -1; i++)
if (addrmap[i].addr == (addr & addrmap[i].mask))
return addrmap[i].tag;
return -1;
}
void Player::update_rpn_map(int ch, int addr, int update_now)
{
int val, drumflag, i, note;
val = channel[ch].rpnmap[addr];
drumflag = 0;
switch (addr) {
case NRPN_ADDR_0108: /* Vibrato Rate */
if (op_nrpn_vibrato) {
//printMessage(CMSG_INFO, VERB_NOISY, "Vibrato Rate (CH:%d VAL:%d)", ch, val - 64);
channel[ch].vibrato_ratio = gs_cnv_vib_rate(val);
}
if (update_now)
adjust_pitch(ch);
break;
case NRPN_ADDR_0109: /* Vibrato Depth */
if (op_nrpn_vibrato) {
//printMessage(CMSG_INFO, VERB_NOISY, "Vibrato Depth (CH:%d VAL:%d)", ch, val - 64);
channel[ch].vibrato_depth = gs_cnv_vib_depth(val);
}
if (update_now)
adjust_pitch(ch);
break;
case NRPN_ADDR_010A: /* Vibrato Delay */
if (op_nrpn_vibrato) {
//printMessage(CMSG_INFO,VERB_NOISY,"Vibrato Delay (CH:%d VAL:%d)", ch, val);
channel[ch].vibrato_delay = gs_cnv_vib_delay(val);
}
if (update_now)
adjust_pitch(ch);
break;
case NRPN_ADDR_0120: /* Filter Cutoff Frequency */
if (timidity_lpf_def) {
//printMessage(CMSG_INFO, VERB_NOISY, "Filter Cutoff (CH:%d VAL:%d)", ch, val - 64);
channel[ch].param_cutoff_freq = val - 64;
}
break;
case NRPN_ADDR_0121: /* Filter Resonance */
if (timidity_lpf_def) {
//printMessage(CMSG_INFO,VERB_NOISY,"Filter Resonance (CH:%d VAL:%d)", ch, val - 64);
channel[ch].param_resonance = val - 64;
}
break;
case NRPN_ADDR_0130: /* EQ BASS */
if (opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ BASS (CH:%d %.2f dB)", ch, 0.19 * (double)(val - 0x40));
channel[ch].eq_xg.bass = val;
recompute_part_eq_xg(&(channel[ch].eq_xg));
}
break;
case NRPN_ADDR_0131: /* EQ TREBLE */
if (opt_eq_control) {
//printMessage(CMSG_INFO,VERB_NOISY,"EQ TREBLE (CH:%d %.2f dB)", ch, 0.19 * (double)(val - 0x40));
channel[ch].eq_xg.treble = val;
recompute_part_eq_xg(&(channel[ch].eq_xg));
}
break;
case NRPN_ADDR_0134: /* EQ BASS frequency */
if (opt_eq_control) {
if(val < 4) {val = 4;}
else if(val > 40) {val = 40;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ BASS frequency (CH:%d %d Hz)", ch, (int32_t)eq_freq_table_xg[val]);
channel[ch].eq_xg.bass_freq = val;
recompute_part_eq_xg(&(channel[ch].eq_xg));
}
break;
case NRPN_ADDR_0135: /* EQ TREBLE frequency */
if (opt_eq_control) {
if(val < 28) {val = 28;}
else if(val > 58) {val = 58;}
//printMessage(CMSG_INFO,VERB_NOISY,"EQ TREBLE frequency (CH:%d %d Hz)", ch, (int32_t)eq_freq_table_xg[val]);
channel[ch].eq_xg.treble_freq = val;
recompute_part_eq_xg(&(channel[ch].eq_xg));
}
break;
case NRPN_ADDR_0163: /* Attack Time */
if (opt_tva_attack) {set_envelope_time(ch, val, EG_ATTACK);}
break;
case NRPN_ADDR_0164: /* EG Decay Time */
if (opt_tva_decay) {set_envelope_time(ch, val, EG_DECAY);}
break;
case NRPN_ADDR_0166: /* EG Release Time */
if (opt_tva_release) {set_envelope_time(ch, val, EG_RELEASE);}
break;
case NRPN_ADDR_1400: /* Drum Filter Cutoff (XG) */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument Filter Cutoff (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_cutoff_freq = val - 64;
break;
case NRPN_ADDR_1500: /* Drum Filter Resonance (XG) */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument Filter Resonance (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_resonance = val - 64;
break;
case NRPN_ADDR_1600: /* Drum EG Attack Time (XG) */
drumflag = 1;
if (opt_tva_attack) {
val = val & 0x7f;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
val -= 64;
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument Attack Time (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_envelope_rate[EG_ATTACK] = val;
}
break;
case NRPN_ADDR_1700: /* Drum EG Decay Time (XG) */
drumflag = 1;
if (opt_tva_decay) {
val = val & 0x7f;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
val -= 64;
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument Decay Time (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_envelope_rate[EG_DECAY1] =
channel[ch].drums[note]->drum_envelope_rate[EG_DECAY2] = val;
}
break;
case NRPN_ADDR_1800: /* Coarse Pitch of Drum (GS) */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
channel[ch].drums[note]->coarse = val - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument Pitch Coarse (CH:%d NOTE:%d VAL:%d)", ch, note, channel[ch].drums[note]->coarse);
channel[ch].pitchfactor = 0;
break;
case NRPN_ADDR_1900: /* Fine Pitch of Drum (XG) */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
channel[ch].drums[note]->fine = val - 64;
printMessage(CMSG_INFO, VERB_NOISY, "Drum Instrument Pitch Fine (CH:%d NOTE:%d VAL:%d)", ch, note, channel[ch].drums[note]->fine);
channel[ch].pitchfactor = 0;
break;
case NRPN_ADDR_1A00: /* Level of Drum */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
//printMessage(CMSG_INFO,VERB_NOISY,"Drum Instrument TVA Level (CH:%d NOTE:%d VAL:%d)", ch, note, val);
channel[ch].drums[note]->drum_level =
calc_drum_tva_level(ch, note, val);
break;
case NRPN_ADDR_1C00: /* Panpot of Drum */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
if(val == 0) {
val = int_rand(128);
channel[ch].drums[note]->pan_random = 1;
} else
channel[ch].drums[note]->pan_random = 0;
channel[ch].drums[note]->drum_panning = val;
if (update_now && adjust_panning_immediately && ! channel[ch].pan_random)
adjust_drum_panning(ch, note);
break;
case NRPN_ADDR_1D00: /* Reverb Send Level of Drum */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
printMessage(CMSG_INFO, VERB_NOISY, "Reverb Send Level of Drum (CH:%d NOTE:%d VALUE:%d)", ch, note, val);
if (channel[ch].drums[note]->reverb_level != val) {
channel[ch].drum_effect_flag = 0;
}
channel[ch].drums[note]->reverb_level = val;
break;
case NRPN_ADDR_1E00: /* Chorus Send Level of Drum */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
printMessage(CMSG_INFO, VERB_NOISY, "Chorus Send Level of Drum (CH:%d NOTE:%d VALUE:%d)", ch, note, val);
if (channel[ch].drums[note]->chorus_level != val) {
channel[ch].drum_effect_flag = 0;
}
channel[ch].drums[note]->chorus_level = val;
break;
case NRPN_ADDR_1F00: /* Variation Send Level of Drum */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Send Level of Drum (CH:%d NOTE:%d VALUE:%d)", ch, note, val);
if (channel[ch].drums[note]->delay_level != val) {
channel[ch].drum_effect_flag = 0;
}
channel[ch].drums[note]->delay_level = val;
break;
case NRPN_ADDR_3000: /* Drum EQ BASS */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
break;
case NRPN_ADDR_3100: /* Drum EQ TREBLE */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
break;
case NRPN_ADDR_3400: /* Drum EQ BASS frequency */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
break;
case NRPN_ADDR_3500: /* Drum EQ TREBLE frequency */
drumflag = 1;
note = channel[ch].lastlrpn;
if (channel[ch].drums[note] == NULL)
play_midi_setup_drums(ch, note);
break;
case RPN_ADDR_0000: /* Pitch bend sensitivity */
printMessage(CMSG_INFO, VERB_DEBUG, "Pitch Bend Sensitivity (CH:%d VALUE:%d)", ch, val);
/* for mod2mid.c, arpeggio */
if (channel[ch].rpnmap[RPN_ADDR_0000] > 24)
channel[ch].rpnmap[RPN_ADDR_0000] = 24;
channel[ch].pitchfactor = 0;
break;
case RPN_ADDR_0001: /* Master Fine Tuning */
printMessage(CMSG_INFO, VERB_DEBUG, "Master Fine Tuning (CH:%d VALUE:%d)", ch, val);
channel[ch].pitchfactor = 0;
break;
case RPN_ADDR_0002: /* Master Coarse Tuning */
printMessage(CMSG_INFO, VERB_DEBUG, "Master Coarse Tuning (CH:%d VALUE:%d)", ch, val);
channel[ch].pitchfactor = 0;
break;
case RPN_ADDR_0003: /* Tuning Program Select */
printMessage(CMSG_INFO, VERB_DEBUG, "Tuning Program Select (CH:%d VALUE:%d)", ch, val);
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE) {
voice[i].temper_instant = 1;
recompute_freq(i);
}
break;
case RPN_ADDR_0004: /* Tuning Bank Select */
printMessage(CMSG_INFO, VERB_DEBUG, "Tuning Bank Select (CH:%d VALUE:%d)", ch, val);
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE) {
voice[i].temper_instant = 1;
recompute_freq(i);
}
break;
case RPN_ADDR_0005: /* GM2: Modulation Depth Range */
channel[ch].mod.lfo1_pitch_depth = (((int32_t)channel[ch].rpnmap[RPN_ADDR_0005] << 7) | channel[ch].rpnmap_lsb[RPN_ADDR_0005]) * 100 / 128;
//printMessage(CMSG_INFO,VERB_NOISY,"Modulation Depth Range (CH:%d VALUE:%d)", ch, channel[ch].rpnmap[RPN_ADDR_0005]);
break;
case RPN_ADDR_7F7F: /* RPN reset */
channel[ch].rpn_7f7f_flag = 1;
break;
case RPN_ADDR_FFFF: /* RPN initialize */
/* All reset to defaults */
channel[ch].rpn_7f7f_flag = 0;
memset(channel[ch].rpnmap, 0, sizeof(channel[ch].rpnmap));
channel[ch].lastlrpn = channel[ch].lastmrpn = 0;
channel[ch].nrpn = 0;
channel[ch].rpnmap[RPN_ADDR_0000] = 2;
channel[ch].rpnmap[RPN_ADDR_0001] = 0x40;
channel[ch].rpnmap[RPN_ADDR_0002] = 0x40;
channel[ch].rpnmap_lsb[RPN_ADDR_0005] = 0x40;
channel[ch].rpnmap[RPN_ADDR_0005] = 0; /* +- 50 cents */
channel[ch].pitchfactor = 0;
break;
}
drumflag = 0;
if (drumflag && midi_drumpart_change(ch, 1)) {
midi_program_change(ch, channel[ch].program);
}
}
void Player::voice_increment(int n)
{
int i;
for(i = 0; i < n; i++)
{
if(voices == max_voices)
break;
voice[voices].status = VOICE_FREE;
voice[voices].temper_instant = 0;
voice[voices].chorus_link = voices;
voices++;
}
}
void Player::voice_decrement(int n)
{
int i, j, lowest;
int32_t lv, v;
/* decrease voice */
for(i = 0; i < n && voices > 0; i++)
{
voices--;
if(voice[voices].status == VOICE_FREE)
continue; /* found */
for(j = 0; j < voices; j++)
if(voice[j].status == VOICE_FREE)
break;
if(j != voices)
{
voice[j] = voice[voices];
continue; /* found */
}
/* Look for the decaying note with the lowest volume */
lv = 0x7FFFFFFF;
lowest = -1;
for(j = 0; j <= voices; j++)
{
if(voice[j].status & ~(VOICE_ON | VOICE_DIE))
{
v = voice[j].left_mix;
if((voice[j].panned==PANNED_MYSTERY) &&
(voice[j].right_mix > v))
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
}
if(lowest != -1)
{
cut_notes++;
free_voice(lowest);
voice[lowest] = voice[voices];
}
else
lost_notes++;
}
if(upper_voices > voices)
upper_voices = voices;
}
/* EAW -- do not throw away good notes, stop decrementing */
void Player::voice_decrement_conservative(int n)
{
int i, j, lowest, finalnv;
int32_t lv, v;
/* decrease voice */
finalnv = voices - n;
for(i = 1; i <= n && voices > 0; i++)
{
if(voice[voices-1].status == VOICE_FREE) {
voices--;
continue; /* found */
}
for(j = 0; j < finalnv; j++)
if(voice[j].status == VOICE_FREE)
break;
if(j != finalnv)
{
voice[j] = voice[voices-1];
voices--;
continue; /* found */
}
/* Look for the decaying note with the lowest volume */
lv = 0x7FFFFFFF;
lowest = -1;
for(j = 0; j < voices; j++)
{
if(voice[j].status & ~(VOICE_ON | VOICE_DIE) &&
!(voice[j].sample->note_to_use &&
ISDRUMCHANNEL(voice[j].channel)))
{
v = voice[j].left_mix;
if((voice[j].panned==PANNED_MYSTERY) &&
(voice[j].right_mix > v))
v = voice[j].right_mix;
if(v < lv)
{
lv = v;
lowest = j;
}
}
}
if(lowest != -1)
{
voices--;
cut_notes++;
free_voice(lowest);
voice[lowest] = voice[voices];
}
else break;
}
if(upper_voices > voices)
upper_voices = voices;
}
void Player::mix_signal(int32_t *dest, int32_t *src, int32_t count)
{
int32_t i;
for (i = 0; i < count; i++) {
dest[i] += src[i];
}
}
int Player::is_insertion_effect_xg(int ch)
{
int i;
for (i = 0; i < XG_INSERTION_EFFECT_NUM; i++) {
if (reverb->insertion_effect_xg[i].part == ch) {
return 1;
}
}
for (i = 0; i < XG_VARIATION_EFFECT_NUM; i++) {
if (reverb->variation_effect_xg[i].connection == XG_CONN_INSERTION
&& reverb->variation_effect_xg[i].part == ch) {
return 1;
}
}
return 0;
}
/* do_compute_data_midi() with DSP Effect */
void Player::do_compute_data(int32_t count)
{
int i, j, uv, stereo, n, ch, note;
int32_t *vpblist[MAX_CHANNELS];
int channel_effect, channel_reverb, channel_chorus, channel_delay, channel_eq;
int32_t cnt = count * 2, rev_max_delay_out;
struct DrumPartEffect *de;
stereo = true;
n = count * ((stereo) ? 8 : 4); /* in bytes */
memset(buffer_pointer, 0, n);
memset(insertion_effect_buffer, 0, n);
if (timidity_reverb == 3) {
rev_max_delay_out = 0x7fffffff; /* disable */
} else {
rev_max_delay_out = REVERB_MAX_DELAY_OUT;
}
/* are effects valid? / don't supported in mono */
channel_reverb = (stereo && (timidity_reverb == 1
|| timidity_reverb == 3
|| (timidity_reverb < 0 && timidity_reverb & 0x80)));
channel_chorus = (stereo && timidity_chorus && !timidity_surround_chorus);
channel_delay = 0;
/* is EQ valid? */
channel_eq = 0;
channel_effect = (stereo && (channel_reverb || channel_chorus
|| channel_delay || channel_eq || opt_insertion_effect));
uv = upper_voices;
for(i = 0; i < uv; i++) {
if(voice[i].status != VOICE_FREE) {
channel[voice[i].channel].lasttime = current_sample + count;
}
}
/* appropriate buffers for channels */
if(channel_effect) {
int buf_index = 0;
if(reverb_buffer == NULL) { /* allocating buffer for channel effect */
reverb_buffer = (char *)safe_malloc(MAX_CHANNELS * AUDIO_BUFFER_SIZE * 8);
}
for(i = 0; i < MAX_CHANNELS; i++) {
if(opt_insertion_effect && channel[i].insertion_effect) {
vpblist[i] = insertion_effect_buffer;
} else if(channel[i].eq_gs || (get_reverb_level(i) != DEFAULT_REVERB_SEND_LEVEL
&& current_sample - channel[i].lasttime < rev_max_delay_out)
|| channel[i].chorus_level > 0 || channel[i].delay_level > 0
|| channel[i].eq_xg.valid
|| channel[i].dry_level != 127
|| (timidity_drum_effect && ISDRUMCHANNEL(i))
|| is_insertion_effect_xg(i)) {
vpblist[i] = (int32_t*)(reverb_buffer + buf_index);
buf_index += n;
} else {
vpblist[i] = buffer_pointer;
}
/* clear buffers of drum-part effect */
if (timidity_drum_effect && ISDRUMCHANNEL(i)) {
for (j = 0; j < channel[i].drum_effect_num; j++) {
if (channel[i].drum_effect[j].buf != NULL) {
memset(channel[i].drum_effect[j].buf, 0, n);
}
}
}
}
if(buf_index) {memset(reverb_buffer, 0, buf_index);}
}
for (i = 0; i < uv; i++) {
if (voice[i].status != VOICE_FREE) {
int32_t *vpb = NULL;
int8_t flag;
if (channel_effect) {
flag = 0;
ch = voice[i].channel;
if (timidity_drum_effect && ISDRUMCHANNEL(ch)) {
make_drum_effect(ch);
note = voice[i].note;
for (j = 0; j < channel[ch].drum_effect_num; j++) {
if (channel[ch].drum_effect[j].note == note) {
vpb = channel[ch].drum_effect[j].buf;
flag = 1;
}
}
if (flag == 0) {vpb = vpblist[ch];}
} else {
vpb = vpblist[ch];
}
} else {
vpb = buffer_pointer;
}
if(!IS_SET_CHANNELMASK(channel_mute, voice[i].channel)) {
mixer->mix_voice(vpb, i, count);
} else {
free_voice(i);
}
if(voice[i].timeout == 1 && voice[i].timeout < current_sample) {
free_voice(i);
}
}
}
while(uv > 0 && voice[uv - 1].status == VOICE_FREE) {uv--;}
upper_voices = uv;
if(play_system_mode == XG_SYSTEM_MODE && channel_effect) { /* XG */
if (opt_insertion_effect) { /* insertion effect */
for (i = 0; i < XG_INSERTION_EFFECT_NUM; i++) {
if (reverb->insertion_effect_xg[i].part <= MAX_CHANNELS) {
reverb->do_insertion_effect_xg(vpblist[reverb->insertion_effect_xg[i].part], cnt, &reverb->insertion_effect_xg[i]);
}
}
for (i = 0; i < XG_VARIATION_EFFECT_NUM; i++) {
if (reverb->variation_effect_xg[i].part <= MAX_CHANNELS) {
reverb->do_insertion_effect_xg(vpblist[reverb->variation_effect_xg[i].part], cnt, &reverb->variation_effect_xg[i]);
}
}
}
for(i = 0; i < MAX_CHANNELS; i++) { /* system effects */
int32_t *p;
p = vpblist[i];
if(p != buffer_pointer) {
if (timidity_drum_effect && ISDRUMCHANNEL(i)) {
for (j = 0; j < channel[i].drum_effect_num; j++) {
de = &(channel[i].drum_effect[j]);
if (de->reverb_send > 0) {
reverb->set_ch_reverb(de->buf, cnt, de->reverb_send);
}
if (de->chorus_send > 0) {
reverb->set_ch_chorus(de->buf, cnt, de->chorus_send);
}
if (de->delay_send > 0) {
reverb->set_ch_delay(de->buf, cnt, de->delay_send);
}
mix_signal(p, de->buf, cnt);
}
} else {
if(channel_eq && channel[i].eq_xg.valid) {
reverb->do_ch_eq_xg(p, cnt, &(channel[i].eq_xg));
}
if(channel_chorus && channel[i].chorus_level > 0) {
reverb->set_ch_chorus(p, cnt, channel[i].chorus_level);
}
if(channel_delay && channel[i].delay_level > 0) {
reverb->set_ch_delay(p, cnt, channel[i].delay_level);
}
if(channel_reverb && channel[i].reverb_level > 0
&& current_sample - channel[i].lasttime < rev_max_delay_out) {
reverb->set_ch_reverb(p, cnt, channel[i].reverb_level);
}
}
if(channel[i].dry_level == 127) {
reverb->set_dry_signal(p, cnt);
} else {
reverb->set_dry_signal_xg(p, cnt, channel[i].dry_level);
}
}
}
if(channel_reverb) {
reverb->set_ch_reverb(buffer_pointer, cnt, DEFAULT_REVERB_SEND_LEVEL);
}
reverb->set_dry_signal(buffer_pointer, cnt);
/* mixing signal and applying system effects */
reverb->mix_dry_signal(buffer_pointer, cnt);
if(channel_delay) { reverb->do_variation_effect1_xg(buffer_pointer, cnt);}
if(channel_chorus) { reverb->do_ch_chorus_xg(buffer_pointer, cnt);}
if(channel_reverb) { reverb->do_ch_reverb(buffer_pointer, cnt);}
if(reverb->multi_eq_xg.valid) { reverb->do_multi_eq_xg(buffer_pointer, cnt);}
} else if(channel_effect) { /* GM & GS */
if(opt_insertion_effect) { /* insertion effect */
/* applying insertion effect */
reverb->do_insertion_effect_gs(insertion_effect_buffer, cnt);
/* sending insertion effect voice to channel effect */
reverb->set_ch_chorus(insertion_effect_buffer, cnt, reverb->insertion_effect_gs.send_chorus);
reverb->set_ch_delay(insertion_effect_buffer, cnt, reverb->insertion_effect_gs.send_delay);
reverb->set_ch_reverb(insertion_effect_buffer, cnt, reverb->insertion_effect_gs.send_reverb);
if(reverb->insertion_effect_gs.send_eq_switch && channel_eq) {
reverb->set_ch_eq_gs(insertion_effect_buffer, cnt);
} else {
reverb->set_dry_signal(insertion_effect_buffer, cnt);
}
}
for(i = 0; i < MAX_CHANNELS; i++) { /* system effects */
int32_t *p;
p = vpblist[i];
if(p != buffer_pointer && p != insertion_effect_buffer) {
if (timidity_drum_effect && ISDRUMCHANNEL(i)) {
for (j = 0; j < channel[i].drum_effect_num; j++) {
de = &(channel[i].drum_effect[j]);
if (de->reverb_send > 0) {
reverb->set_ch_reverb(de->buf, cnt, de->reverb_send);
}
if (de->chorus_send > 0) {
reverb->set_ch_chorus(de->buf, cnt, de->chorus_send);
}
if (de->delay_send > 0) {
reverb->set_ch_delay(de->buf, cnt, de->delay_send);
}
mix_signal(p, de->buf, cnt);
}
} else {
if(channel_chorus && channel[i].chorus_level > 0) {
reverb->set_ch_chorus(p, cnt, channel[i].chorus_level);
}
if(channel_delay && channel[i].delay_level > 0) {
reverb->set_ch_delay(p, cnt, channel[i].delay_level);
}
if(channel_reverb && channel[i].reverb_level > 0
&& current_sample - channel[i].lasttime < rev_max_delay_out) {
reverb->set_ch_reverb(p, cnt, channel[i].reverb_level);
}
}
if(channel_eq && channel[i].eq_gs) {
reverb->set_ch_eq_gs(p, cnt);
} else {
reverb->set_dry_signal(p, cnt);
}
}
}
if(channel_reverb) {
reverb->set_ch_reverb(buffer_pointer, cnt, DEFAULT_REVERB_SEND_LEVEL);
}
reverb->set_dry_signal(buffer_pointer, cnt);
/* mixing signal and applying system effects */
reverb->mix_dry_signal(buffer_pointer, cnt);
if(channel_eq) { reverb->do_ch_eq_gs(buffer_pointer, cnt);}
if(channel_chorus) { reverb->do_ch_chorus(buffer_pointer, cnt);}
if(channel_delay) { reverb->do_ch_delay(buffer_pointer, cnt);}
if(channel_reverb) { reverb->do_ch_reverb(buffer_pointer, cnt);}
}
current_sample += count;
}
int Player::compute_data(float *buffer, int32_t count)
{
if (count == 0) return RC_OK;
std::lock_guard<std::mutex> lock(ConfigMutex);
if (last_reverb_setting != timidity_reverb)
{
// If the reverb mode has changed some buffers need to be reallocated before doing any sound generation.
reverb->free_effect_buffers();
reverb->init_reverb();
last_reverb_setting = timidity_reverb;
}
buffer_pointer = common_buffer;
computed_samples += count;
while (count > 0)
{
int process = std::min(count, AUDIO_BUFFER_SIZE);
do_compute_data(process);
count -= process;
effect->do_effect(common_buffer, process);
// pass to caller
for (int i = 0; i < process*2; i++)
{
*buffer++ = (common_buffer[i])*(5.f / 0x80000000u);
}
}
return RC_OK;
}
void Player::update_modulation_wheel(int ch)
{
int i, uv = upper_voices;
channel[ch].pitchfactor = 0;
for(i = 0; i < uv; i++)
if(voice[i].status != VOICE_FREE && voice[i].channel == ch)
{
/* Set/Reset mod-wheel */
voice[i].vibrato_control_counter = voice[i].vibrato_phase = 0;
recompute_amp(i);
mixer->apply_envelope_to_amp(i);
recompute_freq(i);
recompute_voice_filter(i);
}
}
void Player::drop_portamento(int ch)
{
int i, uv = upper_voices;
channel[ch].porta_control_ratio = 0;
for(i = 0; i < uv; i++)
if(voice[i].status != VOICE_FREE &&
voice[i].channel == ch &&
voice[i].porta_control_ratio)
{
voice[i].porta_control_ratio = 0;
recompute_freq(i);
}
channel[ch].last_note_fine = -1;
}
void Player::update_portamento_controls(int ch)
{
if(!channel[ch].portamento ||
(channel[ch].portamento_time_msb | channel[ch].portamento_time_lsb)
== 0)
drop_portamento(ch);
else
{
double mt, dc;
int d;
mt = midi_time_table[channel[ch].portamento_time_msb & 0x7F] *
midi_time_table2[channel[ch].portamento_time_lsb & 0x7F] *
PORTAMENTO_TIME_TUNING;
dc = playback_rate * mt;
d = (int)(1.0 / (mt * PORTAMENTO_CONTROL_RATIO));
d++;
channel[ch].porta_control_ratio = (int)(d * dc + 0.5);
channel[ch].porta_dpb = d;
}
}
void Player::update_portamento_time(int ch)
{
int i, uv = upper_voices;
int dpb;
int32_t ratio;
update_portamento_controls(ch);
dpb = channel[ch].porta_dpb;
ratio = channel[ch].porta_control_ratio;
for(i = 0; i < uv; i++)
{
if(voice[i].status != VOICE_FREE &&
voice[i].channel == ch &&
voice[i].porta_control_ratio)
{
voice[i].porta_control_ratio = ratio;
voice[i].porta_dpb = dpb;
recompute_freq(i);
}
}
}
void Player::update_legato_controls(int ch)
{
double mt, dc;
int d;
mt = 0.06250 * PORTAMENTO_TIME_TUNING * 0.3;
dc = playback_rate * mt;
d = (int)(1.0 / (mt * PORTAMENTO_CONTROL_RATIO));
d++;
channel[ch].porta_control_ratio = (int)(d * dc + 0.5);
channel[ch].porta_dpb = d;
}
int Player::play_event(MidiEvent *ev)
{
int32_t i, j;
int k, l, ch, orig_ch, port_ch, offset, layered;
current_event = ev;
#ifndef SUPPRESS_CHANNEL_LAYER
orig_ch = ev->channel;
layered = !IS_SYSEX_EVENT_TYPE(ev);
for (k = 0; k < MAX_CHANNELS; k += 16) {
port_ch = (orig_ch + k) % MAX_CHANNELS;
offset = port_ch & ~0xf;
for (l = offset; l < offset + 16; l++) {
if (!layered && (k || l != offset))
continue;
if (layered) {
if (!IS_SET_CHANNELMASK(channel[l].channel_layer, port_ch)
|| channel[l].port_select != (orig_ch >> 4))
continue;
ev->channel = l;
}
#endif
ch = ev->channel;
switch (ev->type)
{
/* MIDI Events */
case ME_NOTEOFF:
note_off(ev);
break;
case ME_NOTEON:
note_on(ev);
break;
case ME_KEYPRESSURE:
adjust_pressure(ev);
break;
case ME_PROGRAM:
midi_program_change(ch, ev->a);
break;
case ME_CHANNEL_PRESSURE:
adjust_channel_pressure(ev);
break;
case ME_PITCHWHEEL:
channel[ch].pitchbend = ev->a + ev->b * 128;
channel[ch].pitchfactor = 0;
/* Adjust pitch for notes already playing */
adjust_pitch(ch);
break;
/* Controls */
case ME_TONE_BANK_MSB:
channel[ch].bank_msb = ev->a;
break;
case ME_TONE_BANK_LSB:
channel[ch].bank_lsb = ev->a;
break;
case ME_MODULATION_WHEEL:
channel[ch].mod.val = ev->a;
update_modulation_wheel(ch);
break;
case ME_MAINVOLUME:
channel[ch].volume = ev->a;
adjust_volume(ch);
break;
case ME_PAN:
channel[ch].panning = ev->a;
channel[ch].pan_random = 0;
if (adjust_panning_immediately && !channel[ch].pan_random)
adjust_panning(ch);
break;
case ME_EXPRESSION:
channel[ch].expression = ev->a;
adjust_volume(ch);
break;
case ME_SUSTAIN:
if (channel[ch].sustain == 0 && ev->a >= 64) {
update_redamper_controls(ch);
}
channel[ch].sustain = ev->a;
if (channel[ch].damper_mode == 0) { /* half-damper is not allowed. */
if (channel[ch].sustain >= 64) { channel[ch].sustain = 127; }
else { channel[ch].sustain = 0; }
}
if (channel[ch].sustain == 0 && channel[ch].sostenuto == 0)
drop_sustain(ch);
break;
case ME_SOSTENUTO:
channel[ch].sostenuto = (ev->a >= 64);
if (channel[ch].sustain == 0 && channel[ch].sostenuto == 0)
drop_sustain(ch);
else { update_sostenuto_controls(ch); }
break;
case ME_LEGATO_FOOTSWITCH:
channel[ch].legato = (ev->a >= 64);
break;
case ME_HOLD2:
break;
case ME_BREATH:
break;
case ME_FOOT:
break;
case ME_BALANCE:
break;
case ME_PORTAMENTO_TIME_MSB:
channel[ch].portamento_time_msb = ev->a;
update_portamento_time(ch);
break;
case ME_PORTAMENTO_TIME_LSB:
channel[ch].portamento_time_lsb = ev->a;
update_portamento_time(ch);
break;
case ME_PORTAMENTO:
channel[ch].portamento = (ev->a >= 64);
if (!channel[ch].portamento)
drop_portamento(ch);
break;
case ME_SOFT_PEDAL:
if (timidity_lpf_def) {
channel[ch].soft_pedal = ev->a;
//printMessage(CMSG_INFO,VERB_NOISY,"Soft Pedal (CH:%d VAL:%d)", ch, channel[ch].soft_pedal);
}
break;
case ME_HARMONIC_CONTENT:
if (timidity_lpf_def) {
channel[ch].param_resonance = ev->a - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"Harmonic Content (CH:%d VAL:%d)", ch, channel[ch].param_resonance);
}
break;
case ME_BRIGHTNESS:
if (timidity_lpf_def) {
channel[ch].param_cutoff_freq = ev->a - 64;
//printMessage(CMSG_INFO,VERB_NOISY,"Brightness (CH:%d VAL:%d)", ch, channel[ch].param_cutoff_freq);
}
break;
case ME_DATA_ENTRY_MSB:
if (channel[ch].rpn_7f7f_flag) /* disable */
break;
if ((i = last_rpn_addr(ch)) >= 0)
{
channel[ch].rpnmap[i] = ev->a;
update_rpn_map(ch, i, 1);
}
break;
case ME_DATA_ENTRY_LSB:
if (channel[ch].rpn_7f7f_flag) /* disable */
break;
if ((i = last_rpn_addr(ch)) >= 0)
{
channel[ch].rpnmap_lsb[i] = ev->a;
}
break;
case ME_REVERB_EFFECT:
if (timidity_reverb) {
if (ISDRUMCHANNEL(ch) && get_reverb_level(ch) != ev->a) { channel[ch].drum_effect_flag = 0; }
set_reverb_level(ch, ev->a);
}
break;
case ME_CHORUS_EFFECT:
if (timidity_chorus)
{
if (timidity_chorus == 1) {
if (ISDRUMCHANNEL(ch) && channel[ch].chorus_level != ev->a) { channel[ch].drum_effect_flag = 0; }
channel[ch].chorus_level = ev->a;
}
else {
channel[ch].chorus_level = -timidity_chorus;
}
if (ev->a) {
//printMessage(CMSG_INFO,VERB_NOISY,"Chorus Send (CH:%d LEVEL:%d)", ch, ev->a);
}
}
break;
case ME_TREMOLO_EFFECT:
//printMessage(CMSG_INFO,VERB_NOISY,"Tremolo Send (CH:%d LEVEL:%d)", ch, ev->a);
break;
case ME_CELESTE_EFFECT:
if (opt_delay_control) {
if (ISDRUMCHANNEL(ch) && channel[ch].delay_level != ev->a) { channel[ch].drum_effect_flag = 0; }
channel[ch].delay_level = ev->a;
if (play_system_mode == XG_SYSTEM_MODE) {
//printMessage(CMSG_INFO,VERB_NOISY,"Variation Send (CH:%d LEVEL:%d)", ch, ev->a);
}
else {
//printMessage(CMSG_INFO,VERB_NOISY,"Delay Send (CH:%d LEVEL:%d)", ch, ev->a);
}
}
break;
case ME_ATTACK_TIME:
if (!opt_tva_attack) { break; }
set_envelope_time(ch, ev->a, EG_ATTACK);
break;
case ME_RELEASE_TIME:
if (!opt_tva_release) { break; }
set_envelope_time(ch, ev->a, EG_RELEASE);
break;
case ME_PHASER_EFFECT:
//printMessage(CMSG_INFO,VERB_NOISY,"Phaser Send (CH:%d LEVEL:%d)", ch, ev->a);
break;
case ME_RPN_INC:
if (channel[ch].rpn_7f7f_flag) /* disable */
break;
if ((i = last_rpn_addr(ch)) >= 0)
{
if (channel[ch].rpnmap[i] < 127)
channel[ch].rpnmap[i]++;
update_rpn_map(ch, i, 1);
}
break;
case ME_RPN_DEC:
if (channel[ch].rpn_7f7f_flag) /* disable */
break;
if ((i = last_rpn_addr(ch)) >= 0)
{
if (channel[ch].rpnmap[i] > 0)
channel[ch].rpnmap[i]--;
update_rpn_map(ch, i, 1);
}
break;
case ME_NRPN_LSB:
channel[ch].lastlrpn = ev->a;
channel[ch].nrpn = 1;
break;
case ME_NRPN_MSB:
channel[ch].lastmrpn = ev->a;
channel[ch].nrpn = 1;
break;
case ME_RPN_LSB:
channel[ch].lastlrpn = ev->a;
channel[ch].nrpn = 0;
break;
case ME_RPN_MSB:
channel[ch].lastmrpn = ev->a;
channel[ch].nrpn = 0;
break;
case ME_ALL_SOUNDS_OFF:
all_sounds_off(ch);
break;
case ME_RESET_CONTROLLERS:
reset_controllers(ch);
break;
case ME_ALL_NOTES_OFF:
all_notes_off(ch);
break;
case ME_MONO:
channel[ch].mono = 1;
all_notes_off(ch);
break;
case ME_POLY:
channel[ch].mono = 0;
all_notes_off(ch);
break;
/* TiMidity Extensionals */
case ME_RANDOM_PAN:
channel[ch].panning = int_rand(128);
channel[ch].pan_random = 1;
if (adjust_panning_immediately && !channel[ch].pan_random)
adjust_panning(ch);
break;
case ME_SET_PATCH:
i = channel[ch].special_sample = current_event->a;
instruments->setSpecialPatchOffset(i, 0);
break;
case ME_TEMPO:
current_play_tempo = ch + ev->b * 256 + ev->a * 65536;
break;
case ME_CHORUS_TEXT:
case ME_LYRIC:
case ME_MARKER:
case ME_INSERT_TEXT:
case ME_TEXT:
case ME_KARAOKE_LYRIC:
case ME_GSLCD:
break;
case ME_MASTER_VOLUME:
master_volume_ratio = (int32_t)ev->a + 256 * (int32_t)ev->b;
adjust_master_volume();
break;
case ME_RESET:
change_system_mode(ev->a);
reset_midi(1);
break;
case ME_PATCH_OFFS:
i = channel[ch].special_sample;
instruments->setSpecialPatchOffset(i, current_event->a | (256 * current_event->b));
break;
case ME_WRD:
break;
case ME_SHERRY:
break;
case ME_DRUMPART:
if (midi_drumpart_change(ch, current_event->a))
{
/* Update bank information */
midi_program_change(ch, channel[ch].program);
}
break;
case ME_KEYSHIFT:
i = (int)current_event->a - 0x40;
if (i != channel[ch].key_shift)
{
all_sounds_off(ch);
channel[ch].key_shift = (int8_t)i;
}
break;
case ME_KEYSIG:
if (opt_init_keysig != 8)
break;
current_keysig = current_event->a + current_event->b * 16;
if (opt_force_keysig != 8) {
i = current_keysig - ((current_keysig < 8) ? 0 : 16), j = 0;
while (i != opt_force_keysig && i != opt_force_keysig + 12)
i += (i > 0) ? -5 : 7, j++;
while (abs(j - note_key_offset) > 7)
j += (j > note_key_offset) ? -12 : 12;
if (abs(j - timidity_key_adjust) >= 12)
j += (j > timidity_key_adjust) ? -12 : 12;
note_key_offset = j;
kill_all_voices();
}
i = current_keysig + ((current_keysig < 8) ? 7 : -9), j = 0;
while (i != 7)
i += (i < 7) ? 5 : -7, j++;
j += note_key_offset, j -= floor(j / 12.0) * 12;
current_freq_table = j;
break;
case ME_MASTER_TUNING:
set_master_tuning((ev->b << 8) | ev->a);
adjust_all_pitch();
break;
case ME_SCALE_TUNING:
recache->resamp_cache_refer_alloff(ch, computed_samples);
channel[ch].scale_tuning[current_event->a] = current_event->b;
adjust_pitch(ch);
break;
case ME_BULK_TUNING_DUMP:
set_single_note_tuning(ch, current_event->a, current_event->b, 0);
break;
case ME_SINGLE_NOTE_TUNING:
set_single_note_tuning(ch, current_event->a, current_event->b, 1);
break;
case ME_TEMPER_KEYSIG:
current_temper_keysig = (current_event->a + 8) % 32 - 8;
temper_adj = ((current_event->a + 8) & 0x20) ? 1 : 0;
i = current_temper_keysig + ((current_temper_keysig < 8) ? 7 : -9);
j = 0;
while (i != 7)
i += (i < 7) ? 5 : -7, j++;
j += note_key_offset, j -= floor(j / 12.0) * 12;
current_temper_freq_table = j;
if (current_event->b)
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE) {
voice[i].temper_instant = 1;
recompute_freq(i);
}
break;
case ME_TEMPER_TYPE:
channel[ch].temper_type = current_event->a;
if (temper_type_mute) {
if (temper_type_mute & (1 << (current_event->a
- ((current_event->a >= 0x40) ? 0x3c : 0)))) {
SET_CHANNELMASK(channel_mute, ch);
}
else {
UNSET_CHANNELMASK(channel_mute, ch);
}
}
if (current_event->b)
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE) {
voice[i].temper_instant = 1;
recompute_freq(i);
}
break;
case ME_MASTER_TEMPER_TYPE:
for (i = 0; i < MAX_CHANNELS; i++) {
channel[i].temper_type = current_event->a;
}
if (temper_type_mute) {
if (temper_type_mute & (1 << (current_event->a
- ((current_event->a >= 0x40) ? 0x3c : 0)))) {
FILL_CHANNELMASK(channel_mute);
}
else {
CLEAR_CHANNELMASK(channel_mute);
}
}
if (current_event->b)
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE) {
voice[i].temper_instant = 1;
recompute_freq(i);
}
break;
case ME_USER_TEMPER_ENTRY:
set_user_temper_entry(ch, current_event->a, current_event->b);
break;
case ME_SYSEX_LSB:
process_sysex_event(ME_SYSEX_LSB, ch, current_event->a, current_event->b);
break;
case ME_SYSEX_MSB:
process_sysex_event(ME_SYSEX_MSB, ch, current_event->a, current_event->b);
break;
case ME_SYSEX_GS_LSB:
process_sysex_event(ME_SYSEX_GS_LSB, ch, current_event->a, current_event->b);
break;
case ME_SYSEX_GS_MSB:
process_sysex_event(ME_SYSEX_GS_MSB, ch, current_event->a, current_event->b);
break;
case ME_SYSEX_XG_LSB:
process_sysex_event(ME_SYSEX_XG_LSB, ch, current_event->a, current_event->b);
break;
case ME_SYSEX_XG_MSB:
process_sysex_event(ME_SYSEX_XG_MSB, ch, current_event->a, current_event->b);
break;
case ME_NOTE_STEP:
break;
case ME_EOT:
break;
}
#ifndef SUPPRESS_CHANNEL_LAYER
}
}
ev->channel = orig_ch;
#endif
return RC_OK;
}
void Player::set_master_tuning(int tune)
{
if (tune & 0x4000) /* 1/8192 semitones + 0x2000 | 0x4000 */
tune = (tune & 0x3FFF) - 0x2000;
else if (tune & 0x8000) /* 1 semitones | 0x8000 */
tune = ((tune & 0x7F) - 0x40) << 13;
else /* millisemitones + 0x400 */
tune = (((tune - 0x400) << 13) + 500) / 1000;
master_tuning = tune;
}
void Player::set_single_note_tuning(int part, int a, int b, int rt)
{
static int tp; /* tuning program number */
static int kn; /* MIDI key number */
static int st; /* the nearest equal-tempered semitone */
double f, fst; /* fraction of semitone */
int i;
switch (part) {
case 0:
tp = a;
break;
case 1:
kn = a, st = b;
break;
case 2:
if (st == 0x7f && a == 0x7f && b == 0x7f) /* no change */
break;
f = 440 * pow(2.0, (st - 69) / 12.0);
fst = pow(2.0, (a << 7 | b) / 196608.0);
freq_table_tuning[tp][kn] = f * fst * 1000 + 0.5;
if (rt)
for (i = 0; i < upper_voices; i++)
if (voice[i].status != VOICE_FREE) {
voice[i].temper_instant = 1;
recompute_freq(i);
}
break;
}
}
void Player::set_user_temper_entry(int part, int a, int b)
{
static int tp; /* temperament program number */
static int ll; /* number of formula */
static int fh, fl; /* applying pitch bit mask (forward) */
static int bh, bl; /* applying pitch bit mask (backward) */
static int aa, bb; /* fraction (aa/bb) */
static int cc, dd; /* power (cc/dd)^(ee/ff) */
static int ee, ff;
static int ifmax, ibmax, count;
static double rf[11], rb[11];
int i, j, k, l, n, m;
double ratio[12], f, sc;
switch (part) {
case 0:
for (i = 0; i < 11; i++)
rf[i] = rb[i] = 1;
ifmax = ibmax = 0;
count = 0;
tp = a, ll = b;
break;
case 1:
fh = a, fl = b;
break;
case 2:
bh = a, bl = b;
break;
case 3:
aa = a, bb = b;
break;
case 4:
cc = a, dd = b;
break;
case 5:
ee = a, ff = b;
for (i = 0; i < 11; i++) {
if (((fh & 0xf) << 7 | fl) & 1 << i) {
rf[i] *= (double) aa / bb
* pow((double) cc / dd, (double) ee / ff);
if (ifmax < i + 1)
ifmax = i + 1;
}
if (((bh & 0xf) << 7 | bl) & 1 << i) {
rb[i] *= (double) aa / bb
* pow((double) cc / dd, (double) ee / ff);
if (ibmax < i + 1)
ibmax = i + 1;
}
}
if (++count < ll)
break;
ratio[0] = 1;
for (i = n = m = 0; i < ifmax; i++, m = n) {
n += (n > 4) ? -5 : 7;
ratio[n] = ratio[m] * rf[i];
if (ratio[n] > 2)
ratio[n] /= 2;
}
for (i = n = m = 0; i < ibmax; i++, m = n) {
n += (n > 6) ? -7 : 5;
ratio[n] = ratio[m] / rb[i];
if (ratio[n] < 1)
ratio[n] *= 2;
}
sc = 27 / ratio[9] / 16; /* syntonic comma */
for (i = 0; i < 12; i++)
for (j = -1; j < 11; j++) {
f = 440 * pow(2.0, (i - 9) / 12.0 + j - 5);
for (k = 0; k < 12; k++) {
l = i + j * 12 + k;
if (l < 0 || l >= 128)
continue;
if (! (fh & 0x40)) { /* major */
freq_table_user[tp][i][l] =
f * ratio[k] * 1000 + 0.5;
freq_table_user[tp][i + 36][l] =
f * ratio[k] * sc * 1000 + 0.5;
}
if (! (bh & 0x40)) { /* minor */
freq_table_user[tp][i + 12][l] =
f * ratio[k] * sc * 1000 + 0.5;
freq_table_user[tp][i + 24][l] =
f * ratio[k] * 1000 + 0.5;
}
}
}
break;
}
}
struct midi_file_info *Player::new_midi_file_info()
{
struct midi_file_info *p = &midifileinfo;
/* Initialize default members */
memset(p, 0, sizeof(struct midi_file_info));
p->hdrsiz = -1;
p->format = -1;
p->tracks = -1;
p->divisions = -1;
p->time_sig_n = p->time_sig_d = -1;
p->samples = -1;
p->max_channel = -1;
COPY_CHANNELMASK(p->drumchannels, default_drumchannels);
COPY_CHANNELMASK(p->drumchannel_mask, default_drumchannel_mask);
return p;
}
/*
* For MIDI stream player.
*/
void Player::playmidi_stream_init(void)
{
int i;
static int first = 1;
note_key_offset = timidity_key_adjust;
midi_time_ratio = timidity_tempo_adjust;
CLEAR_CHANNELMASK(channel_mute);
if (temper_type_mute & 1)
FILL_CHANNELMASK(channel_mute);
if (first)
{
first = 0;
init_mblock(&playmidi_pool);
midi_streaming = 1;
}
else
reuse_mblock(&playmidi_pool);
/* Fill in current_file_info */
current_file_info = &midifileinfo;
current_file_info->readflag = 1;
current_file_info->hdrsiz = 0;
current_file_info->format = 0;
current_file_info->tracks = 0;
current_file_info->divisions = 192; /* ?? */
current_file_info->time_sig_n = 4; /* 4/ */
current_file_info->time_sig_d = 4; /* /4 */
current_file_info->time_sig_c = 24; /* clock */
current_file_info->time_sig_b = 8; /* q.n. */
current_file_info->samples = 0;
current_file_info->max_channel = MAX_CHANNELS;
current_file_info->compressed = 0;
current_play_tempo = 500000;
check_eot_flag = 0;
/* Setup default drums */
COPY_CHANNELMASK(current_file_info->drumchannels, default_drumchannels);
COPY_CHANNELMASK(current_file_info->drumchannel_mask, default_drumchannel_mask);
for(i = 0; i < MAX_CHANNELS; i++)
memset(channel[i].drums, 0, sizeof(channel[i].drums));
change_system_mode(DEFAULT_SYSTEM_MODE);
reset_midi(0);
playmidi_tmr_reset();
}
void Player::playmidi_tmr_reset(void)
{
int i;
current_sample = 0;
buffer_pointer = common_buffer;
for(i = 0; i < MAX_CHANNELS; i++)
channel[i].lasttime = 0;
}
/*! initialize Part EQ (XG) */
void Player::init_part_eq_xg(struct part_eq_xg *p)
{
p->bass = 0x40;
p->treble = 0x40;
p->bass_freq = 0x0C;
p->treble_freq = 0x36;
p->valid = 0;
}
/*! recompute Part EQ (XG) */
void Player::recompute_part_eq_xg(struct part_eq_xg *p)
{
int8_t vbass, vtreble;
if(p->bass_freq >= 4 && p->bass_freq <= 40 && p->bass != 0x40) {
vbass = 1;
p->basss.q = 0.7;
p->basss.freq = eq_freq_table_xg[p->bass_freq];
if(p->bass == 0) {p->basss.gain = -12.0;}
else {p->basss.gain = 0.19 * (double)(p->bass - 0x40);}
reverb->calc_filter_shelving_low(&(p->basss));
} else {vbass = 0;}
if(p->treble_freq >= 28 && p->treble_freq <= 58 && p->treble != 0x40) {
vtreble = 1;
p->trebles.q = 0.7;
p->trebles.freq = eq_freq_table_xg[p->treble_freq];
if(p->treble == 0) {p->trebles.gain = -12.0;}
else {p->trebles.gain = 0.19 * (double)(p->treble - 0x40);}
reverb->calc_filter_shelving_high(&(p->trebles));
} else {vtreble = 0;}
p->valid = vbass || vtreble;
}
void Player::init_midi_controller(midi_controller *p)
{
p->val = 0;
p->pitch = 0;
p->cutoff = 0;
p->amp = 0.0;
p->lfo1_rate = p->lfo2_rate = p->lfo1_tva_depth = p->lfo2_tva_depth = 0;
p->lfo1_pitch_depth = p->lfo2_pitch_depth = p->lfo1_tvf_depth = p->lfo2_tvf_depth = 0;
p->variation_control_depth = p->insertion_control_depth = 0;
}
float Player::get_midi_controller_amp(midi_controller *p)
{
return (1.0 + (float)p->val * (1.0f / 127.0f) * p->amp);
}
float Player::get_midi_controller_filter_cutoff(midi_controller *p)
{
return ((float)p->val * (1.0f / 127.0f) * (float)p->cutoff);
}
float Player::get_midi_controller_filter_depth(midi_controller *p)
{
return ((float)p->val * (1.0f / 127.0f) * (float)p->lfo1_tvf_depth);
}
int32_t Player::get_midi_controller_pitch(midi_controller *p)
{
return ((int32_t)(p->val * p->pitch) << 6);
}
int16_t Player::get_midi_controller_pitch_depth(midi_controller *p)
{
return (int16_t)((float)p->val * (float)p->lfo1_pitch_depth * (1.0f / 127.0f * 256.0 / 400.0));
}
int16_t Player::get_midi_controller_amp_depth(midi_controller *p)
{
return (int16_t)((float)p->val * (float)p->lfo1_tva_depth * (1.0f / 127.0f * 256.0));
}
void Player::init_rx(int ch)
{
channel[ch].rx = 0xFFFFFFFF; /* all on */
}
void Player::set_rx(int ch, int32_t rx, int flag)
{
if(ch > MAX_CHANNELS) {return;}
if(flag) {channel[ch].rx |= rx;}
else {channel[ch].rx &= ~rx;}
}
void Player::init_rx_drum(struct DrumParts *p)
{
p->rx = 0xFFFFFFFF; /* all on */
}
void Player::set_rx_drum(struct DrumParts *p, int32_t rx, int flag)
{
if(flag) {p->rx |= rx;}
else {p->rx &= ~rx;}
}
int32_t Player::get_rx_drum(struct DrumParts *p, int32_t rx)
{
return (p->rx & rx);
}
Instrument *Player::play_midi_load_instrument(int dr, int bk, int prog)
{
bool load_success;
// The inner workings of this function which alters the instrument data has been put into the Instruments class.
auto instr = instruments->play_midi_load_instrument(dr, bk, prog, &load_success);
//if (load_success) send_output(NULL, 0); /* Update software buffer */
return instr;
}
void Player::change_system_mode(int mode)
{
pan_table = sc_pan_table;
switch (mode)
{
case GM_SYSTEM_MODE:
if (play_system_mode == DEFAULT_SYSTEM_MODE)
{
play_system_mode = GM_SYSTEM_MODE;
vol_table = def_vol_table;
}
break;
case GM2_SYSTEM_MODE:
play_system_mode = GM2_SYSTEM_MODE;
vol_table = def_vol_table;
pan_table = gm2_pan_table;
break;
case GS_SYSTEM_MODE:
play_system_mode = GS_SYSTEM_MODE;
vol_table = gs_vol_table;
break;
case XG_SYSTEM_MODE:
if (play_system_mode != XG_SYSTEM_MODE) { reverb->init_all_effect_xg(); }
play_system_mode = XG_SYSTEM_MODE;
vol_table = xg_vol_table;
break;
default:
play_system_mode = DEFAULT_SYSTEM_MODE;
vol_table = def_vol_table;
break;
}
}
/*! initialize channel layers. */
void Player::init_channel_layer(int ch)
{
if (ch >= MAX_CHANNELS)
return;
CLEAR_CHANNELMASK(channel[ch].channel_layer);
SET_CHANNELMASK(channel[ch].channel_layer, ch);
channel[ch].port_select = ch >> 4;
}
static const struct ctl_chg_types {
unsigned char mtype;
int ttype;
} ctl_chg_list[] = {
{ 0, ME_TONE_BANK_MSB },
{ 1, ME_MODULATION_WHEEL },
{ 2, ME_BREATH },
{ 4, ME_FOOT },
{ 5, ME_PORTAMENTO_TIME_MSB },
{ 6, ME_DATA_ENTRY_MSB },
{ 7, ME_MAINVOLUME },
{ 8, ME_BALANCE },
{ 10, ME_PAN },
{ 11, ME_EXPRESSION },
{ 32, ME_TONE_BANK_LSB },
{ 37, ME_PORTAMENTO_TIME_LSB },
{ 38, ME_DATA_ENTRY_LSB },
{ 64, ME_SUSTAIN },
{ 65, ME_PORTAMENTO },
{ 66, ME_SOSTENUTO },
{ 67, ME_SOFT_PEDAL },
{ 68, ME_LEGATO_FOOTSWITCH },
{ 69, ME_HOLD2 },
{ 71, ME_HARMONIC_CONTENT },
{ 72, ME_RELEASE_TIME },
{ 73, ME_ATTACK_TIME },
{ 74, ME_BRIGHTNESS },
{ 84, ME_PORTAMENTO_CONTROL },
{ 91, ME_REVERB_EFFECT },
{ 92, ME_TREMOLO_EFFECT },
{ 93, ME_CHORUS_EFFECT },
{ 94, ME_CELESTE_EFFECT },
{ 95, ME_PHASER_EFFECT },
{ 96, ME_RPN_INC },
{ 97, ME_RPN_DEC },
{ 98, ME_NRPN_LSB },
{ 99, ME_NRPN_MSB },
{ 100, ME_RPN_LSB },
{ 101, ME_RPN_MSB },
{ 120, ME_ALL_SOUNDS_OFF },
{ 121, ME_RESET_CONTROLLERS },
{ 123, ME_ALL_NOTES_OFF },
{ 126, ME_MONO },
{ 127, ME_POLY },
};
int Player::convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret)
{
for (auto &t : ctl_chg_list)
{
if (t.mtype == type)
{
if (val > 127) val = 127;
ev_ret->type = t.ttype;
ev_ret->channel = chn;
ev_ret->a = val;
ev_ret->b = 0;
return 1;
}
}
return 0;
}
int Player::send_event(int status, int parm1, int parm2)
{
MidiEvent ev;
ev.type = ME_NONE;
ev.channel = status & 0x0000000f;
//ev.channel = ev.channel + port * 16;
ev.a = (uint8_t)parm1;
ev.b = (uint8_t)parm2;
switch ((int)(status & 0x000000f0))
{
case 0x80:
ev.type = ME_NOTEOFF;
break;
case 0x90:
ev.type = (ev.b) ? ME_NOTEON : ME_NOTEOFF;
break;
case 0xa0:
ev.type = ME_KEYPRESSURE;
break;
case 0xb0:
if (!convert_midi_control_change(ev.channel, ev.a, ev.b, &ev))
ev.type = ME_NONE;
break;
case 0xc0:
ev.type = ME_PROGRAM;
break;
case 0xd0:
ev.type = ME_CHANNEL_PRESSURE;
break;
case 0xe0:
ev.type = ME_PITCHWHEEL;
break;
/*
case 0xf0:
if ((status & 0x000000ff) == 0xf2)
{
ev.type = ME_PROGRAM;
}
break;
*/
default:
break;
}
if (ev.type != ME_NONE)
{
play_event(&ev);
}
return 0;
}
void Player::send_long_event(const uint8_t *sysexbuffer, int exlen)
{
int i, ne;
MidiEvent ev;
MidiEvent evm[260];
SysexConvert sc;
if ((sysexbuffer[0] != 0xf0) && (sysexbuffer[0] != 0xf7)) return;
if (sc.parse_sysex_event(sysexbuffer + 1, exlen - 1, &ev, instruments))
{
if (ev.type == ME_RESET)
{
kill_all_voices();
for (int i = 0; i < MAX_CHANNELS; i++)
init_channel_layer(i);
/* initialize effect status */
reverb->init_effect_status(play_system_mode);
effect->init_effect();
instruments->init_userdrum();
instruments->init_userinst();
playmidi_stream_init();
}
play_event(&ev);
return;
}
if ((ne = sc.parse_sysex_event_multi(sysexbuffer + 1, exlen - 1, evm, instruments)))
{
for (i = 0; i < ne; i++)
{
play_event(&evm[i]);
}
}
}
}