Updated X3 library to 2.2.6

This commit is contained in:
Douglas Gillespie 2023-11-15 13:08:02 +00:00
parent a4f484c76c
commit acc806d375
9 changed files with 258 additions and 68 deletions

View File

@ -8,6 +8,7 @@
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes> <attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>

View File

@ -4,7 +4,7 @@
<groupId>org.pamguard</groupId> <groupId>org.pamguard</groupId>
<artifactId>Pamguard</artifactId> <artifactId>Pamguard</artifactId>
<name>Pamguard Java12+</name> <name>Pamguard Java12+</name>
<version>2.02.09b</version> <version>2.02.09c</version>
<description>Pamguard for Java 12+, using Maven to control dependcies</description> <description>Pamguard for Java 12+, using Maven to control dependcies</description>
<url>www.pamguard.org</url> <url>www.pamguard.org</url>
<organization> <organization>

View File

@ -786,7 +786,7 @@ C:\Users\*yourusername*\.m2\repository\pamguard\org\x3\2.2.2-->
<dependency> <dependency>
<groupId>pamguard.org</groupId> <groupId>pamguard.org</groupId>
<artifactId>x3</artifactId> <artifactId>x3</artifactId>
<version>2.2.3</version> <version>2.2.6</version>
</dependency> </dependency>

View File

@ -0,0 +1,4 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Wed Nov 15 12:43:42 GMT 2023
x3-2.2.6.jar>=
x3-2.2.6.pom>=

Binary file not shown.

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>pamguard.org</groupId>
<artifactId>x3</artifactId>
<version>2.2.6</version>
<description>POM was created from install:install-file</description>
</project>

View File

@ -7,23 +7,35 @@ import java.util.Arrays;
import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.SwingUtilities;
import org.pamguard.x3.sud.ChunkHeader;
import org.pamguard.x3.sud.SudMapListener;
import PamController.PamController;
import PamUtils.worker.PamWorkProgressMessage;
import PamUtils.worker.PamWorkWrapper;
import PamUtils.worker.PamWorker;
/** /**
* Opens a .sud audio file. * Opens a .sud audio file.
* <p> * <p>
* Sud files contain X3 compressed audio data. The sud * Sud files contain X3 compressed audio data. The sud file reader opens files,
* file reader opens files, creating a map of the file and saving * creating a map of the file and saving the map as a.sudx file so it can be
* the map as a.sudx file so it can be read more rapidly when the file * read more rapidly when the file is next accessed.
* is next accessed.
* <p> * <p>
* The SudioAudioInput stream fully implements AudioInputStream and so * The SudioAudioInput stream fully implements AudioInputStream and so sud files
* sud files can be accessed using much of the same code as .wav files. * can be accessed using much of the same code as .wav files.
* *
* @author Jamie Macaulay * @author Jamie Macaulay
* *
*/ */
public class SudAudioFile extends WavAudioFile { public class SudAudioFile extends WavAudioFile {
private Object conditionSync = new Object();
private volatile PamWorker<AudioInputStream> worker;
private volatile SudMapWorker sudMapWorker;
public SudAudioFile() { public SudAudioFile() {
super(); super();
@ -35,20 +47,153 @@ public class SudAudioFile extends WavAudioFile {
return "SUD"; return "SUD";
} }
@Override @Override
public AudioInputStream getAudioStream(File soundFile) { public AudioInputStream getAudioStream(File soundFile) {
synchronized (conditionSync) {
// System.out.println("Get SUD getAudioStream : " + soundFile.getName());
if (soundFile.exists() == false) { if (soundFile.exists() == false) {
System.err.println("The sud file does not exist: " + soundFile); System.err.println("The sud file does not exist: " + soundFile);
return null; return null;
} }
if (soundFile != null) { if (soundFile != null) {
if (new File(soundFile.getAbsolutePath() + "x").exists()) {
// System.out.println("----NO NEED TO MAP SUD FILE-----" + soundFile);
try { try {
return new SudAudioFileReader().getAudioInputStream(soundFile); return new SudAudioFileReader().getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
// don't do anything and it will try the built in Audiosystem } else {
catch (UnsupportedAudioFileException e) {
System.err.println("UnsupportedAudioFileException: Could not open sud file: not a supported file " + soundFile.getName()); // System.out.println("----MAP SUD FILE ON OTHER THREAD-----" + soundFile);
/**
* We need to map the sud file. But we don't want this o just freeze the current
* GUI thread. Therefore add a listener to the mapping process and show a
* blocking dialog to indicate that something is happening. The mapping is put
* on a separate thread and blocks stuff from happening until the mapping
* process has completed.
*/
if (sudMapWorker == null || !sudMapWorker.getSudFile().equals(soundFile)) {
sudMapWorker = new SudMapWorker(soundFile);
worker = new PamWorker<AudioInputStream>(sudMapWorker,
PamController.getInstance().getMainFrame(), 1,
"Mapping sud file: " + soundFile.getName());
// System.out.println("Sud Audio Stream STARTED: " + soundFile.getName());
SwingUtilities.invokeLater(() -> {
worker.start();
});
// this should block AWT thread but won't block if called on another thread..
}
// this is only ever called if this function is called on another thread other
// than the event dispatch thread.
while (sudMapWorker == null || !sudMapWorker.isDone()) {
// do nothing
// System.out.println("Waiting for the SUD file map: " + soundFile.getName() + " worker: " + worker);
try {
// Thread.sleep(100);
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
AudioInputStream stream = sudMapWorker.getSudAudioStream();
// sudMapWorker= null;
// worker = null;
// System.out.println("----RETURN SUD FILE ON OTHER THREAD-----" + stream);
return stream;
}
}
}
return null;
}
public class SudMapProgress implements SudMapListener {
PamWorker<AudioInputStream> sudMapWorker;
public SudMapProgress(PamWorker<AudioInputStream> sudMapWorker) {
this.sudMapWorker = sudMapWorker;
}
@Override
public void chunkProcessed(ChunkHeader chunkHeader, int count) {
// System.out.println("Sud Map Progress: " + count);
if (count % 500 == 0) {
// don't update too often or everything just freezes
sudMapWorker.update(new PamWorkProgressMessage(-1, ("Mapped " + count + " sud file chunks")));
}
if (count == -1) {
sudMapWorker.update(new PamWorkProgressMessage(-1, ("Mapping sud file finished")));
}
}
}
/**
* Opens an sud file on a different thread and adds a listener for a mapping.
* This allows a callback to show map progress.
*
* @author Jamie Macaulay
*
*/
public class SudMapWorker implements PamWorkWrapper<AudioInputStream> {
private File soundFile;
private SudMapProgress sudMapListener;
private volatile boolean done = false;
private AudioInputStream result;
public SudMapWorker(File soundFile) {
this.soundFile = soundFile;
}
public File getSudFile() {
return soundFile;
}
public AudioInputStream getSudAudioStream() {
return result;
}
@Override
public AudioInputStream runBackgroundTask(PamWorker<AudioInputStream> pamWorker) {
AudioInputStream stream;
try {
// System.out.println("START OPEN SUD FILE:");
this.sudMapListener = new SudMapProgress(pamWorker);
stream = new SudAudioFileReader().getAudioInputStream(soundFile, sudMapListener);
// System.out.println("END SUD FILE:");
// for some reason - task finished may not be called on other
// thread so put this here.
this.result = stream;
this.done = true;
return stream;
} catch (UnsupportedAudioFileException e) {
System.err.println("UnsupportedAudioFileException: Could not open sud file: not a supported file "
+ soundFile.getName());
System.err.println(e.getMessage()); System.err.println(e.getMessage());
// e.printStackTrace(); // e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
@ -56,8 +201,20 @@ public class SudAudioFile extends WavAudioFile {
e.printStackTrace(); e.printStackTrace();
} }
}
return null; return null;
} }
@Override
public void taskFinished(AudioInputStream result) {
// System.out.println("TASK FINSIHED:");
this.result = result;
this.done = true;
}
public boolean isDone() {
return done;
}
}
} }

View File

@ -30,8 +30,9 @@ public class SudAudioFileReader {
sudParams = new SudParams(); sudParams = new SudParams();
//set up the sud params for default. i.e. just read files and //set up the sud params for default. i.e. just read files and
//don't save any decompressed or meta data. //don't save any decompressed or meta data.
sudParams.saveWav = false; // sudParams.saveWav = false;
sudParams.saveMeta = false; // sudParams.saveMeta = false;
sudParams.setFileSave(false, false, false, false);
sudParams.zeroPad = true; sudParams.zeroPad = true;
} }
@ -51,5 +52,25 @@ public class SudAudioFileReader {
} }
return sudAudioInputStream; return sudAudioInputStream;
} }
/**
* Get the audio input stream for a sud file.
* @param file - the .sud file to open.
* @param mapListener- a listener for the sud file maps - can be null.
* @return the sud AudioStream.
* @throws UnsupportedAudioFileException
* @throws IOException
*/
public AudioInputStream getAudioInputStream(File file, SudMapListener mapListener) throws UnsupportedAudioFileException, IOException {
// System.out.println("Get SUD getAudioInputStream");
try {
sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, mapListener, false);
} catch (Exception e) {
String msg = String.format("Corrupt sud file %s: %s", file.getName(), e.getMessage());
throw new UnsupportedAudioFileException(msg);
}
return sudAudioInputStream;
}
} }

View File

@ -2,17 +2,11 @@ package Acquisition.sud;
import java.io.File; import java.io.File;
import org.pamguard.x3.sud.ChunkHeader;
import org.pamguard.x3.sud.SudAudioInputStream; import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudFileMap;
import org.pamguard.x3.sud.SudParams;
import PamUtils.PamCalendar;
public class SUDFileTime { public class SUDFileTime {
private static long sudTime; private static long sudTime;
private static String lastFilePath = ""; private static String lastFilePath = "";
/** /**
* Temp measure to get the time from the first available sud record. * Temp measure to get the time from the first available sud record.
@ -20,6 +14,7 @@ public class SUDFileTime {
* @return * @return
*/ */
public static long getSUDFileTime(File file) { public static long getSUDFileTime(File file) {
//System.out.println("Get sud file time: " + file.getName());
if (file == null || file.exists() == false) { if (file == null || file.exists() == false) {
return Long.MIN_VALUE; return Long.MIN_VALUE;
} }
@ -36,22 +31,26 @@ public class SUDFileTime {
*/ */
// long t1 = System.currentTimeMillis(); // long t1 = System.currentTimeMillis();
sudTime = Long.MIN_VALUE; sudTime = Long.MIN_VALUE;
SudParams sudParams = new SudParams(); // SudParams sudParams = new SudParams();
sudParams.saveMeta = false; // sudParams.saveMeta = false;
sudParams.saveWav = false; // sudParams.saveWav = false;
try { try {
SudAudioInputStream sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, false); //
if (sudAudioInputStream == null) { // SudAudioInputStream sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, false);
return Long.MIN_VALUE; // if (sudAudioInputStream == null) {
} // return Long.MIN_VALUE;
SudFileMap sudMap = sudAudioInputStream.getSudMap(); // }
if (sudMap == null) { // SudFileMap sudMap = sudAudioInputStream.getSudMap();
return Long.MIN_VALUE; // if (sudMap == null) {
} // return Long.MIN_VALUE;
long t = sudMap.getFirstChunkTimeMillis(); // }
// long t = sudMap.getFirstChunkTimeMillis();
long t = SudAudioInputStream.quickFileTime(file);
t=t/1000; //turn to milliseconds.
if (t != 0) { if (t != 0) {
sudTime = t; sudTime = t;
} }
// sudAudioInputStream.addSudFileListener((chunkID, sudChunk)->{ // sudAudioInputStream.addSudFileListener((chunkID, sudChunk)->{
// ChunkHeader chunkHead = sudChunk.chunkHeader; // ChunkHeader chunkHead = sudChunk.chunkHeader;
// if (chunkHead == null || sudTime != Long.MIN_VALUE) { // if (chunkHead == null || sudTime != Long.MIN_VALUE) {
@ -70,14 +69,13 @@ public class SUDFileTime {
// sudAudioInputStream.read(); // sudAudioInputStream.read();
// } // }
// //
sudAudioInputStream.close(); // sudAudioInputStream.close();
// long t2 = System.currentTimeMillis(); // long t2 = System.currentTimeMillis();
// System.out.printf("SUD file time %s extracted in %d milliseconds\n", PamCalendar.formatDBDateTime(sudTime), t2-t1); // System.out.printf("SUD file time %s extracted in %d milliseconds\n", PamCalendar.formatDBDateTime(sudTime), t2-t1);
} catch (Exception e) { } catch (Exception e) {
System.err.println("Error getting time from SUD file: " + e.getMessage()); System.err.println("Error getting time from SUD file: " + file + " " + e.getMessage());
e.printStackTrace();
} }
return sudTime; return sudTime;
} }