OSDN Git Service

Support for single-note tuning change
authorShoichi Tamuki <tamuki@linet.gr.jp>
Sun, 6 Jul 2003 06:17:06 +0000 (06:17 +0000)
committerShoichi Tamuki <tamuki@linet.gr.jp>
Sun, 6 Jul 2003 06:17:06 +0000 (06:17 +0000)
ChangeLog
timidity/playmidi.c
timidity/playmidi.h
timidity/readmidi.c
timidity/tables.c
timidity/tables.h
timidity/timidity.c

index 5acb907..fcf067a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2003-07-06  TAMUKI Shoichi <tamuki@linet.gr.jp>
+
+       * timidity/playmidi.[ch], timidity/readmidi.c, timidity/tables.[ch],
+         timidity/timidity.c:
+         Support for single-note tuning change
+         Support for channel mute by user-defined temperament type
+         Fix around temperament type redrawing on ME_RESET
+         Fix around channel mute by temperament type on ME_RESET
+
 2003-07-03  TAMUKI Shoichi <tamuki@linet.gr.jp>
 
        * timidity/playmidi.c, timidity/tables.[ch], timidity/timidity.c:
index 8885e4a..b78855d 100644 (file)
@@ -254,6 +254,7 @@ 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);
 
 #define IS_SYSEX_EVENT_TYPE(type) ((type) == ME_NONE || (type) >= ME_RANDOM_PAN)
 
@@ -332,6 +333,7 @@ static char *event_name(int type)
        EVENT_NAME(ME_TIMESIG);
        EVENT_NAME(ME_KEYSIG);
        EVENT_NAME(ME_SCALE_TUNING);
+       EVENT_NAME(ME_SINGLE_NOTE_TUNING);
        EVENT_NAME(ME_TEMPER_KEYSIG);
        EVENT_NAME(ME_TEMPER_TYPE);
        EVENT_NAME(ME_MASTER_TEMPER_TYPE);
@@ -543,6 +545,9 @@ static void redraw_controllers(int c)
     ctl_mode_event(CTLE_MOD_WHEEL, 1, c, channel[c].modulation_wheel);
     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));
 }
@@ -585,6 +590,12 @@ static void reset_midi(int playing)
     }
        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) {
@@ -600,6 +611,7 @@ static void reset_midi(int playing)
 
     master_volume_ratio = 0xFFFF;
     adjust_amplification();
+    init_freq_table_tuning();
     if(current_file_info)
     {
        COPY_CHANNELMASK(drumchannels, current_file_info->drumchannels);
@@ -686,7 +698,7 @@ void recompute_freq(int v)
        if (! opt_pure_intonation && voice[v].temper_instant) {
                switch (tt) {
                case 0:
-                       f = freq_table[note];
+                       f = freq_table_tuning[0][note];
                        break;
                case 1:
                        f = freq_table_pytha[current_freq_table][note];
@@ -710,7 +722,7 @@ void recompute_freq(int v)
                                else
                                        f = freq_table_user[tt][current_freq_table + 12][note];
                        } else
-                               f = freq_table[note];
+                               f = freq_table_tuning[0][note];
                        break;
                }
                voice[v].orig_frequency = f;
@@ -1738,7 +1750,7 @@ static int select_play_sample(Sample *splist, int nsp,
        } else
                switch (tt) {
                case 0:
-                       f = freq_table[note];
+                       f = freq_table_tuning[0][note];
                        break;
                case 1:
                        f = freq_table_pytha[current_freq_table][note];
@@ -1762,7 +1774,7 @@ static int select_play_sample(Sample *splist, int nsp,
                                else
                                        f = freq_table_user[tt][current_freq_table + 12][note];
                        } else
-                               f = freq_table[note];
+                               f = freq_table_tuning[0][note];
                        break;
                }
        fs = freq_table[note];
@@ -4100,6 +4112,10 @@ static void seek_forward(int32 until_time)
                channel[ch].scale_tuning[current_event->a] = current_event->b;
                break;
 
+       case ME_SINGLE_NOTE_TUNING:
+               set_single_note_tuning(ch, current_event->a, current_event->b);
+               break;
+
        case ME_TEMPER_KEYSIG:
                current_temper_keysig = current_event->a;
                break;
@@ -5987,6 +6003,15 @@ int play_event(MidiEvent *ev)
                adjust_pitch(ch);
                break;
 
+       case ME_SINGLE_NOTE_TUNING:
+               set_single_note_tuning(ch, current_event->a, 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_KEYSIG:
                current_temper_keysig = current_event->a;
                ctl_mode_event(CTLE_TEMPER_KEYSIG, 1, current_temper_keysig, 0);
@@ -6007,6 +6032,7 @@ int play_event(MidiEvent *ev)
        case ME_TEMPER_TYPE:
                channel[ch].temper_type = current_event->a;
                ctl_mode_event(CTLE_TEMPER_TYPE, 1, ch, channel[ch].temper_type);
+               current_event->a -= (current_event->a >= 0x40) ? 0x3c : 0;
                if (temper_type_mute) {
                        if (temper_type_mute & 1 << current_event->a) {
                                SET_CHANNELMASK(channel_mute, ch);
@@ -6029,6 +6055,7 @@ int play_event(MidiEvent *ev)
                        channel[i].temper_type = current_event->a;
                        ctl_mode_event(CTLE_TEMPER_TYPE, 1, i, channel[i].temper_type);
                }
+               current_event->a -= (current_event->a >= 0x40) ? 0x3c : 0;
                if (temper_type_mute) {
                        if (temper_type_mute & 1 << current_event->a) {
                                FILL_CHANNELMASK(channel_mute);
@@ -6091,6 +6118,31 @@ int play_event(MidiEvent *ev)
     return RC_NONE;
 }
 
+static void set_single_note_tuning(int part, int a, int b)
+{
+       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 seminote */
+       
+       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 | ((a & 0x40) ? 0xc000 : 0)) / 98304.0);
+               freq_table_tuning[tp][kn] = f * fst * 1000 + 0.5;
+               break;
+       }
+}
+
 static int play_midi(MidiEvent *eventlist, int32 samples)
 {
     int rc;
index c42335b..355748e 100644 (file)
@@ -121,6 +121,7 @@ enum midi_event_t
     ME_TIMESIG,                        /* Time signature */
     ME_KEYSIG,                 /* Key signature */
     ME_SCALE_TUNING,           /* Scale tuning */
+    ME_SINGLE_NOTE_TUNING,     /* Single-note tuning */
     ME_TEMPER_KEYSIG,          /* Temperament key signature */
     ME_TEMPER_TYPE,            /* Temperament type */
     ME_MASTER_TEMPER_TYPE,     /* Master Temperament type */
index 5e021a7..5a4316a 100644 (file)
@@ -552,8 +552,8 @@ int convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret)
       case  65: type = ME_PORTAMENTO; break;
       case  66: type = ME_SOSTENUTO; break;
       case  67: type = ME_SOFT_PEDAL; break;
-         case  68: type = ME_LEGATO_FOOTSWITCH; break;
-         case  69: type = ME_HOLD2; break;
+      case  68: type = ME_LEGATO_FOOTSWITCH; break;
+      case  69: type = ME_HOLD2; break;
       case  71: type = ME_HARMONIC_CONTENT; break;
       case  72: type = ME_RELEASE_TIME; break;
       case  73: type = ME_ATTACK_TIME; break;
@@ -613,7 +613,7 @@ static int block_to_part(int block, int port)
 int parse_sysex_event_multi(uint8 *val, int32 len, MidiEvent *evm)
 {
     int num_events = 0;                                /* Number of events added */
-       uint16 channel_st;
+       uint16 channel_tt;
        int i, j;
 
     if(current_file_info->mid == 0 || current_file_info->mid >= 0x7e)
@@ -1593,15 +1593,26 @@ int parse_sysex_event_multi(uint8 *val, int32 len, MidiEvent *evm)
                        break;
                case 0x08:      /* MIDI Tuning Standard */
                        switch (val[3]) {
+                       case 0x02:
+                               SETMIDIEVENT(evm[0], 0, ME_SINGLE_NOTE_TUNING,
+                                               0, val[4], 0);
+                               for (i = 0; i < val[5]; i++) {
+                                       SETMIDIEVENT(evm[i * 2 + 1], 0, ME_SINGLE_NOTE_TUNING,
+                                                       1, val[6], val[7]);
+                                       SETMIDIEVENT(evm[i * 2 + 2], 0, ME_SINGLE_NOTE_TUNING,
+                                                       2, val[8], val[9]);
+                               }
+                               num_events = val[5] * 2 + 1;
+                               break;
                        case 0x0b:
-                               channel_st = val[4] << 14 | val[5] << 7 | val[6];
+                               channel_tt = val[4] << 14 | val[5] << 7 | val[6];
                                if (val[1] == 0x7f) {
                                        SETMIDIEVENT(evm[0], 0, ME_MASTER_TEMPER_TYPE,
                                                        0, val[7], (val[0] == 0x7f) ? 1 : 0);
                                        num_events++;
                                } else {
                                        for (i = 0, j = 0; i < 16; i++)
-                                               if (channel_st & 1 << i) {
+                                               if (channel_tt & 1 << i) {
                                                        SETMIDIEVENT(evm[j], 0, ME_TEMPER_TYPE,
                                                                        MERGE_CHANNEL_PORT(i),
                                                                        val[7], (val[0] == 0x7f) ? 1 : 0);
@@ -2927,7 +2938,7 @@ static MidiEvent *groom_list(int32 divisions, int32 *eventsp, int32 *samplesp)
            bank_lsb[ch] = meep->event.a;
            break;
 
-         case ME_CHORUS_TEXT:                            
+         case ME_CHORUS_TEXT:
          case ME_LYRIC:
          case ME_MARKER:
          case ME_INSERT_TEXT:
index ec21638..c14aa11 100644 (file)
@@ -41,6 +41,7 @@
 #include "tables.h"
 
 int32 freq_table[128];
+int32 freq_table_tuning[128][128];
 int32 freq_table_pytha[12][128];
 int32 freq_table_meantone[24][128];
 int32 freq_table_pureint[24][128];
@@ -54,6 +55,18 @@ void init_freq_table(void)
                freq_table[i] = 440 * pow(2.0, (i - 69) / 12.0) * 1000 + 0.5;
 }
 
+void init_freq_table_tuning(void)
+{
+       int p, i;
+       double f;
+       
+       for (i = 0; i < 128; i++) {
+               f = 440 * pow(2.0, (i - 69) / 12.0);
+               for (p = 0; p < 128; p++)
+                       freq_table_tuning[p][i] = f * 1000 + 0.5;
+       }
+}
+
 void init_freq_table_pytha(void)
 {
        int i, j, k, l;
index c492797..a655ebd 100644 (file)
@@ -34,6 +34,7 @@ extern FLOAT_T lookup_log(int x);
 
 #define SINE_CYCLE_LENGTH 1024
 extern int32 freq_table[];
+extern int32 freq_table_tuning[][128];
 extern int32 freq_table_pytha[][128];
 extern int32 freq_table_meantone[][128];
 extern int32 freq_table_pureint[][128];
@@ -75,6 +76,7 @@ extern FLOAT_T cb_to_amp_table[];
 extern FLOAT_T reverb_time_table[];
 
 extern void init_freq_table(void);
+extern void init_freq_table_tuning(void);
 extern void init_freq_table_pytha(void);
 extern void init_freq_table_meantone(void);
 extern void init_freq_table_pureint(void);
index 770e10b..f480264 100644 (file)
@@ -3148,7 +3148,7 @@ MAIN_INTERFACE int set_tim_opt(int c, char *optarg)
 
        case 'Q':
                if (strchr(optarg, 't')) {
-                       if (set_value(&tmpi32, atoi(optarg), 0, 3, "Quiet temperament"))
+                       if (set_value(&tmpi32, atoi(optarg), 0, 7, "Quiet temperament"))
                                return 1;
                        temper_type_mute |= 1 << tmpi32;
                } else
@@ -3411,6 +3411,7 @@ MAIN_INTERFACE void timidity_start_initialize(void)
            url_add_module(url_module_list[i]);
        init_string_table(&opt_config_string);
        init_freq_table();
+       init_freq_table_tuning();
        init_freq_table_pytha();
        init_freq_table_meantone();
        init_freq_table_pureint();