Replacing SoundStreamHeads with MP3

This commit is contained in:
Jindra Petřík
2022-12-26 23:00:29 +01:00
parent cc71ba8cef
commit a940ea1c6f
9 changed files with 333 additions and 17 deletions

Binary file not shown.

View File

@@ -163,12 +163,13 @@ public abstract class SoundStreamHeadTypeTag extends Tag implements CharacterIdT
newSoundSize = true;
newSoundType = fr.isStereo();
int len = snd.sampleCount();
/*int len = snd.sampleCount();
if (fr.isStereo()) {
len = len / 2;
}
}*/
newSoundSampleCount = len;
newSoundSampleCount = (int) Math.ceil(soundRateHz / swf.frameRate);
//newSoundSampleCount = len;
}
mp3Frames = snd.frames;
@@ -237,7 +238,7 @@ public abstract class SoundStreamHeadTypeTag extends Tag implements CharacterIdT
}
if (mp3Frames != null) {
/*int frame = 0;
int frame = 0;
int mp3FrameNum = 0;
long lastNumSamplesLong = 0;
@@ -252,21 +253,28 @@ public abstract class SoundStreamHeadTypeTag extends Tag implements CharacterIdT
List<MP3FRAME> blockMp3Frames = new ArrayList<>();
int blockSamples = 0;
while(lastNumSamplesLong < numSamplesAfterFrame) {
while(lastNumSamplesLong < numSamplesAfterFrame && mp3FrameNum < mp3Frames.size()) {
MP3FRAME mp3Frame = mp3Frames.get(mp3FrameNum);
lastNumSamplesLong += mp3Frame.getSampleCount();
blockSamples += mp3Frame.getSampleCount();
blockMp3Frames.add(mp3Frame);
mp3FrameNum++;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION, null);
try {
sos.writeUI16(blockSamples);
sos.writeSI16(seekSamples);
for (MP3FRAME mp3Frame:blockMp3Frames) {
sos.write(mp3Frame.getBytes());
}
} catch (IOException ex) {
Logger.getLogger(SoundStreamHeadTypeTag.class.getName()).log(Level.SEVERE, null, ex);
}
} */
block.streamSoundData = new ByteArrayRange(baos.toByteArray());
blocks.add(block);
frame++;
}
}
ReadOnlyTagList tags = timelined.getTags();

View File

@@ -35,11 +35,22 @@ public class MP3FRAME {
private Header h;
private SampleBuffer samples;
private byte[] fullData;
private MP3FRAME() {
}
public void setFullData(byte[] fullData) {
this.fullData = fullData;
}
public byte[] getBytes() {
return fullData;
}
public static MP3FRAME readFrame(Bitstream bitstream, Decoder decoder) throws IOException {
MP3FRAME ret = new MP3FRAME();
try {
@@ -60,24 +71,24 @@ public class MP3FRAME {
}
public int getSampleCount() {
if (h.version() == 3) {
if (h.version() == Header.MPEG1) {
switch(h.layer()) {
case 1:
return 1152;
return 384;
case 2:
return 1152;
case 3:
return 384;
return 1152;
}
}
if (h.version() == 2 || h.version() == 0) {
if (h.version() == Header.MPEG2_LSF || h.version() == Header.MPEG25_LSF) {
switch(h.layer()) {
case 1:
return 576;
return 384;
case 2:
return 1152;
case 3:
return 384;
return 576;
}
}
return 0;

View File

@@ -20,9 +20,12 @@ import com.jpexs.decompiler.flash.SWFInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javazoom.jl.decoder.Bitstream;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.MarkingBufferedInputStream;
import javazoom.jl.decoder.MarkingPushbackInputStream;
/**
*
@@ -41,10 +44,23 @@ public class MP3SOUNDDATA {
frames = new ArrayList<>();
MP3FRAME f;
Decoder decoder = new Decoder();
Bitstream bitstream = new Bitstream(new ByteArrayInputStream(sis.readBytesEx(sis.available(), "soundStream")));
while ((f = MP3FRAME.readFrame(bitstream, decoder)) != null) {
frames.add(f);
}
byte data[] = sis.readBytesEx(sis.available(), "soundStream");
MarkingBufferedInputStream mis = new MarkingBufferedInputStream(new ByteArrayInputStream(data));
Bitstream bitstream = new Bitstream(mis); //new ByteArrayInputStream(data)
long initLen = mis.getPosition();
MarkingPushbackInputStream mpis = bitstream.getSource();
while (true) {
//System.err.println("initLen = "+initLen);
long posBefore = initLen+mpis.getPosition();
MP3FRAME frame = MP3FRAME.readFrame(bitstream, decoder);
if (frame == null) {
break;
}
long posAfter = initLen+mpis.getPosition();
frame.setFullData(Arrays.copyOfRange(data, (int)posBefore, (int)posAfter));
frames.add(frame);
}
}
public int sampleCount() {

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2010-2022 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.types.sound;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class MarkingInputStream extends InputStream {
private InputStream is;
private long pos = 0;
public MarkingInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
pos++;
return is.read();
}
public long getPos() {
return pos;
}
}

View File

@@ -146,7 +146,24 @@ public final class Bitstream implements BitstreamErrors {
closeFrame();
}
//JPEXS
public Bitstream(MarkingBufferedInputStream in) {
if (in == null)
throw new NullPointerException("in");
loadID3v2(in);
in.setFixed(true);
firstframe = true;
source = new MarkingPushbackInputStream(in, BUFFER_INT_SIZE * 4);
closeFrame();
}
//JPEXS
public MarkingPushbackInputStream getSource() {
return (MarkingPushbackInputStream) source;
}
/**
* Return position of the first audio header.
*

View File

@@ -0,0 +1,99 @@
package javazoom.jl.decoder;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class MarkingBufferedInputStream extends BufferedInputStream {
private BufferedInputStream is;
private long pos = 0;
private long markedPos = -1;
private boolean fixed = false;
public long getPosition() {
return pos;
}
public void setFixed(boolean fixed) {
this.fixed = fixed;
}
public MarkingBufferedInputStream(InputStream in) {
super(in);
this.is = new BufferedInputStream(in);
}
@Override
public synchronized int read() throws IOException {
if (!fixed) pos++;
return is.read();
}
@Override
public int read(byte[] b) throws IOException {
int ret = is.read(b);
if (!fixed) pos += ret;
return ret;
}
@Override
public synchronized int read(byte[] b, int off, int len) throws IOException {
int ret = is.read(b, off, len);
if (!fixed) pos += ret;
return ret;
}
@Override
public synchronized void reset() throws IOException {
if (markedPos > -1) {
if (!fixed) pos = markedPos;
markedPos = -1;
}
is.reset();
}
@Override
public synchronized void mark(int readlimit) {
markedPos = pos;
is.mark(readlimit);
}
@Override
public synchronized int available() throws IOException {
return is.available();
}
@Override
public synchronized long skip(long n) throws IOException {
long ret = is.skip(n);
if (!fixed) pos+=ret;
return ret;
}
@Override
public void skipNBytes(long n) throws IOException {
if (!fixed) pos+=n;
is.skipNBytes(n);
}
@Override
public void close() throws IOException {
is.close();
}
@Override
public boolean markSupported() {
return is.markSupported();
}
}

View File

@@ -0,0 +1,104 @@
package javazoom.jl.decoder;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
/**
*
* @author JPEXS
*/
public class MarkingPushbackInputStream extends PushbackInputStream {
private PushbackInputStream is;
private long pos = 0;
public long getPosition() {
return pos;
}
public MarkingPushbackInputStream(InputStream in, int size) {
super(in, size);
is = new PushbackInputStream(in, size);
}
@Override
public int available() throws IOException {
return is.available();
}
@Override
public synchronized void close() throws IOException {
is.close();
}
@Override
public synchronized void mark(int readlimit) {
is.mark(readlimit);
}
@Override
public boolean markSupported() {
return is.markSupported();
}
@Override
public int read() throws IOException {
pos++;
return is.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int ret = is.read(b, off, len);
pos += ret;
return ret;
}
@Override
public int read(byte[] b) throws IOException {
int ret = is.read(b);
pos += ret;
return ret;
}
@Override
public synchronized void reset() throws IOException {
is.reset();
}
@Override
public void unread(byte[] b) throws IOException {
pos -= b.length;
is.unread(b);
}
@Override
public void unread(int b) throws IOException {
pos--;
is.unread(b);
}
@Override
public void unread(byte[] b, int off, int len) throws IOException {
pos -= len;
is.unread(b, off, len);
}
@Override
public long skip(long n) throws IOException {
long ret = is.skip(n);
pos += ret;
return ret;
}
@Override
public void skipNBytes(long n) throws IOException {
pos += n;
is.skipNBytes(n);
}
}

View File

@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.OpenableSourceInfo;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.RenameType;
import com.jpexs.decompiler.flash.abc.ScriptPack;
@@ -156,6 +157,7 @@ import com.jpexs.decompiler.flash.tags.PlaceObjectTag;
import com.jpexs.decompiler.flash.tags.ProductInfoTag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.TagInfo;
import com.jpexs.decompiler.flash.tags.UnknownTag;
@@ -4752,7 +4754,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
previewPanel.closeTag();
}
public static void showPreview(TreeItem treeItem, PreviewPanel previewPanel, int frame, Timelined timelinedContainer) {
public static void showPreview(TreeItem treeItem, PreviewPanel previewPanel, int frame, Timelined timelinedContainer) {
previewPanel.clear();
if (treeItem == null) {
previewPanel.showEmpty();
@@ -5034,6 +5036,20 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
showDetail(DETAILCARDEMPTYPANEL);
}
if (treeItem instanceof SoundStreamBlockTag) {
SoundStreamBlockTag block = (SoundStreamBlockTag)treeItem;
byte[] data = block.streamSoundData.getRangeData();
try{
SWFInputStream sis = new SWFInputStream(block.getSwf(), data);
int sampleCount = sis.readUI16("sampleCount");
int seekSamples = sis.readSI16("seekSamples");
System.out.println("sampleCount = "+sampleCount);
System.out.println("seekSamples = "+seekSamples);
System.out.println("============");
}catch(Exception ex){
}
}
if (treeItem instanceof HeaderItem) {
headerPanel.load((SWF) ((HeaderItem) treeItem).getOpenable());
showCard(CARDHEADER);