MIDI-SoundFont
view release on metacpan or search on metacpan
doc/timidity/playmidi.c view on Meta::CPAN
#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_TUNING
static 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;
#endif
static 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_ALLOW
int opt_modulation_wheel = 1;
#else
int opt_modulation_wheel = 0;
#endif /* MODULATION_WHEEL_ALLOW */
#ifdef PORTAMENTO_ALLOW
int opt_portamento = 1;
#else
int opt_portamento = 0;
#endif /* PORTAMENTO_ALLOW */
#ifdef NRPN_VIBRATO_ALLOW
int opt_nrpn_vibrato = 1;
#else
int opt_nrpn_vibrato = 0;
#endif /* NRPN_VIBRATO_ALLOW */
#ifdef REVERB_CONTROL_ALLOW
int opt_reverb_control = 1;
#else
#ifdef FREEVERB_CONTROL_ALLOW
int opt_reverb_control = 3;
#else
int opt_reverb_control = 0;
#endif /* FREEVERB_CONTROL_ALLOW */
#endif /* REVERB_CONTROL_ALLOW */
doc/timidity/playmidi.c view on Meta::CPAN
}
static void redraw_controllers(int c)
{
ctl_mode_event(CTLE_VOLUME, 1, c, channel[c].volume);
ctl_mode_event(CTLE_EXPRESSION, 1, c, channel[c].expression);
ctl_mode_event(CTLE_SUSTAIN, 1, c, channel[c].sustain);
ctl_mode_event(CTLE_MOD_WHEEL, 1, c, channel[c].mod.val);
ctl_mode_event(CTLE_PITCH_BEND, 1, c, channel[c].pitchbend);
ctl_prog_event(c);
ctl_mode_event(CTLE_TEMPER_TYPE, 1, c, channel[c].temper_type);
ctl_mode_event(CTLE_MUTE, 1,
c, (IS_SET_CHANNELMASK(channel_mute, c)) ? 1 : 0);
ctl_mode_event(CTLE_CHORUS_EFFECT, 1, c, get_chorus_level(c));
ctl_mode_event(CTLE_REVERB_EFFECT, 1, c, get_reverb_level(c));
}
static void reset_midi(int playing)
{
int i, cnt;
for (i = 0; i < MAX_CHANNELS; i++) {
reset_controllers(i);
reset_nrpn_controllers(i);
reset_module_dependent_controllers(i);
/* The rest of these are unaffected
* by the Reset All Controllers event
*/
channel[i].program = default_program[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 = 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);
}
for (i = 0; i < MAX_CHANNELS; i++)
redraw_controllers(i);
if (midi_streaming && free_instruments_afterwards) {
free_instruments(0);
/* free unused memory */
cnt = free_global_mblock();
if (cnt > 0)
ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
"%d memory blocks are free", cnt);
}
} else
reset_voices();
master_volume_ratio = 0xffff;
adjust_amplification();
init_freq_table_tuning();
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);
}
ctl_mode_event(CTLE_MASTER_VOLUME, 0, amplification, 0);
ctl_mode_event(CTLE_KEY_OFFSET, 0, note_key_offset, 0);
ctl_mode_event(CTLE_TIME_RATIO, 0, 100 / midi_time_ratio + 0.5, 0);
}
void recompute_freq(int v)
{
int i;
int ch = voice[v].channel;
int note = voice[v].note;
int32 tuning = 0;
int8 st = channel[ch].scale_tuning[note % 12];
int8 tt = channel[ch].temper_type;
uint8 tp = channel[ch].rpnmap[RPN_ADDR_0003];
int32 f;
int pb = channel[ch].pitchbend;
int32 tmp;
FLOAT_T pf, root_freq;
int32 a;
Voice *vp = &(voice[v]);
if (! voice[v].sample->sample_rate)
return;
if (! opt_modulation_wheel)
channel[ch].mod.val = 0;
if (! opt_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 (opt_channel_pressure || opt_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))
doc/timidity/playmidi.c view on Meta::CPAN
}
static void update_portamento_time(int ch)
{
int i, uv = upper_voices;
int dpb;
int32 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);
}
}
}
static void update_legato_controls(int ch)
{
double mt, dc;
int d;
mt = 0.06250 * PORTAMENTO_TIME_TUNING * 0.3;
dc = play_mode->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 play_event(MidiEvent *ev)
{
int32 i, j, cet;
int k, l, ch, orig_ch, port_ch, offset, layered;
if(play_mode->flag & PF_MIDI_EVENT)
return play_mode->acntl(PM_REQ_MIDI, ev);
if(!(play_mode->flag & PF_PCM_STREAM))
return RC_NONE;
current_event = ev;
cet = MIDI_EVENT_TIME(ev);
if(ctl->verbosity >= VERB_DEBUG_SILLY)
ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
"Midi Event %d: %s %d %d %d", cet,
event_name(ev->type), ev->channel, ev->a, ev->b);
if(cet > current_sample)
{
int rc;
if(midi_streaming!=0){
if ( (cet - current_sample) * 1000 / play_mode->rate > stream_max_compute ) {
kill_all_voices();
/* reset_voices(); */
/* ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY, "play_event: discard %d samples", cet - current_sample); */
current_sample = cet;
}
}
rc = compute_data(cet - current_sample);
ctl_mode_event(CTLE_REFRESH, 0, 0, 0);
if(rc == RC_JUMP)
{
ctl_timestamp();
return RC_NONE;
}
if(rc != RC_NONE)
return rc;
}
#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);
ctl_prog_event(ch);
break;
case ME_CHANNEL_PRESSURE:
adjust_channel_pressure(ev);
break;
doc/timidity/playmidi.c view on Meta::CPAN
if(ISDRUMCHANNEL(ch)) {
bank = channel[ch].bank;
if (drumset[bank] == NULL) return "";
prog = 0;
comm = drumset[bank]->tone[prog].comment;
if (comm == NULL) return "";
return comm;
}
if(channel[ch].program == SPECIAL_PROGRAM)
return "Special Program";
if(IS_CURRENT_MOD_FILE)
{
int pr;
pr = channel[ch].special_sample;
if(pr > 0 &&
special_patch[pr] != NULL &&
special_patch[pr]->name != NULL)
return special_patch[pr]->name;
return "MOD";
}
bank = channel[ch].bank;
prog = channel[ch].program;
instrument_map(channel[ch].mapID, &bank, &prog);
if (tonebank[bank] == NULL) {alloc_instrument_bank(0, bank);}
if (tonebank[bank]->tone[prog].name) {
comm = tonebank[bank]->tone[prog].comment;
if (comm == NULL) {comm = tonebank[bank]->tone[prog].name;}
} else {
comm = tonebank[0]->tone[prog].comment;
if (comm == NULL) {comm = tonebank[0]->tone[prog].name;}
}
return comm;
}
/*
* For MIDI stream player.
*/
void playmidi_stream_init(void)
{
int i;
static int first = 1;
note_key_offset = key_adjust;
midi_time_ratio = tempo_adjust;
CLEAR_CHANNELMASK(channel_mute);
if (temper_type_mute & 1)
FILL_CHANNELMASK(channel_mute);
midi_restart_time = 0;
if(first)
{
first = 0;
init_mblock(&playmidi_pool);
current_file_info = get_midi_file_info("TiMidity", 1);
midi_streaming=1;
}
else
reuse_mblock(&playmidi_pool);
/* Fill in current_file_info */
current_file_info->readflag = 1;
current_file_info->seq_name = safe_strdup("TiMidity server");
current_file_info->karaoke_title = current_file_info->first_text = NULL;
current_file_info->mid = 0x7f;
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_file_info->midi_data = NULL;
current_file_info->midi_data_size = 0;
current_file_info->file_type = IS_OTHER_FILE;
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 playmidi_tmr_reset(void)
{
int i;
aq_flush(0);
current_sample = 0;
buffered_count = 0;
buffer_pointer = common_buffer;
for(i = 0; i < MAX_CHANNELS; i++)
channel[i].lasttime = 0;
play_mode->acntl(PM_REQ_PLAY_START, NULL);
}
/*! initialize Part EQ (XG) */
void 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;
}
( run in 1.339 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )