Skip to content

Commit

Permalink
Fix sound skipping frames in safari re-play
Browse files Browse the repository at this point in the history
  • Loading branch information
ffont committed Jan 22, 2024
1 parent f746124 commit 5084b13
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export const createAudioElement = parentNode => {

audioElement.addEventListener('ended', () => {
onPlayerTimeUpdate(audioElement, parentNode);
audioElement.currentTime = 0.0;
})

audioElement.addEventListener('pause', () => {
Expand Down
21 changes: 15 additions & 6 deletions freesound/static/bw-frontend/src/components/player/player-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import { formatAudioDuration, playAtTime, getAudioElementDurationOrDurationPrope
import { createIconElement } from '../../utils/icons'
import { createAudioElement, setProgressIndicator, onPlayerTimeUpdate } from './audio-element'
import { rulerFrequencyMapping } from './utils'
import { isDesktopMacOSWithSafari, isTouchEnabledDevice } from '../../utils/browser'

const removeAllLastPlayedClasses = () => {
document.getElementsByClassName('last-played').forEach(element => {
element.classList.remove('last-played');
});
}

const isTouchEnabledDevice = () => {
return (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0))
}

if (isTouchEnabledDevice()){
document.addEventListener('click', (evt) => {
/* In touch devics, make sure we remove the last-played class when user touches
Expand Down Expand Up @@ -223,7 +220,19 @@ const createPlayButton = (audioElement, playerSize) => {
if (simultaneousPlaybackDisallowed() || evt.altKey){
stopAllPlayers();
}
audioElement.play()
if (isDesktopMacOSWithSafari()){
// In some "oldish" macs with safari there is an issue in which re-playing a sound that has already been played results in
// the first few milliseconds of the sound being skipped. To avoid this, we reload the audio element before playing
// again. This means that the sound is loaded again from the server. This is not ideal but it's the only way to
// get around this issue. The check of isDesktopMacOSWithSafari() is not perfect because it also includes newer macs, but
// it is useful to filter out most of the case in which this issue does not happen.
const previousCurrentTime = audioElement.currentTime;
audioElement.load()
audioElement.currentTime = previousCurrentTime;
audioElement.play()
} else {
audioElement.play()
}
}
evt.stopPropagation()
})
Expand Down Expand Up @@ -704,4 +713,4 @@ const createPlayer = parentNode => {
}


export {createPlayer, isTouchEnabledDevice};
export {createPlayer};
3 changes: 2 additions & 1 deletion freesound/static/bw-frontend/src/components/player/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable import/prefer-default-export */
import {createPlayer, isTouchEnabledDevice} from './player-ui'
import {createPlayer} from './player-ui'

export const simultaneousPlaybackDisallowed = () => {
return document.cookie.indexOf('disallowSimultaneousAudioPlayback=yes') > -1;
Expand Down Expand Up @@ -109,3 +109,4 @@ var y_min = Math.log(100.0) / Math.LN10; // See utils.audioprocessing.processin
var y_max = Math.log(22050.0) / Math.LN10;
for (var y = 500;y >= 0; y--)
rulerFrequencyMapping.push(Math.pow(10.0, y_min + y / 500.0 * (y_max - y_min)));

20 changes: 20 additions & 0 deletions freesound/static/bw-frontend/src/utils/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { UAParser } from 'ua-parser-js';

const { browser, cpu, device } = UAParser(navigator.userAgent);

const isIPad = () => {
return device.model === 'iPad';
}

const isSafari = () => {
return browser.name === 'Safari';
}

export const isTouchEnabledDevice = () => {
return (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0))
}

export const isDesktopMacOSWithSafari = () => {
return isSafari() && !isTouchEnabledDevice();
}

23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"lodash.throttle": "^4.1.1",
"normalize.css": "^8.0.1",
"regenerator-runtime": "^0.13.3",
"ua-parser-js": "^1.0.37",
"whatwg-fetch": "^3.0.0"
}
}

0 comments on commit 5084b13

Please sign in to comment.