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>
<groupId>org.pamguard</groupId>
<artifactId>Pamguard</artifactId>
<version>2.02.13a</version>
<version>2.02.13b</version>
<name>Pamguard</name>
<description>Pamguard using Maven to control dependencies</description>
<url>www.pamguard.org</url>

View File

@ -31,12 +31,12 @@ public class PamguardVersionInfo {
* Version number, major version.minorversion.sub-release.
* 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
*/
static public final String date = "27 August 2024";
static public final String date = "September 2024";
// /**
// * Release type - Beta or Core

View File

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

View File

@ -71,6 +71,7 @@ public class PlaybackProcess extends PamInstantProcess {
// super.prepareProcess();
// System.out.println("Playback prepare process");
prepareProcess(getSourceSampleRate());
remainDelayMillis = 0;
}
public boolean prepareProcess(double sourceSampleRate) {
@ -204,7 +205,10 @@ public class PlaybackProcess extends PamInstantProcess {
@Override
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 pos = channelPos[channel];
// 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);
if (!playOK) {
playWarning.setWarning("PlaybackProcess: playData return error", 2);
runSpeedLimit(o, arg);
noteNewSettings(); // forces full reset of playback
}
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) {
int isNull = 0;
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
return false;
}
if (deviceNumber >= mixerinfos.size()) {
if (deviceNumber >= mixerinfos.size() || deviceNumber < 0) {
deviceNumber = 0;// reset to default device.
}
Mixer.Info thisMixerInfo = mixerinfos.get(deviceNumber);
currentMixer = AudioSystem.getMixer(thisMixerInfo);
if (currentMixer.getSourceLineInfo().length <= 0){