diff --git a/.gitignore b/.gitignore index 498c5319..a3c99fff 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ /.classpath /.project /.DS_Store + +/.idea +*.iml +*.ipr diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaMOXFEWFMEntry.java b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaMOXFEWFMEntry.java new file mode 100644 index 00000000..982ee6d7 --- /dev/null +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaMOXFEWFMEntry.java @@ -0,0 +1,37 @@ +package de.mossgrabers.convertwithmoss.format.yamaha.ysfc; + +import de.mossgrabers.convertwithmoss.file.StreamUtils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class YamahaMOXFEWFMEntry extends YamahaYsfcEntry { + + @Override + protected byte[] createContent() throws IOException { + final ByteArrayOutputStream contentStream = new ByteArrayOutputStream (); + + StreamUtils.padBytes(contentStream, 4); + + // Size of the item corresponding to this entry + StreamUtils.writeUnsigned32(contentStream, this.correspondingDataSize, true); + StreamUtils.padBytes(contentStream, 4); + // Offset of the item chunk within the data block + StreamUtils.writeUnsigned32(contentStream, this.correspondingDataOffset, true); + // Type specific - e.g. Program number + StreamUtils.writeUnsigned32(contentStream, this.specificValue, true); + + StreamUtils.padBytes(contentStream, 2); + + StreamUtils.writeNullTerminatedASCII (contentStream, this.itemName); + StreamUtils.writeNullTerminatedASCII (contentStream, this.itemTitle); + + // Optional additional data - type specific, only used by EPFM + contentStream.write (this.additionalData); + + // Finally, write the chunk + final byte [] content = contentStream.toByteArray (); + this.length = content.length; + return content; + } +} diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaMOXFEWIMEntry.java b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaMOXFEWIMEntry.java new file mode 100644 index 00000000..53b01a48 --- /dev/null +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaMOXFEWIMEntry.java @@ -0,0 +1,45 @@ +package de.mossgrabers.convertwithmoss.format.yamaha.ysfc; + +import de.mossgrabers.convertwithmoss.file.StreamUtils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class YamahaMOXFEWIMEntry extends YamahaYsfcEntry { + + @Override + protected byte[] createContent() throws IOException { + final ByteArrayOutputStream contentStream = new ByteArrayOutputStream (); + + StreamUtils.padBytes(contentStream, 4); + + // Size of the item corresponding to this entry + StreamUtils.writeUnsigned32 (contentStream, this.correspondingDataSize, true); + + StreamUtils.padBytes(contentStream, 4); + + // Offset of the item chunk within the data block + StreamUtils.writeUnsigned32 (contentStream, this.correspondingDataOffset, true); + // Type specific - e.g. Program number + StreamUtils.writeUnsigned32 (contentStream, this.specificValue, true); + + // Flags - type specific +// contentStream.write (this.flags); + + // ID of the entry object for ordering +// StreamUtils.writeUnsigned32 (contentStream, this.entryID, true); + + StreamUtils.padBytes(contentStream, 2); + + StreamUtils.writeNullTerminatedASCII (contentStream, this.itemName); + StreamUtils.writeNullTerminatedASCII (contentStream, this.itemTitle); + + // Optional additional data - type specific, only used by EPFM + contentStream.write (this.additionalData); + + // Finally, write the chunk + final byte [] content = contentStream.toByteArray (); + this.length = content.length; + return content; + } +} diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcCreator.java b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcCreator.java index 246d518d..b520bc08 100644 --- a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcCreator.java +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcCreator.java @@ -7,11 +7,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; +import java.util.*; import de.mossgrabers.convertwithmoss.core.IMultisampleSource; import de.mossgrabers.convertwithmoss.core.INotifier; @@ -35,6 +31,8 @@ import javafx.scene.control.ToggleGroup; +record MOXFData(int numberOfSamplesWritten, int numberOfChannelsWritten) {} + /** * Creator for Yamaha YSFC files. * @@ -55,7 +53,8 @@ private enum OutputFormat MONTAGE_USER, MONTAGE_LIBRARY, MODX_USER, - MODX_LIBRARY + MODX_LIBRARY, + MOXF_LIBRARY } @@ -68,11 +67,13 @@ private enum OutputFormat ENDING_MAP.put (OutputFormat.MONTAGE_LIBRARY, ".X7L"); ENDING_MAP.put (OutputFormat.MODX_USER, ".X8U"); ENDING_MAP.put (OutputFormat.MODX_LIBRARY, ".X8L"); + ENDING_MAP.put (OutputFormat.MOXF_LIBRARY, ".X3A"); VERSION_MAP.put (OutputFormat.MONTAGE_USER, "4.0.5"); VERSION_MAP.put (OutputFormat.MONTAGE_LIBRARY, "4.0.5"); VERSION_MAP.put (OutputFormat.MODX_USER, "5.0.1"); VERSION_MAP.put (OutputFormat.MODX_LIBRARY, "5.0.1"); + VERSION_MAP.put (OutputFormat.MOXF_LIBRARY, "1.0.2"); } private ToggleGroup outputFormatGroup; @@ -97,7 +98,7 @@ public Node getEditPane () panel.createSeparator ("@IDS_YSFC_LIBRARY_FORMAT"); this.outputFormatGroup = new ToggleGroup (); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 5; i++) { final RadioButton order = panel.createRadioButton ("@IDS_YSFC_OUTPUT_FORMAT_OPTION" + i); order.setAccessibleHelp (Functions.getMessage ("IDS_YSFC_LIBRARY_FORMAT")); @@ -173,11 +174,29 @@ public void create (final File destinationFolder, final List */ private static void storeMultisamples (final List multisampleSources, final File multiFile, final OutputFormat outputFormat) throws IOException { - final YsfcFile ysfcFile = new YsfcFile (); + final YsfcFile ysfcFile; + if (!outputFormat.equals(OutputFormat.MOXF_LIBRARY)) { + ysfcFile = YsfcFile.withChunks ("EWFM", "DWFM", "EWIM", "DWIM"); + } else { + ysfcFile = YsfcFile.withChunks ("EWFM", "DWFM", "EWIM", "DWIM", "EARP", "DARP", "EVCE", "DVCE"); + } + ysfcFile.setVersionStr (VERSION_MAP.get (outputFormat)); final int libraryID = 0x10001; + Optional moxfData; + if (outputFormat.equals(OutputFormat.MOXF_LIBRARY)) { + // Yamaha MOXF has following additional fields: + // - a field that for each keygroup (across all keybanks) stores total index of the samples in the library + // starting at 0x10. + // - a field that for each channel data stores its total index in DWIM block (counting channels of all + // samples in the library starting at 1. + moxfData = Optional.of(new MOXFData(16, 0)); + } else { + moxfData = Optional.empty(); + } + // Numbering covers all(!) samples int sampleNumber = 1; @@ -212,24 +231,36 @@ private static void storeMultisamples (final List multisampl throw new IOException (ex); } - final byte [] data = dataChunk.getData (); + final byte[] data = dataChunk.getData(); final boolean isStereo = numberOfChannels == 2; - for (int channel = 0; channel < numberOfChannels; channel++) - { - keybankList.add (createKeybank (sampleNumber, zone, formatChunk, numSamples)); + keybankList.add(createKeybank(moxfData, sampleNumber, zone, formatChunk, numSamples)); + for (int channel = 0; channel < numberOfChannels; channel++) { + final YamahaYsfcWaveData waveData = new YamahaYsfcWaveData(); + waveDataList.add(waveData); + waveData.setData(isStereo ? getChannelData(channel, data) : data); + } + sampleNumber++; - final YamahaYsfcWaveData waveData = new YamahaYsfcWaveData (); - waveDataList.add (waveData); - waveData.setData (isStereo ? getChannelData (channel, data) : data); + // For MOXF: + // - calculating total count of the samples + 0x10 + // - calculating total count of the channels across all samples + moxfData = moxfData.map(storage -> new MOXFData( + storage.numberOfSamplesWritten() + numSamples * numberOfChannels, + storage.numberOfChannelsWritten() + numberOfChannels) + ); - sampleNumber++; - } } final int sampleIndex = libraryID + i; - final YamahaYsfcEntry keyBankEntry = new YamahaYsfcEntry (); - keyBankEntry.setSpecificValue (sampleIndex); + final YamahaYsfcEntry keyBankEntry; + if (!outputFormat.equals(OutputFormat.MOXF_LIBRARY)) { + keyBankEntry = new YamahaYsfcEntry (); + keyBankEntry.setSpecificValue (sampleIndex); + } else { + keyBankEntry = new YamahaMOXFEWFMEntry(); + keyBankEntry.setSpecificValue (sampleIndex - libraryID + 1); + } // Set the category String n = multisampleName; @@ -241,10 +272,22 @@ private static void storeMultisamples (final List multisampl n = categoryID.toString () + ":" + n; } keyBankEntry.setItemName (n); + if (outputFormat.equals(OutputFormat.MOXF_LIBRARY)) { + keyBankEntry.setItemTitle(String.format("%04d-Waveform.wfm", i + 1)); + } - final YamahaYsfcEntry waveDataEntry = new YamahaYsfcEntry (); + + final YamahaYsfcEntry waveDataEntry; + if (!outputFormat.equals(OutputFormat.MOXF_LIBRARY)) { + waveDataEntry = new YamahaYsfcEntry (); + waveDataEntry.setSpecificValue (sampleIndex); + } else { + waveDataEntry = new YamahaMOXFEWIMEntry(); + waveDataEntry.setSpecificValue (sampleIndex - libraryID + 1); + waveDataEntry.setItemTitle(String.format("%04d-Waveform.wim", i + 1)); + } waveDataEntry.setItemName (multisampleName); - waveDataEntry.setSpecificValue (sampleIndex); + ysfcFile.fillWaveChunks (keyBankEntry, keybankList, waveDataEntry, waveDataList); } @@ -256,11 +299,16 @@ private static void storeMultisamples (final List multisampl } - private static YamahaYsfcKeybank createKeybank (final int sampleNumber, final ISampleZone zone, final FormatChunk formatChunk, final int numSamples) + private static YamahaYsfcKeybank createKeybank (Optional moxfData, int sampleNumber, final ISampleZone zone, final FormatChunk formatChunk, final int numSamples) { final YamahaYsfcKeybank keybank = new YamahaYsfcKeybank (); keybank.setNumber (sampleNumber); + moxfData.ifPresent(data -> { + keybank.setVersion1TotalSampleOffset(data.numberOfSamplesWritten()); + keybank.setVersion1TotalChannelOffset(data.numberOfChannelsWritten()); + }); + final int numberOfChannels = formatChunk.getNumberOfChannels (); keybank.setChannels (numberOfChannels); keybank.setSampleFrequency (formatChunk.getSampleRate ()); @@ -280,11 +328,11 @@ private static YamahaYsfcKeybank createKeybank (final int sampleNumber, final IS final double gain = zone.getGain (); keybank.setLevel (gain < -95.25 ? 0 : (int) Math.round ((Math.clamp (gain, -95.25, 0) + 95.25) / 0.375) + 1); - if (numberOfChannels == 1) - { - final double panorama = zone.getPanorama (); - keybank.setPanorama ((int) (panorama < 0 ? panorama * 64 : panorama * 63)); - } +// if (numberOfChannels == 1) +// { + final double panorama = zone.getPanorama (); + keybank.setPanorama ((int) (panorama < 0 ? panorama * 64 : panorama * 63)); +// } keybank.setPlayStart (zone.getStart ()); keybank.setPlayEnd (zone.getStop ()); diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcEntry.java b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcEntry.java index fe5757ab..2df7328d 100644 --- a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcEntry.java +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcEntry.java @@ -21,15 +21,15 @@ */ public class YamahaYsfcEntry { - private int length; - private byte [] flags = new byte [6]; - private String itemName = ""; - private String itemTitle = ""; - private byte [] additionalData = new byte [0]; - private int correspondingDataSize = 0; - private int correspondingDataOffset = 0; - private int specificValue = 0; - private int entryID = 0xFFFFFFFF; + protected int length; + private byte [] flags = new byte [6]; + protected String itemName = ""; + protected String itemTitle = ""; + protected byte [] additionalData = new byte [0]; + protected int correspondingDataSize = 0; + protected int correspondingDataOffset = 0; + protected int specificValue = 0; + protected int entryID = 0xFFFFFFFF; /** @@ -111,7 +111,7 @@ public void write (final OutputStream out) throws IOException } - private byte [] createContent () throws IOException + protected byte [] createContent () throws IOException { final ByteArrayOutputStream contentStream = new ByteArrayOutputStream (); @@ -229,6 +229,16 @@ public String getItemTitle () return this.itemTitle; } + /** + * Set the title of the item. Used by Yamaha MOXF + * + * @param itemTitle The filename + */ + public void setItemTitle (final String itemTitle) + { + this.itemTitle = itemTitle; + } + /** * Get the flags. diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcKeybank.java b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcKeybank.java index 93765b95..5d82176f 100644 --- a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcKeybank.java +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YamahaYsfcKeybank.java @@ -19,6 +19,11 @@ */ public class YamahaYsfcKeybank { + + // output format for the case of writing + private int version1TotalSampleOffset = -1; + private int version1TotalChannelOffset = -1; + private boolean isVersion1; private int keyRangeLower; private int keyRangeUpper; private int velocityRangeLower; @@ -96,7 +101,6 @@ public void read (final InputStream in, final int version) throws IOException this.channels = in.read (); this.loopTune = in.read (); - // Ignore in.skipNBytes (1); final int waveFormat = in.read (); @@ -118,7 +122,7 @@ public void read (final InputStream in, final int version) throws IOException in.skipNBytes (12); if (!isVersion1) - in.skipNBytes (4); + in.skipNBytes (4); // 0x00 0x00 0x00 0xFF this.sampleFrequency = (int) StreamUtils.readUnsigned32 (in, isBigEndian); this.playStart = (int) StreamUtils.readUnsigned32 (in, isBigEndian); @@ -177,50 +181,102 @@ public void write (final OutputStream out) throws IOException out.write (this.keyRangeUpper); out.write (this.velocityRangeLower); out.write (this.velocityRangeUpper); - out.write (this.level); + out.write (!this.isVersion1 ? this.level : this.level / 2); out.write (this.panorama); out.write (0x00); - out.write (this.fixedPitch); + + if (!this.isVersion1) { + out.write(this.fixedPitch); + } else { + out.write(0x00); + } out.write (this.rootNote); out.write (this.coarseTune); out.write (this.fineTune); out.write (this.channels); - out.write (0x00); - // Always 2 for Montage - out.write (0x02); + out.write (0x00); // loopTune + // Always 2 for Montage, 0 for MOXF + out.write (!this.isVersion1 ? 0x02 : 0x00); // 16-bit linear - out.write (0x05); + out.write (!this.isVersion1 ? 0x05 : 0x00); // for Montage - 16-bit 0x05 , for MOXF - 16-bit 0x00, 8-bit 0x02 out.write (this.loopMode); // Unknown but should be only padding - out.write (0x00); - out.write (0x00); - - out.write (this.loopPoint % 16); + out.write (0x00); // isEncrypted + out.write (0x00); // padding + + if (!this.isVersion1) { + out.write(this.loopPoint % 16); // loopPointRest + } else { + // MOXF has this 0 + out.write(0x00); + } // Unknown but should work - out.write (1); + out.write (!this.isVersion1 ? 0x01 : 0xFF); StreamUtils.padBytes (out, 12); // Padding / reserved - StreamUtils.padBytes (out, 3); - out.write (0xFF); + if (!this.isVersion1) { + StreamUtils.padBytes(out, 3); + out.write(0xFF); + } StreamUtils.writeUnsigned32 (out, this.sampleFrequency, false); StreamUtils.writeUnsigned32 (out, this.playStart, false); - StreamUtils.writeUnsigned32 (out, this.loopPoint / 16, false); + if (!this.isVersion1) { + StreamUtils.writeUnsigned32(out, this.loopPoint / 16, false); + } else { + StreamUtils.writeUnsigned32(out, this.loopPoint, false); + } StreamUtils.writeUnsigned32 (out, this.playEnd, false); // Padding / reserved - StreamUtils.padBytes (out, 4); + if (!this.isVersion1) { + StreamUtils.padBytes(out, 4); - StreamUtils.writeUnsigned32 (out, this.number, false); + StreamUtils.writeUnsigned32(out, this.number, false); + } StreamUtils.writeUnsigned32 (out, this.sampleLength, false); + + // TODO implement handling of MOTIF +// if (isMotif) { +// // 00 00 00 00 - 00 00 00 00 - FF FF FF FF - FF FF FF FF +// +// } + + if (this.isVersion1) { + StreamUtils.writeUnsigned16(out, this.version1TotalSampleOffset + this.sampleLength, false); + out.write(0x00); + out.write(0xC0); + if (this.channels == 2) { + StreamUtils.writeUnsigned16(out, this.version1TotalSampleOffset + this.sampleLength * 2, false); + out.write(0x00); + out.write(0xC0); + } else { + // 1 channel only, pad information for second channel wiwht 0xFF 0xFF 0xFF 0xFF + StreamUtils.padBytes(out, 4, 0xFF); + } + + // Index of keygroup wave in DWIM block across all Data entries in the DWIM section. + // The code above supports single sample per keygroup and + // maximum of 2 channels. + // The indexing starts from 1. + StreamUtils.writeUnsigned16(out, version1TotalChannelOffset + 1, false); + StreamUtils.padBytes(out, 2); + if (channels == 2) { + StreamUtils.writeUnsigned16(out, version1TotalChannelOffset + 2, false); + StreamUtils.padBytes(out, 2); + } else { + // If mono, the second channel data is padded with 0xFF 0xFF 0xFF 0xFF + StreamUtils.padBytes(out, 4, 0xFF); + } + } } @@ -264,6 +320,15 @@ public int getKeyRangeLower () return this.keyRangeLower; } + public void setVersion1TotalChannelOffset(int totalChannelOffset) { + this.isVersion1 = true; + this.version1TotalChannelOffset = totalChannelOffset; + } + + public void setVersion1TotalSampleOffset(int totalSampleOffset) { + this.isVersion1 = true; + this.version1TotalSampleOffset = totalSampleOffset; + } /** * Set the lower bound of the key range. diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YsfcFile.java b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YsfcFile.java index 65168a33..f0dca750 100644 --- a/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YsfcFile.java +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/yamaha/ysfc/YsfcFile.java @@ -12,10 +12,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import de.mossgrabers.convertwithmoss.exception.FormatException; import de.mossgrabers.convertwithmoss.file.StreamUtils; @@ -30,6 +27,7 @@ public class YsfcFile { private static final String YAMAHA_YSFC = "YAMAHA-YSFC"; private static final int HEADER_SIZE = 64; + public static final String MOXF_LIBRARY_VERSION = "1.0.2"; private File sourceFile; private String versionStr; @@ -38,12 +36,16 @@ public class YsfcFile private final Map chunks = HashMap.newHashMap (4); + public static YsfcFile withChunks (String... chunkIDs) { + return new YsfcFile(chunkIDs); + } + /** * Default constructor. */ - public YsfcFile () + private YsfcFile (final String... chunkIDs) { - this.createChunks ("EWFM", "DWFM", "EWIM", "DWIM"); + this.createChunks (chunkIDs); } @@ -191,21 +193,28 @@ public void write (final OutputStream outputStream) throws IOException StreamUtils.writeASCII (outputStream, YAMAHA_YSFC, 16); StreamUtils.writeASCII (outputStream, this.versionStr, 16); StreamUtils.writeUnsigned32 (outputStream, catalogSize, true); - StreamUtils.padBytes (outputStream, 12, 0xFF); - // The size of the library block - fixed - final int librarySize = 81; - StreamUtils.writeUnsigned32 (outputStream, librarySize, true); + if (!versionStr.equals(MOXF_LIBRARY_VERSION)) { + StreamUtils.padBytes(outputStream, 12, 0xFF); + + // The size of the library block - fixed + final int librarySize = 81; + StreamUtils.writeUnsigned32 (outputStream, librarySize, true); + + StreamUtils.padBytes (outputStream, 8, 0xFF); - StreamUtils.padBytes (outputStream, 8, 0xFF); + StreamUtils.writeUnsigned32 (outputStream, this.maxEntryID, true); - StreamUtils.writeUnsigned32 (outputStream, this.maxEntryID, true); + writeCatalog (outputStream, orderedChunks, HEADER_SIZE + catalogSize + librarySize); - writeCatalog (outputStream, orderedChunks, HEADER_SIZE + catalogSize + librarySize); + // Write empty library references + StreamUtils.padBytes (outputStream, librarySize - 1, 0xFF); + StreamUtils.padBytes (outputStream, 1, 0x00); + } else { + StreamUtils.padBytes(outputStream, 28, 0xFF); - // Write empty library references - StreamUtils.padBytes (outputStream, librarySize - 1, 0xFF); - StreamUtils.padBytes (outputStream, 1, 0x00); + writeCatalog (outputStream, orderedChunks, HEADER_SIZE + catalogSize); + } writeChunks (outputStream, orderedChunks); } @@ -301,10 +310,20 @@ private List sortAndUpdateChunks () this.maxEntryID = 10001 + ewfm.getEntryListChunks ().size () * 2; final List orderedChunks = new ArrayList<> (); - orderedChunks.add (ewfm); - orderedChunks.add (dwfm); - orderedChunks.add (ewim); - orderedChunks.add (dwim); + + // both Montage and MOXF library have these sections first in this order + orderedChunks.add(ewfm); + orderedChunks.add(dwfm); + orderedChunks.add(ewim); + orderedChunks.add(dwim); + + if (versionStr.equals(MOXF_LIBRARY_VERSION)) { + orderedChunks.add(chunks.get("EARP")); + orderedChunks.add(chunks.get("DARP")); + orderedChunks.add(chunks.get("EVCE")); + orderedChunks.add(chunks.get("DVCE")); + } + return orderedChunks; } @@ -316,7 +335,7 @@ private List sortAndUpdateChunks () * @param dataChunk The data chunk with the referenced data * @param entryID The entryID to start with */ - private static void updateEntryReferences (final YamahaYsfcChunk entryChunk, final YamahaYsfcChunk dataChunk, final int entryID) + private void updateEntryReferences (final YamahaYsfcChunk entryChunk, final YamahaYsfcChunk dataChunk, final int entryID) { final List entryListChunks = entryChunk.getEntryListChunks (); final List dataArrays = dataChunk.getDataArrays (); @@ -325,8 +344,12 @@ private static void updateEntryReferences (final YamahaYsfcChunk entryChunk, fin { final YamahaYsfcEntry ysfcEntry = entryListChunks.get (i); final byte [] dataArray = dataArrays.get (i); + if (!this.versionStr.equals(MOXF_LIBRARY_VERSION)) { + ysfcEntry.setEntryID (entryID + i * 2); + } else { + ysfcEntry.setEntryID(i + 1); + } - ysfcEntry.setEntryID (entryID + i * 2); ysfcEntry.setCorrespondingDataOffset (offset); ysfcEntry.setCorrespondingDataSize (dataArray.length); diff --git a/src/main/resources/Strings.properties b/src/main/resources/Strings.properties index 4ad31e3d..f51a36ba 100644 --- a/src/main/resources/Strings.properties +++ b/src/main/resources/Strings.properties @@ -345,3 +345,4 @@ IDS_YSFC_OUTPUT_FORMAT_OPTION0=Montage User (*.X7U) IDS_YSFC_OUTPUT_FORMAT_OPTION1=Montage Library (*.X7L) IDS_YSFC_OUTPUT_FORMAT_OPTION2=MODX/MODX+ User (*.X8U) IDS_YSFC_OUTPUT_FORMAT_OPTION3=MODX/MODX+ Library (*.X8L) +IDS_YSFC_OUTPUT_FORMAT_OPTION4=MOXF All File (*.X3A)