// license:BSD-3-Clause // copyright-holders:pSXAuthor, R. Belmont #include "emu.h" #include "spu.h" #include "spureverb.h" const float spu_device::linear_rate[]= { ms_to_rate(0.05f), ms_to_rate(0.06f), ms_to_rate(0.07f), ms_to_rate(0.09f), ms_to_rate(0.10f), ms_to_rate(0.12f), ms_to_rate(0.15f), ms_to_rate(0.18f), ms_to_rate(0.21f), ms_to_rate(0.24f), ms_to_rate(0.29f), ms_to_rate(0.36f), ms_to_rate(0.41f), ms_to_rate(0.48f), ms_to_rate(0.58f), ms_to_rate(0.73f), ms_to_rate(0.83f), ms_to_rate(0.97f), ms_to_rate(1.2f), ms_to_rate(1.5f), ms_to_rate(1.7f), ms_to_rate(1.9f), ms_to_rate(2.3f), ms_to_rate(2.9f), ms_to_rate(3.3f), ms_to_rate(3.9f), ms_to_rate(4.6f), ms_to_rate(5.8f), ms_to_rate(6.6f), ms_to_rate(7.7f), ms_to_rate(9.3f), ms_to_rate(12.0f), ms_to_rate(13.0f), ms_to_rate(15.0f), ms_to_rate(19.0f), ms_to_rate(23.0f), ms_to_rate(27.0f), ms_to_rate(31.0f), ms_to_rate(37.0f), ms_to_rate(46.0f), ms_to_rate(53.0f), ms_to_rate(62.0f), ms_to_rate(74.0f), ms_to_rate(93.0f), s_to_rate(0.11f), s_to_rate(0.12f), s_to_rate(0.15f), s_to_rate(0.19f), s_to_rate(0.21f), s_to_rate(0.25f), s_to_rate(0.30f), s_to_rate(0.37f), s_to_rate(0.42f), s_to_rate(0.50f), s_to_rate(0.59f), s_to_rate(0.74f), s_to_rate(0.85f), s_to_rate(0.99f), s_to_rate(1.2f), s_to_rate(1.5f), s_to_rate(1.7f), s_to_rate(2.0f), s_to_rate(2.4f), s_to_rate(3.0f), s_to_rate(3.4f), s_to_rate(4.0f), s_to_rate(4.8f), s_to_rate(5.9f), s_to_rate(6.8f), s_to_rate(7.9f), s_to_rate(9.5f), s_to_rate(12.0f), s_to_rate(14.0f), s_to_rate(16.0f), s_to_rate(19.0f), s_to_rate(24.0f), s_to_rate(27.0f), s_to_rate(32.0f), s_to_rate(38.0f), s_to_rate(48.0f), s_to_rate(54.0f), s_to_rate(63.0f), s_to_rate(76.0f), s_to_rate(95.0f), s_to_rate(109.0f), s_to_rate(127.0f), s_to_rate(152.0f), s_to_rate(190.0f), s_to_rate(218.0f), s_to_rate(254.0f), s_to_rate(304.0f), s_to_rate(380.0f), s_to_rate(436.0f), s_to_rate(508.0f), s_to_rate(608.0f), s_to_rate(760.0f), s_to_rate(872.0f), s_to_rate(1016.0f), s_to_rate(1216.0f), s_to_rate(1520.0f), s_to_rate(1744.0f), s_to_rate(2032.0f), s_to_rate(2432.0f), s_to_rate(3040.0f), s_to_rate(3488.0f), s_to_rate(4064.0f), s_to_rate(4864.0f), s_to_rate(6080.0f) }; const float spu_device::pos_exp_rate[]= { ms_to_rate(0.09f), ms_to_rate(0.11f), ms_to_rate(0.13f), ms_to_rate(0.16f), ms_to_rate(0.18f), ms_to_rate(0.21f), ms_to_rate(0.25f), ms_to_rate(0.32f), ms_to_rate(0.36f), ms_to_rate(0.42f), ms_to_rate(0.51f), ms_to_rate(0.64f), ms_to_rate(0.73f), ms_to_rate(0.85f), ms_to_rate(1.0f), ms_to_rate(1.3f), ms_to_rate(1.5f), ms_to_rate(1.7f), ms_to_rate(2.0f), ms_to_rate(2.5f), ms_to_rate(2.9f), ms_to_rate(3.4f), ms_to_rate(4.1f), ms_to_rate(5.1f), ms_to_rate(5.8f), ms_to_rate(6.8f), ms_to_rate(8.1f), ms_to_rate(10.0f), ms_to_rate(12.0f), ms_to_rate(14.0f), ms_to_rate(16.0f), ms_to_rate(20.0f), ms_to_rate(23.0f), ms_to_rate(27.0f), ms_to_rate(33.0f), ms_to_rate(41.0f), ms_to_rate(46.0f), ms_to_rate(54.0f), ms_to_rate(65.0f), ms_to_rate(81.0f), ms_to_rate(93.0f), s_to_rate(0.11f), s_to_rate(0.13f), s_to_rate(0.16f), s_to_rate(0.19f), s_to_rate(0.22f), s_to_rate(0.26f), s_to_rate(0.33f), s_to_rate(0.37f), s_to_rate(0.43f), s_to_rate(0.52f), s_to_rate(0.65f), s_to_rate(0.74f), s_to_rate(0.87f), s_to_rate(1.0f), s_to_rate(1.3f), s_to_rate(1.5f), s_to_rate(1.7f), s_to_rate(2.1f), s_to_rate(2.6f), s_to_rate(3.0f), s_to_rate(3.5f), s_to_rate(4.2f), s_to_rate(5.2f), s_to_rate(5.9f), s_to_rate(6.9f), s_to_rate(8.3f), s_to_rate(10.0f), s_to_rate(12.0f), s_to_rate(14.0f), s_to_rate(17.0f), s_to_rate(21.0f), s_to_rate(24.0f), s_to_rate(28.0f), s_to_rate(33.0f), s_to_rate(42.0f), s_to_rate(48.0f), s_to_rate(55.0f), s_to_rate(67.0f), s_to_rate(83.0f), s_to_rate(95.0f), s_to_rate(111.0f), s_to_rate(133.0f), s_to_rate(166.0f), s_to_rate(190.0f), s_to_rate(222.0f), s_to_rate(266.0f), s_to_rate(333.0f), s_to_rate(380.0f), s_to_rate(444.0f), s_to_rate(532.0f), s_to_rate(666.0f), s_to_rate(760.0f), s_to_rate(888.0f), s_to_rate(1064.0f), s_to_rate(1332.0f), s_to_rate(1520.0f), s_to_rate(1776.0f), s_to_rate(2128.0f), s_to_rate(2664.0f) }; const float spu_device::neg_exp_rate[]= { ms_to_rate(0.07f), ms_to_rate(0.09f), ms_to_rate(0.11f), ms_to_rate(0.14f), ms_to_rate(0.18f), ms_to_rate(0.21f), ms_to_rate(0.25f), ms_to_rate(0.31f), ms_to_rate(0.39f), ms_to_rate(0.45f), ms_to_rate(0.53f), ms_to_rate(0.64f), ms_to_rate(0.81f), ms_to_rate(0.93f), ms_to_rate(1.1f), ms_to_rate(1.3f), ms_to_rate(1.6f), ms_to_rate(1.9f), ms_to_rate(2.2f), ms_to_rate(2.6f), ms_to_rate(3.3f), ms_to_rate(3.8f), ms_to_rate(4.4f), ms_to_rate(5.3f), ms_to_rate(6.7f), ms_to_rate(7.6f), ms_to_rate(8.9f), ms_to_rate(11.0f), ms_to_rate(13.0f), ms_to_rate(15.0f), ms_to_rate(18.0f), ms_to_rate(21.0f), ms_to_rate(27.0f), ms_to_rate(31.0f), ms_to_rate(36.0f), ms_to_rate(43.0f), ms_to_rate(53.0f), ms_to_rate(61.0f), ms_to_rate(71.0f), ms_to_rate(86.0f), s_to_rate(0.11f), s_to_rate(0.12f), s_to_rate(0.14f), s_to_rate(0.17f), s_to_rate(0.21f), s_to_rate(0.24f), s_to_rate(0.29f), s_to_rate(0.34f), s_to_rate(0.43f), s_to_rate(0.49f), s_to_rate(0.57f), s_to_rate(0.68f), s_to_rate(0.86f), s_to_rate(0.98f), s_to_rate(1.1f), s_to_rate(1.4f), s_to_rate(1.7f), s_to_rate(2.0f), s_to_rate(2.3f), s_to_rate(2.7f), s_to_rate(3.4f), s_to_rate(3.9f), s_to_rate(4.6f), s_to_rate(5.5f), s_to_rate(6.8f), s_to_rate(7.8f), s_to_rate(9.1f), s_to_rate(11.0f), s_to_rate(14.0f), s_to_rate(16.0f), s_to_rate(18.0f), s_to_rate(22.0f), s_to_rate(27.0f), s_to_rate(31.0f), s_to_rate(36.0f), s_to_rate(44.0f), s_to_rate(55.0f), s_to_rate(63.0f), s_to_rate(73.0f), s_to_rate(88.0f), s_to_rate(109.0f), s_to_rate(125.0f), s_to_rate(146.0f), s_to_rate(175.0f), s_to_rate(219.0f), s_to_rate(250.0f), s_to_rate(292.0f), s_to_rate(350.0f), s_to_rate(438.0f), s_to_rate(500.0f), s_to_rate(584.0f), s_to_rate(700.0f), s_to_rate(876.0f), s_to_rate(1000.0f), s_to_rate(1168.0f), s_to_rate(1400.0f), s_to_rate(1752.0f), s_to_rate(2000.0f), s_to_rate(2336.0f), s_to_rate(2800.0f), s_to_rate(3504.0f), s_to_rate(4000.0f), s_to_rate(4672.0f), s_to_rate(5600.0f), s_to_rate(7008.0f), s_to_rate(8000.0f), s_to_rate(9344.0f), s_to_rate(11200.0f) }; const float spu_device::decay_rate[16]= { ms_to_rate(0.07f), ms_to_rate(0.18f), ms_to_rate(0.39f), ms_to_rate(0.81f), ms_to_rate(1.6f), ms_to_rate(3.3f), ms_to_rate(6.7f), ms_to_rate(13.0f), ms_to_rate(27.0f), ms_to_rate(53.0f), s_to_rate(0.11f), s_to_rate(0.21f), s_to_rate(0.43f), s_to_rate(0.86f), s_to_rate(1.7f), s_to_rate(3.4f), }; const float spu_device::linear_release_rate[]= { ms_to_rate(0.04f), ms_to_rate(0.09f), ms_to_rate(0.18f), ms_to_rate(0.36f), ms_to_rate(0.73f), ms_to_rate(1.5f), ms_to_rate(2.9f), ms_to_rate(5.8f), ms_to_rate(12.0f), ms_to_rate(23.0f), ms_to_rate(46.0f), ms_to_rate(93.0f), s_to_rate(0.19f), s_to_rate(0.37f), s_to_rate(1.74f), s_to_rate(1.5f), s_to_rate(3.0f), s_to_rate(5.9f), s_to_rate(12.0f), s_to_rate(24.0f), s_to_rate(48.0f), s_to_rate(95.0f), s_to_rate(190.0f), s_to_rate(380.0f), s_to_rate(760.0f), s_to_rate(1520.0f), s_to_rate(3040.0f) }; const float spu_device::exp_release_rate[]= { ms_to_rate(0.07f), ms_to_rate(0.18f), ms_to_rate(0.39f), ms_to_rate(0.81f), ms_to_rate(1.6f), ms_to_rate(3.3f), ms_to_rate(6.7f), ms_to_rate(13.0f), ms_to_rate(27.0f), ms_to_rate(53.0f), s_to_rate(0.11f), s_to_rate(0.21f), s_to_rate(0.43f), s_to_rate(0.86f), s_to_rate(1.7f), s_to_rate(3.4f), s_to_rate(6.8f), s_to_rate(14.0f), s_to_rate(27.0f), s_to_rate(55.0f), s_to_rate(109.0f), s_to_rate(219.0f), s_to_rate(438.0f), s_to_rate(876.0f), s_to_rate(1752.0f), s_to_rate(3504.0f), s_to_rate(7008.0f) }; // // // spu_device::reverb_preset spu_device::reverb_presets[]= { { "Reverb off", { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 } }, { "Room", { 0x007D, 0x005B, 0x6D80, 0x54B8, 0xBED0, 0x0000, 0x0000, 0xBA80, 0x5800, 0x5300, 0x04D6, 0x0333, 0x03F0, 0x0227, 0x0374, 0x01EF, 0x0334, 0x01B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01B4, 0x0136, 0x00B8, 0x005C, 0x8000, 0x8000 }, { // made up from studio small [used by BOF3] -0.3112f, 0.7832f, { { 20.7f, 31.3f,40.1711f,51.6803f }, { 21.7025f,30.2f,42.6655f,48.6691f } }, 0.8f, 0.0f, 0.0f } }, { "Studio Small", { 0x0033, 0x0025, 0x70F0, 0x4FA8, 0xBCE0, 0x4410, 0xC0F0, 0x9C00, 0x5280, 0x4EC0, 0x03E4, 0x031B, 0x03A4, 0x02AF, 0x0372, 0x0266, 0x031C, 0x025D, 0x025C, 0x018E, 0x022F, 0x0135, 0x01D2, 0x00B7, 0x018F, 0x00B5, 0x00B4, 0x0080, 0x004C, 0x0026, 0x8000, 0x8000 }, { // made up from studio large [used by Fighters Impact] -0.3112f, 0.7832f, { { 24.7f,44.3f,49.1711f,59.6803f }, { 27.7025f,38.2f,51.6655f,59.6691f } }, 0.6462f, 0.0f, 0.0f } }, { "Studio Medium", { 0x00B1, 0x007F, 0x70F0, 0x4FA8, 0xBCE0, 0x4510, 0xBEF0, 0xB4C0, 0x5280, 0x4EC0, 0x0904, 0x076B, 0x0824, 0x065F, 0x07A2, 0x0616, 0x076C, 0x05ED, 0x05EC, 0x042E, 0x050F, 0x0305, 0x0462, 0x02B7, 0x042F, 0x0265, 0x0264, 0x01B2, 0x0100, 0x0080, 0x8000, 0x8000 }, { // made up from studio large -0.3112f, 0.7832f, { { 37.7f,62.3f,82.1711f,71.6803f }, { 43.7025f,62.2f,85.6655f,78.6691f } }, 0.6462f, 0.0f, 0.0f } }, { "Studio Large", { 0x00E3, 0x00A9, 0x6F60, 0x4FA8, 0xBCE0, 0x4510, 0xBEF0, 0xA680, 0x5680, 0x52C0, 0x0DFB, 0x0B58, 0x0D09, 0x0A3C, 0x0BD9, 0x0973, 0x0B59, 0x08DA, 0x08D9, 0x05E9, 0x07EC, 0x04B0, 0x06EF, 0x03D2, 0x05EA, 0x031D, 0x031C, 0x0238, 0x0154, 0x00AA, 0x8000, 0x8000 }, { // tuned from xenogears ost -0.3112f, 0.7832f, { { 37.7f,62.3f,82.1711f,71.6803f }, { 43.7025f,62.2f,85.6655f,78.6691f } }, 0.8462f, 0.0f, 0.0f } }, { "Hall", { 0x01A5, 0x0139, 0x6000, 0x5000, 0x4C00, 0xB800, 0xBC00, 0xC000, 0x6000, 0x5C00, 0x15BA, 0x11BB, 0x14C2, 0x10BD, 0x11BC, 0x0DC1, 0x11C0, 0x0DC3, 0x0DC0, 0x09C1, 0x0BC4, 0x07C1, 0x0A00, 0x06CD, 0x09C2, 0x05C1, 0x05C0, 0x041A, 0x0274, 0x013A, 0x8000, 0x8000 }, { // made up -0.4222f, 0.8889f, { { 20.37f,79.63f,107.40f,94.44f }, { 31.47f,72.22f,116.66f,105.55f } }, 0.8889f, 0.0f, 0.0f } }, { "Space Echo", { 0x033D, 0x0231, 0x7E00, 0x5000, 0xB400, 0xB000, 0x4C00, 0xB000, 0x6000, 0x5400, 0x1ED6, 0x1A31, 0x1D14, 0x183B, 0x1BC2, 0x16B2, 0x1A32, 0x15EF, 0x15EE, 0x1055, 0x1334, 0x0F2D, 0x11F6, 0x0C5D, 0x1056, 0x0AE1, 0x0AE0, 0x07A2, 0x0464, 0x0232, 0x8000, 0x8000 }, { // made up 0.3951f, 0.7552f, { { 36.7138f, 134.6171f, 24.4758f, 194.0596f }, { 54.1932f, 90.9070f, 29.7174f, 200.0000f }, }, 0.9301f, 109.2563f, 0.4222f } }, { "Echo", { 0x0001, 0x0001, 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x8100, 0x0000, 0x0000, 0x1FFF, 0x0FFF, 0x1005, 0x0005, 0x0000, 0x0000, 0x1005, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1004, 0x1002, 0x0004, 0x0002, 0x8000, 0x8000 } }, { "Delay", { 0x0001, 0x0001, 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FFF, 0x0FFF, 0x1005, 0x0005, 0x0000, 0x0000, 0x1005, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1004, 0x1002, 0x0004, 0x0002, 0x8000, 0x8000, } }, { "Half Echo", { 0x0017, 0x0013, 0x70F0, 0x4FA8, 0xBCE0, 0x4510, 0xBEF0, 0x8500, 0x5F80, 0x54C0, 0x0371, 0x02AF, 0x02E5, 0x01DF, 0x02B0, 0x01D7, 0x0358, 0x026A, 0x01D6, 0x011E, 0x012D, 0x00B1, 0x011F, 0x0059, 0x01A0, 0x00E3, 0x0058, 0x0040, 0x0028, 0x0014, 0x8000, 0x8000 }, { // made up from space echo 0.3951f, 0.7552f, { { 36.7138f, 134.6171f, 24.4758f, 194.0596f }, { 54.1932f, 90.9070f, 29.7174f, 200.0000f }, }, 0.7301f, 109.2563f, 0.7222f } }, { nullptr } }; // // // float spu_device::get_linear_rate(const int n) { static constexpr int num_linear_rates=ARRAY_LENGTH(linear_rate); if (n>=num_linear_rates) return 0.0f; return linear_rate[n]*freq_multiplier; } float spu_device::get_linear_rate_neg_phase(const int n) { if (n==0) return ms_to_rate(0.04f); return get_linear_rate(n-1); } float spu_device::get_pos_exp_rate(const int n) { static constexpr int num_pos_exp_rates=ARRAY_LENGTH(pos_exp_rate); if (n>=num_pos_exp_rates) return 0.0f; return pos_exp_rate[n]*freq_multiplier; } float spu_device::get_pos_exp_rate_neg_phase(const int n) { if (n==0) return ms_to_rate(0.04f); return get_pos_exp_rate(n-1); } float spu_device::get_neg_exp_rate(const int n) { static constexpr int num_neg_exp_rates=ARRAY_LENGTH(neg_exp_rate); if (n>=num_neg_exp_rates) return 0.0f; return -neg_exp_rate[n]*freq_multiplier; } float spu_device::get_neg_exp_rate_neg_phase(const int n) { if (n==0) return -ms_to_rate(0.04f); return get_neg_exp_rate(n-1); } float spu_device::get_decay_rate(const int n) { return decay_rate[n]*freq_multiplier; } float spu_device::get_sustain_level(const int n) { return ((float)(n+1))/16.0f; } float spu_device::get_linear_release_rate(const int n) { static constexpr int num_linear_release_rates=ARRAY_LENGTH(linear_release_rate); if (n>=num_linear_release_rates) return 0.0f; return linear_release_rate[n]*freq_multiplier; } float spu_device::get_exp_release_rate(const int n) { static constexpr int num_exp_release_rates=ARRAY_LENGTH(exp_release_rate); if (n>=num_exp_release_rates) return 0.0f; return exp_release_rate[n]*freq_multiplier; } spu_device::reverb_preset *spu_device::find_reverb_preset(const unsigned short *param) { for (int i=0; reverb_presets[i].name; i++) { int j; for (j=0; j<32; j++) if (reverb_presets[i].param[j]!=param[j]) break; if (j==32) return &reverb_presets[i]; } return nullptr; }