Merge from Jamie

Difficult merge, with many files becoming corrupted and having to be copied manually from Macster to PAMguard. hopefully all OK now.
This commit is contained in:
Douglas Gillespie 2024-08-23 16:38:20 +01:00
parent 3dfe44d383
commit 744e22d84e
12 changed files with 446 additions and 294 deletions

View File

@ -6,9 +6,8 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Amazon Corretto 21 [21.0.2]">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>

View File

@ -1,6 +1,5 @@
eclipse.preferences.version=1
encoding//src/rawDeepLearningClassifer/segmenter/SegmenterProcess.java=UTF-8
encoding//src/test=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8
encoding/src=UTF-8

View File

@ -11,9 +11,9 @@ org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=19
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=19
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@ -23,4 +23,4 @@ org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=19
org.eclipse.jdt.core.compiler.source=17

View File

@ -305,14 +305,14 @@
<dependency>
<groupId>io.github.macster110</groupId>
<artifactId>jpamutils</artifactId>
<version>0.0.59</version>
<version>0.0.59d</version>
</dependency>
<!--jpam project - Deep learning java library -->
<dependency>
<groupId>io.github.macster110</groupId>
<artifactId>jdl4pam</artifactId>
<version>0.0.99b</version>
<version>0.0.99d</version>
</dependency>
<!-- https://mvnrepository.com/artifact/gov.nist.math/jama -->

View File

@ -1,10 +1,12 @@
package export.CSVExport;
import java.awt.Component;
import java.io.File;
import java.util.List;
import PamguardMVC.PamDataUnit;
import export.PamDataUnitExporter;
import javafx.scene.layout.Pane;
/**
@ -50,4 +52,22 @@ public class CSVExportManager implements PamDataUnitExporter{
return false;
}
@Override
public Component getOptionsPanel() {
// TODO Auto-generated method stub
return null;
}
@Override
public Pane getOptionsPane() {
// TODO Auto-generated method stub
return null;
}
@Override
public void prepareExport() {
}
}

View File

@ -1,5 +1,6 @@
package export.MLExport;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
@ -11,6 +12,7 @@ import java.util.zip.Deflater;
import PamUtils.PamArrayUtils;
import PamguardMVC.PamDataUnit;
import export.PamDataUnitExporter;
import javafx.scene.layout.Pane;
import us.hebi.matlab.mat.format.Mat5;
import us.hebi.matlab.mat.format.Mat5File;
import us.hebi.matlab.mat.format.Mat5Writer;
@ -272,7 +274,23 @@ public class MLDetectionsManager implements PamDataUnitExporter {
return false;
}
@Override
public Component getOptionsPanel() {
// TODO Auto-generated method stub
return null;
}
@Override
public Pane getOptionsPane() {
// TODO Auto-generated method stub
return null;
}
@Override
public void prepareExport() {
this.currentFile = null;
}
}

View File

@ -1,10 +1,12 @@
package export;
import java.awt.Component;
import java.io.File;
import java.util.List;
import PamguardMVC.PamDataUnit;
import javafx.scene.layout.Pane;
/**
* Manages the exporting of data units to a particular type of file e.g. CSV, MATLAB, R, WAV files
@ -57,5 +59,22 @@ public interface PamDataUnitExporter {
*/
public boolean isNeedsNewFile();
/**
* An optional panel that displays additional options for the user.
* @return additional options panel - can be null.
*/
public Component getOptionsPanel();
/**
* An optional JavaFX pane that displays additional options for the user.
* @return pane with additonal options - can be null.
*/
public Pane getOptionsPane();
/**
* Called whenever a new export run is prepared.
*/
public void prepareExport();
}

View File

@ -11,8 +11,7 @@ import PamguardMVC.PamDataUnit;
import export.CSVExport.CSVExportManager;
import export.MLExport.MLDetectionsManager;
import export.RExport.RExportManager;
import export.layoutFX.ExportParams;
import export.wavExport.WavFileExportManager;
import export.wavExport.WavDetExportManager;
/**
* Exports data to external files. Manages the file sizes and creates data buffers for
@ -62,8 +61,8 @@ public class PamExporterManager {
//add the MATLAB export
pamExporters.add(new MLDetectionsManager());
pamExporters.add(new RExportManager(this));
pamExporters.add(new WavFileExportManager());
pamExporters.add(new CSVExportManager());
pamExporters.add(new WavDetExportManager());
// pamExporters.add(new CSVExportManager());
}
/**
@ -73,11 +72,11 @@ public class PamExporterManager {
public boolean exportDataUnit(PamDataUnit<?, ?> dataUnit, boolean force) {
boolean exportOK = true;
System.out.println("Add data unit " + dataUnit + " to: "+ currentFile);
//System.out.println("Add data unit " + dataUnit + " to: "+ currentFile);
if (dataUnit==null) {
if (force) {
System.out.println("Write data 1!!" + dataUnitBuffer.size() );
//System.out.println("Write data 1!!" + dataUnitBuffer.size() );
//finish off saving any buffered data
exportOK = pamExporters.get(exportParams.exportChoice).exportData(currentFile, dataUnitBuffer, true);
dataUnitBuffer.clear();
@ -101,7 +100,7 @@ public class PamExporterManager {
dataUnitBuffer.add(dataUnit);
System.out.println("Write data unit " + dataUnitBuffer.size() + " to: "+ currentFile);
//System.out.println("Write data unit " + dataUnitBuffer.size() + " to: "+ currentFile);
if (dataUnitBuffer.size()>=BUFFER_SIZE || force) {
// System.out.println("Write data 2!!" + dataUnitBuffer.size());
@ -181,6 +180,21 @@ public class PamExporterManager {
}
/**
* Get the currently selected exporter.
* @return the currently selected exporter.
*/
public PamDataUnitExporter getCurretnExporter() {
return this.pamExporters.get(this.exportParams.exportChoice);
}
public void perpareExport() {
for (PamDataUnitExporter exporter:pamExporters) {
exporter.prepareExport();
}
}

View File

@ -1,5 +1,6 @@
package export.RExport;
import java.awt.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -20,6 +21,7 @@ import PamguardMVC.PamDataUnit;
import export.PamDataUnitExporter;
import export.PamExporterManager;
import export.MLExport.MLDetectionsManager;
import javafx.scene.layout.Pane;
/**
* Handles exporting pam data units into an rdata.
@ -54,8 +56,10 @@ public class RExportManager implements PamDataUnitExporter {
@Override
public boolean exportData(File fileName, List<PamDataUnit> dataUnits, boolean append) {
if (dataUnits==null || dataUnits.size()<=0) return false;
/**
* Note - there is no way to save data units to R files wothout loading the file into memory.
* Note - there is no way to save data units to R files without loading the file into memory.
* So everything is stored in memory until saved.
*/
PamDataUnit minByTime = PamArrayUtils.getMinTimeMillis(dataUnits);
@ -183,7 +187,9 @@ public class RExportManager implements PamDataUnitExporter {
//check whether the same.
if (rDataExport.get(i).getUnitClass().isAssignableFrom(dataUnits.get(j).getClass()) && !alreadyStruct[j]) {
dataList=rDataExport.get(i).detectionToStruct(dataUnits.get(j), n);
dataListArray.add((rDataExport.get(i).getName() + "_" + dataUnits.get(j).getUID()), dataList);
//dataListArray.add((rDataExport.get(i).getName() + "_" + dataUnits.get(j).getUID()), dataList);
// format used in PAMBinaries
dataListArray.add(String.valueOf(dataUnits.get(j).getUID()), dataList);
sampleRate = dataUnits.get(j).getParentDataBlock().getSampleRate();
n++;
@ -267,11 +273,30 @@ public class RExportManager implements PamDataUnitExporter {
//TODO
//check file size against the export params.
System.out.println("RData length: " + allData.length());
// System.out.println("RData length: " + allData.length());
return false;
}
@Override
public Component getOptionsPanel() {
// TODO Auto-generated method stub
return null;
}
@Override
public Pane getOptionsPane() {
// TODO Auto-generated method stub
return null;
}
@Override
public void prepareExport() {
}
}

View File

@ -1,5 +1,6 @@
package export.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
@ -33,9 +34,10 @@ import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.PamPanel;
import PamguardMVC.PamDataBlock;
import export.ExportParams;
import export.PamExporterManager;
import export.layoutFX.ExportParams;
import offlineProcessing.OLProcessDialog;
import offlineProcessing.OLProcessDialog.OLMonitor;
import offlineProcessing.OfflineTaskGroup;
import offlineProcessing.TaskMonitor;
import offlineProcessing.TaskMonitorData;
@ -145,6 +147,10 @@ public class ExportProcessDialog {
*/
private JToggleButton[] exportButtons;
private PamPanel extraSettingsPanel;
private PamPanel mainPanel;
public ExportOLDialog(Window parentFrame, OfflineTaskGroup taskGroup, String title) {
super(parentFrame, taskGroup, title);
@ -155,19 +161,23 @@ public class ExportProcessDialog {
super.getDeleteOldDataBox().setVisible(false);
//construc tthe panel.
PamPanel mainPanel = new PamPanel();
mainPanel = new PamPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
mainPanel.setBorder(new TitledBorder("Export Settings"));
buttonGroup = new ButtonGroup();
extraSettingsPanel = new PamPanel();
PamPanel buttonPanel = new PamPanel();
ActionListener listener = actionEvent -> {
// System.out.println(actionEvent.getActionCommand() + " Selected");
// System.out.println(actionEvent.getActionCommand() + " Selected");
//TODO set the buttons to be disabled or enabled.
enableTasks(getExportSelection());
enableTasks();
};
exportButtons = new JToggleButton[exportManager.getNumExporters()];
@ -189,6 +199,8 @@ public class ExportProcessDialog {
}
PamPanel p = new PamPanel(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints();
c.gridwidth = 3;
@ -238,14 +250,14 @@ public class ExportProcessDialog {
c.gridx ++;
addComponent(p, new JLabel("MB"), c);
mainPanel.add(p);
mainPanel.add(buttonPanel);
mainPanel.add(extraSettingsPanel);
//add the main panel at a different index.
getMainPanel().add(mainPanel, 1);
this.getTasksPanel().setBorder(new TitledBorder("Export Data"));
pack();
}
@ -255,17 +267,26 @@ public class ExportProcessDialog {
* Enable which task are disables and enabled.
* @param exportSelection
*/
private void enableTasks(int exportSelection) {
private void enableTasks() {
this.currentParams = getExportParams();
exportManager.setExportParams(currentParams);
// ExportTask task;
// for (int i=0; i<this.getTaskGroup().getNTasks(); i++) {
// task = (ExportTask) this.getTaskGroup().getTask(i);
// }
// ExportTask task;
// for (int i=0; i<this.getTaskGroup().getNTasks(); i++) {
// task = (ExportTask) this.getTaskGroup().getTask(i);
// }
enableControls();
//add additional controls if needed
extraSettingsPanel.removeAll();
if (exportManager.getCurretnExporter().getOptionsPanel()!=null) {
extraSettingsPanel.add(exportManager.getCurretnExporter().getOptionsPanel(), BorderLayout.CENTER);// add extra settings.
}
mainPanel.validate();
pack();
}
private Ikon getIconFromString(String iconString) {
Ikon icon = null;
@ -325,6 +346,8 @@ public class ExportProcessDialog {
@Override
public boolean getParams() {
System.out.println("EXPORT: GET PARAMS:");
//make sure we update the current paramters before processing starts.
this.currentParams = getExportParams();
exportManager.setExportParams(currentParams);
@ -339,52 +362,96 @@ public class ExportProcessDialog {
public void setParams(ExportParams params) {
// System.out.println("EXPORT: SET PARAMS: " +params);
if (params ==null) currentParams = new ExportParams();
currentParams = params.clone();
buttonGroup.clearSelection();
exportButtons[params.exportChoice].setSelected(true);
// System.out.println("EXPORT: SET PARAMS: " +currentParams.folder);
exportTo.setText(currentParams.folder);
spinner.setValue(currentParams.maximumFileSize);
enableTasks();
}
/**
* Ok, this is a bit of a hack but because we run tasks for multiple data blocks
* we have to run a new task whenever the previous task is finished. So we use a task monitor
* to deetct when the task is finsihed and then, instead of finishing we run a new task.
*/
class ExportTaskMonitor extends OLMonitor {
}
private int taskIndex;
class ExportTaskMonitor implements TaskMonitor {
private ExportTaskGroup exportTaskGroup;
private int taskIndex;
private boolean started = false;
private ExportTaskGroup exportTaskGroup;
private int activeTasks;
private boolean started = false;
public ExportTaskMonitor(int i, ExportTaskGroup exportTaskGroup) {
super();
this.taskIndex = i;
this.exportTaskGroup = exportTaskGroup;
public ExportTaskMonitor(int i, ExportTaskGroup exportTaskGroup) {
this.taskIndex = i;
this.exportTaskGroup = exportTaskGroup;
}
this.activeTasks = 0;
for (int i1=0; i1<exportTaskGroup.getNTasks(); i1++) {
if (exportTaskGroup.getTask(i1).isDoRun()) {
activeTasks++;
}
}
}
@Override
public void setTaskStatus(TaskMonitorData taskMonitorData) {
if (taskMonitorData.taskStatus== TaskStatus.COMPLETE && !started) {
System.out.println(" TASK COMPLETE:");
if (taskIndex<exportTaskGroup.getNTasks()) {
exportTaskGroup.runTaskFrom(taskIndex+1);
started = true;
@Override
public void setTaskStatus(TaskMonitorData taskMonitorData) {
//System.out.println();
switch (taskMonitorData.taskStatus) {
case COMPLETE:
if (taskIndex<exportTaskGroup.getNTasks() && !started) {
exportTaskGroup.runTaskFrom(taskIndex+1);
started = true;
}
else super.setTaskStatus(taskMonitorData);
break;
default:
super.setTaskStatus(taskMonitorData);
}
//A hack which sets the global
switch (taskMonitorData.taskActivity) {
case LINKING:
case LOADING:
//the progress of one datablocks
double progress = ((double) taskMonitorData.progValue)/taskMonitorData.progMaximum;
double totalProgress = ((double) taskIndex)/activeTasks + progress/activeTasks;
// System.out.println("Total progress: " + taskMonitorData.progValue + " of " + taskMonitorData.progMaximum + " - " + totalProgress + "%" + " " + progress + " " + activeTasks + " " + taskIndex);
//needs to be added to the overall progress
int max = getGlobalProgress().getMaximum();
getGlobalProgress().setValue((int) (totalProgress*max));
default:
break;
}
}
}
public ExportTaskMonitor newExportTaskMonitor(int i, ExportTaskGroup exportTaskGroup) {
return new ExportTaskMonitor(i, exportTaskGroup);
}
}
/**
* Export task
*/
@ -406,19 +473,19 @@ public class ExportProcessDialog {
* @param i - the index
*/
public void runTaskFrom(int i) {
System.out.println("RUN TASK FROM :" + i);
//sets the porimary datablock to that of the relevent task.
this.setPrimaryDataBlock(getTask(i).getDataBlock());
if (i<getNTasks()-1) {
//will start a new thread after this one has finished
this.setTaskMonitor(new ExportTaskMonitor(i, this));
this.setTaskMonitor(mtOfflineDialog.newExportTaskMonitor(i, this));
}
super.runTasks();
}
/**
* Override the tasks o it runs through all tasks for each datablock. Usually
* Override the tasks so it runs through all tasks for each datablock. Usually
* task groups deal with just one parent datablock but exporters export from
* different data blocks. The only way to deal with this is to let the task run
* again and again through all tasks and letting tasks themselves check the

View File

@ -38,6 +38,14 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
}
/**
* Called at the start of the thread which executes this task.
*/
@Override
public void prepareTask() {
exporter.perpareExport();
}
@Override
public String getName() {
return this.getDataBlock().getDataName();
@ -46,17 +54,18 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
@Override
public boolean processDataUnit(PamDataUnit<?, ?> dataUnit) {
// System.out.println("Huh? " + this.getDataBlock().getDataName() + " " + dataUnit + " " + dataUnit.getParentDataBlock().equals(this.getDataBlock()));
//System.out.println("Huh? " + this.getDataBlock().getDataName() + " " + dataUnit + " " + dataUnit.getParentDataBlock().equals(this.getDataBlock()));
if (dataUnit.getParentDataBlock().equals(this.getDataBlock())) {
//this is very important because the way the exporter works is that it iterates through multiple parent data blocks
System.out.println(this.getDataBlock().getDataName() + " " + dataUnit + " " + dataSelector.scoreData(dataUnit));
//System.out.println(this.getDataBlock().getDataName() + " " + dataUnit + " " + dataSelector.scoreData(dataUnit));
if (dataSelector==null) {
// System.out.println("Data selector null: " + this.getDataBlock().getDataName() + " " + dataUnit);
//System.out.println("Data selector null: " + this.getDataBlock().getDataName() + " " + dataUnit);
exporter.exportDataUnit(dataUnit, false);
}
else if (dataSelector.scoreData(dataUnit)>=0 || dataSelector.getParams().getCombinationFlag() == DataSelectParams.DATA_SELECT_DISABLE) {
// System.out.println("Data selector OK: " + this.getDataBlock().getDataName() + " " + dataUnit);
else if (dataSelector.scoreData(dataUnit)>0 || dataSelector.getParams().getCombinationFlag() == DataSelectParams.DATA_SELECT_DISABLE) {
//System.out.println("Data selector OK: " + this.getDataBlock().getDataName() + " " + dataUnit);
exporter.exportDataUnit(dataUnit, false);
}
}
@ -72,7 +81,7 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
@Override
public void loadedDataComplete() {
System.out.println("EXPORTER: loaded data complete");
// System.out.println("EXPORTER: loaded data complete");
//force the exporter so save any renaming data units in the buffer
exporter.exportDataUnit(null, true);
exporter.close();

View File

@ -22,34 +22,33 @@ import PamguardMVC.PamRawDataBlock;
import PamguardMVC.dataOffline.OfflineDataLoading;
import dataMap.OfflineDataMapPoint;
import detectiongrouplocaliser.DetectionGroupSummary;
import export.PamDataUnitExporter;
import wavFiles.Wav16AudioFormat;
import wavFiles.WavFileWriter;
/**
* Manages .wav file writing based on what type of data unit is selected and whether raw data is available.
* @author Jamie Macaulay
*
*/
public class WavFileExportManager implements PamDataUnitExporter {
public class WavDetExport {
/**
* Successful writing of .wav file.
*/
public static final int SUCCESS_WAV=0;
// public static final int SUCCESS_WAV=0;
/**
* Successful writing of .wav file from data contained in detections.
*/
public static final int SUCCESS_DET_WAV=1;
// public static final int SUCCESS_DET_WAV=1;
/**
* General failure in wav file writing
*/
public static final int FAILURE_WAV=2;
// public static final int FAILURE_WAV=2;
public static final int LOADING_WAV=2;
// public static final int LOADING_WAV=2;
/**
* The maximum allowed size
*/
private static final double MAX_ZEROPAD_SIZE_MEGABYTES = 1024; //MB
/**
* The default path to write files to
@ -66,9 +65,12 @@ public class WavFileExportManager implements PamDataUnitExporter {
private WavSaveCallback saveCallback;
public WavFileExportManager() {
wavDataUnitExports.add(new RawHolderWavExport());
private WavExportOptions wavFileoptions = new WavExportOptions();
private WavOptionsPanel wavOptionsPanel;
public WavDetExport() {
wavDataUnitExports.add(new RawHolderWavExport());
defaultPath=FileSystemView.getFileSystemView().getDefaultDirectory().getPath();
defaultPath=defaultPath + File.separator + "Pamguard Manual Export";
@ -153,12 +155,20 @@ public class WavFileExportManager implements PamDataUnitExporter {
}
/**
* Convert the mark/dataunits to a .wav file.
* Convert the mark/dataunits to a .wav file. makes a decision as to what to
* save
*
* 1) Data units with no raw data in which case we want to export a wav clip
* from raw data <br> 2) Data units which all have raw data in which case we want to
* export data unit clips as a zero padded wav file (this counts for a single
* data unit too) <b> 3) Mixed data units in which case we want to export a wav clip
* from raw data.
*
* @param foundDataUnits - found data units.
* @param selectedIndex - the currently selected data unit.
* @param mark - overlay mark.
* @param selectedIndex - the currently selected data unit.
* @param mark - overlay mark.
*/
public int dataUnits2Wav(DetectionGroupSummary foundDataUnits, int selectedIndex, OverlayMark mark) {
public int writeOverlayMarkWav(DetectionGroupSummary foundDataUnits, int selectedIndex, OverlayMark mark) {
System.out.println("Data units 2 wav");
//this order for .wav files.
//if there is a mark then save limits of mark. If there is one data unit then set limits of data units
@ -203,15 +213,18 @@ public class WavFileExportManager implements PamDataUnitExporter {
int flag=-1;
String currentFileS = createFileName(foundDataUnits.getFirstTimeMillis());
File file = new File(currentFileS);
if (hasAllWavClips) {
flag = saveDataUnitWav(foundDataUnits);
flag = writeDetGroupWav(foundDataUnits, file, false);
}
else if (!hasAllWavClips && haveRawData) {
//no raw data
flag = saveRawWav(start, end, rawDataBlock);
}
else {
flag = saveDataUnitWav(foundDataUnits);
flag = writeDetGroupWav(foundDataUnits, file, false);
}
return flag;
@ -219,6 +232,7 @@ public class WavFileExportManager implements PamDataUnitExporter {
/**
* Save a clip of wav data from a pre existing .wav or other audio file within in PG.
*
* @param start - the start of the wav file.
* @param end - the end of the wac file.
*/
@ -237,6 +251,168 @@ public class WavFileExportManager implements PamDataUnitExporter {
return 0;
}
/**
* Save wav data from a data unit instead of from the raw file store.
* @param foundDataUnits - the list of found data units.
* @param currentFile - path to current file to save to.
* @param zeroPad - if true will zeroPad detections.
* @return the number of data units that were saved.
*/
public int writeDetGroupWav(DetectionGroupSummary foundDataUnits, File filename, boolean zeroPad) {
return writeDataUnitWav(foundDataUnits.getDataList(), filename, zeroPad);
}
/**
* Save data units which contain raw data to individual wav files within a folder.
* @param foundDataUnits - list of data units to save.
* @param currentFile - the current folder. If this is a file name the parent directory will be used.
* @return the number of data units saved
*/
public int writeDataUnitWavs(List<PamDataUnit> foundDataUnits, File currentFile) {
int n=0;
WavFileWriter wavWrite = null;
for (PamDataUnit fnDataUnit: foundDataUnits){
AudioFormat audioFormat = new Wav16AudioFormat(fnDataUnit.getParentDataBlock().getSampleRate(), PamUtils.getNumChannels(fnDataUnit.getChannelBitmap()));
String currentFileS = createFileName(fnDataUnit.getTimeMilliseconds());
//System.out.println("Save detection wav." + foundDataUnits.size());
for (int i=0; i<wavDataUnitExports.size(); i++) {
if (wavDataUnitExports.get(i).getUnitClass().isAssignableFrom(fnDataUnit.getClass())) {
wavWrite= new WavFileWriter(currentFileS, audioFormat);
System.out.println("Write individual wav." + foundDataUnits.size());
//save the wav file of detection
wavWrite.append(wavDataUnitExports.get(i).getWavClip(fnDataUnit));
n++;
wavWrite.close();
break;
}
}
}
return n;
}
/**
* Save data units which contain raw data to a wav file. Note that this assumed
* the data units all contain raw data, the raw data is at the same sample rate and number of channels
* and the data units are in order. This will APPEND to the wav file if it currently exists.
*
* @param foundDataUnits - data units containing raw data.
* @param currentFile - path to current file to save to.
* @param zeroPad - if true will zeroPad detections.
* @return the number of data units saved - this should be the same as the size
* of the data unit list.
*/
public int writeDataUnitWav(List<PamDataUnit> foundDataUnits, File currentFile, boolean zeroPad) {
int n=0;
WavFileWriter wavWrite = null;
PamDataUnit lastfnDataUnit = null;
if (foundDataUnits==null || foundDataUnits.size()<=0) {
return 0;
}
//System.out.println("Save detection wav." + foundDataUnits.size());
AudioFormat audioFormat = new Wav16AudioFormat(foundDataUnits.get(0).getParentDataBlock().getSampleRate(), PamUtils.getNumChannels(foundDataUnits.get(0).getChannelBitmap()));
wavWrite= new WavFileWriter(currentFile.getAbsolutePath(), audioFormat);
for (PamDataUnit fnDataUnit: foundDataUnits){
for (int i=0; i<wavDataUnitExports.size(); i++) {
if (wavDataUnitExports.get(i).getUnitClass().isAssignableFrom(fnDataUnit.getClass())) {
System.out.println("Append wav. data unit: " + n + " samples: " + wavDataUnitExports.get(i).getWavClip(fnDataUnit)[0].length + " zeroPad: " + zeroPad);
if (zeroPad && lastfnDataUnit!=null) {
//we need to append zero samples between the detections.
long timeMillisDiff = fnDataUnit.getTimeMilliseconds() - lastfnDataUnit.getTimeMilliseconds();
long sampleDiff = fnDataUnit.getStartSample() - lastfnDataUnit.getStartSample();
int samplesPad;
//are the two similar? - are they within 5 milliseconds
if (Math.abs(((sampleDiff/audioFormat.getSampleRate())*1000.) - timeMillisDiff)<5){
//use the sample diff
samplesPad = (int) sampleDiff;
}
else {
//use time millis for padding. May indicate that data units are from different wav files.
samplesPad = (int) ((((double) timeMillisDiff)/1000.)*audioFormat.getSampleRate());
}
//now safety check - is this more than one GB of data. Each sample is 16bits but the input double array is 64 bits each.
double size = samplesPad*16*audioFormat.getChannels()/1024/1024;
System.out.println("Append wav. zero pad" + samplesPad);
//
if (size>MAX_ZEROPAD_SIZE_MEGABYTES) {
wavWrite.close();
System.err.println(String.format("WavDetExport: A zero padding of %.2f MB was requested. The maximum allowed size is %.2f - "
+ "the .wav file was closed and any additional data units have not been written %s", size, MAX_ZEROPAD_SIZE_MEGABYTES, currentFile));
return n;
}
wavWrite.append(new double[audioFormat.getChannels()][samplesPad]);
}
//save the wav file of detection
if (wavWrite.append(wavDataUnitExports.get(i).getWavClip(fnDataUnit))) {
n++;
}
lastfnDataUnit = fnDataUnit;
break;
}
}
}
wavWrite.close();
//send a message that the wav file has saved
if (wavWrite!=null && saveCallback!=null) saveCallback.wavSaved(wavWrite.getFileName(), 0);
return n;
}
/**
* Save wav data from a data unit instead of from the raw file store.
* @param foundDataUnits - the list of found data units.
* @return
*/
private int getNWavDataUnits(DetectionGroupSummary foundDataUnits) {
int n=0;
for (PamDataUnit fnDataUnit: foundDataUnits.getDataList()){
//System.out.println("Save detection wav." + foundDataUnits.getNumDataUnits());
for (int i=0; i<wavDataUnitExports.size(); i++) {
if (wavDataUnitExports.get(i).getUnitClass().isAssignableFrom(fnDataUnit.getClass())) {
n++;
break;
}
}
}
return n;
}
/**
* Set a callback for saving .wav data.
* @param saveCallback - the callback
*/
public void setOnWavSaved(WavSaveCallback saveCallback) {
this.saveCallback=saveCallback;
}
/**
* Observes incoming raw data and saves to a wav file
*
@ -346,198 +522,4 @@ public class WavFileExportManager implements PamDataUnitExporter {
}
/**
* Save wav data from a data unit instead of from the raw file store.
* @param foundDataUnits - the list of found data units.
* @return
*/
private int saveDataUnitWav(DetectionGroupSummary foundDataUnits) {
//TODO - need to pad the detections...with zeros.
//System.out.println("Save data unit wav: " + foundDataUnits.getNumDataUnits());
int n=0;
WavFileWriter wavWrite = null;
for (PamDataUnit fnDataUnit: foundDataUnits.getDataList()){
String currentFile = createFileName(fnDataUnit.getTimeMilliseconds());
AudioFormat audioFormat = new Wav16AudioFormat(fnDataUnit.getParentDataBlock().getSampleRate(), PamUtils.getNumChannels(fnDataUnit.getChannelBitmap()));
System.out.println("Save detection wav." + foundDataUnits.getNumDataUnits());
for (int i=0; i<wavDataUnitExports.size(); i++) {
if (wavDataUnitExports.get(i).getUnitClass().isAssignableFrom(fnDataUnit.getClass())) {
wavWrite= new WavFileWriter(currentFile, audioFormat);
System.out.println("Append wav." + foundDataUnits.getNumDataUnits());
//save the wav file of detection
wavWrite.append(wavDataUnitExports.get(i).getWavClip(fnDataUnit));
n++;
wavWrite.close();
break;
}
}
}
if (wavWrite!=null && saveCallback!=null) saveCallback.wavSaved(wavWrite.getFileName(), 0);
return n;
}
/**
* Save wav data from a data unit instead of from the raw file store.
* @param foundDataUnits - the list of found data units.
* @return
*/
private int getNWavDataUnits(DetectionGroupSummary foundDataUnits) {
int n=0;
for (PamDataUnit fnDataUnit: foundDataUnits.getDataList()){
//System.out.println("Save detection wav." + foundDataUnits.getNumDataUnits());
for (int i=0; i<wavDataUnitExports.size(); i++) {
if (wavDataUnitExports.get(i).getUnitClass().isAssignableFrom(fnDataUnit.getClass())) {
n++;
break;
}
}
}
return n;
}
/**
* Set a callback for saving .wav data.
* @param saveCallback - the callback
*/
public void setOnWavSaved(WavSaveCallback saveCallback) {
this.saveCallback=saveCallback;
}
@Override
public boolean hasCompatibleUnits(Class dataUnitType) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean exportData(File fileName,
List<PamDataUnit> dataUnits, boolean append) {
// TODO Auto-generated method stub
return false;
}
@Override
public String getFileExtension() {
return "wav";
}
@Override
public String getIconString() {
// TODO Auto-generated method stub
return "mdi2f-file-music";
}
@Override
public String getName() {
return "raw sound";
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public boolean isNeedsNewFile() {
return false;
}
// hello(){
//
//
// if (mark==null) {
// start= foundDataUnits.getFirstTimeMillis();
// end= foundDataUnits.getLastTimeMillis();
// }
//
// File folder = new File(currentFolder);
//
// //save a .wav file clip.
// if (!folder.exists()){
// if (!folder.mkdir()){
// //TODO- warning message.
// return;
// }
// }
//
// String currentPath = PamCalendar.formatFileDateTime();
// //add data types to the filen,ae
// for (int i=0 ;i<mlData.size(); i++ ){
// currentPath=currentPath + "_" + mlData.get(i).getName();
// }
// //add correct file type.
// currentPath = currentPath + ".mat";
// currentPath = currentFolder+"\\"+currentPath;
//
//
// if (append && clipControl.clipSettings.storageOption == ClipSettings.STORE_WAVFILES) {
// wavFile.append(rawData);
// lastClipDataUnit.setSampleDuration(rawEnd-lastClipDataUnit.getStartSample());
// clipDataBlock.updatePamData(lastClipDataUnit, dataUnit.getTimeMilliseconds());
// // System.out.println(String.format("%d samples added to file", rawData[0].length));
// }
// else {
// ClipDataUnit clipDataUnit;
// long startMillis = dataUnit.getTimeMilliseconds() - (long) (clipGenSetting.preSeconds*1000.);
// if (clipControl.clipSettings.storageOption == ClipSettings.STORE_WAVFILES) {
// String folderName = getClipFileFolder(dataUnit.getTimeMilliseconds(), true);
// String fileName = getClipFileName(startMillis);
// AudioFormat af = new Wav16AudioFormat(getSampleRate(), rawData.length);
// wavFile = new WavFileWriter(folderName+fileName, af);
// wavFile.write(rawData);
// wavFile.close();
// // make a data unit to go with it.
// clipDataUnit = new ClipDataUnit(startMillis, dataUnit.getTimeMilliseconds(), rawStart,
// (int)(rawEnd-rawStart), channelMap, fileName, dataBlock.getDataName(), rawData, getSampleRate());
// }
// else {
// clipDataUnit = new ClipDataUnit(startMillis, dataUnit.getTimeMilliseconds(), rawStart,
// (int)(rawEnd-rawStart), channelMap, "", dataBlock.getDataName(), rawData, getSampleRate());
// }
// clipDataUnit.setFrequency(dataUnit.getFrequency());
// lastClipDataUnit = clipDataUnit;
// if (bearingLocaliser != null) {
// localiseClip(clipDataUnit, bearingLocaliser, hydrophoneMap);
// }
// clipDataBlock.addPamData(clipDataUnit);
// }
//
// return 0; // no error.
// }
//
// }
// }
}