📄 m2m.c
字号:
event[0] = 0x80 | (ch & 0x0F); event[1] = newnote; event[2] = ev->b; /* only issue a NOTEOFF is there is a note playing on the ch */ if (ch != 9 && current_channel_note[ch] == -1) n = 0; current_channel_note[ch] = -1; current_track_note[old_ch] = -1; break; case ME_NOTEON: n = 3; if (is_drum_sample[mod_sample]) newnote = sample_to_program[mod_sample]; else { newnote = ev->a + transpose[mod_sample]; scan_ahead_for_m2m_tweaks(ev, ch, newnote, mod_sample); newnote += tweak_note_offset[ch]; } while (newnote > 127) newnote -= 12; while (newnote < 0) newnote += 12; event[0] = 0x90 | (ch & 0x0F); event[1] = newnote; event[2] = ev->b; expression = ROUND(orig_track_expr[old_ch] * vol_amp[mod_sample] / 100.0); /* max expression at 127 */ if (expression > 127) expression = 127; if (is_drum_sample[mod_sample]) { event[2] = vol_nonlin_to_lin[expression][0]; } /* current expression may not be what's wanted for the sample */ /* HACK -- insert a prior expression event */ else if (expression != current_channel_expr[ch]) { /* NOTEON event */ n = 11; event[7] = 0x00; event[8] = event[0]; event[9] = event[1]; event[10] = event[2]; /* non-linear expression event */ event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x0B; event[2] = vol_nonlin_to_lin[expression][0]; /* non-linear volume event */ event[3] = 0x00; event[4] = 0xB0 | (ch & 0x0F); event[5] = 0x07; event[6] = vol_nonlin_to_lin[expression][1]; current_channel_expr[ch] = expression; } current_channel_note[ch] = newnote; current_track_note[old_ch] = newnote; break; case ME_KEYPRESSURE: n = 3; if (is_drum_sample[mod_sample]) newnote = sample_to_program[mod_sample]; else { newnote = ev->a + transpose[mod_sample]; newnote += tweak_note_offset[ch]; } while (newnote > 127) newnote -= 12; while (newnote < 0) newnote += 12; event[0] = 0xA0 | (ch & 0x0F); event[1] = newnote; event[2] = ev->b; break; case ME_SET_PATCH: n = 2; current_track_sample[old_ch] = ev->a; if (is_drum_sample[ev->a]) { ch = 9; current_channel_program[ch] = sample_to_program[ev->a]; /* don't emit any event at all */ n = 0; /* change drum banks if necessary */ if (banks[ev->a] != current_channel_bank[ch]) { if (n) event[n++] = 0x00; event[n++] = 0xC0 | (ch & 0x0F); event[n++] = current_channel_bank[ch] = banks[ev->a]; } } else { if (ch == 9) ch = first_free_track; /* program already set, no need to change it */ if (sample_to_program[ev->a] == current_channel_program[ch] && banks[ev->a] == current_channel_bank[ch]) { n = 0; } /* no need to change bank, it's already set correctly */ else if (banks[ev->a] == current_channel_bank[ch]) { event[0] = 0xC0 | (ch & 0x0F); event[1] = sample_to_program[ev->a]; } /* need to change bank to that of the new instrument */ else { n = 10; /* Bank Select MSB */ event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x00; event[2] = banks[ev->a]; current_channel_bank[ch] = banks[ev->a]; /* Bank Select LSB */ event[3] = 0x00; event[4] = 0xB0 | (ch & 0x0F); event[5] = 0x20; event[6] = 0; /* Program Change */ event[7] = 0x00; event[8] = 0xC0 | (ch & 0x0F); event[9] = sample_to_program[ev->a]; } current_channel_program[ch] = sample_to_program[ev->a]; } break; case ME_PITCHWHEEL: n = 3; event[0] = 0xE0 | (ch & 0x0F); /* max pitch bend sensitivity is 24, scale stuff */ value = ev->b * 128 + ev->a; value = ROUND((value - 0x2000) * old_pb_sensitivity / (float) pb_sensitivity); value += fine_tune[mod_sample]; value += tweak_pb_offset[ch]; /* fudge stuff by an octave multiple if it's out of bounds */ /* this hasn't been tested much, but it seems to sound OK */ if (value > 8191) { value = (value % 8191) % 4095 + 4096; } else if (value < -8191) { value = -value; value = (value % 8191) % 4095 + 4096; value = -value; } /* add the offset back in, save it */ value += 0x2000; event[1] = value & 0x7F; event[2] = value >> 7; break; case ME_DATA_ENTRY_MSB: n = 3; event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x06; event[2] = ev->a; /* pitch sensitivity maxes out at 24, not 128 */ if (rpn_msb == 0 && rpn_lsb == 0) { old_pb_sensitivity = pb_sensitivity = ev->a; if (pb_sensitivity > MAX_PB_SENSITIVITY) pb_sensitivity = MAX_PB_SENSITIVITY; event[2] = pb_sensitivity; notes_per_pb = pb_sensitivity / 8191.0; pb_per_note = 8191.0 / pb_sensitivity; } break; case ME_MAINVOLUME: n = 3; event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x07; event[2] = ev->a; break; case ME_PAN: n = 3; track_pans[ch] = ev->a; event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x0A; event[2] = ev->a; break; case ME_EXPRESSION: n = 7; orig_track_expr[old_ch] = ev->a; expression = ROUND(ev->a * vol_amp[mod_sample] / 100.0); /* max expression at 127 */ if (expression > 127) expression = 127; if (current_channel_expr[ch] == expression) skip_ch_expr_flag = 1; else current_channel_expr[ch] = expression;#ifdef MUTATE_EXPRESSION_TO_KEYPRESSURE /* HACK - mutate it into a KEYPRESSUE event */ /* but only if there's a note playing */ if (current_track_note[old_ch] >= 0) { event_type = ME_KEYPRESSURE; event[0] = 0xA0 | (ch & 0x0F); event[1] = current_track_note[old_ch]; event[2] = expression; } else n = 0;#endif /* non-linear expression event */ event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x0B; event[2] = vol_nonlin_to_lin[expression][0]; /* non-linear volume event */ event[3] = 0x00; event[4] = 0xB0 | (ch & 0x0F); event[5] = 0x07; event[6] = vol_nonlin_to_lin[expression][1]; break; case ME_RPN_LSB: n = 3; event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x64; event[2] = ev->a; rpn_lsb = ev->a; break; case ME_RPN_MSB: n = 3; event[0] = 0xB0 | (ch & 0x0F); event[1] = 0x65; event[2] = ev->a; rpn_msb = ev->a; break; case ME_TEMPO: n = 6; event[0] = 0xFF; event[1] = 0x51; event[2] = 3; event[3] = ev->a; event[4] = ev->b; event[5] = ch; tempo = ch + ev->b * 256 + ev->a * 65536; break; case ME_ALL_NOTES_OFF: n = 3; event[0] = 0xB0 | (ch & 0x0F); event[1] = 123; event[2] = 0; break;/* case ME_DRUMPART: break;*/ } /* I here by decree that all tempo events shall go on the first ch */ if (event_type == ME_TEMPO) ch = min_enabled_track; /* ah ha, we shall keep this event */ if (n) { if (!(ch == 9 && (event_type == ME_EXPRESSION || event_type == ME_PITCHWHEEL || event_type == ME_PAN)) && !skip_ch_expr_flag) { /* resize the track event array */ length = track_size[ch]; num_dt_bytes = set_dt_array(dt_array, time - last_track_event_time[ch]); track_size[ch] += n + num_dt_bytes; track_events[ch] = safe_realloc(track_events[ch], track_size[ch] * sizeof(unsigned char)); /* save the delta_time */ p_track_event = track_events[ch] + length; for (i = 0; i < num_dt_bytes; i++) { p_track_event[i] = dt_array[i]; } /* save the events */ p_track_event += num_dt_bytes; for (i = 0; i < n; i++) { p_track_event[i] = event[i]; } /* spawn extra events for chords */ /* don't forget that there could be a preceeding expr event */ chord = sample_chords[mod_sample]; if (chord >= 0 && (event_type == ME_NOTEON || event_type == ME_NOTEOFF || event_type == ME_KEYPRESSURE)) { extra = 2; length = track_size[ch]; track_size[ch] += 4 * extra; track_events[ch] = safe_realloc(track_events[ch], track_size[ch] * sizeof(unsigned char)); p_track_event = track_events[ch] + length; for (i = 0; i < 3; i++) { chord_type = chord / 3; chord_subtype = chord % 3; newnote = event[n - 2] + chord_table[chord_type][chord_subtype][i]; if (newnote == event[n - 2]) continue; while (newnote > 127) newnote -= 12; while (newnote < 0) newnote += 12; p_track_event[0] = 0x00; p_track_event[1] = event[n - 3]; p_track_event[2] = newnote; p_track_event[3] = event[n - 1]; p_track_event += 4; } } last_track_event_time[ch] = time; } /* moved it for drums, issue control events to old channel too */ if (moved_to_drums && old_ch != first_free_track && event_type != ME_NOTEON && event_type != ME_NOTEOFF && event_type != ME_KEYPRESSURE && !(event_type == ME_EXPRESSION && (current_channel_note[old_ch] < 0 || current_channel_expr[old_ch] == expression)) && event_type != ME_TEMPO) { /* resize the track event array */ length = track_size[old_ch]; num_dt_bytes = set_dt_array(dt_array, time - last_track_event_time[old_ch]); track_size[old_ch] += n + num_dt_bytes; track_events[old_ch] = safe_realloc(track_events[old_ch], track_size[old_ch] * sizeof(unsigned char)); /* save the delta_time */ p_track_event = track_events[old_ch] + length; for (i = 0; i < num_dt_bytes; i++) { p_track_event[i] = dt_array[i]; } /* replace channel nibble with old channel */ event[0] = (event[0] & 0xF0) | (old_ch & 0x0F); /* save the events */ p_track_event += num_dt_bytes; for (i = 0; i < n; i++) { p_track_event[i] = event[i]; } last_track_event_time[old_ch] = time; } } }}void m2m_output_midi_file(void){ FILE *outfile; int extra; int i, j; outfile = fopen(actual_outname, "wb"); if (!outfile) { ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Uh oh, can't open '%s' output file. Bombing out...", actual_outname); return; } /* finish up the file header */ header[10] = (num_tracks & 0xFF00) >> 8; header[11] = num_tracks & 0x00FF; header[12] = (divisions & 0xFF00) >> 8; header[13] = divisions & 0x00FF; /* output the file header */ for (i = 0; i < 14; i++) { fprintf(outfile, "%c", header[i]); } /* output each track */ for (i = 0; i < 34; i++) { if (!tracks_enabled[i]) continue; /* do the track header */ for (j = 0; j < 4; j++) { fprintf(outfile, "%c", mtrk[j]); } length = track_size[i] + 4; extra = 4; ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Track %d Size %d", i, length); fprintf(outfile, "%c", (length & 0xFF000000) >> 24); fprintf(outfile, "%c", (length & 0x00FF0000) >> 16); fprintf(outfile, "%c", (length & 0x0000FF00) >> 8); fprintf(outfile, "%c", length & 0x000000FF); /* write the events */ p_track_event = track_events[i]; for (j = 0; j < length - extra; j++, p_track_event++) { fprintf(outfile, "%c", *p_track_event); } /* write the terminal event */ fprintf(outfile, "%c", 0x00); fprintf(outfile, "%c", 0xFF); fprintf(outfile, "%c", 0x2F); fprintf(outfile, "%c", 0x00); } ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Number of tracks actually used: %d", num_tracks); ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Track accepting drum refugees: %d", first_free_track); ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Number of unlooped notes killed early: %ld", num_killed_early); ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Number of pitch slides > 2 octaves: %ld", num_big_pitch_slides); ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Number of pitch slides > 4 octaves: %ld", num_huge_pitch_slides); fclose(outfile);}void convert_mod_to_midi_file(MidiEvent * ev){ int i; change_system_mode(DEFAULT_SYSTEM_MODE); /* use user volume curve if specified, rather than the default */ if (opt_user_volume_curve) fill_vol_nonlin_to_lin_table(); initialize_m2m_stuff(); /* this either isn't a MOD, or it doesn't have any samples... */ if (!maxsample) { ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Aborting! This doesn't look like a MOD file!"); return; } read_m2m_cfg_file(); m2m_prescan(ev); m2m_process_events(ev); m2m_output_midi_file(); /* free track event arrays */ for (i = 0; i < 34; i++) { if (track_events[i]) free(track_events[i]); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -