mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-27 12:30:46 +00:00
Added #2259 Optional resampling sound to 44kHz on playback and on export
This commit is contained in:
@@ -3251,8 +3251,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
}
|
||||
}
|
||||
|
||||
public void putToCache(SOUNDINFO soundInfo, SoundTag soundTag, byte[] data) {
|
||||
SoundInfoSoundCacheEntry key = new SoundInfoSoundCacheEntry(soundInfo, soundTag);
|
||||
public void putToCache(SOUNDINFO soundInfo, SoundTag soundTag, boolean resample, byte[] data) {
|
||||
SoundInfoSoundCacheEntry key = new SoundInfoSoundCacheEntry(soundInfo, soundTag, resample);
|
||||
soundCache.put(key, data);
|
||||
}
|
||||
|
||||
@@ -3399,8 +3399,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] getFromCache(SOUNDINFO soundInfo, SoundTag soundTag) {
|
||||
SoundInfoSoundCacheEntry key = new SoundInfoSoundCacheEntry(soundInfo, soundTag);
|
||||
public byte[] getFromCache(SOUNDINFO soundInfo, SoundTag soundTag, boolean resample) {
|
||||
SoundInfoSoundCacheEntry key = new SoundInfoSoundCacheEntry(soundInfo, soundTag, resample);
|
||||
if (soundCache.contains(key)) {
|
||||
return soundCache.get(key);
|
||||
}
|
||||
|
||||
@@ -993,6 +993,14 @@ public final class Configuration {
|
||||
@ConfigurationCategory("export")
|
||||
public static ConfigurationItem<Boolean> flaExportFixShapes = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("export")
|
||||
public static ConfigurationItem<Boolean> lastExportResampleWav = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(true)
|
||||
@ConfigurationCategory("display")
|
||||
public static ConfigurationItem<Boolean> previewResampleSound = null;
|
||||
|
||||
private enum OSId {
|
||||
WINDOWS, OSX, UNIX
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class SoundExporter {
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName()) + ext);
|
||||
new RetryTask(() -> {
|
||||
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
exportSound(os, st, settings.mode);
|
||||
exportSound(os, st, settings.mode, settings.resampleWav);
|
||||
}
|
||||
}, handler).run();
|
||||
|
||||
@@ -144,13 +144,13 @@ public class SoundExporter {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public byte[] exportSound(SoundTag t, SoundExportMode mode) throws IOException {
|
||||
public byte[] exportSound(SoundTag t, SoundExportMode mode, boolean resampleWav) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
exportSound(baos, t, mode);
|
||||
exportSound(baos, t, mode, resampleWav);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public void exportSound(OutputStream fos, SoundTag st, SoundExportMode mode) throws IOException {
|
||||
public void exportSound(OutputStream fos, SoundTag st, SoundExportMode mode, boolean resampleWav) throws IOException {
|
||||
SoundFormat fmt = st.getSoundFormat();
|
||||
SoundExportFormat nativeFormat = fmt.getNativeExportFormat();
|
||||
|
||||
@@ -194,7 +194,7 @@ public class SoundExporter {
|
||||
}
|
||||
} else {
|
||||
List<ByteArrayRange> soundData = st.getRawSoundData();
|
||||
fmt.createWav(null, soundData, fos, st.getInitialLatency());
|
||||
fmt.createWav(null, soundData, fos, st.getInitialLatency(), resampleWav);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -536,7 +536,7 @@ public class AS3ScriptExporter {
|
||||
return ret;
|
||||
}
|
||||
SoundExporter se = new SoundExporter();
|
||||
se.exportSounds(handler, ASSETS_DIR, rttl, new SoundExportSettings(SoundExportMode.MP3_WAV), evl);
|
||||
se.exportSounds(handler, ASSETS_DIR, rttl, new SoundExportSettings(SoundExportMode.MP3_WAV, exportSettings.resampleWav), evl);
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+5
-1
@@ -38,19 +38,23 @@ public class ScriptExportSettings {
|
||||
public boolean exportEmbed;
|
||||
|
||||
public boolean exportEmbedFlaMode;
|
||||
|
||||
public boolean resampleWav;
|
||||
|
||||
public ScriptExportSettings(
|
||||
ScriptExportMode mode,
|
||||
boolean singleFile,
|
||||
boolean ignoreFrameScripts,
|
||||
boolean exportEmbed,
|
||||
boolean exportEmbedFlaMode
|
||||
boolean exportEmbedFlaMode,
|
||||
boolean resampleWav
|
||||
) {
|
||||
this.mode = mode;
|
||||
this.singleFile = singleFile;
|
||||
this.ignoreFrameScripts = ignoreFrameScripts;
|
||||
this.exportEmbed = exportEmbed;
|
||||
this.exportEmbedFlaMode = exportEmbedFlaMode;
|
||||
this.resampleWav = resampleWav;
|
||||
}
|
||||
|
||||
public String getFileExtension() {
|
||||
|
||||
+4
-1
@@ -27,8 +27,11 @@ public class SoundExportSettings {
|
||||
public static final String EXPORT_FOLDER_NAME = "sounds";
|
||||
|
||||
public SoundExportMode mode;
|
||||
|
||||
public boolean resampleWav;
|
||||
|
||||
public SoundExportSettings(SoundExportMode mode) {
|
||||
public SoundExportSettings(SoundExportMode mode, boolean resampleWav) {
|
||||
this.mode = mode;
|
||||
this.resampleWav = resampleWav;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
|
||||
//This compiled code won't be used at all in original SWF,
|
||||
//it is used only by Flex to properly compile current script
|
||||
AS3ScriptExporter ex = new AS3ScriptExporter();
|
||||
ex.exportActionScript3(swfCopy, null, tempDir.getAbsolutePath(), removedPacks, new ScriptExportSettings(ScriptExportMode.AS_METHOD_STUBS, false, false, false /* ??? FIXME */, false), false, null);
|
||||
ex.exportActionScript3(swfCopy, null, tempDir.getAbsolutePath(), removedPacks, new ScriptExportSettings(ScriptExportMode.AS_METHOD_STUBS, false, false, false /* ??? FIXME */, false, true), false, null);
|
||||
|
||||
//now really remove the classes from SWF copy
|
||||
for (ABC a : modAbcs) {
|
||||
|
||||
@@ -55,7 +55,7 @@ public class AS3ScriptImporter {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
File file = pack.getExportFile(scriptsFolder, new ScriptExportSettings(ScriptExportMode.AS, false, false, false, false));
|
||||
File file = pack.getExportFile(scriptsFolder, new ScriptExportSettings(ScriptExportMode.AS, false, false, false, false, true));
|
||||
if (file.exists()) {
|
||||
Openable openable = pack.getOpenable();
|
||||
SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC) openable).getSwf();
|
||||
|
||||
@@ -224,7 +224,78 @@ public class SoundFormat {
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
public boolean createWav(SOUNDINFO soundInfo, List<ByteArrayRange> dataRanges, OutputStream os, int skipSamples) throws IOException {
|
||||
private byte[] resample(byte[] decodedData) throws IOException {
|
||||
if (samplingRate == 44100) {
|
||||
return decodedData;
|
||||
}
|
||||
boolean resamplingFromStereo = true;
|
||||
|
||||
ByteArrayOutputStream baosResampled = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < decodedData.length; i += (resamplingFromStereo ? 4 : 2)) {
|
||||
if (i + 1 >= decodedData.length) {
|
||||
break;
|
||||
}
|
||||
int left = ((decodedData[i] & 0xff) + ((decodedData[i + 1] & 0xff) << 8)) << 16 >> 16;
|
||||
int right = left;
|
||||
if (resamplingFromStereo)
|
||||
{
|
||||
if (i + 3 >= decodedData.length) {
|
||||
break;
|
||||
}
|
||||
right = ((decodedData[i + 2] & 0xff) + ((decodedData[i + 3] & 0xff) << 8)) << 16 >> 16;
|
||||
}
|
||||
|
||||
int nextLeft = left;
|
||||
int nextRight = right;
|
||||
int nextI = i + (resamplingFromStereo ? 4 : 2);
|
||||
if (nextI < decodedData.length) {
|
||||
nextLeft = ((decodedData[nextI] & 0xff) + ((decodedData[nextI + 1] & 0xff) << 8)) << 16 >> 16;
|
||||
nextRight = nextLeft;
|
||||
if (resamplingFromStereo) {
|
||||
if (nextI + 3 >= decodedData.length) {
|
||||
//ignore
|
||||
} else {
|
||||
nextRight = ((decodedData[nextI + 2] & 0xff) + ((decodedData[nextI + 3] & 0xff) << 8)) << 16 >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeLE(baosResampled, left, 2);
|
||||
writeLE(baosResampled, right, 2);
|
||||
if (samplingRate == 5512) {
|
||||
writeLE(baosResampled, left + (nextLeft - left) / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) / 8, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 2 / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 2 / 8, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 3 / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 3 / 8, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 4 / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 4 / 8, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 5 / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 5 / 8, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 6 / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 6 / 8, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 7 / 8, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 7 / 8, 2);
|
||||
}
|
||||
if (samplingRate == 11025) {
|
||||
writeLE(baosResampled, left + (nextLeft - left) / 4, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) / 4, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 2 / 4, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 2 / 4, 2);
|
||||
writeLE(baosResampled, left + (nextLeft - left) * 3 / 4, 2);
|
||||
writeLE(baosResampled, right + (nextRight - right) * 3 / 4, 2);
|
||||
}
|
||||
if (samplingRate == 22050)
|
||||
{
|
||||
writeLE(baosResampled, (left + nextLeft) / 2, 2);
|
||||
writeLE(baosResampled, (right + nextRight) / 2, 2);
|
||||
}
|
||||
}
|
||||
return baosResampled.toByteArray();
|
||||
}
|
||||
|
||||
public boolean createWav(SOUNDINFO soundInfo, List<ByteArrayRange> dataRanges, OutputStream os, int skipSamples, boolean resample) throws IOException {
|
||||
|
||||
byte[] decodedData = decode(soundInfo, dataRanges, skipSamples);
|
||||
boolean convertedStereo = stereo;
|
||||
@@ -252,8 +323,8 @@ public class SoundFormat {
|
||||
break;
|
||||
}
|
||||
right = ((decodedData[i + 2] & 0xff) + ((decodedData[i + 3] & 0xff) << 8)) << 16 >> 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (soundInfo.hasEnvelope) {
|
||||
for (int e = 0; e < soundInfo.envelopeRecords.length - 1; e++) {
|
||||
int envPosBytes = inPointBytes + (int) (soundInfo.envelopeRecords[e].pos44 * samplingRate / 44100.0 * 2 * (stereo ? 2 : 1));
|
||||
@@ -274,13 +345,16 @@ public class SoundFormat {
|
||||
}
|
||||
|
||||
writeLE(baosFiltered, left, 2);
|
||||
writeLE(baosFiltered, right, 2);
|
||||
writeLE(baosFiltered, right, 2);
|
||||
}
|
||||
convertedStereo = true;
|
||||
}
|
||||
|
||||
|
||||
byte[] resampled = resample ? resample(baosFiltered.toByteArray()) : baosFiltered.toByteArray();
|
||||
|
||||
try {
|
||||
createWavFromPcmData(os, samplingRate, true, convertedStereo, baosFiltered.toByteArray());
|
||||
createWavFromPcmData(os, resample ? 44100 : samplingRate, true, convertedStereo, resampled);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
|
||||
+11
-8
@@ -28,17 +28,20 @@ public class SoundInfoSoundCacheEntry {
|
||||
|
||||
public SOUNDINFO soundInfo;
|
||||
public SoundTag soundTag;
|
||||
public boolean resample;
|
||||
|
||||
public SoundInfoSoundCacheEntry(SOUNDINFO soundInfo, SoundTag soundTag) {
|
||||
public SoundInfoSoundCacheEntry(SOUNDINFO soundInfo, SoundTag soundTag, boolean resample) {
|
||||
this.soundInfo = soundInfo;
|
||||
this.soundTag = soundTag;
|
||||
this.resample = resample;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 47 * hash + Objects.hashCode(this.soundInfo);
|
||||
hash = 47 * hash + Objects.hashCode(this.soundTag);
|
||||
hash = 97 * hash + Objects.hashCode(this.soundInfo);
|
||||
hash = 97 * hash + Objects.hashCode(this.soundTag);
|
||||
hash = 97 * hash + (this.resample ? 1 : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -54,13 +57,13 @@ public class SoundInfoSoundCacheEntry {
|
||||
return false;
|
||||
}
|
||||
final SoundInfoSoundCacheEntry other = (SoundInfoSoundCacheEntry) obj;
|
||||
if (this.resample != other.resample) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.soundInfo, other.soundInfo)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.soundTag, other.soundTag)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return Objects.equals(this.soundTag, other.soundTag);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2139,7 +2139,7 @@ public class XFLConverter {
|
||||
SoundFormat fmt = st.getSoundFormat();
|
||||
byte[] data = SWFInputStream.BYTE_ARRAY_EMPTY;
|
||||
try {
|
||||
data = new SoundExporter().exportSound(st, convertMp3ToWav ? SoundExportMode.WAV : SoundExportMode.MP3_WAV);
|
||||
data = new SoundExporter().exportSound(st, convertMp3ToWav ? SoundExportMode.WAV : SoundExportMode.MP3_WAV, true);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
@@ -5345,7 +5345,7 @@ public class XFLConverter {
|
||||
}
|
||||
if (useAS3 && settings.exportScript) {
|
||||
try {
|
||||
ScriptExportSettings scriptExportSettings = new ScriptExportSettings(ScriptExportMode.AS, false, true, false, true);
|
||||
ScriptExportSettings scriptExportSettings = new ScriptExportSettings(ScriptExportMode.AS, false, true, false, true, true);
|
||||
swf.exportActionScript(handler, scriptsDir.getAbsolutePath(), scriptExportSettings, parallel, null);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Error during ActionScript3 export", ex);
|
||||
|
||||
Reference in New Issue
Block a user