|
1 | | -#include <algorithm> // std::clamp |
| 1 | +#include <algorithm> // std::clamp, std::min |
2 | 2 | #include <cmath> // pow |
3 | 3 | #include <filesystem> |
4 | 4 | #include <iostream> |
@@ -400,26 +400,28 @@ bool NeuralAmpModeler::SerializeState(IByteChunk& chunk) const |
400 | 400 | int NeuralAmpModeler::UnserializeState(const IByteChunk& chunk, int startPos) |
401 | 401 | { |
402 | 402 | WDL_String header; |
403 | | - startPos = chunk.GetStr(header, startPos); |
404 | | - // TODO: Handle legacy plugin serialized states. |
405 | | - // if strncmp (header.Get(), "###NeuralAmpModeler###") |
406 | | - //{ |
407 | | - // return UnserializeStateLegacy(header, startPos); // (We'll assume 0.7.9). |
408 | | - //} |
409 | | - WDL_String version; |
410 | | - startPos = chunk.GetStr(version, startPos); |
411 | | - // Version-specific loading here if needed. |
412 | | - // ... |
413 | | - |
414 | | - // Current version loading: |
415 | | - startPos = chunk.GetStr(mNAMPath, startPos); |
416 | | - startPos = chunk.GetStr(mIRPath, startPos); |
417 | | - int retcode = UnserializeParams(chunk, startPos); |
| 403 | + int pos = startPos; |
| 404 | + pos = chunk.GetStr(header, pos); |
| 405 | + // Unseralization: |
| 406 | + { |
| 407 | + // Handle legacy plugin serialized states: |
| 408 | + // In v0.7.9, this was the NAM filepath. So, if we dont' get the expected header, then we can attempt to unserialize |
| 409 | + // as v0.7.9: |
| 410 | + const char* kExpectedHeader = "###NeuralAmpModeler###"; |
| 411 | + if (strcmp(header.Get(), kExpectedHeader) == 0) |
| 412 | + { |
| 413 | + pos = _UnserializeStateCurrent(chunk, pos); |
| 414 | + } |
| 415 | + else |
| 416 | + { |
| 417 | + pos = _UnserializeStateLegacy_0_7_9(chunk, startPos); |
| 418 | + } |
| 419 | + } |
418 | 420 | if (mNAMPath.GetLength()) |
419 | 421 | _StageModel(mNAMPath); |
420 | 422 | if (mIRPath.GetLength()) |
421 | 423 | _StageIR(mIRPath); |
422 | | - return retcode; |
| 424 | + return pos; |
423 | 425 | } |
424 | 426 |
|
425 | 427 | void NeuralAmpModeler::OnUIOpen() |
@@ -804,6 +806,81 @@ void NeuralAmpModeler::_ProcessOutput(iplug::sample** inputs, iplug::sample** ou |
804 | 806 | #endif |
805 | 807 | } |
806 | 808 |
|
| 809 | +int NeuralAmpModeler::_UnserializeStateCurrent(const IByteChunk& chunk, int pos) |
| 810 | +{ |
| 811 | + WDL_String version; |
| 812 | + pos = chunk.GetStr(version, pos); |
| 813 | + // Post-v0.7.9 legacy loading here once needed: |
| 814 | + // ... |
| 815 | + |
| 816 | + // Current version loading: |
| 817 | + pos = chunk.GetStr(mNAMPath, pos); |
| 818 | + pos = chunk.GetStr(mIRPath, pos); |
| 819 | + pos = UnserializeParams(chunk, pos); |
| 820 | + return pos; |
| 821 | +} |
| 822 | + |
| 823 | +int NeuralAmpModeler::_UnserializeStateLegacy_0_7_9(const IByteChunk& chunk, int startPos) |
| 824 | +{ |
| 825 | + WDL_String dir; |
| 826 | + int pos = startPos; |
| 827 | + pos = chunk.GetStr(mNAMPath, pos); |
| 828 | + pos = chunk.GetStr(mIRPath, pos); |
| 829 | + auto unserialize = [&](const IByteChunk& chunk, int startPos) { |
| 830 | + // cf IPluginBase::UnserializeParams(const IByteChunk& chunk, int startPos) |
| 831 | + |
| 832 | + // These are the parameter names, in the order that they were serialized in v0.7.9. |
| 833 | + std::vector<std::string> oldParamNames{ |
| 834 | + "Input", "Gate", "Bass", "Middle", "Treble", "Output", "NoiseGateActive", "ToneStack", "OutNorm", "IRToggle"}; |
| 835 | + // These are their current names. |
| 836 | + // IF YOU CHANGE THE NAMES OF THE PARAMETERS, THEN YOU NEED TO UPDATE THIS! |
| 837 | + std::unordered_map<std::string, std::string> newNames{{"Gate", "Threshold"}}; |
| 838 | + auto getParamByOldName = [&, newNames](std::string& oldName) { |
| 839 | + std::string name = newNames.find(oldName) != newNames.end() ? newNames.at(oldName) : oldName; |
| 840 | + // Could use a map but eh |
| 841 | + for (int i = 0; i < kNumParams; i++) |
| 842 | + { |
| 843 | + IParam* param = GetParam(i); |
| 844 | + if (strcmp(param->GetName(), name.c_str()) == 0) |
| 845 | + { |
| 846 | + return param; |
| 847 | + } |
| 848 | + } |
| 849 | + return (IParam*)nullptr; |
| 850 | + }; |
| 851 | + TRACE |
| 852 | + int pos = startPos; |
| 853 | + ENTER_PARAMS_MUTEX |
| 854 | + int i = 0; |
| 855 | + for (auto it = oldParamNames.begin(); it != oldParamNames.end(); ++it, i++) |
| 856 | + { |
| 857 | + // Here's the change: instead of assuming that we can iterate through the parameters, we look for the one that now |
| 858 | + // holds this info. |
| 859 | + // IParam* pParam = mParams.Get(i); |
| 860 | + IParam* pParam = getParamByOldName(*it); |
| 861 | + |
| 862 | + double v = 0.0; |
| 863 | + pos = chunk.Get(&v, pos); |
| 864 | + // It's possible that future versions will not have all of the params of previous versions. If that's the case, |
| 865 | + // then this is a null ptr and we skip it. |
| 866 | + if (pParam) |
| 867 | + { |
| 868 | + pParam->Set(v); |
| 869 | + Trace(TRACELOC, "%d %s %f", i, pParam->GetName(), pParam->Value()); |
| 870 | + } |
| 871 | + else |
| 872 | + { |
| 873 | + Trace(TRACELOC, "%d NOT-FOUND", i); |
| 874 | + } |
| 875 | + } |
| 876 | + OnParamReset(kPresetRecall); |
| 877 | + LEAVE_PARAMS_MUTEX |
| 878 | + return pos; |
| 879 | + }; |
| 880 | + pos = unserialize(chunk, pos); |
| 881 | + return pos; |
| 882 | +} |
| 883 | + |
807 | 884 | void NeuralAmpModeler::_UpdateMeters(sample** inputPointer, sample** outputPointer, const size_t nFrames, |
808 | 885 | const size_t nChansIn, const size_t nChansOut) |
809 | 886 | { |
|
0 commit comments