weData.cpp (11789B)
1 #include "weData.h" 2 3 #include "xtController.h" 4 5 #include "baseLib/filesystem.h" 6 7 #include "synthLib/midiToSysex.h" 8 9 #include "xtLib/xtState.h" 10 11 namespace xtJucePlugin 12 { 13 WaveEditorData::WaveEditorData(Controller& _controller, const std::string& _cacheDir) : m_controller(_controller), m_cacheDir(baseLib::filesystem::validatePath(_cacheDir)) 14 { 15 loadRomCache(); 16 loadUserData(); 17 } 18 19 void WaveEditorData::requestData() 20 { 21 if(isWaitingForData()) 22 return; 23 24 for(uint16_t i=0; i<static_cast<uint16_t>(m_tables.size()); ++i) 25 { 26 const auto id = xt::TableId(i); 27 if(!m_tables[i] && !xt::wave::isAlgorithmicTable(id)) 28 { 29 requestTable(id); 30 return; 31 } 32 } 33 34 for(uint16_t i=0; i<static_cast<uint16_t>(m_romWaves.size()); ++i) 35 { 36 const auto id = xt::WaveId(i); 37 if(!m_romWaves[i]) 38 { 39 requestWave(id); 40 return; 41 } 42 } 43 44 for(uint32_t i=0; i<m_ramWaves.size(); ++i) 45 { 46 if(!m_ramWaves[i]) 47 { 48 requestWave(xt::WaveId(static_cast<uint16_t>(i + xt::wave::g_firstRamWaveIndex))); 49 return; 50 } 51 } 52 53 onAllDataReceived(); 54 } 55 56 void WaveEditorData::onReceiveWave(const std::vector<uint8_t>& _msg, const bool _sendToDevice) 57 { 58 if(!parseMidi(_msg)) 59 return; 60 61 const auto command = toCommand(_msg); 62 const auto id = xt::WaveId(toIndex(_msg)); 63 64 if(command == xt::SysexCommand::WaveDump && m_currentWaveRequestIndex == id) 65 { 66 m_currentWaveRequestIndex = g_invalidWaveIndex; 67 requestData(); 68 } 69 70 if(_sendToDevice) 71 sendWaveToDevice(id); 72 } 73 74 void WaveEditorData::onReceiveTable(const std::vector<uint8_t>& _msg, const bool _sendToDevice) 75 { 76 if(!parseMidi(_msg)) 77 return; 78 79 const auto command = toCommand(_msg); 80 const auto id = xt::TableId(toIndex(_msg)); 81 82 if(command == xt::SysexCommand::WaveCtlDump && m_currentTableRequestIndex == id) 83 { 84 m_currentTableRequestIndex = g_invalidTableIndex; 85 requestData(); 86 } 87 88 if(_sendToDevice) 89 sendTableToDevice(id); 90 } 91 92 std::optional<xt::WaveData> WaveEditorData::getWave(const xt::WaveId _waveId) const 93 { 94 auto i = _waveId.rawId(); 95 96 if(i < m_romWaves.size()) 97 return m_romWaves[i]; 98 99 if(i < xt::wave::g_firstRamWaveIndex) 100 return {}; 101 i -= xt::wave::g_firstRamWaveIndex; 102 if(i >= m_ramWaves.size()) 103 return {}; 104 105 return m_ramWaves[i]; 106 } 107 108 xt::WaveId WaveEditorData::getWaveId(const xt::TableId _tableId, const xt::TableIndex _tableIndex) const 109 { 110 if(_tableId.rawId() >= m_tables.size()) 111 return g_invalidWaveIndex; 112 if(_tableIndex.rawId() >= std::tuple_size<xt::TableData>()) 113 return g_invalidWaveIndex; 114 const auto table = m_tables[_tableId.rawId()]; 115 if(!table) 116 return g_invalidWaveIndex; 117 return (*table)[_tableIndex.rawId()]; 118 } 119 120 std::optional<xt::TableData> WaveEditorData::getTable(const xt::TableId _tableId) const 121 { 122 if(_tableId.rawId() >= m_tables.size()) 123 return {}; 124 return m_tables[_tableId.rawId()]; 125 } 126 127 bool WaveEditorData::swapTableEntries(const xt::TableId _tableId, const xt::TableIndex _indexA, const xt::TableIndex _indexB) 128 { 129 if(_indexA == _indexB) 130 return false; 131 if(_tableId.rawId() >= m_tables.size()) 132 return false; 133 const auto& table = m_tables[_tableId.rawId()]; 134 if(!table) 135 return false; 136 auto t = *table; 137 std::swap(t[_indexA.rawId()], t[_indexB.rawId()]); 138 m_tables[_tableId.rawId()] = t; 139 onTableChanged(_tableId); 140 saveTable(_tableId); 141 return true; 142 } 143 144 bool WaveEditorData::setTableWave(const xt::TableId _tableId, const xt::TableIndex _tableIndex, const xt::WaveId _waveId) 145 { 146 if(_tableId.rawId() >= m_tables.size()) 147 return false; 148 const auto& table = m_tables[_tableId.rawId()]; 149 if(!table) 150 return false; 151 auto t = *table; 152 if(_tableIndex.rawId() >= t.size()) 153 return false; 154 if(t[_tableIndex.rawId()] == _waveId) 155 return false; 156 t[_tableIndex.rawId()] = _waveId; 157 m_tables[_tableId.rawId()] = t; 158 onTableChanged(_tableId); 159 saveTable(_tableId); 160 return true; 161 } 162 163 bool WaveEditorData::copyTable(const xt::TableId _dest, const xt::TableId _source) 164 { 165 const auto dst = _dest.rawId(); 166 const auto src = _source.rawId(); 167 168 if(dst >= m_tables.size() || src >= m_tables.size()) 169 return false; 170 171 auto& srcTable = m_tables[src]; 172 if(!srcTable) 173 return false; 174 m_tables[dst] = *srcTable; 175 onTableChanged(_dest); 176 saveTable(_dest); 177 return true; 178 } 179 180 bool WaveEditorData::copyWave(const xt::WaveId _dest, const xt::WaveId _source) 181 { 182 const auto sourceWave = getWave(_source); 183 if(!sourceWave) 184 return false; 185 return setWave(_dest, *sourceWave); 186 } 187 188 std::optional<xt::WaveData> WaveEditorData::getWave(const xt::TableId _tableIndex, const xt::TableIndex _indexInTable) const 189 { 190 return getWave(getWaveId(_tableIndex, _indexInTable)); 191 } 192 193 bool WaveEditorData::setWave(xt::WaveId _id, const xt::WaveData& _data) 194 { 195 auto i = _id.rawId(); 196 197 if(i < m_romWaves.size()) 198 { 199 m_romWaves[i] = _data; 200 onWaveChanged(_id); 201 return true; 202 } 203 204 if(i < xt::wave::g_firstRamWaveIndex) 205 return false; 206 207 i -= xt::wave::g_firstRamWaveIndex; 208 209 if(i >= m_ramWaves.size()) 210 return false; 211 212 m_ramWaves[i] = _data; 213 onWaveChanged(_id); 214 saveWave(_id); 215 return true; 216 } 217 218 bool WaveEditorData::setTable(const xt::TableId _id, const xt::TableData& _data) 219 { 220 if(_id.rawId() >= m_tables.size()) 221 return false; 222 223 m_tables[_id.rawId()] = _data; 224 onTableChanged(_id); 225 saveTable(_id); 226 return true; 227 } 228 229 bool WaveEditorData::sendTableToDevice(const xt::TableId _id) const 230 { 231 const auto index = _id.rawId(); 232 if(index >= m_tables.size()) 233 return false; 234 auto& table = m_tables[index]; 235 if(!table) 236 return false; 237 auto& t = *table; 238 const auto sysex = xt::State::createTableData(t, index, false); 239 m_controller.sendSysEx(sysex); 240 return true; 241 } 242 243 bool WaveEditorData::sendWaveToDevice(const xt::WaveId _id) const 244 { 245 const auto wave = getWave(_id); 246 if(!wave) 247 return false; 248 const auto sysex = xt::State::createWaveData(*wave, _id.rawId(), false); 249 m_controller.sendSysEx(sysex); 250 return true; 251 } 252 253 void WaveEditorData::getWaveDataForSingle(std::vector<xt::SysEx>& _results, const xt::SysEx& _single) const 254 { 255 const auto tableId = xt::State::getWavetableFromSingleDump(_single); 256 257 if(xt::wave::isReadOnly(tableId)) 258 return; 259 260 const auto table = getTable(tableId); 261 262 if(!table) 263 return; 264 265 auto& t = *table; 266 267 auto waves = xt::State::getWavesForTable(t); 268 269 for (const auto waveId : waves) 270 { 271 if(!xt::wave::isValidWaveIndex(waveId.rawId())) 272 continue; 273 274 if(xt::wave::isReadOnly(waveId)) 275 continue; 276 277 const auto wave = getWave(waveId); 278 if(!wave) 279 continue; 280 281 const auto& w = *wave; 282 283 _results.emplace_back(xt::State::createWaveData(w, waveId.rawId(), false)); 284 } 285 286 _results.emplace_back(xt::State::createTableData(t, tableId.rawId(), false)); 287 } 288 289 bool WaveEditorData::requestWave(const xt::WaveId _id) 290 { 291 if(isWaitingForData()) 292 return false; 293 294 if(!m_controller.requestWave(_id.rawId())) 295 return false; 296 m_currentWaveRequestIndex = _id; 297 return true; 298 } 299 300 bool WaveEditorData::requestTable(const xt::TableId _id) 301 { 302 if(isWaitingForData()) 303 return false; 304 305 if(!m_controller.requestTable(_id.rawId())) 306 return false; 307 m_currentTableRequestIndex = _id; 308 return true; 309 } 310 311 void WaveEditorData::onAllDataReceived() const 312 { 313 saveRomCache(); 314 } 315 316 xt::SysexCommand WaveEditorData::toCommand(const std::vector<uint8_t>& _sysex) 317 { 318 return static_cast<xt::SysexCommand>(_sysex[4]); 319 } 320 321 uint16_t WaveEditorData::toIndex(const std::vector<uint8_t>& _sysex) 322 { 323 const uint32_t hh = _sysex[5]; 324 const uint32_t ll = _sysex[6]; 325 326 const uint16_t index = static_cast<uint16_t>((hh << 7) | ll); 327 328 return index; 329 } 330 331 bool WaveEditorData::parseMidi(const std::vector<uint8_t>& _sysex) 332 { 333 if(_sysex.size() < 10 || _sysex.front() != 0xf0 || _sysex.back() != 0xf7) 334 return false; 335 if(_sysex[1] != wLib::IdWaldorf) 336 return false; 337 if(_sysex[2] != xt::IdMw2) 338 return false; 339 340 const auto cmd = toCommand(_sysex); 341 const auto index = toIndex(_sysex); 342 343 switch (cmd) // NOLINT(clang-diagnostic-switch-enum) 344 { 345 case xt::SysexCommand::WaveDump: 346 { 347 if(!xt::wave::isValidWaveIndex(index)) 348 return false; 349 350 const auto id = xt::WaveId(index); 351 352 xt::WaveData data; 353 xt::State::parseWaveData(data, _sysex); 354 355 setWave(id, data); 356 } 357 return true; 358 case xt::SysexCommand::WaveCtlDump: 359 { 360 if(!xt::wave::isValidTableIndex(index)) 361 return false; 362 363 const auto id = xt::TableId(index); 364 365 xt::TableData table; 366 367 xt::State::parseTableData(table, _sysex); 368 369 setTable(id, table); 370 } 371 return true; 372 default: 373 return false; 374 } 375 } 376 377 std::string WaveEditorData::getRomCacheFilename() const 378 { 379 return m_cacheDir + "romWaves.syx"; 380 } 381 382 void WaveEditorData::saveRomCache() const 383 { 384 const auto romWaves = getRomCacheFilename(); 385 386 std::vector<uint8_t> data; 387 388 for(uint16_t i=0; i<static_cast<uint16_t>(m_romWaves.size()); ++i) 389 { 390 auto& romWave = m_romWaves[i]; 391 assert(romWave); 392 if(!romWave) 393 continue; 394 auto sysex = xt::State::createWaveData(*romWave, i, false); 395 data.insert(data.end(), sysex.begin(), sysex.end()); 396 } 397 398 assert(xt::wave::g_firstRamTableIndex < m_tables.size()); 399 400 for(uint16_t i=0; i<xt::wave::g_firstRamTableIndex; ++i) 401 { 402 auto& table = m_tables[i]; 403 assert(table || xt::wave::isAlgorithmicTable(xt::TableId(i))); 404 if(!table) 405 continue; 406 auto sysex = xt::State::createTableData(*table, i, false); 407 data.insert(data.end(), sysex.begin(), sysex.end()); 408 } 409 410 baseLib::filesystem::createDirectory(m_cacheDir); 411 baseLib::filesystem::writeFile(romWaves, data); 412 } 413 414 void WaveEditorData::loadRomCache() 415 { 416 std::vector<uint8_t> data; 417 if(!baseLib::filesystem::readFile(data, getRomCacheFilename())) 418 return; 419 420 std::vector<std::vector<uint8_t>> sysexMessages; 421 synthLib::MidiToSysex::splitMultipleSysex(sysexMessages, data); 422 for (const auto& sysex : sysexMessages) 423 parseMidi(sysex); 424 } 425 426 void WaveEditorData::saveTable(const xt::TableId _id) const 427 { 428 if (xt::wave::isReadOnly(_id)) 429 return; // we don't want to store rom tables 430 431 const auto table = getTable(_id); 432 if (!table) 433 return; 434 435 const auto filename = toFilename(_id); 436 const auto data = xt::State::createTableData(*table, _id.rawId(), true); 437 baseLib::filesystem::writeFile(m_cacheDir + filename, data); 438 } 439 440 void WaveEditorData::saveWave(const xt::WaveId _id) const 441 { 442 if (xt::wave::isReadOnly(_id)) 443 return; // we don't want to store rom waves 444 445 const auto wave = getWave(_id); 446 if (!wave) 447 return; 448 449 const auto filename = toFilename(_id); 450 const auto data = xt::State::createWaveData(*wave, _id.rawId(), true); 451 baseLib::filesystem::writeFile(m_cacheDir + filename, data); 452 } 453 454 void WaveEditorData::loadUserData() 455 { 456 for (uint16_t i = 0; i < static_cast<uint16_t>(m_ramWaves.size()); ++i) 457 { 458 const auto id = xt::WaveId(i + xt::wave::g_firstRamWaveIndex); 459 const auto filename = toFilename(id); 460 std::vector<uint8_t> data; 461 if (!baseLib::filesystem::readFile(data, m_cacheDir + filename)) 462 continue; 463 xt::WaveData wave; 464 if (xt::State::parseWaveData(wave, data)) 465 m_ramWaves[i] = wave; 466 } 467 468 for (uint16_t i = xt::wave::g_firstRamTableIndex; i < xt::wave::g_tableCount; ++i) 469 { 470 const auto id = xt::TableId(i); 471 const auto filename = toFilename(id); 472 std::vector<uint8_t> data; 473 if (!baseLib::filesystem::readFile(data, m_cacheDir + filename)) 474 continue; 475 xt::TableData table; 476 if (xt::State::parseTableData(table, data)) 477 m_tables[i] = table; 478 } 479 } 480 481 std::string WaveEditorData::toFilename(const xt::WaveId _id) 482 { 483 return "wave_" + std::to_string(_id.rawId()) + ".syx"; 484 } 485 486 std::string WaveEditorData::toFilename(const xt::TableId _id) 487 { 488 std::stringstream ss; 489 ss << "table_" << std::setw(3) << std::setfill('0') << _id.rawId() << ".syx"; 490 return ss.str(); 491 } 492 }