ALL: synced with ScummVM

This commit is contained in:
Pawel Kolodziejski 2014-07-17 14:44:26 +02:00
parent 9bf27c050d
commit 022c027ab4
40 changed files with 532 additions and 322 deletions

View File

@ -112,9 +112,10 @@ Tim Phillips
Edward Rudd Edward Rudd
Eugene Sandulenko Eugene Sandulenko
Johannes Schickel Johannes Schickel
Keith Scroggins
Won Star Won Star
Ludvig Strigeus Ludvig Strigeus
Keith Scroggins Fedor Strizhniou
David Symonds David Symonds
Jordi Vilalta Jordi Vilalta
Robin Watts Robin Watts

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -34,70 +34,143 @@ static const Bit32u PROCESS_DELAY = 1;
static const Bit32u MODE_3_ADDITIONAL_DELAY = 1; static const Bit32u MODE_3_ADDITIONAL_DELAY = 1;
static const Bit32u MODE_3_FEEDBACK_DELAY = 1; static const Bit32u MODE_3_FEEDBACK_DELAY = 1;
// Default reverb settings for modes 0-2. These correspond to CM-32L / LAPC-I "new" reverb settings. MT-32 reverb is a bit different. // Default reverb settings for "new" reverb model implemented in CM-32L / LAPC-I.
// Found by tracing reverb RAM data lines (thanks go to Lord_Nightmare & balrog). // Found by tracing reverb RAM data lines (thanks go to Lord_Nightmare & balrog).
const BReverbSettings &BReverbModel::getCM32L_LAPCSettings(const ReverbMode mode) {
static const Bit32u MODE_0_NUMBER_OF_ALLPASSES = 3;
static const Bit32u MODE_0_ALLPASSES[] = {994, 729, 78};
static const Bit32u MODE_0_NUMBER_OF_COMBS = 4; // Well, actually there are 3 comb filters, but the entrance LPF + delay can be processed via a hacked comb.
static const Bit32u MODE_0_COMBS[] = {705 + PROCESS_DELAY, 2349, 2839, 3632};
static const Bit32u MODE_0_OUTL[] = {2349, 141, 1960};
static const Bit32u MODE_0_OUTR[] = {1174, 1570, 145};
static const Bit32u MODE_0_COMB_FACTOR[] = {0xA0, 0x60, 0x60, 0x60};
static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
static const Bit32u MODE_0_DRY_AMP[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xD0};
static const Bit32u MODE_0_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0};
static const Bit32u MODE_0_LPF_AMP = 0x60;
static const Bit32u MODE_0_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_1_NUMBER_OF_ALLPASSES = 3;
static const Bit32u MODE_0_ALLPASSES[] = {994, 729, 78}; static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176};
static const Bit32u MODE_0_NUMBER_OF_COMBS = 4; // Well, actually there are 3 comb filters, but the entrance LPF + delay can be processed via a hacked comb. static const Bit32u MODE_1_NUMBER_OF_COMBS = 4; // Same as for mode 0 above
static const Bit32u MODE_0_COMBS[] = {705 + PROCESS_DELAY, 2349, 2839, 3632}; static const Bit32u MODE_1_COMBS[] = {961 + PROCESS_DELAY, 2619, 3545, 4519};
static const Bit32u MODE_0_OUTL[] = {2349, 141, 1960}; static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518};
static const Bit32u MODE_0_OUTR[] = {1174, 1570, 145}; static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274};
static const Bit32u MODE_0_COMB_FACTOR[] = {0xA0, 0x60, 0x60, 0x60}; static const Bit32u MODE_1_COMB_FACTOR[] = {0x80, 0x60, 0x60, 0x60};
static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
static const Bit32u MODE_0_DRY_AMP[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xD0}; static const Bit32u MODE_1_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xE0};
static const Bit32u MODE_0_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; static const Bit32u MODE_1_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0};
static const Bit32u MODE_0_LPF_AMP = 0x60; static const Bit32u MODE_1_LPF_AMP = 0x60;
static const Bit32u MODE_1_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_2_NUMBER_OF_ALLPASSES = 3;
static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176}; static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157};
static const Bit32u MODE_1_NUMBER_OF_COMBS = 4; // Same as for mode 0 above static const Bit32u MODE_2_NUMBER_OF_COMBS = 4; // Same as for mode 0 above
static const Bit32u MODE_1_COMBS[] = {961 + PROCESS_DELAY, 2619, 3545, 4519}; static const Bit32u MODE_2_COMBS[] = {116 + PROCESS_DELAY, 2259, 2839, 3539};
static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518}; static const Bit32u MODE_2_OUTL[] = {2259, 718, 1769};
static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274}; static const Bit32u MODE_2_OUTR[] = {1136, 2128, 1};
static const Bit32u MODE_1_COMB_FACTOR[] = {0x80, 0x60, 0x60, 0x60}; static const Bit32u MODE_2_COMB_FACTOR[] = {0, 0x20, 0x20, 0x20};
static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98, 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0};
static const Bit32u MODE_1_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xE0}; static const Bit32u MODE_2_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xC0, 0xE0};
static const Bit32u MODE_1_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; static const Bit32u MODE_2_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0};
static const Bit32u MODE_1_LPF_AMP = 0x60; static const Bit32u MODE_2_LPF_AMP = 0x80;
static const Bit32u MODE_2_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_3_NUMBER_OF_ALLPASSES = 0;
static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157}; static const Bit32u MODE_3_NUMBER_OF_COMBS = 1;
static const Bit32u MODE_2_NUMBER_OF_COMBS = 4; // Same as for mode 0 above static const Bit32u MODE_3_DELAY[] = {16000 + MODE_3_FEEDBACK_DELAY + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY};
static const Bit32u MODE_2_COMBS[] = {116 + PROCESS_DELAY, 2259, 2839, 3539}; static const Bit32u MODE_3_OUTL[] = {400, 624, 960, 1488, 2256, 3472, 5280, 8000};
static const Bit32u MODE_2_OUTL[] = {2259, 718, 1769}; static const Bit32u MODE_3_OUTR[] = {800, 1248, 1920, 2976, 4512, 6944, 10560, 16000};
static const Bit32u MODE_2_OUTR[] = {1136, 2128, 1}; static const Bit32u MODE_3_COMB_FACTOR[] = {0x68};
static const Bit32u MODE_2_COMB_FACTOR[] = {0, 0x20, 0x20, 0x20}; static const Bit32u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60};
static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static const Bit32u MODE_3_DRY_AMP[] = {0x20, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0, 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50};
0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0, static const Bit32u MODE_3_WET_AMP[] = {0x18, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8};
0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0};
static const Bit32u MODE_2_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xC0, 0xE0};
static const Bit32u MODE_2_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0};
static const Bit32u MODE_2_LPF_AMP = 0x80;
static const Bit32u MODE_3_NUMBER_OF_ALLPASSES = 0; static const BReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_NUMBER_OF_ALLPASSES, MODE_0_ALLPASSES, MODE_0_NUMBER_OF_COMBS, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_DRY_AMP, MODE_0_WET_AMP, MODE_0_LPF_AMP};
static const Bit32u MODE_3_NUMBER_OF_COMBS = 1; static const BReverbSettings REVERB_MODE_1_SETTINGS = {MODE_1_NUMBER_OF_ALLPASSES, MODE_1_ALLPASSES, MODE_1_NUMBER_OF_COMBS, MODE_1_COMBS, MODE_1_OUTL, MODE_1_OUTR, MODE_1_COMB_FACTOR, MODE_1_COMB_FEEDBACK, MODE_1_DRY_AMP, MODE_1_WET_AMP, MODE_1_LPF_AMP};
static const Bit32u MODE_3_DELAY[] = {16000 + MODE_3_FEEDBACK_DELAY + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY}; static const BReverbSettings REVERB_MODE_2_SETTINGS = {MODE_2_NUMBER_OF_ALLPASSES, MODE_2_ALLPASSES, MODE_2_NUMBER_OF_COMBS, MODE_2_COMBS, MODE_2_OUTL, MODE_2_OUTR, MODE_2_COMB_FACTOR, MODE_2_COMB_FEEDBACK, MODE_2_DRY_AMP, MODE_2_WET_AMP, MODE_2_LPF_AMP};
static const Bit32u MODE_3_OUTL[] = {400, 624, 960, 1488, 2256, 3472, 5280, 8000}; static const BReverbSettings REVERB_MODE_3_SETTINGS = {MODE_3_NUMBER_OF_ALLPASSES, NULL, MODE_3_NUMBER_OF_COMBS, MODE_3_DELAY, MODE_3_OUTL, MODE_3_OUTR, MODE_3_COMB_FACTOR, MODE_3_COMB_FEEDBACK, MODE_3_DRY_AMP, MODE_3_WET_AMP, 0};
static const Bit32u MODE_3_OUTR[] = {800, 1248, 1920, 2976, 4512, 6944, 10560, 16000};
static const Bit32u MODE_3_COMB_FACTOR[] = {0x68};
static const Bit32u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60};
static const Bit32u MODE_3_DRY_AMP[] = {0x20, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50};
static const Bit32u MODE_3_WET_AMP[] = {0x18, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8};
static const BReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_NUMBER_OF_ALLPASSES, MODE_0_ALLPASSES, MODE_0_NUMBER_OF_COMBS, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_DRY_AMP, MODE_0_WET_AMP, MODE_0_LPF_AMP}; static const BReverbSettings * const REVERB_SETTINGS[] = {&REVERB_MODE_0_SETTINGS, &REVERB_MODE_1_SETTINGS, &REVERB_MODE_2_SETTINGS, &REVERB_MODE_3_SETTINGS};
static const BReverbSettings REVERB_MODE_1_SETTINGS = {MODE_1_NUMBER_OF_ALLPASSES, MODE_1_ALLPASSES, MODE_1_NUMBER_OF_COMBS, MODE_1_COMBS, MODE_1_OUTL, MODE_1_OUTR, MODE_1_COMB_FACTOR, MODE_1_COMB_FEEDBACK, MODE_1_DRY_AMP, MODE_1_WET_AMP, MODE_1_LPF_AMP};
static const BReverbSettings REVERB_MODE_2_SETTINGS = {MODE_2_NUMBER_OF_ALLPASSES, MODE_2_ALLPASSES, MODE_2_NUMBER_OF_COMBS, MODE_2_COMBS, MODE_2_OUTL, MODE_2_OUTR, MODE_2_COMB_FACTOR, MODE_2_COMB_FEEDBACK, MODE_2_DRY_AMP, MODE_2_WET_AMP, MODE_2_LPF_AMP};
static const BReverbSettings REVERB_MODE_3_SETTINGS = {MODE_3_NUMBER_OF_ALLPASSES, NULL, MODE_3_NUMBER_OF_COMBS, MODE_3_DELAY, MODE_3_OUTL, MODE_3_OUTR, MODE_3_COMB_FACTOR, MODE_3_COMB_FEEDBACK, MODE_3_DRY_AMP, MODE_3_WET_AMP, 0};
static const BReverbSettings * const REVERB_SETTINGS[] = {&REVERB_MODE_0_SETTINGS, &REVERB_MODE_1_SETTINGS, &REVERB_MODE_2_SETTINGS, &REVERB_MODE_3_SETTINGS}; return *REVERB_SETTINGS[mode];
}
// Default reverb settings for "old" reverb model implemented in MT-32.
// Found by tracing reverb RAM data lines (thanks go to Lord_Nightmare & balrog).
const BReverbSettings &BReverbModel::getMT32Settings(const ReverbMode mode) {
static const Bit32u MODE_0_NUMBER_OF_ALLPASSES = 3;
static const Bit32u MODE_0_ALLPASSES[] = {994, 729, 78};
static const Bit32u MODE_0_NUMBER_OF_COMBS = 4; // Same as above in the new model implementation
static const Bit32u MODE_0_COMBS[] = {575 + PROCESS_DELAY, 2040, 2752, 3629};
static const Bit32u MODE_0_OUTL[] = {2040, 687, 1814};
static const Bit32u MODE_0_OUTR[] = {1019, 2072, 1};
static const Bit32u MODE_0_COMB_FACTOR[] = {0xB0, 0x60, 0x60, 0x60};
static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
static const Bit32u MODE_0_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
static const Bit32u MODE_0_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0};
static const Bit32u MODE_0_LPF_AMP = 0x80;
static const Bit32u MODE_1_NUMBER_OF_ALLPASSES = 3;
static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176};
static const Bit32u MODE_1_NUMBER_OF_COMBS = 4; // Same as above in the new model implementation
static const Bit32u MODE_1_COMBS[] = {961 + PROCESS_DELAY, 2619, 3545, 4519};
static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518};
static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274};
static const Bit32u MODE_1_COMB_FACTOR[] = {0x90, 0x60, 0x60, 0x60};
static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
static const Bit32u MODE_1_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
static const Bit32u MODE_1_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0};
static const Bit32u MODE_1_LPF_AMP = 0x80;
static const Bit32u MODE_2_NUMBER_OF_ALLPASSES = 3;
static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157};
static const Bit32u MODE_2_NUMBER_OF_COMBS = 4; // Same as above in the new model implementation
static const Bit32u MODE_2_COMBS[] = {116 + PROCESS_DELAY, 2259, 2839, 3539};
static const Bit32u MODE_2_OUTL[] = {2259, 718, 1769};
static const Bit32u MODE_2_OUTR[] = {1136, 2128, 1};
static const Bit32u MODE_2_COMB_FACTOR[] = {0, 0x60, 0x60, 0x60};
static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
static const Bit32u MODE_2_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
static const Bit32u MODE_2_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0};
static const Bit32u MODE_2_LPF_AMP = 0x80;
static const Bit32u MODE_3_NUMBER_OF_ALLPASSES = 0;
static const Bit32u MODE_3_NUMBER_OF_COMBS = 1;
static const Bit32u MODE_3_DELAY[] = {16000 + MODE_3_FEEDBACK_DELAY + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY};
static const Bit32u MODE_3_OUTL[] = {400, 624, 960, 1488, 2256, 3472, 5280, 8000};
static const Bit32u MODE_3_OUTR[] = {800, 1248, 1920, 2976, 4512, 6944, 10560, 16000};
static const Bit32u MODE_3_COMB_FACTOR[] = {0x68};
static const Bit32u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60};
static const Bit32u MODE_3_DRY_AMP[] = {0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x10, 0x20, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10};
static const Bit32u MODE_3_WET_AMP[] = {0x08, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8};
static const BReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_NUMBER_OF_ALLPASSES, MODE_0_ALLPASSES, MODE_0_NUMBER_OF_COMBS, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_DRY_AMP, MODE_0_WET_AMP, MODE_0_LPF_AMP};
static const BReverbSettings REVERB_MODE_1_SETTINGS = {MODE_1_NUMBER_OF_ALLPASSES, MODE_1_ALLPASSES, MODE_1_NUMBER_OF_COMBS, MODE_1_COMBS, MODE_1_OUTL, MODE_1_OUTR, MODE_1_COMB_FACTOR, MODE_1_COMB_FEEDBACK, MODE_1_DRY_AMP, MODE_1_WET_AMP, MODE_1_LPF_AMP};
static const BReverbSettings REVERB_MODE_2_SETTINGS = {MODE_2_NUMBER_OF_ALLPASSES, MODE_2_ALLPASSES, MODE_2_NUMBER_OF_COMBS, MODE_2_COMBS, MODE_2_OUTL, MODE_2_OUTR, MODE_2_COMB_FACTOR, MODE_2_COMB_FEEDBACK, MODE_2_DRY_AMP, MODE_2_WET_AMP, MODE_2_LPF_AMP};
static const BReverbSettings REVERB_MODE_3_SETTINGS = {MODE_3_NUMBER_OF_ALLPASSES, NULL, MODE_3_NUMBER_OF_COMBS, MODE_3_DELAY, MODE_3_OUTL, MODE_3_OUTR, MODE_3_COMB_FACTOR, MODE_3_COMB_FEEDBACK, MODE_3_DRY_AMP, MODE_3_WET_AMP, 0};
static const BReverbSettings * const REVERB_SETTINGS[] = {&REVERB_MODE_0_SETTINGS, &REVERB_MODE_1_SETTINGS, &REVERB_MODE_2_SETTINGS, &REVERB_MODE_3_SETTINGS};
return *REVERB_SETTINGS[mode];
}
// This algorithm tries to emulate exactly Boss multiplication operation (at least this is what we see on reverb RAM data lines). // This algorithm tries to emulate exactly Boss multiplication operation (at least this is what we see on reverb RAM data lines).
// Also LA32 is suspected to use the similar one to perform PCM interpolation and ring modulation. // Also LA32 is suspected to use the similar one to perform PCM interpolation and ring modulation.
@ -153,14 +226,7 @@ bool RingBuffer::isEmpty() const {
} }
void RingBuffer::mute() { void RingBuffer::mute() {
#if MT32EMU_USE_FLOAT_SAMPLES Synth::muteSampleBuffer(buffer, size);
Sample *buf = buffer;
for (Bit32u i = 0; i < size; i++) {
*buf++ = 0;
}
#else
memset(buffer, 0, size * sizeof(Sample));
#endif
} }
AllpassFilter::AllpassFilter(const Bit32u useSize) : RingBuffer(useSize) {} AllpassFilter::AllpassFilter(const Bit32u useSize) : RingBuffer(useSize) {}
@ -195,10 +261,10 @@ void CombFilter::process(const Sample in) {
const Sample last = buffer[index]; const Sample last = buffer[index];
// prepare input + feedback // prepare input + feedback
const Sample filterIn = in + weirdMul(next(), feedbackFactor, 0xF0 /* Maybe 0x80 ? */); const Sample filterIn = in + weirdMul(next(), feedbackFactor, 0xF0);
// store input + feedback processed by a low-pass filter // store input + feedback processed by a low-pass filter
buffer[index] = weirdMul(last, filterFactor, 0x40) - filterIn; buffer[index] = weirdMul(last, filterFactor, 0xC0) - filterIn;
} }
Sample CombFilter::getOutputAt(const Bit32u outIndex) const { Sample CombFilter::getOutputAt(const Bit32u outIndex) const {
@ -256,8 +322,10 @@ void TapDelayCombFilter::setOutputPositions(const Bit32u useOutL, const Bit32u u
outR = useOutR; outR = useOutR;
} }
BReverbModel::BReverbModel(const ReverbMode mode) BReverbModel::BReverbModel(const ReverbMode mode, const bool mt32CompatibleModel) :
: allpasses(NULL), combs(NULL), currentSettings(*REVERB_SETTINGS[mode]), tapDelayMode(mode == REVERB_MODE_TAP_DELAY) {} allpasses(NULL), combs(NULL),
currentSettings(mt32CompatibleModel ? getMT32Settings(mode) : getCM32L_LAPCSettings(mode)),
tapDelayMode(mode == REVERB_MODE_TAP_DELAY) {}
BReverbModel::~BReverbModel() { BReverbModel::~BReverbModel() {
close(); close();
@ -334,12 +402,21 @@ void BReverbModel::setParameters(Bit8u time, Bit8u level) {
if (time == 0 && level == 0) { if (time == 0 && level == 0) {
dryAmp = wetLevel = 0; dryAmp = wetLevel = 0;
} else { } else {
dryAmp = currentSettings.dryAmps[level]; if (tapDelayMode && ((time == 0) || (time == 1 && level == 1))) {
// Looks like MT-32 implementation has some minor quirks in this mode:
// for odd level values, the output level changes sometimes depending on the time value which doesn't seem right.
dryAmp = currentSettings.dryAmps[level + 8];
} else {
dryAmp = currentSettings.dryAmps[level];
}
wetLevel = currentSettings.wetLevels[level]; wetLevel = currentSettings.wetLevels[level];
} }
} }
bool BReverbModel::isActive() const { bool BReverbModel::isActive() const {
if (combs == NULL) {
return false;
}
for (Bit32u i = 0; i < currentSettings.numberOfAllpasses; i++) { for (Bit32u i = 0; i < currentSettings.numberOfAllpasses; i++) {
if (!allpasses[i]->isEmpty()) return true; if (!allpasses[i]->isEmpty()) return true;
} }
@ -349,14 +426,34 @@ bool BReverbModel::isActive() const {
return false; return false;
} }
bool BReverbModel::isMT32Compatible(const ReverbMode mode) const {
return &currentSettings == &getMT32Settings(mode);
}
void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples) { void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples) {
if (combs == NULL) {
Synth::muteSampleBuffer(outLeft, numSamples);
Synth::muteSampleBuffer(outRight, numSamples);
return;
}
Sample dry; Sample dry;
while (numSamples > 0) { while ((numSamples--) > 0) {
if (tapDelayMode) { if (tapDelayMode) {
dry = *inLeft + *inRight; #if MT32EMU_USE_FLOAT_SAMPLES
dry = (*(inLeft++) * 0.5f) + (*(inRight++) * 0.5f);
#else
dry = (*(inLeft++) >> 1) + (*(inRight++) >> 1);
#endif
} else { } else {
dry = *inLeft / 2 + *inRight / 2; #if MT32EMU_USE_FLOAT_SAMPLES
dry = (*(inLeft++) * 0.25f) + (*(inRight++) * 0.25f);
#elif MT32EMU_BOSS_REVERB_PRECISE_MODE
dry = (*(inLeft++) >> 1) / 2 + (*(inRight++) >> 1) / 2;
#else
dry = (*(inLeft++) >> 2) + (*(inRight++) >> 2);
#endif
} }
// Looks like dryAmp doesn't change in MT-32 but it does in CM-32L / LAPC-I // Looks like dryAmp doesn't change in MT-32 but it does in CM-32L / LAPC-I
@ -365,8 +462,12 @@ void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *
if (tapDelayMode) { if (tapDelayMode) {
TapDelayCombFilter *comb = static_cast<TapDelayCombFilter *> (*combs); TapDelayCombFilter *comb = static_cast<TapDelayCombFilter *> (*combs);
comb->process(dry); comb->process(dry);
*outLeft = weirdMul(comb->getLeftOutput(), wetLevel, 0xFF); if (outLeft != NULL) {
*outRight = weirdMul(comb->getRightOutput(), wetLevel, 0xFF); *(outLeft++) = weirdMul(comb->getLeftOutput(), wetLevel, 0xFF);
}
if (outRight != NULL) {
*(outRight++) = weirdMul(comb->getRightOutput(), wetLevel, 0xFF);
}
} else { } else {
// If the output position is equal to the comb size, get it now in order not to loose it // If the output position is equal to the comb size, get it now in order not to loose it
Sample link = combs[0]->getOutputAt(currentSettings.combSizes[0] - 1); Sample link = combs[0]->getOutputAt(currentSettings.combSizes[0] - 1);
@ -389,33 +490,38 @@ void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *
combs[2]->process(link); combs[2]->process(link);
combs[3]->process(link); combs[3]->process(link);
Sample outL2 = combs[2]->getOutputAt(currentSettings.outLPositions[1]); if (outLeft != NULL) {
Sample outL3 = combs[3]->getOutputAt(currentSettings.outLPositions[2]); Sample outL2 = combs[2]->getOutputAt(currentSettings.outLPositions[1]);
Sample outR1 = combs[1]->getOutputAt(currentSettings.outRPositions[0]); Sample outL3 = combs[3]->getOutputAt(currentSettings.outLPositions[2]);
Sample outR2 = combs[2]->getOutputAt(currentSettings.outRPositions[1]);
Sample outR3 = combs[3]->getOutputAt(currentSettings.outRPositions[2]);
#if MT32EMU_USE_FLOAT_SAMPLES #if MT32EMU_USE_FLOAT_SAMPLES
*outLeft = 1.5f * (outL1 + outL2) + outL3; Sample outSample = 1.5f * (outL1 + outL2) + outL3;
*outRight = 1.5f * (outR1 + outR2) + outR3; #elif MT32EMU_BOSS_REVERB_PRECISE_MODE
/* NOTE:
* Thanks to Mok for discovering, the adder in BOSS reverb chip is found to perform addition with saturation to avoid integer overflow.
* Analysing of the algorithm suggests that the overflow is most probable when the combs output is added below.
* So, despite this isn't actually accurate, we only add the check here for performance reasons.
*/
Sample outSample = Synth::clipBit16s(Synth::clipBit16s(Synth::clipBit16s(Synth::clipBit16s((Bit32s)outL1 + Bit32s(outL1 >> 1)) + (Bit32s)outL2) + Bit32s(outL2 >> 1)) + (Bit32s)outL3);
#else #else
outL1 += outL1 >> 1; Sample outSample = Synth::clipBit16s((Bit32s)outL1 + Bit32s(outL1 >> 1) + (Bit32s)outL2 + Bit32s(outL2 >> 1) + (Bit32s)outL3);
outL2 += outL2 >> 1;
*outLeft = outL1 + outL2 + outL3;
outR1 += outR1 >> 1;
outR2 += outR2 >> 1;
*outRight = outR1 + outR2 + outR3;
#endif #endif
*outLeft = weirdMul(*outLeft, wetLevel, 0xFF); *(outLeft++) = weirdMul(outSample, wetLevel, 0xFF);
*outRight = weirdMul(*outRight, wetLevel, 0xFF); }
if (outRight != NULL) {
Sample outR1 = combs[1]->getOutputAt(currentSettings.outRPositions[0]);
Sample outR2 = combs[2]->getOutputAt(currentSettings.outRPositions[1]);
Sample outR3 = combs[3]->getOutputAt(currentSettings.outRPositions[2]);
#if MT32EMU_USE_FLOAT_SAMPLES
Sample outSample = 1.5f * (outR1 + outR2) + outR3;
#elif MT32EMU_BOSS_REVERB_PRECISE_MODE
// See the note above for the left channel output.
Sample outSample = Synth::clipBit16s(Synth::clipBit16s(Synth::clipBit16s(Synth::clipBit16s((Bit32s)outR1 + Bit32s(outR1 >> 1)) + (Bit32s)outR2) + Bit32s(outR2 >> 1)) + (Bit32s)outR3);
#else
Sample outSample = Synth::clipBit16s((Bit32s)outR1 + Bit32s(outR1 >> 1) + (Bit32s)outR2 + Bit32s(outR2 >> 1) + (Bit32s)outR3);
#endif
*(outRight++) = weirdMul(outSample, wetLevel, 0xFF);
}
} }
numSamples--;
inLeft++;
inRight++;
outLeft++;
outRight++;
} }
} }

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -97,8 +97,11 @@ class BReverbModel {
Bit32u wetLevel; Bit32u wetLevel;
void mute(); void mute();
static const BReverbSettings &getCM32L_LAPCSettings(const ReverbMode mode);
static const BReverbSettings &getMT32Settings(const ReverbMode mode);
public: public:
BReverbModel(const ReverbMode mode); BReverbModel(const ReverbMode mode, const bool mt32CompatibleModel = false);
~BReverbModel(); ~BReverbModel();
// After construction or a close(), open() must be called at least once before any other call (with the exception of close()). // After construction or a close(), open() must be called at least once before any other call (with the exception of close()).
void open(); void open();
@ -107,6 +110,7 @@ public:
void setParameters(Bit8u time, Bit8u level); void setParameters(Bit8u time, Bit8u level);
void process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples); void process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples);
bool isActive() const; bool isActive() const;
bool isMT32Compatible(const ReverbMode mode) const;
}; };
} }

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -33,14 +33,6 @@ static const Bit8u PartialMixStruct[13] = {
1, 3, 3, 2, 2, 2, 2 1, 3, 3, 2, 2, 2, 2
}; };
static const float floatKeyfollow[17] = {
-1.0f, -1.0f / 2.0f, -1.0f / 4.0f, 0.0f,
1.0f / 8.0f, 1.0f / 4.0f, 3.0f / 8.0f, 1.0f / 2.0f, 5.0f / 8.0f, 3.0f / 4.0f, 7.0f / 8.0f, 1.0f,
5.0f / 4.0f, 3.0f / 2.0f, 2.0f,
1.0009765625f, 1.0048828125f
};
RhythmPart::RhythmPart(Synth *useSynth, unsigned int usePartNum): Part(useSynth, usePartNum) { RhythmPart::RhythmPart(Synth *useSynth, unsigned int usePartNum): Part(useSynth, usePartNum) {
strcpy(name, "Rhythm"); strcpy(name, "Rhythm");
rhythmTemp = &synth->mt32ram.rhythmTemp[0]; rhythmTemp = &synth->mt32ram.rhythmTemp[0];

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -20,20 +20,24 @@
namespace MT32Emu { namespace MT32Emu {
// Known ROMs static const ROMInfo *getKnownROMInfoFromList(unsigned int index) {
static const ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL, NULL}; static const ControlROMFeatureSet MT32_COMPATIBLE(true);
static const ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL, NULL}; static const ControlROMFeatureSet CM32L_COMPATIBLE(false);
static const ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL, NULL};
static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL, NULL};
static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL, NULL};
static const ROMInfo CTRL_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL, NULL}; // Known ROMs
static const ROMInfo CTRL_CM32L_V1_02 = {65536, "a439fbb390da38cada95a7cbb1d6ca199cd66ef8", ROMInfo::Control, "ctrl_cm32l_1_02", "CM-32L/LAPC-I Control v1.02", ROMInfo::Full, NULL, NULL}; static const ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL, &MT32_COMPATIBLE};
static const ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL, &MT32_COMPATIBLE};
static const ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL, &MT32_COMPATIBLE};
static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL, &MT32_COMPATIBLE};
static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL, &MT32_COMPATIBLE};
static const ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL, NULL}; static const ROMInfo CTRL_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL, &CM32L_COMPATIBLE};
static const ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL, NULL}; static const ROMInfo CTRL_CM32L_V1_02 = {65536, "a439fbb390da38cada95a7cbb1d6ca199cd66ef8", ROMInfo::Control, "ctrl_cm32l_1_02", "CM-32L/LAPC-I Control v1.02", ROMInfo::Full, NULL, &CM32L_COMPATIBLE};
static const ROMInfo * const ROM_INFOS[] = { static const ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL, NULL};
static const ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL, NULL};
static const ROMInfo * const ROM_INFOS[] = {
&CTRL_MT32_V1_04, &CTRL_MT32_V1_04,
&CTRL_MT32_V1_05, &CTRL_MT32_V1_05,
&CTRL_MT32_V1_06, &CTRL_MT32_V1_06,
@ -45,13 +49,16 @@ static const ROMInfo * const ROM_INFOS[] = {
&PCM_CM32L, &PCM_CM32L,
NULL}; NULL};
return ROM_INFOS[index];
}
const ROMInfo* ROMInfo::getROMInfo(Common::File *file) { const ROMInfo* ROMInfo::getROMInfo(Common::File *file) {
size_t fileSize = file->size(); size_t fileSize = file->size();
// We haven't added the SHA1 checksum code in ScummVM, as the file size // We haven't added the SHA1 checksum code in ScummVM, as the file size
// suffices for our needs for now. // suffices for our needs for now.
//const char *fileDigest = file->getSHA1(); //const char *fileDigest = file->getSHA1();
for (int i = 0; ROM_INFOS[i] != NULL; i++) { for (int i = 0; getKnownROMInfoFromList(i) != NULL; i++) {
const ROMInfo *romInfo = ROM_INFOS[i]; const ROMInfo *romInfo = getKnownROMInfoFromList(i);
if (fileSize == romInfo->fileSize /*&& !strcmp(fileDigest, romInfo->sha1Digest)*/) { if (fileSize == romInfo->fileSize /*&& !strcmp(fileDigest, romInfo->sha1Digest)*/) {
return romInfo; return romInfo;
} }
@ -65,7 +72,7 @@ void ROMInfo::freeROMInfo(const ROMInfo *romInfo) {
static int getROMCount() { static int getROMCount() {
int count; int count;
for(count = 0; ROM_INFOS[count] != NULL; count++) { for(count = 0; getKnownROMInfoFromList(count) != NULL; count++) {
} }
return count; return count;
} }
@ -73,8 +80,8 @@ static int getROMCount() {
const ROMInfo** ROMInfo::getROMInfoList(unsigned int types, unsigned int pairTypes) { const ROMInfo** ROMInfo::getROMInfoList(unsigned int types, unsigned int pairTypes) {
const ROMInfo **romInfoList = new const ROMInfo*[getROMCount() + 1]; const ROMInfo **romInfoList = new const ROMInfo*[getROMCount() + 1];
const ROMInfo **currentROMInList = romInfoList; const ROMInfo **currentROMInList = romInfoList;
for(int i = 0; ROM_INFOS[i] != NULL; i++) { for(int i = 0; getKnownROMInfoFromList(i) != NULL; i++) {
const ROMInfo *romInfo = ROM_INFOS[i]; const ROMInfo *romInfo = getKnownROMInfoFromList(i);
if ((types & (1 << romInfo->type)) && (pairTypes & (1 << romInfo->pairType))) { if ((types & (1 << romInfo->type)) && (pairTypes & (1 << romInfo->pairType))) {
*currentROMInList++ = romInfo; *currentROMInList++ = romInfo;
} }
@ -108,4 +115,11 @@ const ROMInfo* ROMImage::getROMInfo() const {
return romInfo; return romInfo;
} }
ControlROMFeatureSet::ControlROMFeatureSet(bool useDefaultReverbMT32Compatible) : defaultReverbMT32Compatible(useDefaultReverbMT32Compatible) {
}
bool ControlROMFeatureSet::isDefaultReverbMT32Compatible() const {
return defaultReverbMT32Compatible;
}
} }

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -23,6 +23,8 @@
namespace MT32Emu { namespace MT32Emu {
struct ControlROMFeatureSet;
// Defines vital info about ROM file to be used by synth and applications // Defines vital info about ROM file to be used by synth and applications
struct ROMInfo { struct ROMInfo {
@ -34,7 +36,7 @@ public:
const char *description; const char *description;
enum PairType {Full, FirstHalf, SecondHalf, Mux0, Mux1} pairType; enum PairType {Full, FirstHalf, SecondHalf, Mux0, Mux1} pairType;
ROMInfo *pairROMInfo; ROMInfo *pairROMInfo;
void *controlROMInfo; const ControlROMFeatureSet *controlROMFeatures;
// Returns a ROMInfo struct by inspecting the size and the SHA1 hash // Returns a ROMInfo struct by inspecting the size and the SHA1 hash
static const ROMInfo* getROMInfo(Common::File *file); static const ROMInfo* getROMInfo(Common::File *file);
@ -72,6 +74,15 @@ public:
const ROMInfo *getROMInfo() const; const ROMInfo *getROMInfo() const;
}; };
struct ControlROMFeatureSet {
private:
unsigned int defaultReverbMT32Compatible : 1;
public:
ControlROMFeatureSet(bool defaultReverbMT32Compatible);
bool isDefaultReverbMT32Compatible() const;
};
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -20,13 +20,11 @@
//#include <cstdlib> //#include <cstdlib>
//#include <cstring> //#include <cstring>
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#define FORBIDDEN_SYMBOL_EXCEPTION_vprintf
#include "mt32emu.h" #include "mt32emu.h"
#include "mmath.h" #include "mmath.h"
#include "PartialManager.h" #include "PartialManager.h"
#include "BReverbModel.h" #include "BReverbModel.h"
#include "common/debug.h"
namespace MT32Emu { namespace MT32Emu {
@ -42,19 +40,6 @@ static const ControlROMMap ControlROMMaps[7] = {
// (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp) // (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp)
}; };
static inline void muteStream(Sample *stream, Bit32u len) {
if (stream == NULL) return;
#if MT32EMU_USE_FLOAT_SAMPLES
// FIXME: Use memset() where compatibility is guaranteed (if this turns out to be a win)
while (len--) {
*stream++ = 0.0f;
}
#else
memset(stream, 0, len * sizeof(Sample));
#endif
}
static inline void advanceStreamPosition(Sample *&stream, Bit32u posDelta) { static inline void advanceStreamPosition(Sample *&stream, Bit32u posDelta) {
if (stream != NULL) { if (stream != NULL) {
stream += posDelta; stream += posDelta;
@ -74,9 +59,9 @@ Bit8u Synth::calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum) {
Synth::Synth(ReportHandler *useReportHandler) { Synth::Synth(ReportHandler *useReportHandler) {
isOpen = false; isOpen = false;
reverbEnabled = true;
reverbOverridden = false; reverbOverridden = false;
partialCount = DEFAULT_MAX_PARTIALS; partialCount = DEFAULT_MAX_PARTIALS;
controlROMFeatures = NULL;
if (useReportHandler == NULL) { if (useReportHandler == NULL) {
reportHandler = new ReportHandler; reportHandler = new ReportHandler;
@ -86,11 +71,9 @@ Synth::Synth(ReportHandler *useReportHandler) {
isDefaultReportHandler = false; isDefaultReportHandler = false;
} }
reverbModels[REVERB_MODE_ROOM] = new BReverbModel(REVERB_MODE_ROOM); for (int i = 0; i < 4; i++) {
reverbModels[REVERB_MODE_HALL] = new BReverbModel(REVERB_MODE_HALL); reverbModels[i] = NULL;
reverbModels[REVERB_MODE_PLATE] = new BReverbModel(REVERB_MODE_PLATE); }
reverbModels[REVERB_MODE_TAP_DELAY] = new BReverbModel(REVERB_MODE_TAP_DELAY);
reverbModel = NULL; reverbModel = NULL;
setDACInputMode(DACInputMode_NICE); setDACInputMode(DACInputMode_NICE);
setMIDIDelayMode(MIDIDelayMode_DELAY_SHORT_MESSAGES_ONLY); setMIDIDelayMode(MIDIDelayMode_DELAY_SHORT_MESSAGES_ONLY);
@ -106,22 +89,29 @@ Synth::Synth(ReportHandler *useReportHandler) {
Synth::~Synth() { Synth::~Synth() {
close(); // Make sure we're closed and everything is freed close(); // Make sure we're closed and everything is freed
for (int i = 0; i < 4; i++) {
delete reverbModels[i];
}
if (isDefaultReportHandler) { if (isDefaultReportHandler) {
delete reportHandler; delete reportHandler;
} }
} }
void ReportHandler::showLCDMessage(const char *data) { void ReportHandler::showLCDMessage(const char *data) {
// We cannot use printf here. Since we already implement our own
// ReportHandler we simply disable the default implementation since it is
// never called anyway.
#if 0
printf("WRITE-LCD: %s", data); printf("WRITE-LCD: %s", data);
printf("\n"); printf("\n");
#endif
} }
void ReportHandler::printDebug(const char *fmt, va_list list) { void ReportHandler::printDebug(const char *fmt, va_list list) {
// We cannot use (v)printf here. Since we already implement our own
// ReportHandler we simply disable the default implementation since it is
// never called anyway.
#if 0
vprintf(fmt, list); vprintf(fmt, list);
printf("\n"); printf("\n");
#endif
} }
void Synth::polyStateChanged(int partNum) { void Synth::polyStateChanged(int partNum) {
@ -143,11 +133,22 @@ void Synth::printDebug(const char *fmt, ...) {
} }
void Synth::setReverbEnabled(bool newReverbEnabled) { void Synth::setReverbEnabled(bool newReverbEnabled) {
reverbEnabled = newReverbEnabled; if (isReverbEnabled() == newReverbEnabled) return;
if (newReverbEnabled) {
bool oldReverbOverridden = reverbOverridden;
reverbOverridden = false;
refreshSystemReverbParameters();
reverbOverridden = oldReverbOverridden;
} else {
#if MT32EMU_REDUCE_REVERB_MEMORY
reverbModel->close();
#endif
reverbModel = NULL;
}
} }
bool Synth::isReverbEnabled() const { bool Synth::isReverbEnabled() const {
return reverbEnabled; return reverbModel != NULL;
} }
void Synth::setReverbOverridden(bool newReverbOverridden) { void Synth::setReverbOverridden(bool newReverbOverridden) {
@ -158,7 +159,40 @@ bool Synth::isReverbOverridden() const {
return reverbOverridden; return reverbOverridden;
} }
void Synth::setReverbCompatibilityMode(bool mt32CompatibleMode) {
if (reverbModels[REVERB_MODE_ROOM] != NULL) {
if (isMT32ReverbCompatibilityMode() == mt32CompatibleMode) return;
setReverbEnabled(false);
for (int i = 0; i < 4; i++) {
delete reverbModels[i];
}
}
reverbModels[REVERB_MODE_ROOM] = new BReverbModel(REVERB_MODE_ROOM, mt32CompatibleMode);
reverbModels[REVERB_MODE_HALL] = new BReverbModel(REVERB_MODE_HALL, mt32CompatibleMode);
reverbModels[REVERB_MODE_PLATE] = new BReverbModel(REVERB_MODE_PLATE, mt32CompatibleMode);
reverbModels[REVERB_MODE_TAP_DELAY] = new BReverbModel(REVERB_MODE_TAP_DELAY, mt32CompatibleMode);
#if !MT32EMU_REDUCE_REVERB_MEMORY
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
reverbModels[i]->open();
}
#endif
if (isOpen) {
setReverbOutputGain(reverbOutputGain);
setReverbEnabled(true);
}
}
bool Synth::isMT32ReverbCompatibilityMode() const {
return isOpen && (reverbModels[REVERB_MODE_ROOM]->isMT32Compatible(REVERB_MODE_ROOM));
}
void Synth::setDACInputMode(DACInputMode mode) { void Synth::setDACInputMode(DACInputMode mode) {
#if MT32EMU_USE_FLOAT_SAMPLES
// We aren't emulating these in float mode, so better to inform the invoker
if ((mode == DACInputMode_GENERATION1) || (mode == DACInputMode_GENERATION2)) {
mode = DACInputMode_NICE;
}
#endif
dacInputMode = mode; dacInputMode = mode;
} }
@ -174,10 +208,13 @@ MIDIDelayMode Synth::getMIDIDelayMode() const {
return midiDelayMode; return midiDelayMode;
} }
#if MT32EMU_USE_FLOAT_SAMPLES
void Synth::setOutputGain(float newOutputGain) { void Synth::setOutputGain(float newOutputGain) {
if (newOutputGain < 0.0f) newOutputGain = -newOutputGain;
outputGain = newOutputGain; outputGain = newOutputGain;
#if !MT32EMU_USE_FLOAT_SAMPLES
if (256.0f < newOutputGain) newOutputGain = 256.0f;
effectiveOutputGain = int(newOutputGain * 256.0f);
#endif
} }
float Synth::getOutputGain() const { float Synth::getOutputGain() const {
@ -185,38 +222,21 @@ float Synth::getOutputGain() const {
} }
void Synth::setReverbOutputGain(float newReverbOutputGain) { void Synth::setReverbOutputGain(float newReverbOutputGain) {
if (newReverbOutputGain < 0.0f) newReverbOutputGain = -newReverbOutputGain;
reverbOutputGain = newReverbOutputGain; reverbOutputGain = newReverbOutputGain;
if (!isMT32ReverbCompatibilityMode()) newReverbOutputGain *= CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR;
#if MT32EMU_USE_FLOAT_SAMPLES
effectiveReverbOutputGain = newReverbOutputGain;
#else
if (256.0f < newReverbOutputGain) newReverbOutputGain = 256.0f;
effectiveReverbOutputGain = int(newReverbOutputGain * 256.0f);
#endif
} }
float Synth::getReverbOutputGain() const { float Synth::getReverbOutputGain() const {
return reverbOutputGain; return reverbOutputGain;
} }
#else // #if MT32EMU_USE_FLOAT_SAMPLES
void Synth::setOutputGain(float newOutputGain) {
if (newOutputGain < 0.0f) newOutputGain = -newOutputGain;
if (256.0f < newOutputGain) newOutputGain = 256.0f;
outputGain = int(newOutputGain * 256.0f);
}
float Synth::getOutputGain() const {
return outputGain / 256.0f;
}
void Synth::setReverbOutputGain(float newReverbOutputGain) {
if (newReverbOutputGain < 0.0f) newReverbOutputGain = -newReverbOutputGain;
float maxValue = 256.0f / CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR;
if (maxValue < newReverbOutputGain) newReverbOutputGain = maxValue;
reverbOutputGain = int(newReverbOutputGain * 256.0f);
}
float Synth::getReverbOutputGain() const {
return reverbOutputGain / 256.0f;
}
#endif // #if MT32EMU_USE_FLOAT_SAMPLES
void Synth::setReversedStereoEnabled(bool enabled) { void Synth::setReversedStereoEnabled(bool enabled) {
reversedStereoEnabled = enabled; reversedStereoEnabled = enabled;
} }
@ -226,7 +246,6 @@ bool Synth::isReversedStereoEnabled() {
} }
bool Synth::loadControlROM(const ROMImage &controlROMImage) { bool Synth::loadControlROM(const ROMImage &controlROMImage) {
if (&controlROMImage == NULL) return false;
Common::File *file = controlROMImage.getFile(); Common::File *file = controlROMImage.getFile();
const ROMInfo *controlROMInfo = controlROMImage.getROMInfo(); const ROMInfo *controlROMInfo = controlROMImage.getROMInfo();
if ((controlROMInfo == NULL) if ((controlROMInfo == NULL)
@ -234,6 +253,14 @@ bool Synth::loadControlROM(const ROMImage &controlROMImage) {
|| (controlROMInfo->pairType != ROMInfo::Full)) { || (controlROMInfo->pairType != ROMInfo::Full)) {
return false; return false;
} }
controlROMFeatures = controlROMImage.getROMInfo()->controlROMFeatures;
if (controlROMFeatures == NULL) {
#if MT32EMU_MONITOR_INIT
printDebug("Invalid Control ROM Info provided without feature set");
#endif
return false;
}
#if MT32EMU_MONITOR_INIT #if MT32EMU_MONITOR_INIT
printDebug("Found Control ROM: %s, %s", controlROMInfo->shortName, controlROMInfo->description); printDebug("Found Control ROM: %s, %s", controlROMInfo->shortName, controlROMInfo->description);
#endif #endif
@ -254,7 +281,6 @@ bool Synth::loadControlROM(const ROMImage &controlROMImage) {
} }
bool Synth::loadPCMROM(const ROMImage &pcmROMImage) { bool Synth::loadPCMROM(const ROMImage &pcmROMImage) {
if (&pcmROMImage == NULL) return false;
Common::File *file = pcmROMImage.getFile(); Common::File *file = pcmROMImage.getFile();
const ROMInfo *pcmROMInfo = pcmROMImage.getROMInfo(); const ROMInfo *pcmROMInfo = pcmROMImage.getROMInfo();
if ((pcmROMInfo == NULL) if ((pcmROMInfo == NULL)
@ -373,14 +399,6 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u
} }
partialCount = usePartialCount; partialCount = usePartialCount;
abortingPoly = NULL; abortingPoly = NULL;
#if MT32EMU_MONITOR_INIT
printDebug("Initialising Constant Tables");
#endif
#if !MT32EMU_REDUCE_REVERB_MEMORY
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
reverbModels[i]->open();
}
#endif
// This is to help detect bugs // This is to help detect bugs
memset(&mt32ram, '?', sizeof(mt32ram)); memset(&mt32ram, '?', sizeof(mt32ram));
@ -411,6 +429,15 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u
return false; return false;
} }
#if MT32EMU_MONITOR_INIT
printDebug("Initialising Reverb Models");
#endif
bool mt32CompatibleReverb = controlROMFeatures->isDefaultReverbMT32Compatible();
#if MT32EMU_MONITOR_INIT
printDebug("Using %s Compatible Reverb Models", mt32CompatibleReverb ? "MT-32" : "CM-32L");
#endif
setReverbCompatibilityMode(mt32CompatibleReverb);
#if MT32EMU_MONITOR_INIT #if MT32EMU_MONITOR_INIT
printDebug("Initialising Timbre Bank A"); printDebug("Initialising Timbre Bank A");
#endif #endif
@ -484,7 +511,11 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u
mt32ram.system.chanAssign[i] = i + 1; mt32ram.system.chanAssign[i] = i + 1;
} }
mt32ram.system.masterVol = 100; // Confirmed mt32ram.system.masterVol = 100; // Confirmed
bool oldReverbOverridden = reverbOverridden;
reverbOverridden = false;
refreshSystem(); refreshSystem();
reverbOverridden = oldReverbOverridden;
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
MemParams::PatchTemp *patchTemp = &mt32ram.patchTemp[i]; MemParams::PatchTemp *patchTemp = &mt32ram.patchTemp[i];
@ -526,8 +557,8 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u
return true; return true;
} }
void Synth::close() { void Synth::close(bool forced) {
if (!isOpen) { if (!forced && !isOpen) {
return; return;
} }
@ -548,9 +579,11 @@ void Synth::close() {
deleteMemoryRegions(); deleteMemoryRegions();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
reverbModels[i]->close(); delete reverbModels[i];
reverbModels[i] = NULL;
} }
reverbModel = NULL; reverbModel = NULL;
controlROMFeatures = NULL;
isOpen = false; isOpen = false;
} }
@ -1249,7 +1282,7 @@ void Synth::refreshSystemReverbParameters() {
#if MT32EMU_MONITOR_SYSEX > 0 #if MT32EMU_MONITOR_SYSEX > 0
printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel); printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
#endif #endif
if (reverbOverridden && reverbModel != NULL) { if (reverbOverridden) {
#if MT32EMU_MONITOR_SYSEX > 0 #if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Reverb overridden - ignoring)"); printDebug(" (Reverb overridden - ignoring)");
#endif #endif
@ -1259,17 +1292,31 @@ void Synth::refreshSystemReverbParameters() {
reportHandler->onNewReverbTime(mt32ram.system.reverbTime); reportHandler->onNewReverbTime(mt32ram.system.reverbTime);
reportHandler->onNewReverbLevel(mt32ram.system.reverbLevel); reportHandler->onNewReverbLevel(mt32ram.system.reverbLevel);
BReverbModel *newReverbModel = reverbModels[mt32ram.system.reverbMode]; BReverbModel *oldReverbModel = reverbModel;
#if MT32EMU_REDUCE_REVERB_MEMORY if (mt32ram.system.reverbTime == 0 && mt32ram.system.reverbLevel == 0) {
if (reverbModel != newReverbModel) { // Setting both time and level to 0 effectively disables wet reverb output on real devices.
if (reverbModel != NULL) { // Take a shortcut in this case to reduce CPU load.
reverbModel->close(); reverbModel = NULL;
} } else {
newReverbModel->open(); reverbModel = reverbModels[mt32ram.system.reverbMode];
} }
if (reverbModel != oldReverbModel) {
#if MT32EMU_REDUCE_REVERB_MEMORY
if (oldReverbModel != NULL) {
oldReverbModel->close();
}
if (isReverbEnabled()) {
reverbModel->open();
}
#else
if (isReverbEnabled()) {
reverbModel->mute();
}
#endif #endif
reverbModel = newReverbModel; }
reverbModel->setParameters(mt32ram.system.reverbTime, mt32ram.system.reverbLevel); if (isReverbEnabled()) {
reverbModel->setParameters(mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
}
} }
void Synth::refreshSystemReserveSettings() { void Synth::refreshSystemReserveSettings() {
@ -1468,94 +1515,103 @@ void Synth::renderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample
} }
} }
void Synth::convertSamplesToOutput(Sample *target, const Sample *source, Bit32u len, bool reverb) { // In GENERATION2 units, the output from LA32 goes to the Boss chip already bit-shifted.
if (target == NULL) return; // In NICE mode, it's also better to increase volume before the reverb processing to preserve accuracy.
void Synth::produceLA32Output(Sample *buffer, Bit32u len) {
if (dacInputMode == DACInputMode_PURE) { #if !MT32EMU_USE_FLOAT_SAMPLES
memcpy(target, source, len * sizeof(Sample)); switch (dacInputMode) {
return;
}
#if MT32EMU_USE_FLOAT_SAMPLES
float gain = reverb ? reverbOutputGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR : 2.0f * outputGain;
while (len--) {
*(target++) = *(source++) * gain;
}
#else
int gain;
if (reverb) {
gain = int(reverbOutputGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR);
} else {
gain = outputGain;
switch (dacInputMode) {
case DACInputMode_NICE:
// Since we're not shooting for accuracy here, don't worry about the rounding mode.
gain <<= 1;
break;
case DACInputMode_GENERATION1:
while (len--) {
*target = clipBit16s(Bit32s((*source * gain) >> 8));
*target = (*target & 0x8000) | ((*target << 1) & 0x7FFE);
source++;
target++;
}
return;
case DACInputMode_GENERATION2: case DACInputMode_GENERATION2:
while (len--) { while (len--) {
*target = clipBit16s(Bit32s((*source * gain) >> 8)); *buffer = (*buffer & 0x8000) | ((*buffer << 1) & 0x7FFE) | ((*buffer >> 14) & 0x0001);
*target = (*target & 0x8000) | ((*target << 1) & 0x7FFE) | ((*target >> 14) & 0x0001); ++buffer;
source++;
target++;
} }
return; break;
case DACInputMode_NICE:
while (len--) {
*buffer = clipBit16s(Bit32s(*buffer) << 1);
++buffer;
}
break;
default: default:
break; break;
}
#endif
}
void Synth::convertSamplesToOutput(Sample *buffer, Bit32u len, bool reverb) {
if (dacInputMode == DACInputMode_PURE) return;
#if MT32EMU_USE_FLOAT_SAMPLES
float gain = reverb ? effectiveReverbOutputGain : outputGain;
while (len--) {
*(buffer++) *= gain;
}
#else
int gain = reverb ? effectiveReverbOutputGain : effectiveOutputGain;
if (dacInputMode == DACInputMode_GENERATION1) {
while (len--) {
Bit32s target = Bit16s((*buffer & 0x8000) | ((*buffer << 1) & 0x7FFE));
*(buffer++) = clipBit16s((target * gain) >> 8);
} }
return;
} }
while (len--) { while (len--) {
*(target++) = clipBit16s(Bit32s((*(source++) * gain) >> 8)); *buffer = clipBit16s((Bit32s(*buffer) * gain) >> 8);
++buffer;
} }
#endif #endif
} }
void Synth::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) { void Synth::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) {
if (isEnabled) { // Even if LA32 output isn't desired, we proceed anyway with temp buffers
Sample tmpBufMixLeft[MAX_SAMPLES_PER_RUN], tmpBufMixRight[MAX_SAMPLES_PER_RUN]; Sample tmpBufNonReverbLeft[MAX_SAMPLES_PER_RUN], tmpBufNonReverbRight[MAX_SAMPLES_PER_RUN];
muteStream(tmpBufMixLeft, len); if (nonReverbLeft == NULL) nonReverbLeft = tmpBufNonReverbLeft;
muteStream(tmpBufMixRight, len); if (nonReverbLeft == NULL) nonReverbRight = tmpBufNonReverbRight;
for (unsigned int i = 0; i < getPartialCount(); i++) {
if (!reverbEnabled || !partialManager->shouldReverb(i)) {
partialManager->produceOutput(i, tmpBufMixLeft, tmpBufMixRight, len);
}
}
convertSamplesToOutput(nonReverbLeft, tmpBufMixLeft, len, false);
convertSamplesToOutput(nonReverbRight, tmpBufMixRight, len, false);
} else {
muteStream(nonReverbLeft, len);
muteStream(nonReverbRight, len);
}
if (isEnabled && reverbEnabled) { Sample tmpBufReverbDryLeft[MAX_SAMPLES_PER_RUN], tmpBufReverbDryRight[MAX_SAMPLES_PER_RUN];
Sample tmpBufMixLeft[MAX_SAMPLES_PER_RUN], tmpBufMixRight[MAX_SAMPLES_PER_RUN]; if (reverbDryLeft == NULL) reverbDryLeft = tmpBufReverbDryLeft;
muteStream(tmpBufMixLeft, len); if (reverbDryRight == NULL) reverbDryRight = tmpBufReverbDryRight;
muteStream(tmpBufMixRight, len);
muteSampleBuffer(nonReverbLeft, len);
muteSampleBuffer(nonReverbRight, len);
muteSampleBuffer(reverbDryLeft, len);
muteSampleBuffer(reverbDryRight, len);
if (isEnabled) {
for (unsigned int i = 0; i < getPartialCount(); i++) { for (unsigned int i = 0; i < getPartialCount(); i++) {
if (partialManager->shouldReverb(i)) { if (partialManager->shouldReverb(i)) {
partialManager->produceOutput(i, tmpBufMixLeft, tmpBufMixRight, len); partialManager->produceOutput(i, reverbDryLeft, reverbDryRight, len);
} else {
partialManager->produceOutput(i, nonReverbLeft, nonReverbRight, len);
} }
} }
convertSamplesToOutput(reverbDryLeft, tmpBufMixLeft, len, false);
convertSamplesToOutput(reverbDryRight, tmpBufMixRight, len, false);
Sample tmpBufReverbOutLeft[MAX_SAMPLES_PER_RUN], tmpBufReverbOutRight[MAX_SAMPLES_PER_RUN]; produceLA32Output(reverbDryLeft, len);
reverbModel->process(tmpBufMixLeft, tmpBufMixRight, tmpBufReverbOutLeft, tmpBufReverbOutRight, len); produceLA32Output(reverbDryRight, len);
convertSamplesToOutput(reverbWetLeft, tmpBufReverbOutLeft, len, true);
convertSamplesToOutput(reverbWetRight, tmpBufReverbOutRight, len, true); if (isReverbEnabled()) {
reverbModel->process(reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, len);
if (reverbWetLeft != NULL) convertSamplesToOutput(reverbWetLeft, len, true);
if (reverbWetRight != NULL) convertSamplesToOutput(reverbWetRight, len, true);
} else {
muteSampleBuffer(reverbWetLeft, len);
muteSampleBuffer(reverbWetRight, len);
}
// Don't bother with conversion if the output is going to be unused
if (nonReverbLeft != tmpBufNonReverbLeft) {
produceLA32Output(nonReverbLeft, len);
convertSamplesToOutput(nonReverbLeft, len, false);
}
if (nonReverbRight != tmpBufNonReverbRight) {
produceLA32Output(nonReverbRight, len);
convertSamplesToOutput(nonReverbRight, len, false);
}
if (reverbDryLeft != tmpBufReverbDryLeft) convertSamplesToOutput(reverbDryLeft, len, false);
if (reverbDryRight != tmpBufReverbDryRight) convertSamplesToOutput(reverbDryRight, len, false);
} else { } else {
muteStream(reverbDryLeft, len); muteSampleBuffer(reverbWetLeft, len);
muteStream(reverbDryRight, len); muteSampleBuffer(reverbWetRight, len);
muteStream(reverbWetLeft, len);
muteStream(reverbWetRight, len);
} }
partialManager->clearAlreadyOutputed(); partialManager->clearAlreadyOutputed();
@ -1589,7 +1645,7 @@ bool Synth::isActive() const {
if (hasActivePartials()) { if (hasActivePartials()) {
return true; return true;
} }
if (reverbEnabled) { if (isReverbEnabled()) {
return reverbModel->isActive(); return reverbModel->isActive();
} }
return false; return false;

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@ -322,6 +322,7 @@ private:
PCMWaveEntry *pcmWaves; // Array PCMWaveEntry *pcmWaves; // Array
const ControlROMFeatureSet *controlROMFeatures;
const ControlROMMap *controlROMMap; const ControlROMMap *controlROMMap;
Bit8u controlROMData[CONTROL_ROM_SIZE]; Bit8u controlROMData[CONTROL_ROM_SIZE];
Bit16s *pcmROMData; Bit16s *pcmROMData;
@ -338,18 +339,18 @@ private:
BReverbModel *reverbModels[4]; BReverbModel *reverbModels[4];
BReverbModel *reverbModel; BReverbModel *reverbModel;
bool reverbEnabled;
bool reverbOverridden; bool reverbOverridden;
MIDIDelayMode midiDelayMode; MIDIDelayMode midiDelayMode;
DACInputMode dacInputMode; DACInputMode dacInputMode;
#if MT32EMU_USE_FLOAT_SAMPLES
float outputGain; float outputGain;
float reverbOutputGain; float reverbOutputGain;
#if MT32EMU_USE_FLOAT_SAMPLES
float effectiveReverbOutputGain;
#else #else
int outputGain; int effectiveOutputGain;
int reverbOutputGain; int effectiveReverbOutputGain;
#endif #endif
bool reversedStereoEnabled; bool reversedStereoEnabled;
@ -370,7 +371,8 @@ private:
Bit32u getShortMessageLength(Bit32u msg); Bit32u getShortMessageLength(Bit32u msg);
Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp); Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp);
void convertSamplesToOutput(Sample *target, const Sample *source, Bit32u len, bool reverb); void produceLA32Output(Sample *buffer, Bit32u len);
void convertSamplesToOutput(Sample *buffer, Bit32u len, bool reverb);
bool isAbortingPoly() const; bool isAbortingPoly() const;
void doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len); void doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len);
@ -405,10 +407,23 @@ private:
public: public:
static inline Bit16s clipBit16s(Bit32s sample) { static inline Bit16s clipBit16s(Bit32s sample) {
// Clamp values above 32767 to 32767, and values below -32768 to -32768 // Clamp values above 32767 to 32767, and values below -32768 to -32768
if ((sample + 32768) & ~65535) { // FIXME: Do we really need this stuff? I think these branches are very well predicted. Instead, this introduces a chain.
return (sample >> 31) ^ 32767; // The version below is actually a bit faster on my system...
//return ((sample + 0x8000) & ~0xFFFF) ? (sample >> 31) ^ 0x7FFF : (Bit16s)sample;
return ((-0x8000 <= sample) && (sample <= 0x7FFF)) ? (Bit16s)sample : (sample >> 31) ^ 0x7FFF;
}
static inline void muteSampleBuffer(Sample *buffer, Bit32u len) {
if (buffer == NULL) return;
#if MT32EMU_USE_FLOAT_SAMPLES
// FIXME: Use memset() where compatibility is guaranteed (if this turns out to be a win)
while (len--) {
*(buffer++) = 0.0f;
} }
return (Bit16s)sample; #else
memset(buffer, 0, len * sizeof(Sample));
#endif
} }
static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum); static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum);
@ -424,7 +439,7 @@ public:
bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount = DEFAULT_MAX_PARTIALS); bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount = DEFAULT_MAX_PARTIALS);
// Closes the MT-32 and deallocates any memory used by the synthesizer // Closes the MT-32 and deallocates any memory used by the synthesizer
void close(void); void close(bool forced = false);
// All the enqueued events are processed by the synth immediately. // All the enqueued events are processed by the synth immediately.
void flushMIDIQueue(); void flushMIDIQueue();
@ -464,8 +479,17 @@ public:
void setReverbEnabled(bool reverbEnabled); void setReverbEnabled(bool reverbEnabled);
bool isReverbEnabled() const; bool isReverbEnabled() const;
// Sets override reverb mode. In this mode, emulation ignores sysexes (or the related part of them) which control the reverb parameters.
// This mode is in effect until it is turned off. When the synth is re-opened, the override mode is unchanged but the state
// of the reverb model is reset to default.
void setReverbOverridden(bool reverbOverridden); void setReverbOverridden(bool reverbOverridden);
bool isReverbOverridden() const; bool isReverbOverridden() const;
// Forces reverb model compatibility mode. By default, the compatibility mode corresponds to the used control ROM version.
// Invoking this method with the argument set to true forces emulation of old MT-32 reverb circuit.
// When the argument is false, emulation of the reverb circuit used in new generation of MT-32 compatible modules is enforced
// (these include CM-32L and LAPC-I).
void setReverbCompatibilityMode(bool mt32CompatibleMode);
bool isMT32ReverbCompatibilityMode() const;
void setDACInputMode(DACInputMode mode); void setDACInputMode(DACInputMode mode);
DACInputMode getDACInputMode() const; DACInputMode getDACInputMode() const;
void setMIDIDelayMode(MIDIDelayMode mode); void setMIDIDelayMode(MIDIDelayMode mode);

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by

2
configure vendored
View File

@ -1832,7 +1832,7 @@ fi
echo $_global_constructors echo $_global_constructors
echo_n "Checking for $_host_alias-strings... " >> "$TMPLOG" echo_n "Checking for $_host_alias-strings... " >> "$TMPLOG"
if test ! "x$(which $_host_alias-strings 2>/dev/null)" = "x"; then if `which $_host_alias-strings >/dev/null 2>&1`; then
_strings=$_host_alias-strings _strings=$_host_alias-strings
echo yes >> "$TMPLOG" echo yes >> "$TMPLOG"
else else

View File

@ -352,7 +352,7 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
"\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_Global</_PropertySheetDisplayName>\n" "\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_Global</_PropertySheetDisplayName>\n"
"\t\t<ExecutablePath>$(" << LIBS_DEFINE << ")\\bin;$(ExecutablePath)</ExecutablePath>\n" "\t\t<ExecutablePath>$(" << LIBS_DEFINE << ")\\bin;$(ExecutablePath)</ExecutablePath>\n"
"\t\t<LibraryPath>$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n" "\t\t<LibraryPath>$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n"
"\t\t<IncludePath>$(" << LIBS_DEFINE << ")\\include;$(IncludePath)</IncludePath>\n" "\t\t<IncludePath>$(" << LIBS_DEFINE << ")\\include;$(" << LIBS_DEFINE << ")\\include\\SDL;$(IncludePath)</IncludePath>\n"
"\t\t<OutDir>$(Configuration)" << bits << "\\</OutDir>\n" "\t\t<OutDir>$(Configuration)" << bits << "\\</OutDir>\n"
"\t\t<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n" "\t\t<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n"
"\t</PropertyGroup>\n" "\t</PropertyGroup>\n"

View File

@ -228,7 +228,7 @@ void VisualStudioProvider::outputGlobalPropFile(const BuildSetup &setup, std::of
"\t\tName=\"VCCLCompilerTool\"\n" "\t\tName=\"VCCLCompilerTool\"\n"
"\t\tDisableLanguageExtensions=\"" << (setup.devTools ? "false" : "true") << "\"\n" "\t\tDisableLanguageExtensions=\"" << (setup.devTools ? "false" : "true") << "\"\n"
"\t\tDisableSpecificWarnings=\"" << warnings << "\"\n" "\t\tDisableSpecificWarnings=\"" << warnings << "\"\n"
"\t\tAdditionalIncludeDirectories=\".\\;" << prefix << ";" << prefix << "\\engines;$(" << LIBS_DEFINE << ")\\include;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir)\"\n" "\t\tAdditionalIncludeDirectories=\".\\;" << prefix << ";" << prefix << "\\engines;$(" << LIBS_DEFINE << ")\\include;$(" << LIBS_DEFINE << ")\\include\\SDL;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir)\"\n"
"\t\tPreprocessorDefinitions=\"" << definesList << "\"\n" "\t\tPreprocessorDefinitions=\"" << definesList << "\"\n"
"\t\tExceptionHandling=\"" << ((setup.devTools || setup.tests) ? "1" : "0") << "\"\n"; "\t\tExceptionHandling=\"" << ((setup.devTools || setup.tests) ? "1" : "0") << "\"\n";

View File

@ -34,7 +34,8 @@ BuildRequires: SDL-devel >= 1.2.2
# install scripts # install scripts
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
%prep %prep
%setup -q -a 1 -a 2 -n residualvm-%{version} %setup -q -a 1 -a 2 -a 3 -n residualvm-%{version}
patch0 -p0
mkdir tmp mkdir tmp
%build %build

View File

@ -34,7 +34,8 @@ BuildRequires: SDL-devel >= 1.2.2
# install scripts # install scripts
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
%prep %prep
%setup -q -a 1 -a 2 -n residualvm-%{version} %setup -q -a 1 -a 2 -a 3 -n residualvm-%{version}
patch0 -p0
mkdir tmp mkdir tmp
%build %build

View File

@ -127,6 +127,8 @@ int BrowserDialog::runModal() {
NSOpenPanel *panel = [NSOpenPanel openPanel]; NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:!_isDirBrowser]; [panel setCanChooseFiles:!_isDirBrowser];
[panel setCanChooseDirectories:_isDirBrowser]; [panel setCanChooseDirectories:_isDirBrowser];
if (_isDirBrowser)
[panel setTreatsFilePackagesAsDirectories:true];
[panel setTitle:(NSString *)_titleRef]; [panel setTitle:(NSString *)_titleRef];
[panel setPrompt:(NSString *)_chooseRef]; [panel setPrompt:(NSString *)_chooseRef];

View File

@ -159,7 +159,7 @@ bool TGADecoder::readHeader(Common::SeekableReadStream &tga, byte &imageType, by
warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth); warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
return false; return false;
} }
} else if (imageType == TYPE_BW || TYPE_RLE_BW) { } else if (imageType == TYPE_BW || imageType == TYPE_RLE_BW) {
if (pixelDepth == 8) { if (pixelDepth == 8) {
_format = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0); _format = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
} else { } else {

View File

@ -108,20 +108,18 @@ bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) {
uint32 audioTrackCount = _bink->readUint32LE(); uint32 audioTrackCount = _bink->readUint32LE();
if (audioTrackCount > 0) { if (audioTrackCount > 0) {
_audioTracks.reserve(audioTrackCount); _audioTracks.resize(audioTrackCount);
_bink->skip(4 * audioTrackCount); _bink->skip(4 * audioTrackCount);
// Reading audio track properties // Reading audio track properties
for (uint32 i = 0; i < audioTrackCount; i++) { for (uint32 i = 0; i < audioTrackCount; i++) {
AudioInfo track; AudioInfo &track = _audioTracks[i];
track.sampleRate = _bink->readUint16LE(); track.sampleRate = _bink->readUint16LE();
track.flags = _bink->readUint16LE(); track.flags = _bink->readUint16LE();
_audioTracks.push_back(track); initAudioTrack(track);
initAudioTrack(_audioTracks[i]);
} }
_bink->skip(4 * audioTrackCount); _bink->skip(4 * audioTrackCount);