📄 playmidi.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2004 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*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#ifdef __W32__#include "interface.h"#endif#include <stdio.h>#include <stdlib.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <math.h>#ifdef __W32__#include <windows.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "output.h"#include "mix.h"#include "controls.h"#include "miditrace.h"#include "recache.h"#include "arc.h"#include "reverb.h"#include "wrd.h"#include "aq.h"#include "freq.h"#include "quantity.h"extern void convert_mod_to_midi_file(MidiEvent * ev);#define ABORT_AT_FATAL 1 /*#################*/#define MYCHECK(s) do { if(s == 0) { printf("## L %d\n", __LINE__); abort(); } } while(0)extern VOLATILE int intr;/* #define SUPPRESS_CHANNEL_LAYER */#ifdef SOLARIS/* shut gcc warning up */int usleep(unsigned int useconds);#endif#ifdef SUPPORT_SOUNDSPEC#include "soundspec.h"#endif /* SUPPORT_SOUNDSPEC */#include "tables.h"#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 CHORUS_VELOCITY_TUNING1 0.7#define CHORUS_VELOCITY_TUNING2 0.6#define EOT_PRESEARCH_LEN 32#define SPEED_CHANGE_RATE 1.0594630943592953 /* 2^(1/12) *//* Undefine if you don't want to use auto voice reduce implementation */#define REDUCE_VOICE_TIME_TUNING (play_mode->rate/5) /* 0.2 sec */#ifdef REDUCE_VOICE_TIME_TUNINGstatic int max_good_nv = 1;static int min_bad_nv = 256;static int32 ok_nv_total = 32;static int32 ok_nv_counts = 1;static int32 ok_nv_sample = 0;static int ok_nv = 32;static int old_rate = -1;#endifstatic int midi_streaming = 0;int volatile stream_max_compute = 500; /* compute time limit (in msec) when streaming */static int prescanning_flag;static int32 midi_restart_time = 0;Channel channel[MAX_CHANNELS];int max_voices = DEFAULT_VOICES;Voice *voice = NULL;int8 current_keysig = 0;int8 current_temper_keysig = 0;int temper_adj = 0;int8 opt_init_keysig = 8;int8 opt_force_keysig = 8;int32 current_play_tempo = 500000;int opt_realtime_playing = 0;int reduce_voice_threshold = -1;static MBlockList playmidi_pool;int check_eot_flag;int special_tonebank = -1;int default_tonebank = 0;int playmidi_seek_flag = 0;int play_pause_flag = 0;static int file_from_stdin;int key_adjust = 0;FLOAT_T tempo_adjust = 1.0;int opt_pure_intonation = 0;int current_freq_table = 0;int current_temper_freq_table = 0;static void set_reverb_level(int ch, int level);static int make_rvid_flag = 0; /* For reverb optimization *//* Ring voice id for each notes. This ID enables duplicated note. */static uint8 vidq_head[128 * MAX_CHANNELS], vidq_tail[128 * MAX_CHANNELS];#ifdef MODULATION_WHEEL_ALLOWint opt_modulation_wheel = 1;#elseint opt_modulation_wheel = 0;#endif /* MODULATION_WHEEL_ALLOW */#ifdef PORTAMENTO_ALLOWint opt_portamento = 1;#elseint opt_portamento = 0;#endif /* PORTAMENTO_ALLOW */#ifdef NRPN_VIBRATO_ALLOWint opt_nrpn_vibrato = 1;#elseint opt_nrpn_vibrato = 0;#endif /* NRPN_VIBRATO_ALLOW */#ifdef REVERB_CONTROL_ALLOWint opt_reverb_control = 1;#else#ifdef FREEVERB_CONTROL_ALLOWint opt_reverb_control = 3;#elseint opt_reverb_control = 0;#endif /* FREEVERB_CONTROL_ALLOW */#endif /* REVERB_CONTROL_ALLOW */#ifdef CHORUS_CONTROL_ALLOWint opt_chorus_control = 1;#elseint opt_chorus_control = 0;#endif /* CHORUS_CONTROL_ALLOW */#ifdef SURROUND_CHORUS_ALLOWint opt_surround_chorus = 1;#elseint opt_surround_chorus = 0;#endif /* SURROUND_CHORUS_ALLOW */#ifdef GM_CHANNEL_PRESSURE_ALLOWint opt_channel_pressure = 1;#elseint opt_channel_pressure = 0;#endif /* GM_CHANNEL_PRESSURE_ALLOW */#ifdef VOICE_CHAMBERLIN_LPF_ALLOWint opt_lpf_def = 1;#else#ifdef VOICE_MOOG_LPF_ALLOWint opt_lpf_def = 2;#elseint opt_lpf_def = 0;#endif /* VOICE_MOOG_LPF_ALLOW */#endif /* VOICE_CHAMBERLIN_LPF_ALLOW */#ifdef OVERLAP_VOICE_ALLOWint opt_overlap_voice_allow = 1;#elseint opt_overlap_voice_allow = 0;#endif /* OVERLAP_VOICE_ALLOW */#ifdef TEMPER_CONTROL_ALLOWint opt_temper_control = 1;#elseint opt_temper_control = 0;#endif /* TEMPER_CONTROL_ALLOW */int opt_tva_attack = 0; /* attack envelope control */int opt_tva_decay = 0; /* decay envelope control */int opt_tva_release = 0; /* release envelope control */int opt_delay_control = 0; /* CC#94 delay(celeste) effect control */int opt_eq_control = 0; /* channel equalizer control */int opt_insertion_effect = 0; /* insertion effect control */int opt_drum_effect = 0; /* drumpart effect control */int32 opt_drum_power = 100; /* coef. of drum amplitude */int opt_amp_compensation = 0;int opt_modulation_envelope = 0;int opt_pan_delay = 0; /* phase difference between left ear and right ear. */int opt_user_volume_curve = 0;int opt_default_module = MODULE_TIMIDITY_DEFAULT;int voices=DEFAULT_VOICES, upper_voices;int32 control_ratio=0, amplification=DEFAULT_AMPLIFICATION;static FLOAT_T master_volume;static int32 master_volume_ratio = 0xFFFF;ChannelBitMask default_drumchannel_mask;ChannelBitMask default_drumchannels;ChannelBitMask drumchannel_mask;ChannelBitMask drumchannels;int adjust_panning_immediately = 1;int auto_reduce_polyphony = 1;double envelope_modify_rate = 1.0;int reduce_quality_flag = 0;int no_4point_interpolation = 0;char* pcm_alternate_file = NULL; /* NULL or "none": Nothing (default) * "auto": Auto select * filename: Use it */static int32 lost_notes, cut_notes;static int32 common_buffer[AUDIO_BUFFER_SIZE*2], /* stereo samples */ *buffer_pointer;static int16 wav_buffer[AUDIO_BUFFER_SIZE*2];static int32 buffered_count;static char *reverb_buffer = NULL; /* MAX_CHANNELS*AUDIO_BUFFER_SIZE*8 */#ifdef USE_DSP_EFFECTstatic int32 insertion_effect_buffer[AUDIO_BUFFER_SIZE * 2];#endif /* USE_DSP_EFFECT */#define VIBRATO_DEPTH_MAX 384 /* 600 cent */static MidiEvent *event_list;static MidiEvent *current_event;static int32 sample_count; /* Length of event_list */int32 current_sample; /* Number of calclated samples */int note_key_offset = 0; /* For key up/down */FLOAT_T midi_time_ratio = 1.0; /* For speed up/down */ChannelBitMask channel_mute; /* For channel mute */int temper_type_mute; /* For temperament type mute *//* for auto amplitude compensation */static int mainvolume_max; /* maximum value of mainvolume */static double compensation_ratio = 1.0; /* compensation ratio */static int find_samples(MidiEvent *, int *);static int select_play_sample(Sample *, int, int *, int *, MidiEvent *);static double get_play_note_ratio(int, int);static int find_voice(MidiEvent *);static void update_portamento_controls(int ch);static void update_rpn_map(int ch, int addr, int update_now);static void ctl_prog_event(int ch);static void ctl_timestamp(void);static void ctl_updatetime(int32 samples);static void ctl_pause_event(int pause, int32 samples);static void update_legato_controls(int ch);static void update_channel_freq(int ch);static void set_single_note_tuning(int, int, int, int);static void set_user_temper_entry(int, int, int);void recompute_bank_parameter(int, int);static void init_voice_filter(int);/* XG Part EQ */void init_part_eq_xg(struct part_eq_xg *);void recompute_part_eq_xg(struct part_eq_xg *);/* MIDI controllers (MW, Bend, CAf, PAf,...) */static void init_midi_controller(midi_controller *);static float get_midi_controller_amp(midi_controller *);static float get_midi_controller_filter_cutoff(midi_controller *);static float get_midi_controller_filter_depth(midi_controller *);static int32 get_midi_controller_pitch(midi_controller *);static int16 get_midi_controller_pitch_depth(midi_controller *);static int16 get_midi_controller_amp_depth(midi_controller *);/* Rx. ~ (Rcv ~) */static void init_rx(int);static void set_rx(int, int32, int);static int32 get_rx(int, int32);static void init_rx_drum(struct DrumParts *);static void set_rx_drum(struct DrumParts *, int32, int);static int32 get_rx_drum(struct DrumParts *, int32);#define IS_SYSEX_EVENT_TYPE(event) ((event)->type == ME_NONE || (event)->type >= ME_RANDOM_PAN || (event)->b == SYSEX_TAG)static char *event_name(int type){#define EVENT_NAME(X) case X: return #X switch (type) { EVENT_NAME(ME_NONE); EVENT_NAME(ME_NOTEOFF); EVENT_NAME(ME_NOTEON); EVENT_NAME(ME_KEYPRESSURE); EVENT_NAME(ME_PROGRAM); EVENT_NAME(ME_CHANNEL_PRESSURE); EVENT_NAME(ME_PITCHWHEEL); EVENT_NAME(ME_TONE_BANK_MSB); EVENT_NAME(ME_TONE_BANK_LSB); EVENT_NAME(ME_MODULATION_WHEEL); EVENT_NAME(ME_BREATH); EVENT_NAME(ME_FOOT); EVENT_NAME(ME_MAINVOLUME); EVENT_NAME(ME_BALANCE); EVENT_NAME(ME_PAN); EVENT_NAME(ME_EXPRESSION); EVENT_NAME(ME_SUSTAIN); EVENT_NAME(ME_PORTAMENTO_TIME_MSB); EVENT_NAME(ME_PORTAMENTO_TIME_LSB); EVENT_NAME(ME_PORTAMENTO); EVENT_NAME(ME_PORTAMENTO_CONTROL); EVENT_NAME(ME_DATA_ENTRY_MSB); EVENT_NAME(ME_DATA_ENTRY_LSB); EVENT_NAME(ME_SOSTENUTO); EVENT_NAME(ME_SOFT_PEDAL); EVENT_NAME(ME_LEGATO_FOOTSWITCH); EVENT_NAME(ME_HOLD2); EVENT_NAME(ME_HARMONIC_CONTENT); EVENT_NAME(ME_RELEASE_TIME); EVENT_NAME(ME_ATTACK_TIME); EVENT_NAME(ME_BRIGHTNESS); EVENT_NAME(ME_REVERB_EFFECT); EVENT_NAME(ME_TREMOLO_EFFECT); EVENT_NAME(ME_CHORUS_EFFECT); EVENT_NAME(ME_CELESTE_EFFECT); EVENT_NAME(ME_PHASER_EFFECT); EVENT_NAME(ME_RPN_INC); EVENT_NAME(ME_RPN_DEC); EVENT_NAME(ME_NRPN_LSB); EVENT_NAME(ME_NRPN_MSB); EVENT_NAME(ME_RPN_LSB); EVENT_NAME(ME_RPN_MSB); EVENT_NAME(ME_ALL_SOUNDS_OFF); EVENT_NAME(ME_RESET_CONTROLLERS); EVENT_NAME(ME_ALL_NOTES_OFF); EVENT_NAME(ME_MONO); EVENT_NAME(ME_POLY);#if 0 EVENT_NAME(ME_VOLUME_ONOFF); /* Not supported */#endif EVENT_NAME(ME_SCALE_TUNING); EVENT_NAME(ME_BULK_TUNING_DUMP); EVENT_NAME(ME_SINGLE_NOTE_TUNING); EVENT_NAME(ME_RANDOM_PAN); EVENT_NAME(ME_SET_PATCH); EVENT_NAME(ME_DRUMPART); EVENT_NAME(ME_KEYSHIFT); EVENT_NAME(ME_PATCH_OFFS); EVENT_NAME(ME_TEMPO); EVENT_NAME(ME_CHORUS_TEXT); EVENT_NAME(ME_LYRIC); EVENT_NAME(ME_GSLCD); EVENT_NAME(ME_MARKER); EVENT_NAME(ME_INSERT_TEXT); EVENT_NAME(ME_TEXT); EVENT_NAME(ME_KARAOKE_LYRIC); EVENT_NAME(ME_MASTER_VOLUME); EVENT_NAME(ME_RESET); EVENT_NAME(ME_NOTE_STEP); EVENT_NAME(ME_TIMESIG); EVENT_NAME(ME_KEYSIG); EVENT_NAME(ME_TEMPER_KEYSIG); EVENT_NAME(ME_TEMPER_TYPE); EVENT_NAME(ME_MASTER_TEMPER_TYPE); EVENT_NAME(ME_USER_TEMPER_ENTRY); EVENT_NAME(ME_SYSEX_LSB); EVENT_NAME(ME_SYSEX_MSB); EVENT_NAME(ME_SYSEX_GS_LSB); EVENT_NAME(ME_SYSEX_GS_MSB); EVENT_NAME(ME_SYSEX_XG_LSB); EVENT_NAME(ME_SYSEX_XG_MSB); EVENT_NAME(ME_WRD); EVENT_NAME(ME_SHERRY); EVENT_NAME(ME_BARMARKER); EVENT_NAME(ME_STEP); EVENT_NAME(ME_LAST); EVENT_NAME(ME_EOT); } return "Unknown";#undef EVENT_NAME}/*! convert Hz to internal vibrato control ratio. */static FLOAT_T cnv_Hz_to_vib_ratio(FLOAT_T freq){ return ((FLOAT_T)(play_mode->rate) / (freq * 2.0f * VIBRATO_SAMPLE_INCREMENTS));}static void adjust_amplification(void){ /* compensate master volume */ master_volume = (double)(amplification) / 100.0 * ((double)master_volume_ratio * (compensation_ratio/0xFFFF));}static int new_vidq(int ch, int note){ int i; if(opt_overlap_voice_allow) { i = ch * 128 + note; return vidq_head[i]++; } return 0;}static int last_vidq(int ch, int note){ int i; if(opt_overlap_voice_allow) { i = ch * 128 + note; if(vidq_head[i] == vidq_tail[i]) { ctl->cmsg(CMSG_WARNING, VERB_DEBUG_SILLY, "channel=%d, note=%d: Voice is already OFF", ch, note); return -1; } return vidq_tail[i]++; } return 0;}static void reset_voices(void){ int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -