2929#include " ../../application/service/side_chain_service.hpp"
3030#include " ../../domain/column_settings.hpp"
3131#include " ../../domain/devices/sampler_device.hpp"
32+ #include " ../../domain/devices/synth_device.hpp"
3233#include " ../../domain/instrument.hpp"
3334#include " ../../domain/note_data.hpp"
3435#include " ../../domain/song.hpp"
@@ -709,9 +710,9 @@ void XmlSerializationTest::test_toXmlFromXml_samplerDevice_shouldLoadSamplerDevi
709710 const std::string fileName = " test.wav" ;
710711 const auto samplerName = Constants::samplerDeviceName ().toStdString ();
711712
712- auto engine = std::make_shared<AudioEngine>();
713+ const auto engine = std::make_shared<AudioEngine>();
713714 DeviceService deviceServiceOut { engine };
714- auto samplerOut = std::make_shared<SamplerDevice>(samplerName, std::make_unique<MockAudioFileReader>());
715+ const auto samplerOut = std::make_shared<SamplerDevice>(samplerName, std::make_unique<MockAudioFileReader>());
715716 samplerOut->setId (42 );
716717 samplerOut->loadSample (60 , fileName);
717718 samplerOut->setSamplePan (60 , 0 .75f );
@@ -724,12 +725,12 @@ void XmlSerializationTest::test_toXmlFromXml_samplerDevice_shouldLoadSamplerDevi
724725
725726 const auto xml = editorServiceOut.toXml ();
726727
727- DeviceService deviceServiceIn { std::make_shared<AudioEngine>() } ;
728- auto samplerIn = std::make_shared<SamplerDevice>(samplerName, std::make_unique<MockAudioFileReader>());
729- deviceServiceIn. registerDevice (samplerIn);
728+ const auto deviceServiceIn = std::make_shared<DeviceService>(std::make_shared< AudioEngine>()) ;
729+ const auto samplerIn = std::make_shared<SamplerDevice>(samplerName, std::make_unique<MockAudioFileReader>());
730+ deviceServiceIn-> registerDevice (samplerIn);
730731
731732 EditorService editorServiceIn { std::make_shared<SelectionService>(), std::make_shared<SettingsService>(), std::make_shared<AutomationService>(std::make_shared<PropertyService>()) };
732- connect (&editorServiceIn, &EditorService::devicesDeserializationRequested, & deviceServiceIn, &DeviceService::deserializeFromXml);
733+ connect (&editorServiceIn, &EditorService::devicesDeserializationRequested, deviceServiceIn. get () , &DeviceService::deserializeFromXml);
733734
734735 editorServiceIn.fromXml (xml);
735736
@@ -742,6 +743,70 @@ void XmlSerializationTest::test_toXmlFromXml_samplerDevice_shouldLoadSamplerDevi
742743 QCOMPARE (samplerIn->sampleCutoff (60 ), 0 .4f );
743744}
744745
746+ void XmlSerializationTest::test_toXmlFromXml_synthDevice_shouldPreserveValuesAndDiscreteFlags ()
747+ {
748+ const auto synthName = " Test Synth" ;
749+
750+ const auto engine = std::make_shared<AudioEngine>();
751+ DeviceService deviceServiceOut { engine };
752+ const auto synthOut = std::make_shared<SynthDevice>(synthName);
753+ synthOut->setId (66 );
754+ synthOut->setVco1Waveform (PolyBLEPOscillator::Waveform::Saw);
755+ synthOut->setVco1Octave (1 );
756+ synthOut->setMixVco2 (0 .75f );
757+ synthOut->setLpfCutoff (0 .3f );
758+ synthOut->setAmpAttack (0 .2f );
759+ synthOut->setMultiType (MultiEngine::Type::Decim);
760+ synthOut->setMultiShape (0 .42f );
761+ synthOut->setMultiLevel (0 .88f );
762+ synthOut->setMultiKeyTrack (0 .5f );
763+ synthOut->setMasterPan (0 .12f );
764+ deviceServiceOut.registerDevice (synthOut);
765+
766+ EditorService editorServiceOut { std::make_shared<SelectionService>(), std::make_shared<SettingsService>(), std::make_shared<AutomationService>(std::make_shared<PropertyService>()) };
767+ connect (&editorServiceOut, &EditorService::devicesSerializationRequested, &deviceServiceOut, &DeviceService::serializeToXml);
768+
769+ const auto xml = editorServiceOut.toXml ();
770+
771+ const auto deviceServiceIn = std::make_shared<DeviceService>(std::make_shared<AudioEngine>());
772+ const auto synthIn = std::make_shared<SynthDevice>(synthName);
773+ deviceServiceIn->registerDevice (synthIn);
774+
775+ EditorService editorServiceIn { std::make_shared<SelectionService>(), std::make_shared<SettingsService>(), std::make_shared<AutomationService>(std::make_shared<PropertyService>()) };
776+ connect (&editorServiceIn, &EditorService::devicesDeserializationRequested, deviceServiceIn.get (), &DeviceService::deserializeFromXml);
777+
778+ editorServiceIn.fromXml (xml);
779+
780+ QCOMPARE (synthIn->id (), 66ull );
781+ QCOMPARE (synthIn->vco1Waveform (), PolyBLEPOscillator::Waveform::Saw);
782+ QCOMPARE (synthIn->vco1Octave (), 1 );
783+ QCOMPARE (synthIn->mixVco2 (), 0 .75f );
784+ QCOMPARE (synthIn->lpfCutoff (), 0 .3f );
785+ QCOMPARE (synthIn->ampAttack (), 0 .2f );
786+ QCOMPARE (synthIn->multiType (), MultiEngine::Type::Decim);
787+ QCOMPARE (synthIn->multiShape (), 0 .42f );
788+ QCOMPARE (synthIn->multiLevel (), 0 .88f );
789+ QCOMPARE (synthIn->multiKeyTrack (), 0 .5f );
790+ QCOMPARE (synthIn->masterPan (), 0 .12f );
791+
792+ // Verify discrete flags
793+ const auto vco1Wave = synthIn->parameter (Constants::NahdXml::xmlKeySynthVco1Waveform ().toStdString ());
794+ QVERIFY (vco1Wave.has_value ());
795+ QVERIFY (vco1Wave->get ().isDiscrete ());
796+
797+ const auto vco1Octave = synthIn->parameter (Constants::NahdXml::xmlKeySynthVco1Octave ().toStdString ());
798+ QVERIFY (vco1Octave.has_value ());
799+ QVERIFY (vco1Octave->get ().isDiscrete ());
800+
801+ const auto lpfCutoff = synthIn->parameter (Constants::NahdXml::xmlKeySynthLpfCutoff ().toStdString ());
802+ QVERIFY (lpfCutoff.has_value ());
803+ QVERIFY (!lpfCutoff->get ().isDiscrete ());
804+
805+ const auto multiShape = synthIn->parameter (Constants::NahdXml::xmlKeySynthMultiShape ().toStdString ());
806+ QVERIFY (multiShape.has_value ());
807+ QVERIFY (!multiShape->get ().isDiscrete ());
808+ }
809+
745810void XmlSerializationTest::test_fromXml_samplerDevice_missingId_shouldNotThrow ()
746811{
747812 const auto xml = QString (R"XML(
0 commit comments