Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@
<xs:complexContent>
<xs:extension base="nameable">
<xs:sequence>
<xs:element name="Gain" type="realParameter" minOccurs="0"/>
<xs:choice minOccurs="0">
<xs:element ref="Timeline"/>
<xs:element ref="Lanes"/>
Expand Down
19 changes: 19 additions & 0 deletions Reference.html
Original file line number Diff line number Diff line change
Expand Up @@ -2725,6 +2725,25 @@ <h3 id="Clip" class="element-title">
Required
</th>
</tr>
<tr>
<td style="text-align:center;">
&lt;Gain&gt;
</td>
<td>
Gain applied to the audio content of this clip, in addition to the
fade-in/fade-out envelope and independently of the volume of the channel this
clip plays on. Unity gain is the implied default when this element is
omitted.
</td>
<td style="text-align:center;">
<a href="#RealParameter" class="element-link">
&lt;RealParameter&gt;
</a>
</td>
<td style="text-align:center;">
no
</td>
</tr>
<tr>
<td style="text-align:center;">
from Type
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/bitwig/dawproject/timeline/Clip.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.bitwig.dawproject.timeline;

import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElementRef;
import jakarta.xml.bind.annotation.XmlIDREF;
import jakarta.xml.bind.annotation.XmlRootElement;

import com.bitwig.dawproject.Nameable;
import com.bitwig.dawproject.RealParameter;

/**
* A Clip provides a clipped view on to a Timeline, and is used either on a
Expand Down Expand Up @@ -80,6 +82,15 @@ public class Clip extends Nameable {
@XmlAttribute(required = false)
public Double fadeOutTime;

/**
* Gain applied to the audio content of this clip, in addition to the
* fade-in/fade-out envelope and independently of the volume of the channel this
* clip plays on. Unity gain is the implied default when this element is
* omitted.
*/
@XmlElement(name = "Gain", required = false)
public RealParameter gain;

/** Whether this clip should be played back. Default value is true. */
@XmlAttribute(required = false)
public Boolean enable;
Expand Down
43 changes: 43 additions & 0 deletions src/test/java/com/bitwig/dawproject/DawProjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,49 @@ public void saveAndLoadDawProject() throws IOException {
Assert.assertEquals(project.scenes.size(), loadedProject.scenes.size());
}

/**
* Test storing and loading a clip with gain.
*
* @throws IOException
* Could not store or load the project
*/
@Test
public void saveAndLoadClipGain() throws IOException {
final Project project = createEmptyProject();
final Track masterTrack = Utility.createTrack("Master", EnumSet.noneOf(ContentType.class), MixerRole.MASTER, 1,
0.5);
final var audioTrack = Utility.createTrack("Audio", EnumSet.of(ContentType.AUDIO), MixerRole.REGULAR, 1, 0.5);
audioTrack.channel.destination = masterTrack.channel;
project.structure.add(masterTrack);
project.structure.add(audioTrack);

project.arrangement = new Arrangement();
final var arrangementLanes = new Lanes();
arrangementLanes.timeUnit = TimeUnit.BEATS;
project.arrangement.lanes = arrangementLanes;

final var audio = Utility.createAudio("white-glasses.wav", 44100, 2, 3.097);
final var audioClip = Utility.createClip(audio, 0, 8);
audioClip.contentTimeUnit = TimeUnit.SECONDS;
audioClip.gain = Utility.createRealParameter(Unit.LINEAR, 0.5);

final var clips = Utility.createClips(audioClip);
clips.track = audioTrack;
arrangementLanes.lanes.add(clips);

DawProject.validate(project);

final var file = File.createTempFile("testfile-clip-gain", ".dawproject");
DawProject.save(project, new MetaData(), new HashMap<>(), file);
final var loadedProject = DawProject.loadProject(file);

final var loadedLanes = (Lanes) loadedProject.arrangement.lanes;
final var loadedClips = (Clips) loadedLanes.lanes.get(0);
final var loadedGain = loadedClips.clips.get(0).gain;
Assert.assertEquals(Unit.LINEAR, loadedGain.unit);
Assert.assertEquals(0.5, loadedGain.value.doubleValue(), 0.0);
}

/**
* Test storing a complex project.
*
Expand Down