-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Import/Export of the dawproject open format. #6909
Comments
Proposal to use a code generatorThe project offers an XSD which describes the schema of valid XML documents in the context of the project. The XSD in turn can be used with a code generator, e.g. CodeSynthesis XSD, to generate classes from the XSD. As a result the workflow in the code is roughly the following one:
So using something like this would make the code that maps the data between both representations nicer because data would be moved between high level classes. That way one would not have to care that much about the technical aspect of all that XML. |
I have just played with CodeSynthesis XSD in a Docker container and unfortunately the generated code seems to introduce a compile time dependency to the library and a runtime dependency to Xerces. 🙁 This might be rather unattractive as the project already uses Qt's XML library. |
We already install |
So I spent some time going over the dawproject schema and seeing if I could convert our So far the only things I really hit were:
I've opened up two PRs and we'll see how it goes. So with the two issues above, I modified the Project.xsd slightly to work with my hand made XML for Crunk(Demo) (yeah, by hand... I know it was a long task to do it this way but I learned quite a bit so far). diff --git a/Project.xsd b/Project.xsd
index 12e3696..6cb5350 100644
--- a/Project.xsd
+++ b/Project.xsd
@@ -61,6 +61,8 @@
<xs:element name="Scene" type="scene"/>
+ <xs:element name="StringParameter" type="stringParameter"/>
+
<xs:element name="TimeSignatureParameter" type="timeSignatureParameter"/>
<xs:element name="TimeSignaturePoint" type="timeSignaturePoint"/>
@@ -168,6 +170,15 @@
</xs:complexContent>
</xs:complexType>
+ <xs:complexType name="stringParameter">
+ <xs:complexContent>
+ <xs:extension base="parameter">
+ <xs:sequence/>
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
<xs:complexType name="integerParameter">
<xs:complexContent>
<xs:extension base="parameter">
@@ -327,6 +338,7 @@
<xs:element ref="BoolParameter"/>
<xs:element ref="IntegerParameter"/>
<xs:element ref="EnumParameter"/>
+ <xs:element ref="StringParameter"/>
<xs:element ref="TimeSignatureParameter"/>
</xs:choice>
</xs:sequence>
@@ -496,7 +508,7 @@
</xs:sequence>
<xs:attribute name="time" type="xs:string" use="required"/>
<xs:attribute name="duration" type="xs:string" use="required"/>
- <xs:attribute name="channel" type="xs:int" use="required"/>
+ <xs:attribute name="channel" type="xs:int"/>
<xs:attribute name="key" type="xs:int" use="required"/>
<xs:attribute name="vel" type="xs:string"/>
<xs:attribute name="rel" type="xs:string"/> And then here's the converted (and validated with xmllint with the changes above), please remember this may not be 100% correct or best, but it's following what I understand currently. I'm pretty sure some of the <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Project version="1.0">
<Application name="LMMS" version="1.2.0"/>
<Transport>
<Tempo max="999" min="1" unit="bpm" value="130" id="tempo0" name="Tempo"/>
<TimeSignature denominator="4" numerator="4" id="timesig0"/>
</Transport>
<Structure>
<Track contentType="tracks" id="bbtrack">
<Track contentType="audio" loaded="true" id="afp0" name="Kick 01">
<Channel role="regular" audioChannels="2" solo="false" destination="mixer1">
<Devices>
<BuiltinDevice deviceRole="instrument" deviceName="audiofileprocessor" deviceVendor="LMMS">
<Parameters>
<IntegerParameter value="1" min="1" max="60" name="range"/>
<IntegerParameter value="0" name="pitch"/>
<IntegerParameter value="57" name="baseNote"/>
<BoolParameter value="true" name="useMasterPitch"/>
<RealParameter value="0" unit="decibel" min="-96.0" max="6.0" name="amp"/>
<RealParameter value="0" unit="normalized" min="0" max="1" name="startPoint"/>
<RealParameter value="0" unit="normalized" min="0" max="1" name="loopPoint"/>
<RealParameter value="1" unit="normalized" min="0" max="1" name="endPoint"/>
<BoolParameter value="false" name="reverse"/>
<IntegerParameter value="0" name="looped"/>
<BoolParameter value="false" name="stutter"/>
<IntegerParameter value="1" name="interp"/>
</Parameters>
<State external="false" path="drums/kick01.ogg"/>
</BuiltinDevice>
</Devices>
<Mute value="false"/>
<Pan value="0" unit="linear" min="-100" max="100"/>
<Volume value="-2.4" unit="decibel" min="-96.0" max="6.0"/>
</Channel>
</Track>
<Track contentType="audio" loaded="true" id="afp1" name="Clap 04">
<Channel role="regular" audioChannels="2" solo="false" destination="mixer1">
<Devices>
<BuiltinDevice deviceRole="instrument" deviceName="audiofileprocessor" deviceVendor="LMMS">
<Parameters>
<IntegerParameter value="1" min="1" max="60" name="pitchrange"/>
<IntegerParameter value="0" name="pitch"/>
<IntegerParameter value="57" name="baseNote"/>
<BoolParameter value="true" name="useMasterPitch"/>
<RealParameter value="0" unit="decibel" min="-96.0" max="6.0" name="amp"/>
<RealParameter value="0" unit="normalized" min="0" max="1" name="startPoint"/>
<RealParameter value="0" unit="normalized" min="0" max="1" name="loopPoint"/>
<RealParameter value="1" unit="normalized" min="0" max="1" name="endPoint"/>
<BoolParameter value="false" name="reverse"/>
<IntegerParameter value="0" name="looped"/>
<BoolParameter value="false" name="stutter"/>
<IntegerParameter value="1" name="interp"/>
</Parameters>
<State external="false" path="drums/clap04.ogg"/>
</BuiltinDevice>
</Devices>
<Mute value="false"/>
<Pan value="0" unit="linear" min="-100" max="100"/>
<Volume value="-1.1" unit="decibel" min="-96.0" max="6.0"/>
</Channel>
</Track>
</Track>
<Track contentType="tracks" id="song">
<Track contentType="audio" loaded="true" id="track0" name="Drum">
<Channel role="regular" audioChannels="2" solo="false" destination="mixer1">
<Mute value="false"/>
<Pan value="1" unit="linear" comment="This is actually unused for bbtrack"/>
<Volume value="1" unit="linear" comment="This is actually unused for bbtrack"/>
</Channel>
</Track>
<Track contentType="audio" loaded="true" id="track1" name="Bass">
<Channel role="regular" audioChannels="2" solo="false" destination="mixer2">
<Devices>
<BuiltinDevice deviceRole="instrument" deviceName="audiofileprocessor" deviceVendor="LMMS" id="afp2">
<Parameters>
<IntegerParameter value="1" min="1" max="60" name="pitchrange"/>
<IntegerParameter value="0" name="pitch"/>
<IntegerParameter value="57" name="baseNote"/>
<BoolParameter value="true" name="useMasterPitch"/>
<RealParameter value="0" unit="decibel" min="-96.0" max="6.0" name="amp"/>
<RealParameter value="0" unit="normalized" min="0" max="1" name="startPoint"/>
<RealParameter value="0" unit="normalized" min="0" max="1" name="loopPoint"/>
<RealParameter value="1" unit="normalized" min="0" max="1" name="endPoint"/>
<BoolParameter value="false" name="reverse"/>
<IntegerParameter value="0" name="looped"/>
<BoolParameter value="false" name="stutter"/>
<IntegerParameter value="1" name="interp"/>
</Parameters>
<State external="false" path="basses/bass_hard01.ogg"/>
</BuiltinDevice>
</Devices>
<Mute value="false"/>
<Pan value="0" unit="linear" min="-100" max="100"/>
<Volume value="0" unit="decibel" min="-96.0" max="6.0"/>
</Channel>
</Track>
<Track contentType="audio" loaded="true" id="track2" name="Synth">
<Channel role="regular" audioChannels="2" solo="false" destination="mixer3">
<Devices>
<BuiltinDevice deviceRole="instrument" deviceName="FreeBoy" deviceVendor="LMMS" id="freeboy0">
<Parameters>
<IntegerParameter value="1" min="1" max="60" name="pitchrange"/>
<IntegerParameter value="0" name="pitch"/>
<IntegerParameter value="57" name="baseNote"/>
<BoolParameter value="true" name="useMasterPitch"/>
<RealParameter value="4" unit="linear" min="0" max="7" name="st" comment="ch1SweepTime"/>
<BoolParameter value="0" name="sd" comment="ch1SweepDir"/>
<RealParameter value="0" unit="linear" min="0" max="7" name="srs" comment="ch1SweepRtShift"/>
<RealParameter value="2" unit="linear" min="0" max="3" name="ch1wpd" comment="ch1WavePatternDuty"/>
<RealParameter value="15" unit="linear" min="0" max="15" name="ch1vol" comment="ch1Volume"/>
<BoolParameter value="0" name="ch1vsd" comment="ch1VolSweepDir"/>
<RealParameter value="0" unit="linear" min="0" max="7" name="ch1ssl" comment="ch1SweepStepLength"/>
<RealParameter value="2" unit="linear" min="0" max="3" name="ch2wpd" comment="ch2WavePatternDuty"/>
<RealParameter value="15" unit="linear" min="0" max="15" name="ch2vol" comment="ch2Volume"/>
<BoolParameter value="0" name="ch2vsd" comment="ch2VolSweepDir"/>
<RealParameter value="0" unit="linear" min="0" max="7" name="ch2ssl" comment="ch2SweepStepLength"/>
<RealParameter value="3" unit="linear" min="0" max="3" name="ch3vol" comment="ch3Volume"/>
<RealParameter value="15" unit="linear" min="0" max="15" name="ch4vol" comment="ch4Volume"/>
<BoolParameter value="0" name="ch4vsd" comment="ch4VolSweepDir"/>
<RealParameter value="7" unit="linear" min="0" max="7" name="ch4ssl" comment="ch4SweepStepLength"/>
<BoolParameter value="0" name="srw" comment="ch4ShiftRegWidth"/>
<RealParameter value="7" unit="linear" min="0" max="7" name="so1vol" comment="so1Volume"/>
<RealParameter value="7" unit="linear" min="0" max="7" name="so2vol" comment="so2Volume"/>
<BoolParameter value="1" name="ch1so1" comment="ch1So1"/>
<BoolParameter value="1" name="ch2so1" comment="ch2So1"/>
<BoolParameter value="0" name="ch3so1" comment="ch3So1"/>
<BoolParameter value="0" name="ch4so1" comment="ch4So1"/>
<BoolParameter value="1" name="ch1so2" comment="ch1So2"/>
<BoolParameter value="1" name="ch2so2" comment="ch2So2"/>
<BoolParameter value="0" name="ch3so2" comment="ch3So2"/>
<BoolParameter value="0" name="ch4so2" comment="ch4So2"/>
<RealParameter value="461" unit="linear" min="-1" max="600" name="Bass"/>
<RealParameter value="-11" unit="linear" min="-100" max="200" name="Treble"/>
<StringParameter value="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" name="sampleShape"/>
</Parameters>
</BuiltinDevice>
<AuPlugin deviceRole="audioFX" deviceName="Plate2x2" deviceVendor="caps" loaded="true" name="ladspaeffect0">
<Parameters>
<RealParameter value="1" unit="linear" min="-1" max="1" name="W/D"/>
<IntegerParameter value="1" min="1" max="8000" name="Decay"/>
<RealParameter value="0" unit="linear" min="0" max="1" name="Gate"/>
<RealParameter value="0.18389" unit="linear" min="0.005" max="0.999" name="port02" comment="bandwidth"/>
<RealParameter value="0.5767" unit="linear" min="0" max="0.749" name="port03" comment="tail"/>
<RealParameter value="0.999" unit="linear" min="0.0005" max="1" name="port04" comment="damping"/>
<RealParameter value="0.37" unit="linear" min="0" max="1" name="port05" comment="blend"/>
</Parameters>
<Enabled value="true"/>
</AuPlugin>
</Devices>
<Mute value="false"/>
<Pan value="0" unit="linear" min="-100" max="100"/>
<Volume value="-1.1" unit="decibel" min="-96.0" max="6.0"/>
</Channel>
</Track>
</Track>
<Channel role="master" audioChannels="2" solo="false" id="mixer0" name="Master">
<Mute value="false"/>
<Volume value="100.0" unit="linear" min="0" max="200"/>
</Channel>
<Channel role="regular" audioChannels="2" solo="false" id="mixer1" name="Drums">
<Mute value="false"/>
<Sends>
<Send type="post" destination="mixer0">
<Volume value="1" unit="linear" min="0" max="1"/>
</Send>
</Sends>
<Volume value="100.0" unit="linear" min="0" max="200"/>
</Channel>
<Channel role="regular" audioChannels="2" solo="false" id="mixer2" name="Bass">
<Mute value="false"/>
<Sends>
<Send type="post" destination="mixer0">
<Volume value="1" unit="linear" min="0" max="1"/>
</Send>
</Sends>
<Volume value="100.0" unit="linear" min="0" max="200"/>
</Channel>
<Channel role="regular" audioChannels="2" solo="false" id="mixer3" name="Lead">
<Mute value="false"/>
<Sends>
<Send type="post" destination="mixer0">
<Volume value="1" unit="linear" min="0" max="1"/>
</Send>
</Sends>
<Volume value="100.0" unit="linear" min="0" max="200"/>
</Channel>
</Structure>
<Arrangement>
<Lanes timeUnit="beats" id="id20">
<Lanes track="afp0" id="id21">
<Clips>
<Clip time="0" duration="16">
<Notes>
<Note time="0" duration="-1" key="57" vel="1"/>
<Note time="2.5" duration="-1" key="57" vel="1"/>
</Notes>
</Clip>
</Clips>
</Lanes>
<Lanes track="afp1" id="id23">
<Clips>
<Clip time="0" duration="16">
<Notes>
<Note time="1" duration="-1" key="57" vel="1"/>
<Note time="3" duration="-1" key="57" vel="1"/>
</Notes>
</Clip>
</Clips>
</Lanes>
<Clips track="track0" name="Drum">
<Clip time="0" duration="16" comment="bbtrack clip"/>
<Clip time="4" duration="16" comment="bbtrack clip"/>
</Clips>
<Lanes track="track1">
<Clips name="Bass">
<Clip time="0" duration="16">
<Notes>
<Note time="0" duration="0.75" key="52" vel="1"/>
<Note time="1.5" duration="0.75" key="52" vel="1"/>
<Note time="3" duration="0.75" key="52" vel="1"/>
<Note time="4.5" duration="0.5" key="59" vel="1"/>
<Note time="5" duration="0.5" key="59" vel="1"/>
<Note time="5.75" duration="0.5" key="59" vel="1"/>
<Note time="6.5" duration="0.5" key="59" vel="1"/>
<Note time="7.5" duration="0.5" key="59" vel="1"/>
<Note time="8" duration="0.75" key="60" vel="1"/>
<Note time="9.5" duration="0.75" key="60" vel="1"/>
<Note time="11" duration="0.75" key="60" vel="1"/>
<Note time="12.5" duration="0.5" key="55" vel="1"/>
<Note time="13" duration="0.5" key="55" vel="1"/>
<Note time="13.75" duration="0.5" key="55" vel="1"/>
<Note time="14.5" duration="0.5" key="59" vel="1"/>
<Note time="15.5" duration="0.5" key="59" vel="1"/>
</Notes>
</Clip>
<Clip time="4" duration="16">
<Notes>
<Note time="0" duration="0.75" key="52" vel="1"/>
<Note time="1.5" duration="0.75" key="52" vel="1"/>
<Note time="3" duration="0.75" key="52" vel="1"/>
<Note time="4.5" duration="0.5" key="59" vel="1"/>
<Note time="5" duration="0.5" key="59" vel="1"/>
<Note time="5.75" duration="0.5" key="59" vel="1"/>
<Note time="6.5" duration="0.5" key="59" vel="1"/>
<Note time="7.5" duration="0.5" key="59" vel="1"/>
<Note time="8" duration="0.75" key="60" vel="1"/>
<Note time="9.5" duration="0.75" key="60" vel="1"/>
<Note time="11" duration="0.75" key="60" vel="1"/>
<Note time="12.5" duration="0.5" key="55" vel="1"/>
<Note time="13" duration="0.5" key="55" vel="1"/>
<Note time="13.75" duration="0.5" key="55" vel="1"/>
<Note time="14.5" duration="0.5" key="59" vel="1"/>
<Note time="15.5" duration="0.5" key="59" vel="1"/>
</Notes>
</Clip>
</Clips>
</Lanes>
<Lanes track="track2">
<Clips name="Synth">
<Clip time="0" duration="16">
<Notes>
<Note time="0.5" duration="0.25" key="51" vel="1"/>
<Note time="1.25" duration="0.25" key="58" vel="1"/>
<Note time="2" duration="0.25" key="51" vel="1"/>
<Note time="4.5" duration="0.25" key="58" vel="1"/>
<Note time="5.25" duration="0.25" key="50" vel="1"/>
<Note time="6" duration="0.25" key="58" vel="1"/>
<Note time="8.5" duration="0.25" key="51" vel="1"/>
<Note time="9.25" duration="0.25" key="58" vel="1"/>
<Note time="10" duration="0.25" key="51" vel="1"/>
<Note time="12.5" duration="0.25" key="58" vel="1"/>
<Note time="13.25" duration="0.25" key="50" vel="1"/>
<Note time="14" duration="0.25" key="58" vel="1"/>
</Notes>
</Clip>
<Clip time="4" duration="16">
<Notes>
<Note time="0.5" duration="0.25" key="51" vel="1"/>
<Note time="1.25" duration="0.25" key="58" vel="1"/>
<Note time="2" duration="0.25" key="51" vel="1"/>
<Note time="4.5" duration="0.25" key="58" vel="1"/>
<Note time="5.25" duration="0.25" key="50" vel="1"/>
<Note time="6" duration="0.25" key="58" vel="1"/>
<Note time="8.5" duration="0.25" key="51" vel="1"/>
<Note time="9.25" duration="0.25" key="58" vel="1"/>
<Note time="10" duration="0.25" key="51" vel="1"/>
<Note time="12.5" duration="0.25" key="58" vel="1"/>
<Note time="13.25" duration="0.25" key="50" vel="1"/>
<Note time="14" duration="0.25" key="58" vel="1"/>
</Notes>
</Clip>
</Clips>
</Lanes>
</Lanes>
<TempoAutomation unit="bpm" id="tempo1" name="Automation Track">
<Target parameter="tempo0"/>
<IntegerPoint value="131" time="0"/>
</TempoAutomation>
</Arrangement>
<Scenes/>
</Project> |
@Veratil, that sounds like a lot of work! 👍
I have only glanced over the schema but if I understand correctly the internal state of the plugins is stored under
So the internal state is not contained in the XML itself but in one or more files which are then referenced from the XML. It would be really nice to have the option for completely self-contained XML files though. Assuming that these files are intended to store byte streams I now wonder if this might be one of the limits of the project and the format because in that case one might run into problems of endianess, etc. in case plugins do not always save in the exact binary format on all platforms. Now that I have written all this I also wonder what the other parameters are then intended to be used for and where's the boundary between parameters and state? 🤔 |
I guess that could be done instead, yes. Endianness doesn't matter as long as the reader is made to read it properly. MIDI files for instance are written in big endian, and we read those fine. :) |
Enhancement Summary
This is a note/action plan for implementing dawproject format. I've been working on the DataFile class a lot lately so this is a natural extension of that work.
Justification
Something similar was brough up in #3981
The text was updated successfully, but these errors were encountered: