mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-24 23:21:21 +00:00
Added: Importing sound stream block ranges
Added: Commandline replacing sound stream block ranges
This commit is contained in:
@@ -28,6 +28,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
- [#2463] Export subsprites animation context menu on frames
|
- [#2463] Export subsprites animation context menu on frames
|
||||||
- Open in the Flash Player context menu on graphic/sound tags and frames
|
- Open in the Flash Player context menu on graphic/sound tags and frames
|
||||||
- [#2451] Replacing sound stream block ranges
|
- [#2451] Replacing sound stream block ranges
|
||||||
|
- Importing sound stream block ranges
|
||||||
|
- Commandline replacing sound stream block ranges
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- AS1/2 - Single DoAction tag inside frame is now displayed directly as frame node
|
- AS1/2 - Single DoAction tag inside frame is now displayed directly as frame node
|
||||||
|
|||||||
@@ -370,9 +370,9 @@ public class SoundImporter {
|
|||||||
|| newSoundType != streamHead.getSoundType()
|
|| newSoundType != streamHead.getSoundType()
|
||||||
|| newSoundRate != streamHead.getSoundRate()) {
|
|| newSoundRate != streamHead.getSoundRate()) {
|
||||||
throw new SoundParametersMismatchException(
|
throw new SoundParametersMismatchException(
|
||||||
streamHead.getSoundType(),
|
streamHead.getSoundType(),
|
||||||
streamHead.getSoundSize(),
|
streamHead.getSoundSize(),
|
||||||
streamHead.getSoundRate(),
|
streamHead.getSoundRate(),
|
||||||
streamHead.getSoundFormatId(),
|
streamHead.getSoundFormatId(),
|
||||||
newSoundType,
|
newSoundType,
|
||||||
newSoundSize,
|
newSoundSize,
|
||||||
@@ -405,8 +405,8 @@ public class SoundImporter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (SoundStreamFrameRange range : ranges) {
|
for (SoundStreamFrameRange range : ranges) {
|
||||||
if (range.startFrame == startFrame) {
|
if (range.startFrame == startFrame) {
|
||||||
existingBlocks.addAll(range.blocks);
|
existingBlocks.addAll(range.blocks);
|
||||||
@@ -414,7 +414,7 @@ public class SoundImporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SoundStreamBlockTag block : existingBlocks) {
|
for (SoundStreamBlockTag block : existingBlocks) {
|
||||||
timelined.removeTag(block);
|
timelined.removeTag(block);
|
||||||
}
|
}
|
||||||
@@ -552,15 +552,16 @@ public class SoundImporter {
|
|||||||
* @param soundTag Sound tag
|
* @param soundTag Sound tag
|
||||||
* @param is Input stream
|
* @param is Input stream
|
||||||
* @param newSoundFormat New sound format
|
* @param newSoundFormat New sound format
|
||||||
|
* @param startFrame Starting frame. null = autodetect, replace all
|
||||||
* @return True if sound was imported successfully
|
* @return True if sound was imported successfully
|
||||||
* @throws SoundImportException On sound import error
|
* @throws SoundImportException On sound import error
|
||||||
*/
|
*/
|
||||||
public boolean importSound(SoundTag soundTag, InputStream is, int newSoundFormat) throws SoundImportException {
|
public boolean importSound(SoundTag soundTag, InputStream is, int newSoundFormat, Integer startFrame) throws SoundImportException {
|
||||||
if (soundTag instanceof DefineSoundTag) {
|
if (soundTag instanceof DefineSoundTag) {
|
||||||
return importDefineSound((DefineSoundTag) soundTag, is, newSoundFormat);
|
return importDefineSound((DefineSoundTag) soundTag, is, newSoundFormat);
|
||||||
}
|
}
|
||||||
if (soundTag instanceof SoundStreamHeadTypeTag) {
|
if (soundTag instanceof SoundStreamHeadTypeTag) {
|
||||||
return importSoundStream((SoundStreamHeadTypeTag) soundTag, is, newSoundFormat);
|
return importSoundStreamAtFrame((SoundStreamHeadTypeTag) soundTag, is, newSoundFormat, startFrame);
|
||||||
}
|
}
|
||||||
if (soundTag instanceof SoundStreamFrameRange) {
|
if (soundTag instanceof SoundStreamFrameRange) {
|
||||||
return importSoundStreamAtFrame(((SoundStreamFrameRange) soundTag).getHead(), is, newSoundFormat, ((SoundStreamFrameRange) soundTag).startFrame);
|
return importSoundStreamAtFrame(((SoundStreamFrameRange) soundTag).getHead(), is, newSoundFormat, ((SoundStreamFrameRange) soundTag).startFrame);
|
||||||
@@ -595,16 +596,21 @@ public class SoundImporter {
|
|||||||
});
|
});
|
||||||
|
|
||||||
List<SoundTag> soundTags = new ArrayList<>();
|
List<SoundTag> soundTags = new ArrayList<>();
|
||||||
|
|
||||||
|
List<List<SoundStreamFrameRange>> ranges = new ArrayList<>();
|
||||||
for (int characterId : characters.keySet()) {
|
for (int characterId : characters.keySet()) {
|
||||||
CharacterTag tag = characters.get(characterId);
|
CharacterTag tag = characters.get(characterId);
|
||||||
if (tag instanceof DefineSoundTag) {
|
if (tag instanceof DefineSoundTag) {
|
||||||
soundTags.add((DefineSoundTag) tag);
|
soundTags.add((DefineSoundTag) tag);
|
||||||
|
ranges.add(new ArrayList<>());
|
||||||
}
|
}
|
||||||
if (tag instanceof DefineSpriteTag) {
|
if (tag instanceof DefineSpriteTag) {
|
||||||
DefineSpriteTag sprite = (DefineSpriteTag) tag;
|
DefineSpriteTag sprite = (DefineSpriteTag) tag;
|
||||||
for (Tag subTag : sprite.getTags()) {
|
for (Tag subTag : sprite.getTags()) {
|
||||||
if (subTag instanceof SoundStreamHeadTypeTag) {
|
if (subTag instanceof SoundStreamHeadTypeTag) {
|
||||||
soundTags.add((SoundStreamHeadTypeTag) subTag);
|
soundTags.add((SoundStreamHeadTypeTag) subTag);
|
||||||
|
ranges.add(sprite.getTimeline().getSoundStreamBlocks((SoundStreamHeadTypeTag) subTag));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -612,10 +618,14 @@ public class SoundImporter {
|
|||||||
for (Tag tag : swf.getTags()) {
|
for (Tag tag : swf.getTags()) {
|
||||||
if (tag instanceof SoundStreamHeadTypeTag) {
|
if (tag instanceof SoundStreamHeadTypeTag) {
|
||||||
soundTags.add((SoundStreamHeadTypeTag) tag);
|
soundTags.add((SoundStreamHeadTypeTag) tag);
|
||||||
|
ranges.add(swf.getTimeline().getSoundStreamBlocks((SoundStreamHeadTypeTag) tag));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SoundTag tag : soundTags) {
|
int pos = -1;
|
||||||
|
loopChars: for (SoundTag tag : soundTags) {
|
||||||
|
pos++;
|
||||||
int characterId = tag.getCharacterId();
|
int characterId = tag.getCharacterId();
|
||||||
List<File> existingFilesForSoundTag = new ArrayList<>();
|
List<File> existingFilesForSoundTag = new ArrayList<>();
|
||||||
|
|
||||||
@@ -656,8 +666,38 @@ public class SoundImporter {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ranges.get(pos).isEmpty()) {
|
||||||
|
for (SoundStreamFrameRange r : ranges.get(pos)) {
|
||||||
|
for (File sourceFile : existingFilesForSoundTag) {
|
||||||
|
if (sourceFile.getName().startsWith("" + characterId + "_" + (r.startFrame + 1) + "-")) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (printOut) {
|
||||||
|
System.out.println("Importing character " + characterId + ", start frame " + r.startFrame + " from file " + sourceFile.getName());
|
||||||
|
}
|
||||||
|
int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN;
|
||||||
|
if (sourceFile.getAbsolutePath().toLowerCase(Locale.ENGLISH).endsWith(".mp3")) {
|
||||||
|
soundFormat = SoundFormat.FORMAT_MP3;
|
||||||
|
}
|
||||||
|
try (FileInputStream fis = new FileInputStream(sourceFile)) {
|
||||||
|
importSound(tag, fis, soundFormat, r.startFrame);
|
||||||
|
soundCount++;
|
||||||
|
}
|
||||||
|
} catch (IOException | SoundImportException ex) {
|
||||||
|
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Cannot import sound " + characterId + " from file " + sourceFile.getName(), ex);
|
||||||
|
}
|
||||||
|
if (CancellableWorker.isInterrupted()) {
|
||||||
|
break loopChars;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (existingFilesForSoundTag.size() > 1) {
|
if (existingFilesForSoundTag.size() > 1) {
|
||||||
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Multiple matching files for sound tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForSoundTag.get(0).getName()});
|
Logger.getLogger(SoundImporter.class.getName()).log(Level.WARNING, "Multiple matching files for sound tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForSoundTag.get(0).getName()});
|
||||||
}
|
}
|
||||||
File sourceFile = existingFilesForSoundTag.get(0);
|
File sourceFile = existingFilesForSoundTag.get(0);
|
||||||
|
|
||||||
@@ -670,7 +710,7 @@ public class SoundImporter {
|
|||||||
soundFormat = SoundFormat.FORMAT_MP3;
|
soundFormat = SoundFormat.FORMAT_MP3;
|
||||||
}
|
}
|
||||||
try (FileInputStream fis = new FileInputStream(sourceFile)) {
|
try (FileInputStream fis = new FileInputStream(sourceFile)) {
|
||||||
importSound(tag, fis, soundFormat);
|
importSound(tag, fis, soundFormat, null);
|
||||||
soundCount++;
|
soundCount++;
|
||||||
}
|
}
|
||||||
} catch (IOException | SoundImportException ex) {
|
} catch (IOException | SoundImportException ex) {
|
||||||
|
|||||||
@@ -80,7 +80,9 @@ public class SoundStreamFrameRange implements TreeItem, SoundTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean importSupported() {
|
public boolean importSupported() {
|
||||||
return true;
|
return head.getSoundFormatId() == SoundFormat.FORMAT_MP3
|
||||||
|
|| head.getSoundFormatId() == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN
|
||||||
|
|| head.getSoundFormatId() == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -132,7 +134,6 @@ public class SoundStreamFrameRange implements TreeItem, SoundTag {
|
|||||||
return "SoundStreamBlocks";
|
return "SoundStreamBlocks";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SoundFormat getSoundFormat() {
|
public SoundFormat getSoundFormat() {
|
||||||
return head.getSoundFormat();
|
return head.getSoundFormat();
|
||||||
@@ -177,7 +178,6 @@ public class SoundStreamFrameRange implements TreeItem, SoundTag {
|
|||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SoundStreamBlocks (frame " + (startFrame + 1) + " - " + (endFrame + 1) + ")";
|
return "SoundStreamBlocks (frame " + (startFrame + 1) + " - " + (endFrame + 1) + ")";
|
||||||
|
|||||||
@@ -3001,7 +3001,7 @@ public class CommandLineArgumentParser {
|
|||||||
try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) {
|
try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) {
|
||||||
SWF swf = new SWF(is, Configuration.parallelSpeedUp.get(), charset);
|
SWF swf = new SWF(is, Configuration.parallelSpeedUp.get(), charset);
|
||||||
while (true) {
|
while (true) {
|
||||||
String objectToReplace = args.pop();
|
String objectToReplace = args.pop();
|
||||||
|
|
||||||
if (objectToReplace.matches("\\d+")) {
|
if (objectToReplace.matches("\\d+")) {
|
||||||
// replace character tag
|
// replace character tag
|
||||||
@@ -3104,10 +3104,29 @@ public class CommandLineArgumentParser {
|
|||||||
}).importText(textTag, new String(data, Utf8Helper.charset));
|
}).importText(textTag, new String(data, Utf8Helper.charset));
|
||||||
} else if (characterTag instanceof SoundTag) {
|
} else if (characterTag instanceof SoundTag) {
|
||||||
SoundTag st = (SoundTag) characterTag;
|
SoundTag st = (SoundTag) characterTag;
|
||||||
|
Integer startFrame = null;
|
||||||
|
if (!args.isEmpty()) {
|
||||||
|
if (args.peek().toLowerCase(Locale.ENGLISH).equals("-startframe")) {
|
||||||
|
args.pop();
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
System.err.println("Frame number must be specified");
|
||||||
|
badArguments("replace");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
startFrame = Integer.parseInt(args.pop());
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
System.err.println("Frame number should be integer");
|
||||||
|
badArguments("replace");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
SoundImporter soundImporter = new SoundImporter();
|
SoundImporter soundImporter = new SoundImporter();
|
||||||
try {
|
try {
|
||||||
ok = soundImporter.importSound(st, new ByteArrayInputStream(data), soundFormat);
|
ok = soundImporter.importSound(st, new ByteArrayInputStream(data), soundFormat, startFrame);
|
||||||
|
} catch (SoundParametersMismatchException spm) {
|
||||||
|
System.err.println("Import FAILED. " + spm.getMessage());
|
||||||
|
System.exit(3);
|
||||||
} catch (UnsupportedSamplingRateException usre) {
|
} catch (UnsupportedSamplingRateException usre) {
|
||||||
List<String> supportedRatesStr = new ArrayList<>();
|
List<String> supportedRatesStr = new ArrayList<>();
|
||||||
for (int i : usre.getSupportedRates()) {
|
for (int i : usre.getSupportedRates()) {
|
||||||
|
|||||||
@@ -98,18 +98,21 @@ alias /?
|
|||||||
Convert FlashPaper SWF file <infile> to PDF <outfile>.
|
Convert FlashPaper SWF file <infile> to PDF <outfile>.
|
||||||
Use -zoom parameter to specify image quality.
|
Use -zoom parameter to specify image quality.
|
||||||
|
|
||||||
-replace <infile> <outfile> (<characterId1>|<scriptName1>) <importDataFile1> \
|
-replace <infile> <outfile> \
|
||||||
[nofill] ([<format1>][<methodBodyIndex1>]) \
|
(<characterId1>|<scriptName1>) <importDataFile1> \
|
||||||
[(<characterId2>|<scriptName2>) <importDataFile2> \
|
[nofill] [-startFrame <startFrame>] ([<format1>][<methodBodyIndex1>]) \
|
||||||
[nofill] ([<format2>][<methodBodyIndex2>])]...
|
[(<characterId2>|<scriptName2>) <importDataFile2> \
|
||||||
|
[nofill] [-startFrame <startFrame>] ([<format2>][<methodBodyIndex2>])]...
|
||||||
Replace data.
|
Replace data.
|
||||||
Replaces the data of the specified BinaryData, Image, Shape, Text,
|
Replaces the data of the specified BinaryData, Image, Shape, Text,
|
||||||
Sound tag or Script.
|
Sound tag or Script.
|
||||||
nofill parameter can be specified only for shape replace.
|
nofill parameter can be specified only for shape replace.
|
||||||
|
<startFrame> parameter sets sound range start frame (for sound streams)
|
||||||
<format> parameter can be specified for Image and Shape tags.
|
<format> parameter can be specified for Image and Shape tags.
|
||||||
valid formats: lossless, lossless2, jpeg2, jpeg3, jpeg4.
|
valid formats: lossless, lossless2, jpeg2, jpeg3, jpeg4.
|
||||||
<methodBodyIndexN> parameter should be specified if and only if the imported entity is an AS3 P-Code.
|
<methodBodyIndexN> parameter should be specified if and only if the imported entity is an AS3 P-Code.
|
||||||
Use -1 as characterId to replace main timeline SoundStreamHead.
|
Use -1 as characterId to replace main timeline SoundStreamHead.
|
||||||
|
|
||||||
-replace <infile> <outfile> <argsfile>
|
-replace <infile> <outfile> <argsfile>
|
||||||
Replace data using argsfile.
|
Replace data using argsfile.
|
||||||
Same as -replace command, but the rest of arguments is read as lines from
|
Same as -replace command, but the rest of arguments is read as lines from
|
||||||
|
|||||||
@@ -5175,7 +5175,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
|
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
try {
|
try {
|
||||||
ok = soundImporter.importSound(st, new FileInputStream(selfile), soundFormat);
|
ok = soundImporter.importSound(st, new FileInputStream(selfile), soundFormat, null);
|
||||||
((SWF) ((TreeItem) st).getOpenable()).clearSoundCache();
|
((SWF) ((TreeItem) st).getOpenable()).clearSoundCache();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
//ignore
|
//ignore
|
||||||
|
|||||||
Reference in New Issue
Block a user