From 5aadfcc3740a5144a97fb04710777d41e167292a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 19 Sep 2014 22:01:35 +0200 Subject: [PATCH] Issue #684 Fixed sound streams inside DefineSprites, fixed sound stream blocks handling --- .../flash/exporters/SoundExporter.java | 21 ++++++++--- .../decompiler/flash/tags/DefineSoundTag.java | 14 +++++--- .../flash/tags/SoundStreamHead2Tag.java | 26 +++++++------- .../flash/tags/SoundStreamHeadTag.java | 35 +++++++++---------- .../decompiler/flash/tags/base/SoundTag.java | 6 ++-- .../flash/types/sound/SoundFormat.java | 10 ++++-- .../decompiler/flash/gui/SoundTagPlayer.java | 8 +++-- .../decompiler/flash/gui/TagTreeModel.java | 12 +++++++ 8 files changed, 84 insertions(+), 48 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java index 1accd9114..6bc70f02d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.exporters; import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; @@ -118,12 +119,18 @@ public class SoundExporter { int nativeFormat = fmt.getNativeExportFormat(); if (nativeFormat == SoundFormat.EXPORT_MP3 && mode.hasMP3()) { - fos.write(st.getRawSoundData()); + List datas=st.getRawSoundData(); + for(byte[] data:datas){ + fos.write(data); + } } else if ((nativeFormat == SoundFormat.EXPORT_FLV && mode.hasFlv()) || mode == SoundExportMode.FLV) { if (st instanceof DefineSoundTag) { FLVOutputStream flv = new FLVOutputStream(fos); flv.writeHeader(true, false); - flv.writeTag(new FLVTAG(0, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), st.getRawSoundData()))); + List datas=st.getRawSoundData(); + for(byte[] data:datas){ + flv.writeTag(new FLVTAG(0, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), data))); + } } else if (st instanceof SoundStreamHeadTypeTag) { SoundStreamHeadTypeTag sh = (SoundStreamHeadTypeTag) st; FLVOutputStream flv = new FLVOutputStream(fos); @@ -140,9 +147,13 @@ public class SoundExporter { } } } else { - byte[] soundData = st.getRawSoundData(); + List soundData = st.getRawSoundData(); SWF swf = ((Tag) st).getSwf(); - fmt.createWav(new SWFInputStream(swf, soundData), fos); + List siss=new ArrayList<>(); + for(byte[] data:soundData){ + siss.add(new SWFInputStream(swf, data)); + } + fmt.createWav(siss, fos); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java index 2cae3d8b8..ccd8f575b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; @@ -32,7 +33,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; @@ -303,11 +306,14 @@ public class DefineSoundTag extends CharacterTag implements SoundTag { } @Override - public byte[] getRawSoundData() { + public List getRawSoundData() { + List ret=new ArrayList(); if (soundFormat == SoundFormat.FORMAT_MP3) { - return Arrays.copyOfRange(soundData, 2, soundData.length); + ret.add(Arrays.copyOfRange(soundData, 2, soundData.length)); + return ret; } - return soundData; + ret.add(soundData); + return ret; } @Override 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 239d16c7c..bac13d946 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 @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWFInputStream; @@ -31,6 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -180,7 +182,7 @@ public class SoundStreamHead2Tag extends CharacterIdTag implements SoundStreamHe @Override public List getBlocks() { List ret = new ArrayList<>(); - SoundStreamHeadTag.populateSoundStreamBlocks(swf.tags, this, ret); + SoundStreamHeadTag.populateSoundStreamBlocks(0,swf.tags, this, ret); return ret; } @@ -196,21 +198,17 @@ public class SoundStreamHead2Tag extends CharacterIdTag implements SoundStreamHe } @Override - public byte[] getRawSoundData() { + public List getRawSoundData() { + List ret = new ArrayList(); List blocks = getBlocks(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - for (SoundStreamBlockTag block : blocks) { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - baos.write(block.streamSoundData, 4, block.streamSoundData.length - 4); - } else { - baos.write(block.streamSoundData); - } + for (SoundStreamBlockTag block : blocks) { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + ret.add(Arrays.copyOfRange(block.streamSoundData, 4, block.streamSoundData.length)); + } else { + ret.add(block.streamSoundData); } - } catch (IOException ex) { - return null; } - return baos.toByteArray(); + return ret; } @Override 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 8cbb489cc..0032b10de 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 @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWFInputStream; @@ -33,6 +34,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -170,13 +172,17 @@ public class SoundStreamHeadTag extends CharacterIdTag implements SoundStreamHea return streamSoundType; } - public static void populateSoundStreamBlocks(List tags, Tag head, List output) { + public static void populateSoundStreamBlocks(int containerId,List tags, Tag head, List output) { boolean found = false; for (ContainerItem t : tags) { if (t == head) { found = true; + ((SoundStreamHeadTypeTag)head).setVirtualCharacterId(containerId); continue; } + if (t instanceof Container) { + populateSoundStreamBlocks(((CharacterIdTag)t).getCharacterId(),((Container) t).getSubItems(), head, output); + } if (!found) { continue; } @@ -186,16 +192,13 @@ public class SoundStreamHeadTag extends CharacterIdTag implements SoundStreamHea if (t instanceof SoundStreamHeadTypeTag) { break; } - if (t instanceof Container) { - populateSoundStreamBlocks(((Container) t).getSubItems(), head, output); - } } } @Override public List getBlocks() { List ret = new ArrayList<>(); - populateSoundStreamBlocks(swf.tags, this, ret); + populateSoundStreamBlocks(0,swf.tags, this, ret); return ret; } @@ -211,21 +214,17 @@ public class SoundStreamHeadTag extends CharacterIdTag implements SoundStreamHea } @Override - public byte[] getRawSoundData() { + public List getRawSoundData() { + List ret = new ArrayList(); List blocks = getBlocks(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - for (SoundStreamBlockTag block : blocks) { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - baos.write(block.streamSoundData, 4, block.streamSoundData.length - 4); - } else { - baos.write(block.streamSoundData); - } + for (SoundStreamBlockTag block : blocks) { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + ret.add(Arrays.copyOfRange(block.streamSoundData, 4, block.streamSoundData.length)); + } else { + ret.add(block.streamSoundData); } - } catch (IOException ex) { - return null; } - return baos.toByteArray(); + return ret; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java index 280b31e24..31f5c6d64 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java @@ -12,11 +12,13 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.types.sound.SoundFormat; import java.io.InputStream; +import java.util.List; /** * @@ -34,7 +36,7 @@ public interface SoundTag { public boolean getSoundType(); - public byte[] getRawSoundData(); + public List getRawSoundData(); public int getSoundFormatId(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java index e5c7a4d89..3a4091d7e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.types.sound; import com.jpexs.decompiler.flash.SWFInputStream; @@ -20,6 +21,7 @@ import com.jpexs.helpers.utf8.Utf8Helper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.List; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; @@ -161,10 +163,12 @@ public class SoundFormat { } } - public boolean createWav(SWFInputStream sis, OutputStream os) { + public boolean createWav(List siss, OutputStream os) { ensureFormat(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - decode(sis, baos); + for(SWFInputStream sis:siss){ + decode(sis, baos); + } try { createWavFromPcmData(os, samplingRate, true, stereo, baos.toByteArray()); return true; diff --git a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java index 10a047d90..077802114 100644 --- a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java +++ b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java @@ -70,9 +70,13 @@ public class SoundTagPlayer implements MediaDisplay { this.tag = tag; this.loops = loops; ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] soundData = tag.getRawSoundData(); + List soundData = tag.getRawSoundData(); SWF swf = ((Tag) tag).getSwf(); - tag.getSoundFormat().createWav(new SWFInputStream(swf, soundData), baos); + List siss=new ArrayList<>(); + for(byte[] data:soundData){ + siss.add(new SWFInputStream(swf,data)); + } + tag.getSoundFormat().createWav(siss, baos); player = new SoundPlayer(new ByteArrayInputStream(baos.toByteArray())); } diff --git a/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java index dfd0eb3e0..1aef80bd3 100644 --- a/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java @@ -106,6 +106,17 @@ public class TagTreeModel implements TreeModel { return mainFrame.translate(key); } + + private List getSoundStreams(DefineSpriteTag sprite){ + List ret=new ArrayList<>(); + for(Tag t:sprite.subTags){ + if(t instanceof SoundStreamHeadTypeTag){ + ret.add(new TagNode(t)); + } + } + return ret; + } + private List createTagList(List list, SWF swf, SWFNode swfNode, ClassesListTreeModel classTreeModel) { boolean hasAbc = swf.abcList != null && !swf.abcList.isEmpty(); @@ -138,6 +149,7 @@ public class TagTreeModel implements TreeModel { break; case SPRITE: sprites.add(new TagNode(t)); + sounds.addAll(getSoundStreams((DefineSpriteTag)t)); break; case BUTTON: buttons.add(new TagNode(t));