Change synchronization on RawDataTransforms soit uses the owner data (#26)

holder, not itself for synchronization. Otherwise you get thread locks.
This commit is contained in:
Douglas Gillespie 2022-03-29 11:42:05 +01:00 committed by GitHub
parent d49d204a8a
commit f1d0268ec5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -99,11 +99,35 @@ public class RawDataTransforms {
*/ */
private int shortestFFTLength; private int shortestFFTLength;
/**
* Object for synchronization. Get thread lock if this isn't the same as
* the object holding the data.
*/
private Object synchObject;
/**
* Raw Data Transforms for a RawDataHolder using the rawDataHolder as the synchronization
* object.
* @param rawDataHolder RawDataHolder object (e.g. a click)
*/
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) { public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
this(rawDataHolder, rawDataHolder);
}
/**
* Raw Data Transforms for a RawDataHolder.
* @param rawDataHolder RawDataHolder object (e.g. a click)
* @param synchObject synchronization object, which is most likely the RawDataHolder object.
*/
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder, Object synchObject) {
this.rawData=(RawDataHolder) rawDataHolder; this.rawData=(RawDataHolder) rawDataHolder;
this.dataUnit = rawDataHolder; this.dataUnit = rawDataHolder;
this.synchObject = synchObject;
if (this.synchObject == null) {
this.synchObject = this;
}
} }
@ -143,23 +167,25 @@ public class RawDataTransforms {
* @param fftLength * @param fftLength
* @return Power spectrum * @return Power spectrum
*/ */
public synchronized double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) { public double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
if (minBin==0 && maxBin>=this.getWaveData(0).length-1) { synchronized (synchObject) {
return getPowerSpectrum(channel, fftLength); if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
} return getPowerSpectrum(channel, fftLength);
if (fftLength == 0) { }
fftLength = getCurrentSpectrumLength(); if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
double[] waveformTrim = new double[maxBin-minBin];
// System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
return cData.magsq();
} }
double[] waveformTrim = new double[maxBin-minBin];
// System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
return cData.magsq();
} }
/** /**
@ -170,29 +196,31 @@ public class RawDataTransforms {
* @param fftLength * @param fftLength
* @return Power spectrum * @return Power spectrum
*/ */
public synchronized double[] getPowerSpectrum(int channel, int fftLength) { public double[] getPowerSpectrum(int channel, int fftLength) {
if (powerSpectra == null) { synchronized (synchObject) {
powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][]; if (powerSpectra == null) {
} powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (powerSpectra[channel] == null
|| powerSpectra[channel].length != fftLength / 2) {
ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
currentSpecLen = fftLength;
powerSpectra[channel] = cData.magsq();
if (powerSpectra==null){
System.err.println("DLDetection: could not calculate power spectra");
return null;
} }
if (powerSpectra[channel].length != fftLength/2) { if (fftLength == 0) {
powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2); fftLength = getCurrentSpectrumLength();
} }
if (powerSpectra[channel] == null
|| powerSpectra[channel].length != fftLength / 2) {
ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
currentSpecLen = fftLength;
powerSpectra[channel] = cData.magsq();
if (powerSpectra==null){
System.err.println("DLDetection: could not calculate power spectra");
return null;
}
if (powerSpectra[channel].length != fftLength/2) {
powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
}
}
return powerSpectra[channel];
} }
return powerSpectra[channel];
} }
@ -202,25 +230,27 @@ public class RawDataTransforms {
* @param fftLength * @param fftLength
* @return Sum of power spectra * @return Sum of power spectra
*/ */
public synchronized double[] getTotalPowerSpectrum(int fftLength) { public double[] getTotalPowerSpectrum(int fftLength) {
if (fftLength == 0) { synchronized (synchObject) {
fftLength = getCurrentSpectrumLength(); if (fftLength == 0) {
} fftLength = getCurrentSpectrumLength();
if (fftLength == 0) { }
fftLength = PamUtils.getMinFftLength(getSampleDuration()); if (fftLength == 0) {
} fftLength = PamUtils.getMinFftLength(getSampleDuration());
double[] ps; }
if (totalPowerSpectrum == null double[] ps;
|| totalPowerSpectrum.length != fftLength / 2) { if (totalPowerSpectrum == null
totalPowerSpectrum = new double[fftLength / 2]; || totalPowerSpectrum.length != fftLength / 2) {
for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) { totalPowerSpectrum = new double[fftLength / 2];
ps = getPowerSpectrum(c, fftLength); for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
for (int i = 0; i < fftLength / 2; i++) { ps = getPowerSpectrum(c, fftLength);
totalPowerSpectrum[i] += ps[i]; for (int i = 0; i < fftLength / 2; i++) {
totalPowerSpectrum[i] += ps[i];
}
} }
} }
return totalPowerSpectrum;
} }
return totalPowerSpectrum;
} }
@ -235,15 +265,17 @@ public class RawDataTransforms {
* @param fftLength - the FFT length to use. * @param fftLength - the FFT length to use.
* @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel. * @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel.
*/ */
public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) { public ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())]; synchronized (synchObject) {
if (complexSpectrum[channel] == null complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
|| complexSpectrum.length != fftLength / 2) { if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength); complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
currentSpecLen = fftLength; currentSpecLen = fftLength;
}
return complexSpectrum[channel];
} }
return complexSpectrum[channel];
} }
@ -282,10 +314,12 @@ public class RawDataTransforms {
* @return the spectrogram length. * @return the spectrogram length.
*/ */
private int getCurrentSpectrumLength() { private int getCurrentSpectrumLength() {
if (currentSpecLen<=0) { synchronized (synchObject) {
currentSpecLen = PamUtils.getMinFftLength(dataUnit.getSampleDuration()); if (currentSpecLen<=0) {
currentSpecLen = PamUtils.getMinFftLength(dataUnit.getSampleDuration());
}
return currentSpecLen;
} }
return currentSpecLen;
} }
@ -371,29 +405,31 @@ public class RawDataTransforms {
* @param fftLength * @param fftLength
* @return the complex spectrum * @return the complex spectrum
*/ */
public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) { public ComplexArray getComplexSpectrum(int channel, int fftLength) {
double[] paddedRawData; synchronized (synchObject) {
double[] rawData; double[] paddedRawData;
int i, mn; double[] rawData;
int i, mn;
if (complexSpectrum == null) { if (complexSpectrum == null) {
complexSpectrum = new ComplexArray[getNChan()]; complexSpectrum = new ComplexArray[getNChan()];
}
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
paddedRawData = new double[fftLength];
rawData = getWaveData(channel);
//double[] rotData = getRotationCorrection(channel);
mn = Math.min(fftLength, getSampleDuration().intValue());
for (i = 0; i < mn; i++) {
paddedRawData[i] = rawData[i];//-rotData[i];
} }
for (i = mn; i < fftLength; i++) { if (complexSpectrum[channel] == null
paddedRawData[i] = 0; || complexSpectrum.length != fftLength / 2) {
paddedRawData = new double[fftLength];
rawData = getWaveData(channel);
//double[] rotData = getRotationCorrection(channel);
mn = Math.min(fftLength, getSampleDuration().intValue());
for (i = 0; i < mn; i++) {
paddedRawData[i] = rawData[i];//-rotData[i];
}
for (i = mn; i < fftLength; i++) {
paddedRawData[i] = 0;
}
complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
} }
complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength); return complexSpectrum[channel];
} }
return complexSpectrum[channel];
} }
@ -402,14 +438,16 @@ public class RawDataTransforms {
* @param iChan channel index * @param iChan channel index
* @return analytic waveform * @return analytic waveform
*/ */
public synchronized double[] getAnalyticWaveform(int iChan) { public double[] getAnalyticWaveform(int iChan) {
if (analyticWaveform == null) { synchronized (synchObject) {
analyticWaveform = new double[getNChan()][]; if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
// }
return analyticWaveform[iChan];
} }
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
// }
return analyticWaveform[iChan];
} }
/** /**
@ -421,12 +459,14 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters. * @param fftFilterParams fft filter parameters.
* @return analystic waveform. * @return analystic waveform.
*/ */
public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) { public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
if (filtered == false || fftFilterParams == null) { synchronized (synchObject) {
return getAnalyticWaveform(iChan); if (filtered == false || fftFilterParams == null) {
} return getAnalyticWaveform(iChan);
else { }
return getFilteredAnalyticWaveform(fftFilterParams, iChan); else {
return getFilteredAnalyticWaveform(fftFilterParams, iChan);
}
} }
} }
@ -437,7 +477,8 @@ public class RawDataTransforms {
* @param iChan channel number * @param iChan channel number
* @return envelope of the filtered data. * @return envelope of the filtered data.
*/ */
public synchronized double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) { public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
synchronized (synchObject) {
if (analyticWaveform == null) { if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][]; analyticWaveform = new double[getNChan()][];
} }
@ -446,6 +487,7 @@ public class RawDataTransforms {
getHilbert(getFilteredWaveData(fftFilterParams, iChan)); getHilbert(getFilteredWaveData(fftFilterParams, iChan));
// } // }
return analyticWaveform[iChan]; return analyticWaveform[iChan];
}
} }
/** /**
@ -455,19 +497,21 @@ public class RawDataTransforms {
* @return analystic waveforms * @return analystic waveforms
*/ */
public double[][] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams) { public double[][] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams) {
if (analyticWaveform == null) { synchronized (synchObject) { // new
analyticWaveform = new double[getNChan()][]; if (analyticWaveform == null) {
} analyticWaveform = new double[getNChan()][];
for (int iChan = 0; iChan < getNChan(); iChan++) {
if (fftFilterParams != null) {
analyticWaveform[iChan] = hilbert.
getHilbert(getFilteredWaveData(fftFilterParams, iChan));
} }
else { for (int iChan = 0; iChan < getNChan(); iChan++) {
analyticWaveform[iChan] = getAnalyticWaveform(iChan); if (fftFilterParams != null) {
analyticWaveform[iChan] = hilbert.
getHilbert(getFilteredWaveData(fftFilterParams, iChan));
}
else {
analyticWaveform[iChan] = getAnalyticWaveform(iChan);
}
} }
return analyticWaveform;
} }
return analyticWaveform;
} }
@ -478,7 +522,7 @@ public class RawDataTransforms {
* @param channelIndex channel index * @param channelIndex channel index
* @return filtered waveform data * @return filtered waveform data
*/ */
public synchronized double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) { public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
filteredWaveData = getFilteredWaveData(filterParams); filteredWaveData = getFilteredWaveData(filterParams);
return filteredWaveData[channelIndex]; return filteredWaveData[channelIndex];
} }
@ -489,12 +533,14 @@ public class RawDataTransforms {
* @param filterParams filter parameters * @param filterParams filter parameters
* @return array of filtered data * @return array of filtered data
*/ */
public synchronized double[][] getFilteredWaveData(FFTFilterParams filterParams) { public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
synchronized (synchObject) {
//System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams)); //System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
if (filteredWaveData == null || filterParams != oldFFTFilterParams) { if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
filteredWaveData = makeFilteredWaveData(filterParams); filteredWaveData = makeFilteredWaveData(filterParams);
} }
return filteredWaveData; return filteredWaveData;
}
} }
@ -538,13 +584,15 @@ public class RawDataTransforms {
* @return FFT filter object. * @return FFT filter object.
*/ */
public FFTFilter getFFTFilter(FFTFilterParams fftFilterParams) { public FFTFilter getFFTFilter(FFTFilterParams fftFilterParams) {
if (fftFilter == null) { synchronized (synchObject) {
fftFilter = new FFTFilter(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate()); if (fftFilter == null) {
fftFilter = new FFTFilter(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
}
else {
fftFilter.setParams(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
}
return fftFilter;
} }
else {
fftFilter.setParams(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
}
return fftFilter;
} }
@ -589,7 +637,9 @@ public class RawDataTransforms {
* @return * @return
*/ */
private int getNChan() { private int getNChan() {
return this.rawData.getWaveData().length; synchronized (synchObject) { // new
return this.rawData.getWaveData().length;
}
} }
/** /**
@ -622,9 +672,11 @@ public class RawDataTransforms {
* Free eup some memory by deleting the filtered wave data, power spectra and analytic waveform. * Free eup some memory by deleting the filtered wave data, power spectra and analytic waveform.
*/ */
public void freeMemory() { public void freeMemory() {
filteredWaveData = null; synchronized (synchObject) {
powerSpectra = null; filteredWaveData = null;
analyticWaveform = null; powerSpectra = null;
analyticWaveform = null;
}
} }