mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-28 20:44:55 +00:00
Replace SoundStreamHead (no MP3 support yet)
This commit is contained in:
@@ -35,7 +35,6 @@ public class SoundStreamBlockTag extends Tag {
|
||||
|
||||
public static final String NAME = "SoundStreamBlock";
|
||||
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange streamSoundData;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<ByteArrayRange> getRawSoundData() {
|
||||
List<ByteArrayRange> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ByteArrayRange> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SoundStreamBlockTag> 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<MP3FRAME> 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<SoundStreamBlockTag> 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<SoundStreamBlockTag> 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<SoundStreamBlockTag> getBlocks();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
BIN
libsrc/ffdec_lib/testdata/sounds/sounds.swf
vendored
BIN
libsrc/ffdec_lib/testdata/sounds/sounds.swf
vendored
Binary file not shown.
@@ -3,25 +3,60 @@
|
||||
<DOMFontItem name="Font 1" itemID="604e2b4c-00000400" font="TimesNewRomanPSMT" size="0" id="1" sourceLastImported="1615735628" embedRanges="1|2"/>
|
||||
</fonts>
|
||||
<media>
|
||||
<DOMSoundItem name="514508_gis-sweden_background-techno-loop131bpm_part.mp3" itemID="63a9b533-000001ee" sourceExternalFilepath="./LIBRARY/514508_gis-sweden_background-techno-loop131bpm_part.mp3" sourceLastImported="1672066220" externalFileSize="964275" href="514508_gis-sweden_background-techno-loop131bpm_part.mp3" soundDataHRef="M 3 1672066332.dat" format="44kHz 16bit Stereo" sampleCount="2626560" exportFormat="1" exportBits="7" dataLength="952947" exportNative="true" cacheFormat="5kHz 8bit Stereo" cachedSampleCount="328320"/>
|
||||
<DOMSoundItem name="POOL-Pool_Shot-709343898.wav" itemID="605a2676-00000203" sourceExternalFilepath="../../graphics/graphics/LIBRARY/POOL-Pool_Shot-709343898.wav" sourceLastImported="1515341955" externalFileSize="207370" href="POOL-Pool_Shot-709343898.wav" soundDataHRef="M 5 1616520759.dat" format="44kHz 16bit Stereo" sampleCount="51311"/>
|
||||
<DOMSoundItem name="Yung Raf - Nothing To Lose.mp3" itemID="605a5e7d-00000258" sourceExternalFilepath="../../graphics/graphics/LIBRARY/Yung Raf - Nothing To Lose.mp3" sourceLastImported="1616534842" externalFileSize="2233572" href="Yung Raf - Nothing To Lose.mp3" soundDataHRef="M 6 1616534947.dat" format="44kHz 16bit Stereo" sampleCount="6156288" exportFormat="1" exportBits="7" dataLength="2233572" exportNative="true" cacheFormat="5kHz 8bit Stereo" cachedSampleCount="769536"/>
|
||||
</media>
|
||||
<symbols>
|
||||
<Include href="btnNext.xml" itemIcon="0" loadImmediate="false" itemID="604e2284-000003f0" lastModified="1615733380"/>
|
||||
<Include href="btnPrev.xml" itemIcon="0" loadImmediate="false" itemID="604e2299-000003f6" lastModified="1615733401"/>
|
||||
<Include href="Symbol 1.xml" loadImmediate="false" itemID="63a9b1e8-000001df" lastModified="1672066786"/>
|
||||
</symbols>
|
||||
<timelines>
|
||||
<DOMTimeline name="Scene 1">
|
||||
<DOMTimeline name="Scene 1" currentFrame="11">
|
||||
<layers>
|
||||
<DOMLayer name="Scripts layer" color="#9933CC" autoNamed="false">
|
||||
<frames>
|
||||
<DOMFrame index="0" duration="5" keyMode="9728">
|
||||
<DOMFrame index="0" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stop();]]></script>
|
||||
</Actionscript>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="5" keyMode="9728">
|
||||
<DOMFrame index="1" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stopAllSounds();]]></script>
|
||||
</Actionscript>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="2" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="3" duration="2" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stopAllSounds();]]></script>
|
||||
</Actionscript>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="5" duration="2" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stopAllSounds();]]></script>
|
||||
</Actionscript>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="7" duration="2" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stopAllSounds();]]></script>
|
||||
</Actionscript>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="9" duration="2" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stopAllSounds();]]></script>
|
||||
</Actionscript>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="11" keyMode="9728">
|
||||
<Actionscript>
|
||||
<script><![CDATA[stopAllSounds();]]></script>
|
||||
</Actionscript>
|
||||
@@ -29,9 +64,9 @@
|
||||
</DOMFrame>
|
||||
</frames>
|
||||
</DOMLayer>
|
||||
<DOMLayer name="Prev next buttons" color="#4FFF4F" autoNamed="false">
|
||||
<DOMLayer name="Prev next buttons" color="#4FFF4F" locked="true" current="true" isSelected="true" autoNamed="false">
|
||||
<frames>
|
||||
<DOMFrame index="0" duration="6" keyMode="9728">
|
||||
<DOMFrame index="0" duration="12" keyMode="9728">
|
||||
<elements>
|
||||
<DOMSymbolInstance libraryItemName="btnNext" symbolType="button">
|
||||
<matrix>
|
||||
@@ -68,26 +103,19 @@
|
||||
</SoundEnvelope>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="1" keyMode="9728" soundName="POOL-Pool_Shot-709343898.wav" soundLoop="2">
|
||||
<DOMFrame index="1" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="2" keyMode="9728" soundName="POOL-Pool_Shot-709343898.wav" soundLoop="2">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="2" keyMode="9728" soundName="Yung Raf - Nothing To Lose.mp3" inPoint44="268780" outPoint44="358136" soundZoomLevel="5">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
<DOMFrame index="3" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="3" keyMode="9728" soundEffect="custom" soundName="Yung Raf - Nothing To Lose.mp3" inPoint44="274640" outPoint44="494975" soundZoomLevel="5">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint/>
|
||||
<SoundEnvelopePoint mark44="221341" level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="4" keyMode="9728" soundName="Yung Raf - Nothing To Lose.mp3">
|
||||
<DOMFrame index="4" keyMode="9728" soundName="Yung Raf - Nothing To Lose.mp3" inPoint44="268780" outPoint44="358136" soundZoomLevel="5">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
@@ -96,12 +124,28 @@
|
||||
<DOMFrame index="5" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="6" keyMode="9728" soundEffect="custom" soundName="Yung Raf - Nothing To Lose.mp3" inPoint44="274640" outPoint44="494975" soundZoomLevel="5">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint/>
|
||||
<SoundEnvelopePoint mark44="221341" level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="7" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="8" keyMode="9728" soundName="Yung Raf - Nothing To Lose.mp3">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="9" duration="3" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
</frames>
|
||||
</DOMLayer>
|
||||
<DOMLayer name="Texts inside layer" color="#FF800A" autoNamed="false">
|
||||
<frames/>
|
||||
</DOMLayer>
|
||||
<DOMLayer name="Frame description layer" color="#9933CC" current="true" isSelected="true" autoNamed="false">
|
||||
<DOMLayer name="Frame description layer" color="#9933CC" autoNamed="false">
|
||||
<frames>
|
||||
<DOMFrame index="0" keyMode="9728">
|
||||
<elements>
|
||||
@@ -121,6 +165,9 @@
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="1" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="2" keyMode="9728">
|
||||
<elements>
|
||||
<DOMStaticText width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<matrix>
|
||||
@@ -137,9 +184,12 @@
|
||||
</DOMStaticText>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="2" keyMode="9728">
|
||||
<DOMFrame index="3" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="4" keyMode="9728">
|
||||
<elements>
|
||||
<DOMStaticText selected="true" width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<DOMStaticText width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<matrix>
|
||||
<Matrix tx="22" ty="342"/>
|
||||
</matrix>
|
||||
@@ -154,7 +204,10 @@
|
||||
</DOMStaticText>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="3" keyMode="9728">
|
||||
<DOMFrame index="5" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="6" keyMode="9728">
|
||||
<elements>
|
||||
<DOMStaticText width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<matrix>
|
||||
@@ -171,9 +224,12 @@
|
||||
</DOMStaticText>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="4" keyMode="9728">
|
||||
<DOMFrame index="7" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="8" keyMode="9728">
|
||||
<elements>
|
||||
<DOMStaticText width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<DOMStaticText selected="true" width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<matrix>
|
||||
<Matrix tx="22" ty="342"/>
|
||||
</matrix>
|
||||
@@ -188,7 +244,10 @@
|
||||
</DOMStaticText>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="5" keyMode="9728">
|
||||
<DOMFrame index="9" keyMode="9728">
|
||||
<elements/>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="10" keyMode="9728">
|
||||
<elements>
|
||||
<DOMStaticText width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<matrix>
|
||||
@@ -196,7 +255,32 @@
|
||||
</matrix>
|
||||
<textRuns>
|
||||
<DOMTextRun>
|
||||
<characters>006 Stop</characters>
|
||||
<characters>006 SoundStream</characters>
|
||||
<textAttrs>
|
||||
<DOMTextAttrs aliasText="false" size="30" face="TimesNewRomanPSMT"/>
|
||||
</textAttrs>
|
||||
</DOMTextRun>
|
||||
</textRuns>
|
||||
</DOMStaticText>
|
||||
<DOMSymbolInstance libraryItemName="Symbol 1" centerPoint3DX="218.5" centerPoint3DY="167.5">
|
||||
<matrix>
|
||||
<Matrix tx="132" ty="104"/>
|
||||
</matrix>
|
||||
<transformationPoint>
|
||||
<Point x="86.5" y="63.5"/>
|
||||
</transformationPoint>
|
||||
</DOMSymbolInstance>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="11" keyMode="9728">
|
||||
<elements>
|
||||
<DOMStaticText width="446" height="33.25" includeOutlines="true" isSelectable="false">
|
||||
<matrix>
|
||||
<Matrix tx="22" ty="342"/>
|
||||
</matrix>
|
||||
<textRuns>
|
||||
<DOMTextRun>
|
||||
<characters>007 Stop</characters>
|
||||
<textAttrs>
|
||||
<DOMTextAttrs aliasText="false" size="30" face="TimesNewRomanPSMT"/>
|
||||
</textAttrs>
|
||||
@@ -212,6 +296,12 @@
|
||||
</timelines>
|
||||
<PrinterSettings/>
|
||||
<publishHistory>
|
||||
<PublishItem publishSize="2275383" publishTime="1672066791"/>
|
||||
<PublishItem publishSize="2275382" publishTime="1672066741"/>
|
||||
<PublishItem publishSize="2279372" publishTime="1672066366"/>
|
||||
<PublishItem publishSize="2237594" publishTime="1672065661"/>
|
||||
<PublishItem publishSize="2279405" publishTime="1672065634"/>
|
||||
<PublishItem publishSize="2237595" publishTime="1672065568"/>
|
||||
<PublishItem publishSize="3657857" publishTime="1668349897"/>
|
||||
<PublishItem publishSize="3657883" publishTime="1666634735"/>
|
||||
<PublishItem publishSize="3657878" publishTime="1666634687"/>
|
||||
@@ -226,11 +316,5 @@
|
||||
<PublishItem publishSize="1609" publishTime="1666586837"/>
|
||||
<PublishItem publishSize="1609" publishTime="1666586837"/>
|
||||
<PublishItem publishSize="1609" publishTime="1666586837"/>
|
||||
<PublishItem publishSize="1592" publishTime="1637176557"/>
|
||||
<PublishItem publishSize="1586" publishTime="1637176556"/>
|
||||
<PublishItem publishSize="1586" publishTime="1637176556"/>
|
||||
<PublishItem publishSize="1586" publishTime="1637176556"/>
|
||||
<PublishItem publishSize="3655062" publishTime="1617375217"/>
|
||||
<PublishItem publishSize="2351995" publishTime="1617369003"/>
|
||||
</publishHistory>
|
||||
</DOMDocument>
|
||||
Binary file not shown.
43
libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/Symbol 1.xml
vendored
Normal file
43
libsrc/ffdec_lib/testdata/sounds/sounds/LIBRARY/Symbol 1.xml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<DOMSymbolItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.adobe.com/xfl/2008/" name="Symbol 1" itemID="63a9b1e8-000001df" lastModified="1672066786">
|
||||
<timeline>
|
||||
<DOMTimeline name="Symbol 1" currentFrame="3">
|
||||
<layers>
|
||||
<DOMLayer name="Layer 1" color="#4FFF4F" current="true" isSelected="true">
|
||||
<frames>
|
||||
<DOMFrame index="0" duration="5" keyMode="9728">
|
||||
<elements>
|
||||
<DOMShape>
|
||||
<fills>
|
||||
<FillStyle index="1">
|
||||
<SolidColor color="#FF0000"/>
|
||||
</FillStyle>
|
||||
</fills>
|
||||
<edges>
|
||||
<Edge fillStyle1="1" edges="!3460 2540|0 2540!0 2540|0 0!0 0|3460 0!3460 0|3460 2540"/>
|
||||
</edges>
|
||||
</DOMShape>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
<DOMFrame index="5" duration="458" keyMode="9728" soundName="514508_gis-sweden_background-techno-loop131bpm_part.mp3" soundSync="stream">
|
||||
<SoundEnvelope>
|
||||
<SoundEnvelopePoint level0="32768" level1="32768"/>
|
||||
</SoundEnvelope>
|
||||
<elements>
|
||||
<DOMShape>
|
||||
<fills>
|
||||
<FillStyle index="1">
|
||||
<SolidColor color="#FF0000"/>
|
||||
</FillStyle>
|
||||
</fills>
|
||||
<edges>
|
||||
<Edge fillStyle1="1" edges="!3460 2540|0 2540!0 2540|0 0!0 0|3460 0!3460 0|3460 2540"/>
|
||||
</edges>
|
||||
</DOMShape>
|
||||
</elements>
|
||||
</DOMFrame>
|
||||
</frames>
|
||||
</DOMLayer>
|
||||
</layers>
|
||||
</DOMTimeline>
|
||||
</timeline>
|
||||
</DOMSymbolItem>
|
||||
@@ -5,8 +5,8 @@
|
||||
xmlns:xmp="http://ns.adobe.com/xap/1.0/">
|
||||
<xmp:CreatorTool>Adobe Flash Professional CS6 - build 481</xmp:CreatorTool>
|
||||
<xmp:CreateDate>2021-03-14T08:29:20+01:00</xmp:CreateDate>
|
||||
<xmp:MetadataDate>2022-12-25T06:15:04-08:00</xmp:MetadataDate>
|
||||
<xmp:ModifyDate>2022-12-25T06:15:04-08:00</xmp:ModifyDate>
|
||||
<xmp:MetadataDate>2022-12-26T06:37:55-08:00</xmp:MetadataDate>
|
||||
<xmp:ModifyDate>2022-12-26T06:37:55-08:00</xmp:ModifyDate>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
@@ -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#">
|
||||
<xmpMM:InstanceID>xmp.iid:21E4449F4B7EED119DEE8735AA8CEAC4</xmpMM:InstanceID>
|
||||
<xmpMM:InstanceID>xmp.iid:6034FB37F884ED119D8BF78AEC309D40</xmpMM:InstanceID>
|
||||
<xmpMM:DocumentID>xmp.did:21E4449F4B7EED119DEE8735AA8CEAC4</xmpMM:DocumentID>
|
||||
<xmpMM:OriginalDocumentID>xmp.did:D6D3FE199784EB1187FEAE6972EC5115</xmpMM:OriginalDocumentID>
|
||||
<xmpMM:History>
|
||||
@@ -147,6 +147,12 @@
|
||||
<stEvt:when>2021-03-14T08:29:20+01:00</stEvt:when>
|
||||
<stEvt:softwareAgent>Adobe Flash Professional CS6 - build 481</stEvt:softwareAgent>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<stEvt:action>created</stEvt:action>
|
||||
<stEvt:instanceID>xmp.iid:6034FB37F884ED119D8BF78AEC309D40</stEvt:instanceID>
|
||||
<stEvt:when>2021-03-14T08:29:20+01:00</stEvt:when>
|
||||
<stEvt:softwareAgent>Adobe Flash Professional CS6 - build 481</stEvt:softwareAgent>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpMM:History>
|
||||
<xmpMM:DerivedFrom rdf:parseType="Resource">
|
||||
|
||||
BIN
libsrc/ffdec_lib/testdata/sounds/sounds/bin/M 3 1672066332.dat
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/sounds/sounds/bin/M 3 1672066332.dat
vendored
Normal file
Binary file not shown.
Binary file not shown.
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user