aboutsummaryrefslogtreecommitdiff
path: root/sound/mididrv.cpp
diff options
context:
space:
mode:
authorLionel Ulmer2002-05-08 10:41:30 +0000
committerLionel Ulmer2002-05-08 10:41:30 +0000
commitca382bbc1d8150c10d29537ad9398dc4fedccab0 (patch)
tree283bb6c2fafa6d9825fac622e5a73841a7503884 /sound/mididrv.cpp
parent284a1c887959ba17a14af625da6cced5c1c45330 (diff)
downloadscummvm-rg350-ca382bbc1d8150c10d29537ad9398dc4fedccab0.tar.gz
scummvm-rg350-ca382bbc1d8150c10d29537ad9398dc4fedccab0.tar.bz2
scummvm-rg350-ca382bbc1d8150c10d29537ad9398dc4fedccab0.zip
Hacked away some code from Timidity to support 'Pitch wheel'. The DOTT
intro now sounds a bit better than before using the 'midiemu' driver. svn-id: r4246
Diffstat (limited to 'sound/mididrv.cpp')
-rw-r--r--sound/mididrv.cpp182
1 files changed, 165 insertions, 17 deletions
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index 6c3899ad9e..a6be2ba6aa 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -972,6 +972,7 @@ private:
int vol;
int nshift;
int on;
+ int pitchbend;
};
enum {
@@ -985,7 +986,7 @@ private:
void midi_write_adlib(unsigned int reg, unsigned char val);
void midi_fm_instrument(int voice, unsigned char *inst);
void midi_fm_volume(int voice, int volume);
- void midi_fm_playnote(int voice, int note, int volume);
+ void midi_fm_playnote(int voice, int note, int volume, int pitchbend);
void midi_fm_endnote(int voice);
unsigned char adlib_data[256];
int adlib_style;
@@ -1015,6 +1016,7 @@ MidiDriver_MIDIEMU::MidiDriver_MIDIEMU(){
ch[i].vol = 127;
ch[i].nshift = -25;
ch[i].on = 1;
+ ch[i].pitchbend = 0x2000;
}
/* General init */
@@ -1120,7 +1122,7 @@ void MidiDriver_MIDIEMU::send(uint32 b)
#endif
}
- midi_fm_playnote(on, note + ch[channel].nshift, nv * 2);
+ midi_fm_playnote(on, note + ch[channel].nshift, nv * 2, ch[channel].pitchbend);
chp[on][0] = channel;
chp[on][1] = note;
chp[on][2] = 0;
@@ -1140,17 +1142,21 @@ void MidiDriver_MIDIEMU::send(uint32 b)
}
break;
- case 0xa0: /*key after touch */
- /* this might all be good
- note=getnext(1); vel=getnext(1);
- for (i=0; i<9; i++)
- if (chp[i][0]==c & chp[i][1]==note)
- midi_fm_playnote(i,note+cnote[c],my_midi_fm_vol_table[(cvols[c]*vel)/128]*2);
- */
- debug(1, "MIDI command 0xA0 (Key After Touch) not handled in MIDIEMU driver.");
+ case 0xa0: { /*key after touch */
+ unsigned char note = (unsigned char)((b >> 8) & 0x7F);
+ unsigned char vel = (unsigned char)((b >> 16) & 0x7F);
+
+ for (int i = 0; i < 9; i++)
+ if ((chp[i][0] == channel) & (chp[i][1] == note)) {
+ int nv = (ch[channel].vol * vel) / 128;
+ if (nv > 127) nv = 127;
+ nv = my_midi_fm_vol_table[nv];
+ midi_fm_volume(i, nv * 2);
+ }
+ }
break;
- case 0xb0: { /* control change .. pitch bend? */
+ case 0xb0: { /* control change */
int i;
unsigned char ctrl = (unsigned char)((b >> 8) & 0x7F);
unsigned char vel = (unsigned char)((b >> 16) & 0x7F);
@@ -1167,7 +1173,8 @@ void MidiDriver_MIDIEMU::send(uint32 b)
ch[channel].vol = vel;
break;
case 0x0A: /* Pan */
- debug(1, "MIDI sub-command 0xB0 (Control Change) case %02X (Pan) not handled in MIDIEMU driver.", ctrl);
+ /* This is not a warning as we do not support OPL3 => no stereo anyway
+ debug(1, "MIDI sub-command 0xB0 (Control Change) case %02X (Pan) not handled in MIDIEMU driver.", ctrl); */
break;
case 0x40: /* Sustain on/off */
for (i = 0; i < 9; i++)
@@ -1204,9 +1211,19 @@ void MidiDriver_MIDIEMU::send(uint32 b)
case 0xd0: /* channel touch */
debug(1, "MIDI command 0xD0 (Channel Touch) not handled in MIDIEMU driver.");
break;
- case 0xe0: /* pitch wheel */
- debug(1, "MIDI command 0xE0 (Pitch Wheel) not handled in MIDIEMU driver.");
- break;
+
+ case 0xe0: { /* pitch wheel */
+ int pitchbend = ((b >> 8) & 0x7F) | (((b >> 16) & 0x7F) << 7);
+ ch[channel].pitchbend = pitchbend;
+ for (int i = 0; i < 9; i++) {
+ if (chp[i][0] == channel) {
+ int nv = ch[channel].vol;
+ if (nv > 127) nv = 127;
+ nv = my_midi_fm_vol_table[nv];
+ midi_fm_playnote(i, chp[i][1] + ch[channel].nshift, nv * 2, pitchbend);
+ }
+ }
+ } break;
default:
fprintf(stderr, "Unknown : %08x\n", (int) b);
@@ -1235,8 +1252,10 @@ void MidiDriver_MIDIEMU::midi_write_adlib(unsigned int reg, unsigned char val) {
}
void MidiDriver_MIDIEMU::midi_fm_instrument(int voice, unsigned char *inst) {
+#if 0
/* Just gotta make sure this happens because who knows when it'll be reset otherwise.... */
midi_write_adlib(0xbd, 0);
+#endif
midi_write_adlib(0x20 + adlib_opadd[voice], inst[0]);
midi_write_adlib(0x23 + adlib_opadd[voice], inst[1]);
@@ -1275,12 +1294,141 @@ void MidiDriver_MIDIEMU::midi_fm_volume(int voice, int volume) {
(unsigned char)((63 - volume) | (adlib_data[0x43 + adlib_opadd[voice]] & 0xc0)));
}
-static int fnums[] = { 0x16b,0x181,0x198,0x1b0,0x1ca,0x1e5,0x202,0x220,0x241,0x263,0x287,0x2ae };
+static int fnums[] = { 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2ae };
+
+/* These tables 'borrowed' from Timidity tables.c
+
+ Copyright (C) 1999-2001 Masanao Izumo <mo@goice.co.jp>
+ Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
+*/
+float bend_fine[256] = {
+ 1.0, 1.0002256593050698, 1.0004513695322617, 1.0006771306930664,
+ 1.0009029427989777, 1.0011288058614922, 1.0013547198921082, 1.0015806849023274,
+ 1.0018067009036538, 1.002032767907594, 1.0022588859256572, 1.0024850549693551,
+ 1.0027112750502025, 1.0029375461797159, 1.0031638683694153, 1.0033902416308227,
+ 1.0036166659754628, 1.0038431414148634, 1.0040696679605541, 1.0042962456240678,
+ 1.0045228744169397, 1.0047495543507072, 1.0049762854369111, 1.0052030676870944,
+ 1.0054299011128027, 1.0056567857255843, 1.00588372153699, 1.006110708558573,
+ 1.0063377468018897, 1.0065648362784985, 1.0067919769999607, 1.0070191689778405,
+ 1.0072464122237039, 1.0074737067491204, 1.0077010525656616, 1.0079284496849015,
+ 1.0081558981184175, 1.008383397877789, 1.008610948974598, 1.0088385514204294,
+ 1.0090662052268706, 1.0092939104055114, 1.0095216669679448, 1.0097494749257656,
+ 1.009977334290572, 1.0102052450739643, 1.0104332072875455, 1.0106612209429215,
+ 1.0108892860517005, 1.0111174026254934, 1.0113455706759138, 1.0115737902145781,
+ 1.0118020612531047, 1.0120303838031153, 1.0122587578762337, 1.012487183484087,
+ 1.0127156606383041, 1.0129441893505169, 1.0131727696323602, 1.0134014014954713,
+ 1.0136300849514894, 1.0138588200120575, 1.0140876066888203, 1.0143164449934257,
+ 1.0145453349375237, 1.0147742765327674, 1.0150032697908125, 1.0152323147233171,
+ 1.015461411341942, 1.0156905596583505, 1.0159197596842091, 1.0161490114311862,
+ 1.0163783149109531, 1.0166076701351838, 1.0168370771155553, 1.0170665358637463,
+ 1.0172960463914391, 1.0175256087103179, 1.0177552228320703, 1.0179848887683858,
+ 1.0182146065309567, 1.0184443761314785, 1.0186741975816487, 1.0189040708931674,
+ 1.0191339960777379, 1.0193639731470658, 1.0195940021128593, 1.0198240829868295,
+ 1.0200542157806898, 1.0202844005061564, 1.0205146371749483, 1.0207449257987866,
+ 1.0209752663893958, 1.0212056589585028, 1.0214361035178368, 1.0216666000791297,
+ 1.0218971486541166, 1.0221277492545349, 1.0223584018921241, 1.0225891065786274,
+ 1.0228198633257899, 1.0230506721453596, 1.023281533049087, 1.0235124460487257,
+ 1.0237434111560313, 1.0239744283827625, 1.0242054977406807, 1.0244366192415495,
+ 1.0246677928971357, 1.0248990187192082, 1.025130296719539, 1.0253616269099028,
+ 1.0255930093020766, 1.0258244439078401, 1.0260559307389761, 1.0262874698072693,
+ 1.0265190611245079, 1.0267507047024822, 1.0269824005529853, 1.027214148687813,
+ 1.0274459491187637, 1.0276778018576387, 1.0279097069162415, 1.0281416643063788,
+ 1.0283736740398595, 1.0286057361284953, 1.0288378505841009, 1.0290700174184932,
+ 1.0293022366434921, 1.0295345082709197, 1.0297668323126017, 1.0299992087803651,
+ 1.030231637686041, 1.0304641190414621, 1.0306966528584645, 1.0309292391488862,
+ 1.0311618779245688, 1.0313945691973556, 1.0316273129790936, 1.0318601092816313,
+ 1.0320929581168212, 1.0323258594965172, 1.0325588134325767, 1.0327918199368598,
+ 1.0330248790212284, 1.0332579906975481, 1.0334911549776868, 1.033724371873515,
+ 1.0339576413969056, 1.0341909635597348, 1.0344243383738811, 1.0346577658512259,
+ 1.034891246003653, 1.0351247788430489, 1.0353583643813031, 1.0355920026303078,
+ 1.0358256936019572, 1.0360594373081489, 1.0362932337607829, 1.0365270829717617,
+ 1.0367609849529913, 1.0369949397163791, 1.0372289472738365, 1.0374630076372766,
+ 1.0376971208186156, 1.0379312868297725, 1.0381655056826686, 1.0383997773892284,
+ 1.0386341019613787, 1.0388684794110492, 1.0391029097501721, 1.0393373929906822,
+ 1.0395719291445176, 1.0398065182236185, 1.0400411602399278, 1.0402758552053915,
+ 1.0405106031319582, 1.0407454040315787, 1.0409802579162071, 1.0412151647977996,
+ 1.0414501246883161, 1.0416851375997183, 1.0419202035439705, 1.0421553225330404,
+ 1.042390494578898, 1.042625719693516, 1.0428609978888699, 1.043096329176938,
+ 1.0433317135697009, 1.0435671510791424, 1.0438026417172486, 1.0440381854960086,
+ 1.0442737824274138, 1.044509432523459, 1.044745135796141, 1.0449808922574599,
+ 1.0452167019194181, 1.0454525647940205, 1.0456884808932754, 1.0459244502291931,
+ 1.0461604728137874, 1.0463965486590741, 1.046632677777072, 1.0468688601798024,
+ 1.0471050958792898, 1.047341384887561, 1.0475777272166455, 1.047814122878576,
+ 1.048050571885387, 1.0482870742491166, 1.0485236299818055, 1.0487602390954964,
+ 1.0489969016022356, 1.0492336175140715, 1.0494703868430555, 1.0497072096012419,
+ 1.0499440858006872, 1.0501810154534512, 1.050417998571596, 1.0506550351671864,
+ 1.0508921252522903, 1.0511292688389782, 1.0513664659393229, 1.0516037165654004,
+ 1.0518410207292894, 1.0520783784430709, 1.0523157897188296, 1.0525532545686513,
+ 1.0527907730046264, 1.0530283450388465, 1.0532659706834067, 1.0535036499504049,
+ 1.0537413828519411, 1.0539791694001188, 1.0542170096070436, 1.0544549034848243,
+ 1.0546928510455722, 1.0549308523014012, 1.0551689072644284, 1.0554070159467728,
+ 1.0556451783605572, 1.0558833945179062, 1.0561216644309479, 1.0563599881118126,
+ 1.0565983655726334, 1.0568367968255465, 1.0570752818826903, 1.0573138207562065,
+ 1.057552413458239, 1.0577910600009348, 1.0580297603964437, 1.058268514656918,
+ 1.0585073227945128, 1.0587461848213857, 1.058985100749698, 1.0592240705916123
+};
-void MidiDriver_MIDIEMU::midi_fm_playnote(int voice, int note, int volume) {
+float bend_coarse[128] = {
+ 1.0, 1.0594630943592953, 1.122462048309373, 1.189207115002721,
+ 1.2599210498948732, 1.3348398541700344, 1.4142135623730951, 1.4983070768766815,
+ 1.5874010519681994, 1.681792830507429, 1.7817974362806785, 1.8877486253633868,
+ 2.0, 2.1189261887185906, 2.244924096618746, 2.3784142300054421,
+ 2.5198420997897464, 2.6696797083400687, 2.8284271247461903, 2.996614153753363,
+ 3.1748021039363992, 3.363585661014858, 3.5635948725613571, 3.7754972507267741,
+ 4.0, 4.2378523774371812, 4.4898481932374912, 4.7568284600108841,
+ 5.0396841995794928, 5.3393594166801366, 5.6568542494923806, 5.993228307506727,
+ 6.3496042078727974, 6.727171322029716, 7.1271897451227151, 7.5509945014535473,
+ 8.0, 8.4757047548743625, 8.9796963864749824, 9.5136569200217682,
+ 10.079368399158986, 10.678718833360273, 11.313708498984761, 11.986456615013454,
+ 12.699208415745595, 13.454342644059432, 14.25437949024543, 15.101989002907095,
+ 16.0, 16.951409509748721, 17.959392772949972, 19.027313840043536,
+ 20.158736798317967, 21.357437666720553, 22.627416997969522, 23.972913230026901,
+ 25.398416831491197, 26.908685288118864, 28.508758980490853, 30.203978005814196,
+ 32.0, 33.902819019497443, 35.918785545899944, 38.054627680087073,
+ 40.317473596635935, 42.714875333441107, 45.254833995939045, 47.945826460053802,
+ 50.796833662982394, 53.817370576237728, 57.017517960981706, 60.407956011628393,
+ 64.0, 67.805638038994886, 71.837571091799887, 76.109255360174146,
+ 80.63494719327187, 85.429750666882214, 90.509667991878089, 95.891652920107603,
+ 101.59366732596479, 107.63474115247546, 114.03503592196341, 120.81591202325679,
+ 128.0, 135.61127607798977, 143.67514218359977, 152.21851072034829,
+ 161.26989438654374, 170.85950133376443, 181.01933598375618, 191.78330584021521,
+ 203.18733465192958, 215.26948230495091, 228.07007184392683, 241.63182404651357,
+ 256.0, 271.22255215597971, 287.35028436719938, 304.43702144069658,
+ 322.53978877308765, 341.71900266752868, 362.03867196751236, 383.56661168043064,
+ 406.37466930385892, 430.53896460990183, 456.14014368785394, 483.26364809302686,
+ 512.0, 542.44510431195943, 574.70056873439876, 608.87404288139317,
+ 645.0795775461753, 683.43800533505737, 724.07734393502471, 767.13322336086128,
+ 812.74933860771785, 861.07792921980365, 912.28028737570787, 966.52729618605372,
+ 1024.0, 1084.8902086239189, 1149.4011374687975, 1217.7480857627863,
+ 1290.1591550923506, 1366.8760106701147, 1448.1546878700494, 1534.2664467217226
+};
+
+void MidiDriver_MIDIEMU::midi_fm_playnote(int voice, int note, int volume, int pitchbend) {
int freq = fnums[note % 12];
int oct = note / 12;
int c;
+ float pf;
+
+ pitchbend -= 0x2000;
+ if (pitchbend != 0) {
+ pitchbend *= 2;
+ if(pitchbend >= 0)
+ pf = bend_fine[(pitchbend>>5) & 0xFF] * bend_coarse[(pitchbend>>13) & 0x7F];
+ else {
+ pitchbend = -pitchbend;
+ pf = 1.0 / (bend_fine[(pitchbend>>5) & 0xFF] * bend_coarse[(pitchbend>>13) & 0x7F]);
+ }
+ freq = (int) ((float) freq * pf);
+
+ while (freq >= (fnums[0] * 2)) {
+ freq /= 2;
+ oct += 1;
+ }
+ while (freq < fnums[0]) {
+ freq *= 2;
+ oct -= 1;
+ }
+ }
midi_fm_volume(voice, volume);
midi_write_adlib(0xa0 + voice, (unsigned char) (freq & 0xff));