#2451 Better MP3 stream matching

This commit is contained in:
Jindra Petřík
2025-06-08 23:07:56 +02:00
parent aeb5a51c7e
commit feb4102b85
2 changed files with 40 additions and 10 deletions

View File

@@ -473,6 +473,7 @@ public class SoundImporter {
List<SoundStreamBlockTag> existingBlocks = new ArrayList<>();
Timelined timelined = streamHead.getTimelined();
int firstSeekSamples = 0;
if (startFrame == null) {
for (SoundStreamFrameRange range : ranges) {
@@ -494,6 +495,7 @@ public class SoundImporter {
} else {
for (SoundStreamFrameRange range : ranges) {
if (range.startFrame == startFrame) {
firstSeekSamples = range.getSeekSamples();
existingBlocks.addAll(range.blocks);
break;
}
@@ -538,27 +540,30 @@ public class SoundImporter {
//ignore
}
}
if (mp3Frames != null) {
if (mp3Frames != null && !mp3Frames.isEmpty()) {
MP3FRAME firstMp3Frame = mp3Frames.get(0);
int sampleCountPerMp3Frame = firstMp3Frame.getSampleCount();
int frame = 0;
int frame = startFrame;
int mp3FrameNum = 0;
long lastNumSamplesLong = 0;
long lastNumSamplesLong = Math.round(startFrame * soundRateHz / swf.frameRate) - firstSeekSamples;
while (mp3FrameNum < mp3Frames.size()) {
float timeAfterFrame = (frame + 1) / swf.frameRate;
float numSamplesAfterFrame = (frame + 1) * soundRateHz / swf.frameRate;
float idealNumberOfSamplesAfterFrame = (frame + 1) * soundRateHz / swf.frameRate;
long numSamplesBeforeFrameLong = Math.round(frame * soundRateHz / swf.frameRate);
int seekSamples = (int) (lastNumSamplesLong - numSamplesBeforeFrameLong);
int seekSamples = (int) (numSamplesBeforeFrameLong - lastNumSamplesLong);
SoundStreamBlockTag block = new SoundStreamBlockTag(swf);
block.forceWriteAsLong = true;
List<MP3FRAME> blockMp3Frames = new ArrayList<>();
int blockSamples = 0;
while (lastNumSamplesLong < numSamplesAfterFrame && mp3FrameNum < mp3Frames.size()) {
while (mp3FrameNum < mp3Frames.size()
&& (lastNumSamplesLong + sampleCountPerMp3Frame < idealNumberOfSamplesAfterFrame)) {
MP3FRAME mp3Frame = mp3Frames.get(mp3FrameNum);
lastNumSamplesLong += mp3Frame.getSampleCount();
blockSamples += mp3Frame.getSampleCount();
lastNumSamplesLong += sampleCountPerMp3Frame;
blockSamples += sampleCountPerMp3Frame;
blockMp3Frames.add(mp3Frame);
mp3FrameNum++;
}
@@ -571,11 +576,14 @@ public class SoundImporter {
sos.write(mp3Frame.getBytes());
}
} catch (IOException ex) {
Logger.getLogger(SoundStreamHeadTypeTag.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(SoundImporter.class.getName()).log(Level.SEVERE, null, ex);
}
block.streamSoundData = new ByteArrayRange(baos.toByteArray());
blocks.add(block);
frame++;
//TODO: maybe last frame empty? But how to calculate seekSamples
//lastNumSamplesLong - ((frame + 1) * soundRateHz / swf.frameRate));
}
}

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
import com.jpexs.decompiler.flash.tags.base.SoundTag;
@@ -24,8 +25,11 @@ import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.types.sound.SoundExportFormat;
import com.jpexs.decompiler.flash.types.sound.SoundFormat;
import com.jpexs.helpers.ByteArrayRange;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* SoundStream blocks across frame range.
@@ -109,6 +113,24 @@ public class SoundStreamFrameRange implements TreeItem, SoundTag {
return ret;
}
public int getSeekSamples() {
if (blocks.isEmpty()) {
return 0;
}
if (getSoundFormatId() != SoundFormat.FORMAT_MP3) {
return 0;
}
ByteArrayRange data = blocks.get(0).streamSoundData;
SWFInputStream sis;
try {
sis = new SWFInputStream(null, data.getRangeData(0, 4));
sis.readUI16("numSamples");
return sis.readSI16("seekSamples");
} catch (IOException ex) {
return 0;
}
}
@Override
public int getSoundFormatId() {
return head.getSoundFormatId();