Handle no sound card

Playback when no sound cards are present: Causes problems on new PC's which won't admit to a sound card if nothing is connected, making it impossible to use sound output to slow down processing of files (e.g. during teaching). Have added delay to sort this.
This commit is contained in:
Douglas Gillespie 2024-09-15 13:09:26 +01:00
parent 3c27717479
commit 26475cf366
5 changed files with 53 additions and 8 deletions

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.pamguard</groupId> <groupId>org.pamguard</groupId>
<artifactId>Pamguard</artifactId> <artifactId>Pamguard</artifactId>
<version>2.02.13a</version> <version>2.02.13b</version>
<name>Pamguard</name> <name>Pamguard</name>
<description>Pamguard using Maven to control dependencies</description> <description>Pamguard using Maven to control dependencies</description>
<url>www.pamguard.org</url> <url>www.pamguard.org</url>

View File

@ -31,12 +31,12 @@ public class PamguardVersionInfo {
* Version number, major version.minorversion.sub-release. * Version number, major version.minorversion.sub-release.
* Note: can't go higher than sub-release 'f' * Note: can't go higher than sub-release 'f'
*/ */
static public final String version = "2.02.13a"; static public final String version = "2.02.13b";
/** /**
* Release date * Release date
*/ */
static public final String date = "27 August 2024"; static public final String date = "September 2024";
// /** // /**
// * Release type - Beta or Core // * Release type - Beta or Core

View File

@ -32,8 +32,12 @@ img {
<p> <p>
PAMGuard is compatible PAMGuard is compatible
with <a href="https://tethys.sdsu.edu/tethys3/">Tethys 3.0</a> or with <a href="https://doi.org/10.5281/zenodo.13626338">Tethys 3.1</a> or
later. later available for download from <a href="https://doi.org/10.5281/zenodo.13626338">Zenodo.</a>
</p>
<p>
<a href="https://tethys.sdsu.edu/">Tethys</a> is a freely <a href="https://tethys.sdsu.edu/">Tethys</a> is a freely
available open source temporal-spatial database for metadata available open source temporal-spatial database for metadata
related to acoustic recordings. The database is intended to house related to acoustic recordings. The database is intended to house

View File

@ -71,6 +71,7 @@ public class PlaybackProcess extends PamInstantProcess {
// super.prepareProcess(); // super.prepareProcess();
// System.out.println("Playback prepare process"); // System.out.println("Playback prepare process");
prepareProcess(getSourceSampleRate()); prepareProcess(getSourceSampleRate());
remainDelayMillis = 0;
} }
public boolean prepareProcess(double sourceSampleRate) { public boolean prepareProcess(double sourceSampleRate) {
@ -204,7 +205,10 @@ public class PlaybackProcess extends PamInstantProcess {
@Override @Override
synchronized public void newData(PamObservable o, PamDataUnit arg) { synchronized public void newData(PamObservable o, PamDataUnit arg) {
if (playbackControl.playbackSystem == null) return; if (playbackControl.playbackSystem == null) {
runSpeedLimit(o, arg);
return;
}
int channel = PamUtils.getSingleChannel(arg.getChannelBitmap()); int channel = PamUtils.getSingleChannel(arg.getChannelBitmap());
int pos = channelPos[channel]; int pos = channelPos[channel];
// System.out.printf("Channel %d, pos %d\n", channel, pos); // System.out.printf("Channel %d, pos %d\n", channel, pos);
@ -233,6 +237,7 @@ public class PlaybackProcess extends PamInstantProcess {
boolean playOK = playbackControl.playbackSystem.playData(playUnits, 1); boolean playOK = playbackControl.playbackSystem.playData(playUnits, 1);
if (!playOK) { if (!playOK) {
playWarning.setWarning("PlaybackProcess: playData return error", 2); playWarning.setWarning("PlaybackProcess: playData return error", 2);
runSpeedLimit(o, arg);
noteNewSettings(); // forces full reset of playback noteNewSettings(); // forces full reset of playback
} }
else { else {
@ -255,6 +260,43 @@ public class PlaybackProcess extends PamInstantProcess {
// } // }
} }
double remainDelayMillis = 0;
/**
* Modern desktops won't show a soundcard if no headphones are connected
* or plugged in. e.g. the ones in the teachinglab at work. In this case it's
* almost impossible to run the tutorials since everything happens so fast.
* So this function will cause a small delay before returning when no
* devices are present.
* @param o
* @param arg
*/
private void runSpeedLimit(PamObservable o, PamDataUnit arg) {
Double dataMillis = arg.getDurationInMilliseconds();
if (dataMillis == null) {
return;
}
double speed = playbackControl.playbackParameters.getPlaybackSpeed();
double delay = dataMillis / speed;
int intDelay = (int) Math.floor(delay);
/*
* Be a bit anal and deal with non integer bits by randomly chosing
* to add an extra milli or not.
*/
double remainder = delay - intDelay;
remainDelayMillis += remainder;
while (remainDelayMillis > 1) {
intDelay++;
remainDelayMillis--;
}
if (intDelay > 0) {
try {
Thread.sleep(intDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private RawDataUnit[] preprocessData(RawDataUnit[] inputDataUnits) { private RawDataUnit[] preprocessData(RawDataUnit[] inputDataUnits) {
int isNull = 0; int isNull = 0;
RawDataUnit[] outUnits = new RawDataUnit[inputDataUnits.length]; RawDataUnit[] outUnits = new RawDataUnit[inputDataUnits.length];

View File

@ -94,10 +94,9 @@ public class SoundCardPlaybackBase {
// give up if there are no mixers on the system // give up if there are no mixers on the system
return false; return false;
} }
if (deviceNumber >= mixerinfos.size()) { if (deviceNumber >= mixerinfos.size() || deviceNumber < 0) {
deviceNumber = 0;// reset to default device. deviceNumber = 0;// reset to default device.
} }
Mixer.Info thisMixerInfo = mixerinfos.get(deviceNumber); Mixer.Info thisMixerInfo = mixerinfos.get(deviceNumber);
currentMixer = AudioSystem.getMixer(thisMixerInfo); currentMixer = AudioSystem.getMixer(thisMixerInfo);
if (currentMixer.getSourceLineInfo().length <= 0){ if (currentMixer.getSourceLineInfo().length <= 0){