fix: add delay after AudioContext resume and schedule offset
This commit is contained in:
@@ -124,6 +124,8 @@
|
|||||||
const ctx = getAudioContext()
|
const ctx = getAudioContext()
|
||||||
if (ctx.state === 'suspended') {
|
if (ctx.state === 'suspended') {
|
||||||
await ctx.resume()
|
await ctx.resume()
|
||||||
|
// Wait a frame for currentTime to update after resume
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 50))
|
||||||
}
|
}
|
||||||
const oscillator = ctx.createOscillator()
|
const oscillator = ctx.createOscillator()
|
||||||
const gainNode = ctx.createGain()
|
const gainNode = ctx.createGain()
|
||||||
@@ -134,11 +136,13 @@
|
|||||||
oscillator.frequency.value = frequency
|
oscillator.frequency.value = frequency
|
||||||
oscillator.type = type
|
oscillator.type = type
|
||||||
|
|
||||||
gainNode.gain.setValueAtTime(0.3, ctx.currentTime)
|
// Use small offset to ensure sound is scheduled in the future
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + duration)
|
const startTime = ctx.currentTime + 0.01
|
||||||
|
gainNode.gain.setValueAtTime(0.3, startTime)
|
||||||
|
gainNode.gain.exponentialRampToValueAtTime(0.01, startTime + duration)
|
||||||
|
|
||||||
oscillator.start(ctx.currentTime)
|
oscillator.start(startTime)
|
||||||
oscillator.stop(ctx.currentTime + duration)
|
oscillator.stop(startTime + duration)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to play sound:', e)
|
console.error('Failed to play sound:', e)
|
||||||
}
|
}
|
||||||
@@ -166,7 +170,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMeetingStarted() {
|
async function handleMeetingStarted() {
|
||||||
|
// Pre-initialize AudioContext on user gesture (meeting start click)
|
||||||
|
// This is required because AudioContext can only be resumed during user interaction
|
||||||
|
const ctx = getAudioContext()
|
||||||
|
if (ctx.state === 'suspended') {
|
||||||
|
await ctx.resume()
|
||||||
|
}
|
||||||
meetingActive = true
|
meetingActive = true
|
||||||
currentView = 'main'
|
currentView = 'main'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@
|
|||||||
// Resume context if suspended (required by browsers on first interaction)
|
// Resume context if suspended (required by browsers on first interaction)
|
||||||
if (ctx.state === 'suspended') {
|
if (ctx.state === 'suspended') {
|
||||||
await ctx.resume()
|
await ctx.resume()
|
||||||
|
// Wait a frame for currentTime to update after resume
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 50))
|
||||||
}
|
}
|
||||||
const oscillator = ctx.createOscillator()
|
const oscillator = ctx.createOscillator()
|
||||||
const gainNode = ctx.createGain()
|
const gainNode = ctx.createGain()
|
||||||
@@ -56,11 +58,13 @@
|
|||||||
oscillator.frequency.value = frequency
|
oscillator.frequency.value = frequency
|
||||||
oscillator.type = type
|
oscillator.type = type
|
||||||
|
|
||||||
gainNode.gain.setValueAtTime(0.3, ctx.currentTime)
|
// Use small offset to ensure sound is scheduled in the future
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + duration)
|
const startTime = ctx.currentTime + 0.01
|
||||||
|
gainNode.gain.setValueAtTime(0.3, startTime)
|
||||||
|
gainNode.gain.exponentialRampToValueAtTime(0.01, startTime + duration)
|
||||||
|
|
||||||
oscillator.start(ctx.currentTime)
|
oscillator.start(startTime)
|
||||||
oscillator.stop(ctx.currentTime + duration)
|
oscillator.stop(startTime + duration)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to play sound:', e)
|
console.error('Failed to play sound:', e)
|
||||||
alert('Sound error: ' + e.message)
|
alert('Sound error: ' + e.message)
|
||||||
|
|||||||
Reference in New Issue
Block a user