fix: Prevent multiple audio streams and overlapping audio
CRITICAL AUDIO FIXES: 1. DUPLICATE AUDIO PREVENTION: Fixed skipTask() triggering both 'mocking' + 'denial' punishment audio Added skipAudioPlayed flag to prevent consequence audio when skip audio is playing Modified displayCurrentTask() to check flag before playing consequence audio 2. AUDIO OVERLAP ELIMINATION: Made audio stopping in playAudio() synchronous instead of calling stopCategory() Forcibly stop existing audio immediately: pause() + currentTime=0 + src='' Enhanced stopAllImmediate() to use same aggressive stopping method Removed fadeOut delays in completeTask() and skipTask() (now immediate stop) 3. TIMING IMPROVEMENTS: completeTask() now stops audio immediately (0ms) before playing reward audio skipTask() stops task audio immediately (0ms) before punishment audio Added 100ms delay before reward audio to ensure previous audio fully stopped 4. TECHNICAL DETAILS: - Audio elements now get src='' to fully release resources - Synchronous audio stopping prevents race conditions - Clear fade timeouts to prevent delayed audio operations - Aggressive stopping in both individual playAudio() and global stopAllImmediate() EXPECTED RESULT: - Only ONE audio stream plays at a time - No overlapping punishment/task/reward audio - Clean audio transitions without interruption errors - Proper audio stopping when games end
This commit is contained in:
parent
66bee4821b
commit
f250d015b8
|
|
@ -4455,8 +4455,14 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
|
||||||
|
|
||||||
// Play task audio based on type
|
// Play task audio based on type
|
||||||
if (this.gameState.isConsequenceTask) {
|
if (this.gameState.isConsequenceTask) {
|
||||||
// Play punishment audio for consequence tasks
|
// Play punishment audio for consequence tasks, but not if we just played skip audio
|
||||||
this.audioManager.playPunishmentAudio('denial', { fadeIn: 1000 });
|
if (!this.gameState.skipAudioPlayed) {
|
||||||
|
this.audioManager.playPunishmentAudio('denial', { fadeIn: 1000 });
|
||||||
|
} else {
|
||||||
|
// Clear the flag for next time
|
||||||
|
this.gameState.skipAudioPlayed = false;
|
||||||
|
console.log('Skipping consequence audio - skip punishment audio already playing');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Determine audio intensity based on task difficulty
|
// Determine audio intensity based on task difficulty
|
||||||
const difficulty = this.gameState.currentTask.difficulty || 'Medium';
|
const difficulty = this.gameState.currentTask.difficulty || 'Medium';
|
||||||
|
|
@ -4623,12 +4629,15 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
|
||||||
completeTask() {
|
completeTask() {
|
||||||
if (!this.gameState.isRunning || this.gameState.isPaused) return;
|
if (!this.gameState.isRunning || this.gameState.isPaused) return;
|
||||||
|
|
||||||
// Stop current task audio
|
// Stop current task audio immediately (no fade to prevent overlap)
|
||||||
this.audioManager.stopCategory('tasks', 500);
|
console.log('Task completed - stopping all audio immediately');
|
||||||
this.audioManager.stopCategory('punishments', 500);
|
this.audioManager.stopCategory('tasks', 0);
|
||||||
|
this.audioManager.stopCategory('punishments', 0);
|
||||||
|
|
||||||
// Play reward audio
|
// Brief delay before playing reward audio to ensure previous audio has stopped
|
||||||
this.audioManager.playRewardAudio({ fadeIn: 300 });
|
setTimeout(() => {
|
||||||
|
this.audioManager.playRewardAudio({ fadeIn: 300 });
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// Mark task as used and award points
|
// Mark task as used and award points
|
||||||
if (this.gameState.isConsequenceTask) {
|
if (this.gameState.isConsequenceTask) {
|
||||||
|
|
@ -4717,8 +4726,9 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop current task audio
|
// Stop current task audio immediately (no fade to prevent overlap)
|
||||||
this.audioManager.stopCategory('tasks', 500);
|
console.log('Task skipped - stopping task audio immediately');
|
||||||
|
this.audioManager.stopCategory('tasks', 0);
|
||||||
|
|
||||||
// Play immediate punishment audio
|
// Play immediate punishment audio
|
||||||
this.audioManager.playPunishmentAudio('mocking', { fadeIn: 200 });
|
this.audioManager.playPunishmentAudio('mocking', { fadeIn: 200 });
|
||||||
|
|
@ -4742,6 +4752,7 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
|
||||||
|
|
||||||
// Load a consequence task
|
// Load a consequence task
|
||||||
this.gameState.isConsequenceTask = true;
|
this.gameState.isConsequenceTask = true;
|
||||||
|
this.gameState.skipAudioPlayed = true; // Flag to prevent duplicate audio
|
||||||
this.loadNextTask();
|
this.loadNextTask();
|
||||||
|
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
|
|
|
||||||
|
|
@ -275,8 +275,15 @@ class AudioManager {
|
||||||
|
|
||||||
console.log(`Selected audio file: ${audioFile.path}`);
|
console.log(`Selected audio file: ${audioFile.path}`);
|
||||||
|
|
||||||
// Stop any currently playing audio in this category
|
// Stop any currently playing audio in this category immediately and synchronously
|
||||||
this.stopCategory(category);
|
if (this.categories[category].currentAudio) {
|
||||||
|
const existingAudio = this.categories[category].currentAudio;
|
||||||
|
existingAudio.pause();
|
||||||
|
existingAudio.currentTime = 0;
|
||||||
|
existingAudio.src = ''; // Clear source to fully stop
|
||||||
|
this.categories[category].currentAudio = null;
|
||||||
|
console.log(`Forcibly stopped existing audio in category: ${category}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Create and configure audio element
|
// Create and configure audio element
|
||||||
const audio = new Audio(audioFile.path);
|
const audio = new Audio(audioFile.path);
|
||||||
|
|
@ -368,7 +375,20 @@ class AudioManager {
|
||||||
stopAllImmediate() {
|
stopAllImmediate() {
|
||||||
console.log('Stopping all audio immediately...');
|
console.log('Stopping all audio immediately...');
|
||||||
for (const category in this.categories) {
|
for (const category in this.categories) {
|
||||||
this.stopCategory(category, 0); // No fade, immediate stop
|
if (this.categories[category].currentAudio) {
|
||||||
|
const audio = this.categories[category].currentAudio;
|
||||||
|
audio.pause();
|
||||||
|
audio.currentTime = 0;
|
||||||
|
audio.src = ''; // Clear source to fully stop
|
||||||
|
this.categories[category].currentAudio = null;
|
||||||
|
console.log(`Forcibly stopped audio in category: ${category}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear any pending fade timeouts
|
||||||
|
if (this.categories[category].fadeTimeout) {
|
||||||
|
clearTimeout(this.categories[category].fadeTimeout);
|
||||||
|
this.categories[category].fadeTimeout = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue