diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java index 490cc06e2..8290ccba2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java @@ -35,7 +35,6 @@ public class SoundStreamBlockTag extends Tag { public static final String NAME = "SoundStreamBlock"; - @HideInRawEdit public ByteArrayRange streamSoundData; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java index 1e40cb8cc..e93c0ea1e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java @@ -40,7 +40,7 @@ import java.util.List; * @author JPEXS */ @SWFVersion(from = 3) -public class SoundStreamHead2Tag extends Tag implements SoundStreamHeadTypeTag { +public class SoundStreamHead2Tag extends SoundStreamHeadTypeTag { public static final int ID = 45; @@ -209,11 +209,6 @@ public class SoundStreamHead2Tag extends Tag implements SoundStreamHeadTypeTag { return false; } - @Override - public boolean setSound(InputStream is, int newSoundFormat) { - return false; - } - @Override public List getRawSoundData() { List ret = new ArrayList<>(); @@ -265,4 +260,29 @@ public class SoundStreamHead2Tag extends Tag implements SoundStreamHeadTypeTag { } //getNeededCharacters intentionally not defined + + @Override + protected void setSoundSize(boolean soundSize) { + this.streamSoundSize = soundSize; + } + + @Override + protected void setSoundType(boolean soundType) { + this.streamSoundType = soundType; + } + + @Override + protected void setSoundSampleCount(int soundSampleCount) { + this.streamSoundSampleCount = soundSampleCount; + } + + @Override + protected void setSoundCompression(int soundCompression) { + this.streamSoundCompression = soundCompression; + } + + @Override + protected void setSoundRate(int soundRate) { + this.streamSoundRate = soundRate; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java index 33c68de9b..51ed15ed2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java @@ -41,7 +41,7 @@ import java.util.List; * @author JPEXS */ @SWFVersion(from = 1) -public class SoundStreamHeadTag extends Tag implements SoundStreamHeadTypeTag { +public class SoundStreamHeadTag extends SoundStreamHeadTypeTag { public static final int ID = 18; @@ -217,12 +217,7 @@ public class SoundStreamHeadTag extends Tag implements SoundStreamHeadTypeTag { @Override public boolean importSupported() { return false; - } - - @Override - public boolean setSound(InputStream is, int newSoundFormat) { - return false; - } + } @Override public List getRawSoundData() { @@ -275,4 +270,29 @@ public class SoundStreamHeadTag extends Tag implements SoundStreamHeadTypeTag { } //getNeededCharacters intentionally not defined + + @Override + protected void setSoundSize(boolean soundSize) { + this.streamSoundSize = soundSize; + } + + @Override + protected void setSoundType(boolean soundType) { + this.streamSoundType = soundType; + } + + @Override + protected void setSoundSampleCount(int soundSampleCount) { + this.streamSoundSampleCount = soundSampleCount; + } + + @Override + protected void setSoundCompression(int soundCompression) { + this.streamSoundCompression = soundCompression; + } + + @Override + protected void setSoundRate(int soundRate) { + this.streamSoundRate = soundRate; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundStreamHeadTypeTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundStreamHeadTypeTag.java index f4ce6c46e..0c9acc260 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundStreamHeadTypeTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundStreamHeadTypeTag.java @@ -16,21 +16,276 @@ */ package com.jpexs.decompiler.flash.tags.base; +import com.jpexs.decompiler.flash.ReadOnlyTagList; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; +import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.types.sound.MP3FRAME; +import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.Helper; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; /** * * @author JPEXS */ -public interface SoundStreamHeadTypeTag extends CharacterIdTag, SoundTag { +public abstract class SoundStreamHeadTypeTag extends Tag implements CharacterIdTag, SoundTag { + + public SoundStreamHeadTypeTag(SWF swf, int id, String name, ByteArrayRange data) { + super(swf, id, name, data); + } @Override - public boolean getSoundSize(); + public abstract boolean getSoundSize(); - public long getSoundSampleCount(); + public abstract long getSoundSampleCount(); - public void setVirtualCharacterId(int ch); + public abstract void setVirtualCharacterId(int ch); + + public abstract List getBlocks(); + + protected abstract void setSoundSize(boolean soundSize); + + protected abstract void setSoundType(boolean soundType); + + protected abstract void setSoundSampleCount(int soundSampleCount); + + protected abstract void setSoundCompression(int soundCompression); + + protected abstract void setSoundRate(int soundRate); + + @Override + public boolean setSound(InputStream is, int newSoundFormat) throws UnsupportedSamplingRateException { + + List mp3Frames = null; + int newSoundRate = -1; + boolean newSoundSize = false; + boolean newSoundType = false; + long newSoundSampleCount = -1; + byte[] uncompressedSoundData = null; + int bytesPerSwfFrame = -1; + SWF swf = getSwf(); + switch (newSoundFormat) { + case SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: + try (AudioInputStream audioIs = AudioSystem.getAudioInputStream(new BufferedInputStream(is))) { + AudioFormat fmt = audioIs.getFormat(); + newSoundType = fmt.getChannels() == 2; + newSoundSize = fmt.getSampleSizeInBits() == 16; + //newSoundSampleCount = audioIs.getFrameLength(); + uncompressedSoundData = Helper.readStream(audioIs); + int sampleLen = (newSoundType ? 2 : 1) * (newSoundSize ? 2 : 1); + newSoundRate = (int) Math.round(fmt.getSampleRate()); + newSoundSampleCount = (int) Math.ceil(newSoundRate / swf.frameRate); + + bytesPerSwfFrame = (int) Math.ceil(newSoundRate / swf.frameRate) * sampleLen; + switch (newSoundRate) { + case 5512: + newSoundRate = 0; + break; + case 11025: + newSoundRate = 1; + break; + case 22050: + newSoundRate = 2; + break; + case 44100: + newSoundRate = 3; + break; + default: + throw new UnsupportedSamplingRateException(newSoundRate, new int[]{5512, 11025, 22050, 44100}); + } + + } catch (UnsupportedAudioFileException | IOException ex) { + return false; + } + break; + case SoundFormat.FORMAT_MP3: + BufferedInputStream bis = new BufferedInputStream(is); + loadID3v2(bis); + byte[] mp3data = Helper.readStream(bis); + + final int ID3_V1_LENTGH = 128; + final int ID3_V1_EXT_LENGTH = 227; + + if (mp3data.length > ID3_V1_LENTGH) { + //ID3v1 + if (mp3data[mp3data.length - ID3_V1_LENTGH] == 'T' && mp3data[mp3data.length - ID3_V1_LENTGH + 1] == 'A' && mp3data[mp3data.length - ID3_V1_LENTGH + 2] == 'G') { + mp3data = Arrays.copyOf(mp3data, mp3data.length - ID3_V1_LENTGH); + if (mp3data.length > ID3_V1_EXT_LENGTH) { + //ID3v1 extended + if (mp3data[mp3data.length - ID3_V1_EXT_LENGTH] == 'T' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 1] == 'A' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 2] == 'G' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 3] == '+') { + mp3data = Arrays.copyOf(mp3data, mp3data.length - ID3_V1_EXT_LENGTH); + } + } + } + } + try { + MP3SOUNDDATA snd = new MP3SOUNDDATA(new SWFInputStream(swf, mp3data), true); + if (!snd.frames.isEmpty()) { + MP3FRAME fr = snd.frames.get(0); + newSoundRate = fr.getSamplingRate(); + switch (newSoundRate) { + case 11025: + newSoundRate = 1; + break; + case 22050: + newSoundRate = 2; + break; + case 44100: + newSoundRate = 3; + break; + default: + throw new UnsupportedSamplingRateException(newSoundRate, new int[]{11025, 22050, 44100}); + } + + newSoundSize = true; + newSoundType = fr.isStereo(); + int len = snd.sampleCount(); + if (fr.isStereo()) { + len = len / 2; + } + + newSoundSampleCount = len; + } + + mp3Frames = snd.frames; + } catch (IOException ex) { + return false; + } + break; + default: + return false; + } + + ByteArrayInputStream bais = uncompressedSoundData == null ? null : new ByteArrayInputStream(uncompressedSoundData); + + List existingBlocks = getBlocks(); + int startFrame = 0; + Timelined timelined = getTimelined(); + if (!existingBlocks.isEmpty()) { + ReadOnlyTagList tags = timelined.getTags(); + for (Tag t : tags) { + if (t instanceof ShowFrameTag) { + startFrame++; + } + if (t instanceof SoundStreamBlockTag) { + break; + } + } + } + for (SoundStreamBlockTag block : existingBlocks) { + timelined.removeTag(block); + } + + List blocks = new ArrayList<>(); + if (bais != null) { + DataInputStream dais = new DataInputStream(bais); + try { + while (dais.available() > 0) { + byte buf[] = new byte[bytesPerSwfFrame]; + + dais.readFully(buf); + SoundStreamBlockTag block = new SoundStreamBlockTag(swf); + block.streamSoundData = new ByteArrayRange(buf); + blocks.add(block); + } + } catch (IOException ex) { + //ignore + } + } + + ReadOnlyTagList tags = timelined.getTags(); + int frame = -1; + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if (t instanceof ShowFrameTag) { + frame++; + if (frame >= startFrame && !blocks.isEmpty()) { + SoundStreamBlockTag block = blocks.remove(0); + timelined.addTag(i, block); + tags = timelined.getTags(); + i++; + } + } + } + setSoundCompression(newSoundFormat); + setSoundSampleCount((int)newSoundSampleCount); + setSoundSize(newSoundSize); + setSoundType(newSoundType); + setSoundRate(newSoundRate); + + setModified(true); + timelined.resetTimeline(); + swf.resetTimeline(); //to reload blocks + return true; + } + + private void loadID3v2(InputStream in) { + int size = -1; + try { + // Read ID3v2 header (10 bytes). + in.mark(10); + size = readID3v2Header(in); + } catch (IOException e) { + } finally { + try { + // Unread ID3v2 header (10 bytes). + in.reset(); + } catch (IOException e) { + } + } + // Load ID3v2 tags. + try { + if (size > 0) { + byte[] rawid3v2 = new byte[size]; + in.read(rawid3v2, 0, rawid3v2.length); + } + } catch (IOException e) { + } + } + + /** + * Parse ID3v2 tag header to find out size of ID3v2 frames. + * + * @param in MP3 InputStream + * @return size of ID3v2 frames + header + * @throws IOException + * @author JavaZOOM + */ + private int readID3v2Header(InputStream in) throws IOException { + byte[] id3header = new byte[4]; + int size = -10; + in.read(id3header, 0, 3); + // Look for ID3v2 + if ((id3header[0] == 'I') && (id3header[1] == 'D') && (id3header[2] == '3')) { + in.read(id3header, 0, 3); + int majorVersion = id3header[0]; + int revision = id3header[1]; + in.read(id3header, 0, 4); + size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]); + } + return (size + 10); + } - public List getBlocks(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 8287c5d36..eba9eef31 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1766,9 +1766,10 @@ public class XFLConverter { for (int ch : characters.keySet()) { CharacterTag symbol = characters.get(ch); if (symbol instanceof ImageTag - || symbol instanceof SoundStreamHeadTypeTag || symbol instanceof DefineSoundTag + || symbol instanceof DefineSoundTag || symbol instanceof DefineVideoStreamTag) { - hasMedia = true; + //symbol instanceof SoundStreamHeadTypeTag FIXME + hasMedia = true; } } @@ -1854,7 +1855,7 @@ public class XFLConverter { writer.writeAttribute("frameBottom", image.getHeight()); writer.writeEndElement(); mediaCount++; - } else if ((symbol instanceof SoundStreamHeadTypeTag) || (symbol instanceof DefineSoundTag)) { + } else if (/*(symbol instanceof SoundStreamHeadTypeTag) || FIXME */(symbol instanceof DefineSoundTag)) { int soundFormat = 0; int soundRate = 0; boolean soundType = false; @@ -1863,8 +1864,8 @@ public class XFLConverter { byte[] soundData = SWFInputStream.BYTE_ARRAY_EMPTY; int[] rateMap = {5, 11, 22, 44}; String exportFormat = "flv"; - if (symbol instanceof SoundStreamHeadTypeTag) { - SoundStreamHeadTypeTag sstream = (SoundStreamHeadTypeTag) symbol; + if (false) { //FIXME symbol instanceof SoundStreamHeadTypeTag) { + SoundStreamHeadTypeTag sstream = null; //(SoundStreamHeadTypeTag) symbol; soundFormat = sstream.getSoundFormatId(); soundRate = sstream.getSoundRate(); soundType = sstream.getSoundType(); diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds.swf b/libsrc/ffdec_lib/testdata/sounds/sounds.swf index 8f230cd10..5b54f04c0 100644 Binary files a/libsrc/ffdec_lib/testdata/sounds/sounds.swf and b/libsrc/ffdec_lib/testdata/sounds/sounds.swf differ diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds/DOMDocument.xml b/libsrc/ffdec_lib/testdata/sounds/sounds/DOMDocument.xml index c0fdf4c80..988fda413 100644 --- a/libsrc/ffdec_lib/testdata/sounds/sounds/DOMDocument.xml +++ b/libsrc/ffdec_lib/testdata/sounds/sounds/DOMDocument.xml @@ -3,25 +3,60 @@ + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -29,9 +64,9 @@ - + - + @@ -68,26 +103,19 @@ - + + + + - - - - + - - - - - - - - + @@ -96,12 +124,28 @@ + + + + + + + + + + + + + + + + + + + - - - - + @@ -121,6 +165,9 @@ + + + @@ -137,9 +184,12 @@ - + + + + - + @@ -154,7 +204,10 @@ - + + + + @@ -171,9 +224,12 @@ - + + + + - + @@ -188,7 +244,10 @@ - + + + + @@ -196,7 +255,32 @@ - 006 Stop + 006 SoundStream + + + + + + + + + + + + + + + + + + + + + + + + + 007 Stop @@ -212,6 +296,12 @@ + + + + + + @@ -226,11 +316,5 @@ - - - - - - \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/514508_gis-sweden_background-techno-loop131bpm_part.mp3 b/libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/514508_gis-sweden_background-techno-loop131bpm_part.mp3 new file mode 100644 index 000000000..4b50c44c4 Binary files /dev/null and b/libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/514508_gis-sweden_background-techno-loop131bpm_part.mp3 differ diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/Symbol 1.xml b/libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/Symbol 1.xml new file mode 100644 index 000000000..b5f023637 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/Symbol 1.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds/META-INF/metadata.xml b/libsrc/ffdec_lib/testdata/sounds/sounds/META-INF/metadata.xml index 1a30c90f4..d9075bc2e 100644 --- a/libsrc/ffdec_lib/testdata/sounds/sounds/META-INF/metadata.xml +++ b/libsrc/ffdec_lib/testdata/sounds/sounds/META-INF/metadata.xml @@ -5,8 +5,8 @@ xmlns:xmp="http://ns.adobe.com/xap/1.0/"> Adobe Flash Professional CS6 - build 481 2021-03-14T08:29:20+01:00 - 2022-12-25T06:15:04-08:00 - 2022-12-25T06:15:04-08:00 + 2022-12-26T06:37:55-08:00 + 2022-12-26T06:37:55-08:00 @@ -16,7 +16,7 @@ xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"> - xmp.iid:21E4449F4B7EED119DEE8735AA8CEAC4 + xmp.iid:6034FB37F884ED119D8BF78AEC309D40 xmp.did:21E4449F4B7EED119DEE8735AA8CEAC4 xmp.did:D6D3FE199784EB1187FEAE6972EC5115 @@ -147,6 +147,12 @@ 2021-03-14T08:29:20+01:00 Adobe Flash Professional CS6 - build 481 + + created + xmp.iid:6034FB37F884ED119D8BF78AEC309D40 + 2021-03-14T08:29:20+01:00 + Adobe Flash Professional CS6 - build 481 + diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds/bin/M 3 1672066332.dat b/libsrc/ffdec_lib/testdata/sounds/sounds/bin/M 3 1672066332.dat new file mode 100644 index 000000000..d05c14f07 Binary files /dev/null and b/libsrc/ffdec_lib/testdata/sounds/sounds/bin/M 3 1672066332.dat differ diff --git a/libsrc/ffdec_lib/testdata/sounds/sounds/bin/SymDepend.cache b/libsrc/ffdec_lib/testdata/sounds/sounds/bin/SymDepend.cache index f66172864..2b9fba045 100644 Binary files a/libsrc/ffdec_lib/testdata/sounds/sounds/bin/SymDepend.cache and b/libsrc/ffdec_lib/testdata/sounds/sounds/bin/SymDepend.cache differ diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index c373bc647..473e90d9a 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -172,6 +172,7 @@ import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler; import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; +import com.jpexs.decompiler.flash.tags.base.SoundImportException; import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag; @@ -4032,7 +4033,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se TreeItem ti0 = items.get(0); File file = null; - if (ti0 instanceof DefineSoundTag) { + if (ti0 instanceof SoundTag) { file = showImportFileChooser("filter.sounds|*.mp3;*.wav|filter.sounds.mp3|*.mp3|filter.sounds.wav|*.wav", false); } if (ti0 instanceof ImageTag) { @@ -4059,9 +4060,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (selectedFile == null) { return; } - if (item instanceof DefineSoundTag) { + if (item instanceof SoundTag) { File selfile = Helper.fixDialogFile(selectedFile); - DefineSoundTag ds = (DefineSoundTag) item; + SoundTag st = (SoundTag) item; int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN; if (selfile.getName().toLowerCase(Locale.ENGLISH).endsWith(".mp3")) { soundFormat = SoundFormat.FORMAT_MP3; @@ -4069,8 +4070,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se boolean ok = false; try { - ok = ds.setSound(new FileInputStream(selfile), soundFormat); - ds.getSwf().clearSoundCache(); + ok = st.setSound(new FileInputStream(selfile), soundFormat); + ((Tag)st).getSwf().clearSoundCache(); } catch (IOException ex) { //ignore } catch (UnsupportedSamplingRateException ex) { @@ -4081,6 +4082,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } ViewMessages.showMessageDialog(this, translate("error.sound.rate").replace("%saplingRate%", samplingRateKhz).replace("%supportedRates%", String.join(", ", supportedRatesKhz)), translate("error"), JOptionPane.ERROR_MESSAGE); return; + } catch (SoundImportException ex) { + //ignore } if (!ok) { @@ -4823,7 +4826,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se previewPanel.showImagePanel(timelinedContainer, swf, frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) { previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32"))); - previewPanel.setImageReplaceButtonVisible(false, false, false, !((Tag) treeItem).isReadOnly() && (treeItem instanceof DefineSoundTag), false); + previewPanel.setImageReplaceButtonVisible(false, false, false, !((Tag) treeItem).isReadOnly() && (treeItem instanceof SoundTag), false); try { SoundTagPlayer soundThread = new SoundTagPlayer(null, (SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true); if (!Configuration.autoPlaySounds.get()) { diff --git a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java index 6b490e7a0..a4d1e87eb 100644 --- a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java +++ b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.gui.player.Zoom; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; import com.jpexs.helpers.ByteArrayRange; import java.awt.Color; import java.awt.image.BufferedImage; @@ -197,7 +198,9 @@ public class SoundTagPlayer implements MediaDisplay { } long soundLength44 = 0; - int sampleLen = 2 * (tag.getSoundFormat().stereo ? 2 : 1); + boolean isUnCompressed = tag.getSoundFormatId() == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN || + tag.getSoundFormatId() == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN; + int sampleLen = (isUnCompressed ? (tag.getSoundSize() ? 2 : 1) : 2) * (tag.getSoundFormat().stereo ? 2 : 1); switch (tag.getSoundRate()) { case 0: //5.5kHz soundLength44 = 8 * tag.getTotalSoundSampleCount(); diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 4dcec21fe..f3e35c753 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -67,6 +67,7 @@ import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; +import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.timeline.AS2Package; import com.jpexs.decompiler.flash.timeline.AS3Package; @@ -973,7 +974,7 @@ public class TagTreeContextMenu extends JPopupMenu { replaceMenuItem.setVisible(true); } - if (canReplace.test(it -> it instanceof DefineSoundTag)) { + if (canReplace.test(it -> it instanceof SoundTag)) { replaceMenuItem.setVisible(true); }