Skip to content

Commit cdc8c53

Browse files
committed
Fixed several race conditions
1 parent 74adf7e commit cdc8c53

File tree

4 files changed

+93
-74
lines changed

4 files changed

+93
-74
lines changed

src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/BassSoundSystem.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
import javax.sound.sampled.AudioSystem;
3030
import java.io.InputStream;
3131
import java.net.URL;
32+
import java.util.ArrayList;
3233
import java.util.HashMap;
3334
import java.util.List;
3435
import java.util.Map;
35-
import java.util.concurrent.CopyOnWriteArrayList;
3636

3737
public class BassSoundSystem extends SoundSystem {
3838

@@ -51,11 +51,15 @@ public static BassSoundSystem createPlayback(final int maxSounds) {
5151

5252

5353
private final Map<String, Integer> soundSamples = new HashMap<>();
54-
private final List<Integer> playingChannels = new CopyOnWriteArrayList<>();
54+
private final List<Integer> playingChannels = new ArrayList<>();
5555
private Thread shutdownHook;
5656

5757
@SuppressWarnings("FieldCanBeLocal")
58-
private final BassLibrary.SYNCPROC channelFreeSync = (handle, channel, data, user) -> this.playingChannels.remove((Integer) channel);
58+
private final BassLibrary.SYNCPROC channelFreeSync = (handle, channel, data, user) -> {
59+
synchronized (this) {
60+
this.playingChannels.remove((Integer) channel);
61+
}
62+
};
5963

6064
private BassSoundSystem(final int maxSounds) {
6165
super(maxSounds);
@@ -93,14 +97,12 @@ private BassSoundSystem(final int maxSounds) {
9397
}
9498

9599
@Override
96-
public void playSound(final String sound, final float pitch, final float volume, final float panning) {
100+
public synchronized void playSound(final String sound, final float pitch, final float volume, final float panning) {
97101
if (!this.soundSamples.containsKey(sound)) return;
98102

99103
if (this.playingChannels.size() >= this.maxSounds) {
100104
if (!BassLibrary.INSTANCE.BASS_ChannelFree(this.playingChannels.remove(0))) {
101-
if (BassLibrary.INSTANCE.BASS_ErrorGetCode() != BassLibrary.BASS_ERROR_HANDLE) {
102-
this.checkError("Could not free audio channel");
103-
}
105+
this.checkError("Could not free audio channel", BassLibrary.BASS_ERROR_HANDLE);
104106
}
105107
}
106108

@@ -126,15 +128,13 @@ public void playSound(final String sound, final float pitch, final float volume,
126128
this.checkError("Could not set audio channel end sync");
127129
}
128130
if (!BassLibrary.INSTANCE.BASS_ChannelStart(channel)) {
129-
if (BassLibrary.INSTANCE.BASS_ErrorGetCode() != BassLibrary.BASS_ERROR_START) {
130-
this.checkError("Could not play audio channel");
131-
}
131+
this.checkError("Could not play audio channel");
132132
}
133133
this.playingChannels.add(channel);
134134
}
135135

136136
@Override
137-
public void stopSounds() {
137+
public synchronized void stopSounds() {
138138
if (!BassLibrary.INSTANCE.BASS_Stop()) {
139139
this.checkError("Could not stop sound system");
140140
}
@@ -145,7 +145,7 @@ public void stopSounds() {
145145
}
146146

147147
@Override
148-
public void close() {
148+
public synchronized void close() {
149149
if (this.shutdownHook != null) {
150150
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
151151
this.shutdownHook = null;
@@ -159,12 +159,12 @@ public void close() {
159159
}
160160

161161
@Override
162-
public String getStatusLine() {
162+
public synchronized String getStatusLine() {
163163
return "Sounds: " + this.playingChannels.size() + " / " + this.maxSounds + ", BASS CPU Load: " + (int) BassLibrary.INSTANCE.BASS_GetCPU() + "%";
164164
}
165165

166166
@Override
167-
public void setMasterVolume(final float volume) {
167+
public synchronized void setMasterVolume(final float volume) {
168168
if (!BassLibrary.INSTANCE.BASS_SetConfig(BassLibrary.BASS_CONFIG_GVOL_STREAM, (int) (volume * 10000))) {
169169
this.checkError("Could not set master volume");
170170
}
@@ -192,9 +192,14 @@ private int loadAudioFile(final InputStream inputStream) {
192192
}
193193
}
194194

195-
private void checkError(final String message) {
195+
private void checkError(final String message, final int... allowedErrors) {
196196
final int error = BassLibrary.INSTANCE.BASS_ErrorGetCode();
197197
if (error != BassLibrary.BASS_OK) {
198+
for (int ignoreError : allowedErrors) {
199+
if (error == ignoreError) {
200+
return;
201+
}
202+
}
198203
throw new RuntimeException("BASS error: " + message + " (" + error + ")");
199204
}
200205
}

src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/JavaxSoundSystem.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@
2525
import javax.sound.sampled.AudioFormat;
2626
import javax.sound.sampled.AudioSystem;
2727
import javax.sound.sampled.SourceDataLine;
28+
import java.util.ArrayList;
2829
import java.util.Arrays;
2930
import java.util.List;
3031
import java.util.Map;
31-
import java.util.concurrent.CopyOnWriteArrayList;
3232

3333
public class JavaxSoundSystem extends SoundSystem {
3434

3535
private static final AudioFormat FORMAT = new AudioFormat(44100, 16, 2, true, false);
3636

3737
protected final Map<String, int[]> sounds;
38-
protected final List<SoundInstance> playingSounds = new CopyOnWriteArrayList<>();
38+
protected final List<SoundInstance> playingSounds = new ArrayList<>();
3939
protected final int samplesPerTick;
4040
protected final SourceDataLine dataLine;
4141
protected float masterVolume = 1F;
@@ -58,7 +58,7 @@ public JavaxSoundSystem(final int maxSounds, final float playbackSpeed) {
5858
}
5959

6060
@Override
61-
public void playSound(final String sound, final float pitch, final float volume, final float panning) {
61+
public synchronized void playSound(final String sound, final float pitch, final float volume, final float panning) {
6262
if (!this.sounds.containsKey(sound)) return;
6363

6464
if (this.playingSounds.size() >= this.maxSounds) {
@@ -69,7 +69,7 @@ public void playSound(final String sound, final float pitch, final float volume,
6969
}
7070

7171
@Override
72-
public void writeSamples() {
72+
public synchronized void writeSamples() {
7373
final long[] samples = new long[this.samplesPerTick];
7474
for (SoundInstance playingSound : this.playingSounds) {
7575
playingSound.render();
@@ -80,24 +80,24 @@ public void writeSamples() {
8080
}
8181

8282
@Override
83-
public void stopSounds() {
83+
public synchronized void stopSounds() {
8484
this.dataLine.flush();
8585
this.playingSounds.clear();
8686
this.volumeDividers = null;
8787
}
8888

8989
@Override
90-
public void close() {
90+
public synchronized void close() {
9191
this.dataLine.stop();
9292
}
9393

9494
@Override
95-
public String getStatusLine() {
95+
public synchronized String getStatusLine() {
9696
return "Sounds: " + this.playingSounds.size() + " / " + this.maxSounds;
9797
}
9898

9999
@Override
100-
public void setMasterVolume(final float volume) {
100+
public synchronized void setMasterVolume(final float volume) {
101101
this.masterVolume = volume;
102102
}
103103

src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/MultithreadedJavaxSoundSystem.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,15 @@ public MultithreadedJavaxSoundSystem(final int maxSounds, final float playbackSp
7878
}
7979

8080
@Override
81-
public void writeSamples() {
82-
final long[] samples = new long[this.samplesPerTick];
83-
for (SoundInstance playingSound : this.playingSounds) {
84-
this.soundsToRender.add(playingSound);
85-
this.syncLock.incrementAndGet();
86-
}
81+
public synchronized void writeSamples() {
82+
this.soundsToRender.addAll(this.playingSounds);
83+
this.syncLock.set(this.playingSounds.size());
8784

8885
while (this.syncLock.get() != 0 && !Thread.currentThread().isInterrupted()) {
8986
// Wait for all sounds to be rendered and merged
9087
}
9188

89+
final long[] samples = new long[this.samplesPerTick];
9290
for (long[] threadSamples : this.threadSamples) {
9391
for (int i = 0; i < samples.length; i++) {
9492
samples[i] += threadSamples[i];
@@ -100,13 +98,13 @@ public void writeSamples() {
10098
}
10199

102100
@Override
103-
public void close() {
101+
public synchronized void close() {
104102
this.threadPool.shutdownNow();
105103
super.close();
106104
}
107105

108106
@Override
109-
public String getStatusLine() {
107+
public synchronized String getStatusLine() {
110108
return super.getStatusLine() + ", " + this.threadPool.getActiveCount() + " threads";
111109
}
112110

0 commit comments

Comments
 (0)