device.cpp (16128B)
1 #include "device.h" 2 3 #include "dspMultiTI.h" 4 #include "dspSingleSnow.h" 5 #include "romfile.h" 6 7 #include "dsp56kEmu/jit.h" 8 9 #include "synthLib/deviceException.h" 10 #include "synthLib/midiToSysex.h" 11 12 #include <cstring> 13 14 #include "dspMemoryPatches.h" 15 16 namespace virusLib 17 { 18 Device::Device(const synthLib::DeviceCreateParams& _params, const bool _createDebugger/* = false*/) 19 : synthLib::Device(_params) 20 , m_rom(_params.romData, _params.romName, static_cast<DeviceModel>(_params.customData)) 21 , m_samplerate(getDeviceSamplerate(_params.preferredSamplerate, _params.hostSamplerate)) 22 { 23 m_frontpanelStateMidiEvent.source = synthLib::MidiEventSource::Internal; 24 25 DspSingle* dsp1; 26 createDspInstances(dsp1, m_dsp2, m_rom, m_samplerate); 27 m_dsp.reset(dsp1); 28 29 m_dsp->getAudio().setCallback([this](dsp56k::Audio*) 30 { 31 onAudioWritten(); 32 }, 0); 33 34 m_mc.reset(new Microcontroller(*m_dsp, m_rom, false)); 35 36 if(m_dsp2) 37 m_mc->addDSP(*m_dsp2, true); 38 39 bootDSPs(m_dsp.get(), m_dsp2, m_rom, _createDebugger); 40 41 // m_dsp->getMemory().saveAssembly("P.asm", 0, m_dsp->getMemory().sizeP(), true, false, m_dsp->getDSP().getPeriph(0), m_dsp->getDSP().getPeriph(1)); 42 43 switch(m_rom.getModel()) 44 { 45 case DeviceModel::A: 46 // The A does not send any event to notify that it has finished booting 47 dummyProcess(32); 48 m_dsp->disableESSI1(); 49 break; 50 case DeviceModel::B: 51 // Rack Classic doesn't send that it has finished booting either, wait a bit for the event but abort if it takes too long 52 { 53 constexpr auto maxRetries = 256; 54 uint32_t r=0; 55 while(!m_mc->dspHasBooted() && ++r <= maxRetries) 56 dummyProcess(8); 57 if(r >= maxRetries) 58 LOG("Timed out while waiting for the device to finish booting, expecting that it has booted"); 59 } 60 break; 61 default: 62 while(!m_mc->dspHasBooted()) 63 dummyProcess(8); 64 } 65 66 m_mc->sendInitControlCommands(); 67 68 dummyProcess(8); 69 70 m_mc->createDefaultState(); 71 } 72 73 Device::~Device() 74 { 75 m_dsp->getAudio().setCallback(nullptr,0); 76 m_mc.reset(); 77 m_dsp.reset(); 78 } 79 80 void Device::getSupportedSamplerates(std::vector<float>& _dst) const 81 { 82 switch (m_rom.getModel()) 83 { 84 default: 85 case DeviceModel::A: 86 case DeviceModel::B: 87 case DeviceModel::C: 88 _dst.push_back(12000000.0f / 256.0f); 89 break; 90 case DeviceModel::Snow: 91 case DeviceModel::TI: 92 case DeviceModel::TI2: 93 _dst.push_back(32000.0f); 94 _dst.push_back(44100.0f); 95 _dst.push_back(48000.0f); 96 _dst.push_back(64000.0f); 97 _dst.push_back(88200.0f); 98 _dst.push_back(96000.0f); 99 break; 100 } 101 } 102 103 void Device::getPreferredSamplerates(std::vector<float>& _dst) const 104 { 105 switch (m_rom.getModel()) 106 { 107 default: 108 case DeviceModel::ABC: 109 getSupportedSamplerates(_dst); 110 break; 111 case DeviceModel::Snow: 112 case DeviceModel::TI: 113 case DeviceModel::TI2: 114 _dst.push_back(44100.0f); 115 _dst.push_back(48000.0f); 116 break; 117 } 118 } 119 120 float Device::getSamplerate() const 121 { 122 return m_samplerate; 123 } 124 125 bool Device::setSamplerate(const float _samplerate) 126 { 127 if(!synthLib::Device::setSamplerate(_samplerate)) 128 return false; 129 m_samplerate = _samplerate; 130 configureDSP(*m_dsp, m_rom, m_samplerate); 131 if(m_dsp2) 132 configureDSP(*m_dsp2, m_rom, m_samplerate); 133 m_mc->setSamplerate(_samplerate); 134 return true; 135 } 136 137 bool Device::isValid() const 138 { 139 return m_rom.isValid(); 140 } 141 142 void Device::process(const synthLib::TAudioInputs& _inputs, const synthLib::TAudioOutputs& _outputs, size_t _size, const std::vector<synthLib::SMidiEvent>& _midiIn, std::vector<synthLib::SMidiEvent>& _midiOut) 143 { 144 m_frontpanelStateDSP.clear(); 145 146 synthLib::Device::process(_inputs, _outputs, _size, _midiIn, _midiOut); 147 148 if(m_rom.isTIFamily()) 149 { 150 // Apparently this LED model did not want a completely closed PWM 151 constexpr auto minimumValue = 0.785339653f; 152 constexpr auto maximumValue = 0.999146f; 153 154 if(m_rom.getModel() == DeviceModel::Snow) 155 { 156 m_frontpanelStateDSP.m_lfoPhases[0] = 1.f; 157 m_frontpanelStateDSP.m_lfoPhases[1] = 1.f; 158 m_frontpanelStateDSP.m_lfoPhases[2] = 1.f; 159 m_frontpanelStateDSP.m_logo = 1.f; 160 161 FrontpanelState::updatePhaseFromTimer(m_frontpanelStateDSP.m_bpm, m_dsp->getDSP(), 1, 0.83f, 1.0f); 162 } 163 else 164 { 165 m_frontpanelStateDSP.updateLfoPhaseFromTimer(m_dsp->getDSP(), 0, 1, minimumValue, maximumValue); 166 m_frontpanelStateDSP.updateLfoPhaseFromTimer(m_dsp->getDSP(), 1, 2, minimumValue, maximumValue); 167 m_frontpanelStateDSP.updateLfoPhaseFromTimer(m_dsp->getDSP(), 2, 0, minimumValue, maximumValue); 168 169 FrontpanelState::updatePhaseFromTimer(m_frontpanelStateDSP.m_logo, m_dsp2->getDSP(), 0, 0.963654f, 1); 170 } 171 } 172 else 173 { 174 m_frontpanelStateDSP.updateLfoPhaseFromTimer(m_dsp->getDSP(), 0, 2); // TIMER 1 = ACI = LFO 1 LED 175 m_frontpanelStateDSP.updateLfoPhaseFromTimer(m_dsp->getDSP(), 1, 1); // TIMER 2 = ADO = LFO 2/3 LED 176 } 177 178 m_numSamplesProcessed += static_cast<uint32_t>(_size); 179 180 m_frontpanelStateDSP.toMidiEvent(m_frontpanelStateMidiEvent); 181 _midiOut.push_back(m_frontpanelStateMidiEvent); 182 } 183 184 #if !SYNTHLIB_DEMO_MODE 185 bool Device::getState(std::vector<uint8_t>& _state, const synthLib::StateType _type) 186 { 187 return m_mc->getState(_state, _type); 188 } 189 190 bool Device::setState(const std::vector<uint8_t>& _state, synthLib::StateType _type) 191 { 192 return m_mc->setState(_state, _type); 193 } 194 195 bool Device::setStateFromUnknownCustomData(const std::vector<uint8_t>& _state) 196 { 197 std::vector<synthLib::SMidiEvent> messages; 198 199 if(parseTIcontrolPreset(messages, _state)) 200 return m_mc->setState(messages); 201 202 std::vector<std::vector<uint8_t>> sysexMessages; 203 synthLib::MidiToSysex::splitMultipleSysex(sysexMessages, _state, false); 204 205 if(sysexMessages.empty()) 206 return false; 207 208 for (const auto& sysexMessage : sysexMessages) 209 messages.emplace_back().sysex = sysexMessage; 210 211 return m_mc->setState(messages); 212 } 213 #endif 214 215 bool Device::find4CC(uint32_t& _offset, const std::vector<uint8_t>& _data, const std::string_view& _4cc) 216 { 217 if(_data.size() < (_offset + _4cc.size())) 218 return false; 219 220 for(uint32_t i=_offset; i<_data.size() - _4cc.size(); ++i) 221 { 222 bool valid = true; 223 for(size_t j=0; j<_4cc.size(); ++j) 224 { 225 if(static_cast<char>(_data[i + j]) == _4cc[j]) 226 continue; 227 valid = false; 228 break; 229 } 230 if(valid) 231 { 232 _offset = i; 233 return true; 234 } 235 } 236 return false; 237 } 238 239 bool Device::parseTIcontrolPreset(std::vector<synthLib::SMidiEvent>& _events, const std::vector<uint8_t>& _state) 240 { 241 if(_state.size() < 8) 242 return false; 243 244 uint32_t readPos = 0; 245 246 uint32_t numFound = 0; 247 248 while(readPos < _state.size() - 4) 249 { 250 if(!find4CC(readPos, _state, "MIDI")) 251 break; 252 253 if(readPos >= _state.size()) 254 break; 255 256 auto readLen = [&_state](const size_t _offset) -> uint32_t 257 { 258 if(_offset + 4 > _state.size()) 259 return 0; 260 const uint32_t o = 261 (static_cast<uint32_t>(_state[_offset+0]) << 24) | 262 (static_cast<uint32_t>(_state[_offset+1]) << 16) | 263 (static_cast<uint32_t>(_state[_offset+2]) << 8) | 264 (static_cast<uint32_t>(_state[_offset+3])); 265 return o; 266 }; 267 268 auto nextLen = [&readPos, &readLen]() -> uint32_t 269 { 270 const auto len = readLen(readPos); 271 readPos += 4; 272 return len; 273 }; 274 275 const auto dataLen = nextLen(); 276 277 if(dataLen + readPos > _state.size()) 278 break; 279 280 const auto controllerAssignmentsLen = nextLen(); 281 282 readPos += controllerAssignmentsLen; 283 284 while(readPos < _state.size()) 285 { 286 const auto midiDataLen = nextLen(); 287 288 if(!midiDataLen) 289 break; 290 291 if((readPos + midiDataLen) > _state.size()) 292 break; 293 294 synthLib::SMidiEvent& e = _events.emplace_back(); 295 296 e.sysex.assign(_state.begin() + readPos, _state.begin() + readPos + midiDataLen); 297 298 if(e.sysex.front() != 0xf0) 299 { 300 assert(e.sysex.size() <= 3); 301 e.a = e.sysex[0]; 302 if(e.sysex.size() > 1) 303 e.b = e.sysex[1]; 304 if(e.sysex.size() > 2) 305 e.c = e.sysex[2]; 306 307 e.sysex.clear(); 308 } 309 310 readPos += midiDataLen; 311 312 if(!e.sysex.empty()) 313 ++numFound; 314 } 315 } 316 317 return numFound > 0; 318 } 319 320 bool Device::parsePowercorePreset(std::vector<std::vector<uint8_t>>& _sysexPresets, const std::vector<uint8_t>& _data) 321 { 322 uint32_t off = 0; 323 324 uint32_t numFound = 0; 325 326 while(off < _data.size() - 4) 327 { 328 // VST2 fxp/fxb chunk must exist 329 if(!find4CC(off, _data, "CcnK")) 330 break; 331 332 off += 4; 333 334 uint32_t pos; 335 336 // fxp or fxb? 337 if(find4CC(off, _data, "FPCh")) 338 pos = off + 0x34; // fxp 339 else if(find4CC(off, _data, "FBCh")) 340 pos = off + 0x98; // fxb 341 else 342 continue; 343 344 if(pos >= _data.size()) 345 break; 346 347 ++pos; // skip first byte, version? 348 349 constexpr uint32_t presetSize = 256; // presets seem to be stored without sysex packaging 350 constexpr uint32_t padding = 5; // five unknown bytes betweeen two presets 351 352 uint8_t programIndex = 0; 353 354 while((pos + presetSize) <= static_cast<uint32_t>(_data.size())) 355 { 356 Microcontroller::TPreset p; 357 memcpy(&p.front(), &_data[pos], presetSize); 358 359 const auto version = Microcontroller::getPresetVersion(p); 360 if(version != C) 361 break; 362 const auto name = ROMFile::getSingleName(p); 363 if(name.size() != 10) 364 break; 365 366 // pack into sysex 367 std::vector<uint8_t>& sysex = _sysexPresets.emplace_back(std::vector<uint8_t>{0xf0, 0x00, 0x20, 0x33, 0x01, OMNI_DEVICE_ID, 0x10, 0x01, programIndex}); 368 sysex.insert(sysex.end(), _data.begin() + pos, _data.begin() + pos + presetSize); 369 sysex.push_back(Microcontroller::calcChecksum(sysex)); 370 sysex.push_back(0xf7); 371 372 ++numFound; 373 374 ++programIndex; 375 pos += presetSize; 376 pos += padding; 377 } 378 off = pos; 379 } 380 381 return numFound > 0; 382 } 383 384 bool Device::parseVTIBackup(std::vector<std::vector<uint8_t>>& _sysexPresets, const std::vector<uint8_t>& _data) 385 { 386 if(_data.size() < 512) 387 return false; 388 389 // first 11 bytes are the serial number. Check if they're all ASCII 390 for(size_t i=0; i<11; ++i) 391 { 392 if(_data[i] < 32 || _data[i] > 127) 393 return false; 394 } 395 396 constexpr size_t presetSize = sizeof(Microcontroller::TPreset); 397 Microcontroller::TPreset preset; 398 399 constexpr uint32_t maxPresets = (4 + 26) * 128; // 4x RAM banks, 26x ROM banks, 128 patches per bank 400 401 uint32_t presetIdx = 0; 402 403 // presets start at $20 404 // They are "raw" presets, i.e. 512 bytes of preset data each 405 // The sysex packaging is missing, i.e. the single dump header, the checksums and the sysex terminator 406 for(size_t i=0x20; i<_data.size() - presetSize; i += presetSize) 407 { 408 memcpy(preset.data(), &_data[i], presetSize); 409 410 const auto name = ROMFile::getSingleName(preset); 411 412 if(name.empty()) 413 break; 414 415 auto& sysex = _sysexPresets.emplace_back(std::vector<uint8_t>{ 416 0xf0, 0x00, 0x20, 0x33, 0x01, OMNI_DEVICE_ID, DUMP_SINGLE, 417 static_cast<uint8_t>((presetIdx >> 7) & 0x7f), 418 static_cast<uint8_t>(presetIdx & 0x7f)}); 419 420 sysex.reserve(9 + 256 + 1 + 256 + 2); // header, 256 preset bytes, 1st checksum, 256 preset bytes, 2nd checksum, EOX 421 422 for(size_t j=0; j<256; ++j) 423 sysex.push_back(preset[j]); 424 sysex.push_back(Microcontroller::calcChecksum(sysex)); 425 for(size_t j=256; j<512; ++j) 426 sysex.push_back(preset[j]); 427 sysex.push_back(Microcontroller::calcChecksum(sysex)); 428 sysex.push_back(0xf7); 429 430 ++presetIdx; 431 432 if(presetIdx == maxPresets) 433 break; 434 } 435 436 return true; 437 } 438 439 uint32_t Device::getInternalLatencyMidiToOutput() const 440 { 441 // Note that this is an average value, midi latency drifts in a range of roughly +/- 61 samples 442 constexpr auto latency = 324; 443 444 if(m_rom.isTIFamily()) 445 return latency - 108; // TI seems to have improved a bit 446 447 return latency; 448 } 449 450 uint32_t Device::getInternalLatencyInputToOutput() const 451 { 452 // Measured by using an input init patch. Sent a click to the input and recorded both the input 453 // as direct signal plus the Virus output and checking the resulting latency in a wave editor 454 return 384; 455 } 456 457 uint32_t Device::getChannelCountIn() 458 { 459 return 2; 460 } 461 462 uint32_t Device::getChannelCountOut() 463 { 464 return m_rom.isTIFamily() ? 12 : 6; 465 } 466 467 void Device::createDspInstances(DspSingle*& _dspA, DspSingle*& _dspB, const ROMFile& _rom, const float _samplerate) 468 { 469 if(_rom.getModel() == DeviceModel::Snow) 470 { 471 _dspA = new DspSingleSnow(); 472 } 473 else if(_rom.getModel() == DeviceModel::TI || _rom.getModel() == DeviceModel::TI2) 474 { 475 auto* dsp = new DspMultiTI(); 476 _dspA = dsp; 477 _dspB = &dsp->getDSP2(); 478 } 479 else 480 { 481 _dspA = new DspSingle(_rom.isTIFamily() ? 0x100000 : 0x040000, _rom.isTIFamily(), nullptr, _rom.getModel() == DeviceModel::A); 482 } 483 484 configureDSP(*_dspA, _rom, _samplerate); 485 486 if(_dspB) 487 configureDSP(*_dspB, _rom, _samplerate); 488 } 489 490 bool Device::sendMidi(const synthLib::SMidiEvent& _ev, std::vector<synthLib::SMidiEvent>& _response) 491 { 492 if(_ev.sysex.empty()) 493 { 494 // LOG("MIDI: " << std::hex << (int)_ev.a << " " << (int)_ev.b << " " << (int)_ev.c); 495 auto ev = _ev; 496 ev.offset += m_numSamplesProcessed + getExtraLatencySamples(); 497 return m_mc->sendMIDI(ev, &m_frontpanelStateDSP); 498 } 499 500 std::vector<synthLib::SMidiEvent> responses; 501 502 if(!m_mc->sendSysex(_ev.sysex, responses, _ev.source)) 503 return false; 504 505 for (const auto& response : responses) 506 _response.emplace_back(response); 507 508 return true; 509 } 510 511 void Device::readMidiOut(std::vector<synthLib::SMidiEvent>& _midiOut) 512 { 513 m_mc->readMidiOut(_midiOut); 514 } 515 516 void Device::processAudio(const synthLib::TAudioInputs& _inputs, const synthLib::TAudioOutputs& _outputs, size_t _samples) 517 { 518 constexpr auto maxBlockSize = dsp56k::Audio::RingBufferSize>>2; 519 520 auto inputs(_inputs); 521 auto outputs(_outputs); 522 523 while(_samples > maxBlockSize) 524 { 525 m_dsp->processAudio(inputs, outputs, maxBlockSize, getExtraLatencySamples()); 526 527 _samples -= maxBlockSize; 528 529 for (auto& input : inputs) 530 { 531 if(input) 532 input += maxBlockSize; 533 } 534 535 for (auto& output : outputs) 536 { 537 if(output) 538 output += maxBlockSize; 539 } 540 } 541 542 m_dsp->processAudio(inputs, outputs, _samples, getExtraLatencySamples()); 543 } 544 545 void Device::onAudioWritten() 546 { 547 m_mc->getMidiQueue(0).onAudioWritten(); 548 m_mc->process(); 549 } 550 551 void Device::configureDSP(DspSingle& _dsp, const ROMFile& _rom, const float _samplerate) 552 { 553 auto& jit = _dsp.getJIT(); 554 auto conf = jit.getConfig(); 555 556 if(_rom.isTIFamily()) 557 { 558 auto& clock = _dsp.getPeriphX().getEsaiClock(); 559 560 const auto sr = static_cast<int>(_samplerate); 561 562 clock.setExternalClockFrequency(std::min(sr, 48000) * 256); 563 564 if(_rom.getModel() != DeviceModel::Snow) 565 { 566 clock.setSamplerate(sr * 3); 567 clock.setEsaiDivider(&_dsp.getPeriphY().getEsai(), 0); 568 clock.setEsaiDivider(&_dsp.getPeriphX().getEsai(), 2); 569 } 570 571 conf.aguSupportBitreverse = true; 572 conf.maxDoIterations = 32; 573 574 clock.setClockSource(dsp56k::EsaiClock::ClockSource::Cycles); 575 } 576 else 577 { 578 conf.aguSupportBitreverse = false; 579 } 580 581 jit.setConfig(conf); 582 } 583 584 std::thread Device::bootDSP(DspSingle& _dsp, const ROMFile& _rom, const bool _createDebugger) 585 { 586 auto res = _rom.bootDSP(_dsp); 587 _dsp.startDSPThread(_createDebugger); 588 return res; 589 } 590 591 void Device::bootDSPs(DspSingle* _dspA, DspSingle* _dspB, const ROMFile& _rom, bool _createDebugger) 592 { 593 auto loader = bootDSP(*_dspA, _rom, _createDebugger); 594 595 if(_dspB) 596 { 597 auto loader2 = bootDSP(*_dspB, _rom, false); 598 loader2.join(); 599 } 600 601 loader.join(); 602 603 // applyDspMemoryPatches(_dspA, _dspB, _rom); 604 } 605 606 bool Device::setDspClockPercent(const uint32_t _percent) 607 { 608 if(!m_dsp) 609 return false; 610 611 bool res = m_dsp->getEsxiClock().setSpeedPercent(_percent); 612 613 if(m_dsp2) 614 res &= m_dsp2->getEsxiClock().setSpeedPercent(_percent); 615 616 return res; 617 } 618 619 uint32_t Device::getDspClockPercent() const 620 { 621 return !m_dsp ? 0 : m_dsp->getEsxiClock().getSpeedPercent(); 622 } 623 624 uint64_t Device::getDspClockHz() const 625 { 626 return !m_dsp ? 0 : m_dsp->getEsxiClock().getSpeedInHz(); 627 } 628 629 void Device::applyDspMemoryPatches(const DspSingle* _dspA, const DspSingle* _dspB, const ROMFile& _rom) 630 { 631 DspMemoryPatches::apply(_dspA, _rom.getHash()); 632 DspMemoryPatches::apply(_dspB, _rom.getHash()); 633 } 634 635 void Device::applyDspMemoryPatches() const 636 { 637 applyDspMemoryPatches(m_dsp.get(), m_dsp2, m_rom); 638 } 639 }