Skip to content

Commit 19c9912

Browse files
committed
WIP: Simplify music playback
1 parent 89e3081 commit 19c9912

File tree

4 files changed

+234
-139
lines changed

4 files changed

+234
-139
lines changed

Core/API/WebAudio/AudioTrack.js

Lines changed: 141 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,162 @@
1-
var format = require("util").format;
1+
// var format = require("util").format;
22

33
class AudioTrack {
4-
static ERROR_INVALID_VOICE_HANDLE = "Invalid voice handle";
4+
// static ERROR_INVALID_VOICE_HANDLE = "Invalid voice handle";
55
constructor() {
6-
// this.isPlaying = false;
7-
// this.volumePercent = null;
8-
this.voices = {};
9-
this.volumeGain = 1;
10-
this.numVoices = 0;
6+
this.volume = 1; // TODO set for each track in C_WebAudio
7+
this.isTrackMuted = false;
8+
this.useHRTF = C_Settings.getValue("useHighQualityStereo"); // TODO update via options
119

1210
const currentScene = C_Rendering.getActiveScene();
1311
this.soundtrack = new BABYLON.SoundTrack(currentScene);
1412
}
15-
getAudioSource(soundHandleID) {
16-
if (soundHandleID === undefined) throw new RangeError(AudioTrack.ERROR_INVALID_VOICE_HANDLE + ": " + soundHandleID);
17-
return this.voices[soundHandleID];
13+
getNumSounds() {
14+
return this.soundtrack.soundCollection.length;
1815
}
19-
addAudioSource(audioSource) {
20-
const soundHandleID = audioSource.getUniqueID(); // New index at which the source will be inserted
21-
audioSource.setVolume(this.volumeGain);
22-
// Volumes need to be synchronized or some sounds will stick out like a sore thumb
23-
this.voices[soundHandleID] = audioSource;
24-
this.soundtrack.addSound(audioSource.sound);
25-
audioSource.sound.onEndedObservable.add(() => {
26-
DEBUG("Playback for audio source " + audioSource.uniqueID + " has ended");
27-
this.removeAudioSource(soundHandleID);
28-
});
29-
this.numVoices++;
30-
return soundHandleID;
16+
getUniqueID() {
17+
return this.soundtrack.id;
3118
}
32-
removeAudioSource(soundHandleID) {
33-
// ringbuffer, FIFO - size: music = 1, ambience = 10, sfx = 32, track.hasAudioSource to determine when it's removed? object pool?
34-
DEBUG(format("Removing audio source %s", soundHandleID));
35-
if (soundHandleID === undefined) {
36-
throw new RangeError(AudioTrack.ERROR_INVALID_VOICE_HANDLE + ": " + soundHandleID);
37-
}
38-
const audioSource = this.voices[soundHandleID];
39-
if (audioSource === undefined) return true;
40-
41-
audioSource.stopPlaying();
42-
this.soundtrack.removeSound(audioSource.sound);
43-
audioSource.destroy();
44-
45-
delete this.voices[soundHandleID];
46-
this.numVoices--;
47-
48-
return audioSource;
19+
addSound(sound) {
20+
this.soundtrack.addSound(sound);
4921
}
50-
purgeInactiveVoices() {
51-
for (const soundHandleID of Object.keys(this.voices)) {
52-
const audioSource = this.voices[soundHandleID];
53-
if (!audioSource.isPlaying()) {
54-
DEBUG(format("Purging inactive audio source %s (%s)", soundHandleID, audioSource.getFilePath()));
55-
this.removeAudioSource(soundHandleID);
56-
}
57-
}
22+
removeSound(sound) {
23+
this.soundtrack.removeSound(sound);
5824
}
59-
purgeAllVoices() {
60-
for (const soundHandleID of Object.keys(this.voices)) {
61-
const audioSource = this.voices[soundHandleID];
62-
DEBUG(format("Purging audio source %s (%s)", soundHandleID, audioSource.getFilePath()));
63-
this.removeAudioSource(soundHandleID);
64-
}
25+
connectAnalyzer(analyzer) {
26+
this.soundtrack.connectToAnalyser(analyzer);
6527
}
66-
fadeOutStop(fadeoutTimeInMilliseconds = 500) {
67-
for (const soundHandleID of Object.keys(this.voices)) {
68-
const audioSource = this.voices[soundHandleID];
69-
70-
audioSource.fadeOut(fadeoutTimeInMilliseconds);
71-
audioSource.stopPlaying(fadeoutTimeInMilliseconds);
72-
}
28+
destroy() {
29+
this.soundtrack.dispose();
7330
}
74-
fadeInStart(fadeInTimeInMilliseconds = 500) {
75-
for (const soundHandleID of Object.keys(this.voices)) {
76-
const audioSource = this.voices[soundHandleID];
77-
// Can't fade in properly if it starts blasting at a higher volume immediately
78-
audioSource.setVolume(0);
79-
audioSource.startPlaying();
80-
audioSource.fadeIn(this.volumeGain, fadeInTimeInMilliseconds);
81-
// audioSource.setVolume(this.volumeGain, timeToTransitionInMilliseconds);
82-
}
31+
setVolume(volumeGain) {
32+
this.volume = volumeGain;
33+
if (this.isTrackMuted) return; // Do not change the actual volume until it's unmuted
34+
35+
this.soundtrack.setVolume(volumeGain);
8336
}
84-
getVolume() {
85-
return this.volumeGain;
37+
isMuted() {
38+
return this.isTrackMuted;
8639
}
87-
setVolume(volumeGain, timeToTransitionInMilliseconds = 0) {
88-
this.volumeGain = volumeGain;
89-
for (const soundHandleID of Object.keys(this.voices)) {
90-
const audioSource = this.voices[soundHandleID];
91-
audioSource.setVolume(volumeGain, timeToTransitionInMilliseconds);
92-
}
40+
mute() {
41+
this.isTrackMuted = true;
42+
this.soundtrack.setVolume(0);
9343
}
94-
getNumAudioSources() {
95-
return this.numVoices;
44+
unmute() {
45+
this.isTrackMuted = false;
46+
this.soundtrack.setVolume(this.volume);
9647
}
97-
getNumActiveVoices() {
98-
let count = 0;
48+
useHighQualityStereo(enabledFlag) {
49+
if (enabledFlag) this.soundtrack.switchPanningModelToHRTF();
50+
else this.soundtrack.switchPanningModelToEqualPower();
9951

100-
for (const soundHandleID of Object.keys(this.voices)) {
101-
const audioSource = this.voices[soundHandleID];
102-
if (audioSource.isPlaying()) count++;
103-
}
52+
this.useHRTF = enabledFlag;
53+
}
54+
isUsingHighQualityStereo() {
55+
return this.useHRTF;
56+
}
57+
fadeOutStop(fadeoutTimeInMilliseconds = 500) {
58+
this.soundtrack.soundCollection.forEach((sound) => {
59+
DEBUG("Cleaning up audio source " + sound.name + " (playback has ended)");
60+
sound.setVolume(0, fadeoutTimeInMilliseconds / 1000); // ms to s
61+
sound.stop(fadeoutTimeInMilliseconds / 1000);
10462

105-
return count;
63+
setTimeout(() => {
64+
// Defer cleanup so the fadeout has time to finish
65+
this.removeSound(sound);
66+
sound.dispose();
67+
}, fadeoutTimeInMilliseconds);
68+
});
10669
}
70+
// getAudioSource(soundHandleID) {
71+
// if (soundHandleID === undefined) throw new RangeError(AudioTrack.ERROR_INVALID_VOICE_HANDLE + ": " + soundHandleID);
72+
// return this.voices[soundHandleID];
73+
// }
74+
// addAudioSource(audioSource) {
75+
// const soundHandleID = audioSource.getUniqueID(); // New index at which the source will be inserted
76+
// audioSource.setVolume(this.volumeGain);
77+
// // Volumes need to be synchronized or some sounds will stick out like a sore thumb
78+
// this.voices[soundHandleID] = audioSource;
79+
// this.soundtrack.addSound(audioSource.sound);
80+
// audioSource.sound.onEndedObservable.add(() => {
81+
// DEBUG("Playback for audio source " + audioSource.uniqueID + " has ended");
82+
// this.removeAudioSource(soundHandleID);
83+
// });
84+
// this.numVoices++;
85+
// return soundHandleID;
86+
// }
87+
// removeAudioSource(soundHandleID) {
88+
// // ringbuffer, FIFO - size: music = 1, ambience = 10, sfx = 32, track.hasAudioSource to determine when it's removed? object pool?
89+
// DEBUG(format("Removing audio source %s", soundHandleID));
90+
// if (soundHandleID === undefined) {
91+
// throw new RangeError(AudioTrack.ERROR_INVALID_VOICE_HANDLE + ": " + soundHandleID);
92+
// }
93+
// const audioSource = this.voices[soundHandleID];
94+
// if (audioSource === undefined) return true;
95+
96+
// audioSource.stopPlaying();
97+
// this.soundtrack.removeSound(audioSource.sound);
98+
// audioSource.destroy();
99+
100+
// delete this.voices[soundHandleID];
101+
// this.numVoices--;
102+
103+
// return audioSource;
104+
// }
105+
// purgeInactiveVoices() {
106+
// for (const soundHandleID of Object.keys(this.voices)) {
107+
// const audioSource = this.voices[soundHandleID];
108+
// if (!audioSource.isPlaying()) {
109+
// DEBUG(format("Purging inactive audio source %s (%s)", soundHandleID, audioSource.getFilePath()));
110+
// this.removeAudioSource(soundHandleID);
111+
// }
112+
// }
113+
// }
114+
// purgeAllVoices() {
115+
// for (const soundHandleID of Object.keys(this.voices)) {
116+
// const audioSource = this.voices[soundHandleID];
117+
// DEBUG(format("Purging audio source %s (%s)", soundHandleID, audioSource.getFilePath()));
118+
// this.removeAudioSource(soundHandleID);
119+
// }
120+
// }
121+
// fadeOutStop(fadeoutTimeInMilliseconds = 500) {
122+
// for (const soundHandleID of Object.keys(this.voices)) {
123+
// const audioSource = this.voices[soundHandleID];
124+
125+
// audioSource.fadeOut(fadeoutTimeInMilliseconds);
126+
// audioSource.stopPlaying(fadeoutTimeInMilliseconds);
127+
// }
128+
// }
129+
// fadeInStart(fadeInTimeInMilliseconds = 500) {
130+
// for (const soundHandleID of Object.keys(this.voices)) {
131+
// const audioSource = this.voices[soundHandleID];
132+
// // Can't fade in properly if it starts blasting at a higher volume immediately
133+
// audioSource.setVolume(0);
134+
// audioSource.startPlaying();
135+
// audioSource.fadeIn(this.volumeGain, fadeInTimeInMilliseconds);
136+
// // audioSource.setVolume(this.volumeGain, timeToTransitionInMilliseconds);
137+
// }
138+
// }
139+
// getVolume() {
140+
// return this.volumeGain;
141+
// }
142+
// setVolume(volumeGain, timeToTransitionInMilliseconds = 0) {
143+
// this.volumeGain = volumeGain;
144+
// for (const soundHandleID of Object.keys(this.voices)) {
145+
// const audioSource = this.voices[soundHandleID];
146+
// audioSource.setVolume(volumeGain, timeToTransitionInMilliseconds);
147+
// }
148+
// }
149+
// getNumAudioSources() {
150+
// return this.numVoices;
151+
// }
152+
// getNumActiveVoices() {
153+
// let count = 0;
154+
155+
// for (const soundHandleID of Object.keys(this.voices)) {
156+
// const audioSource = this.voices[soundHandleID];
157+
// if (audioSource.isPlaying()) count++;
158+
// }
159+
160+
// return count;
161+
// }
107162
}

0 commit comments

Comments
 (0)