web-audio-api-player
Advanced tools
Comparing version 5.0.4 to 5.1.0-beta.1
1686
dist/index.js
@@ -15,19 +15,5 @@ /****************************************************************************** | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
/* global Reflect, Promise, SuppressedError, Symbol */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
function __extends(d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
} | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
@@ -43,35 +29,13 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { | ||
var e = new Error(message); | ||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; | ||
}; | ||
var SOUND_STATE_STOPPED = 'sound_state_stopped'; | ||
var PlayerSound = (function () { | ||
function PlayerSound(soundAttributes) { | ||
const SOUND_STATE_STOPPED = 'sound_state_stopped'; | ||
class PlayerSound { | ||
constructor(soundAttributes) { | ||
this.url = null; | ||
this.codec = null; | ||
this.loop = false; | ||
this.sourceNode = null; | ||
@@ -88,2 +52,3 @@ this.gainNode = null; | ||
this.startTime = 0; | ||
this.elapsedPlayTime = 0; | ||
this.playTime = 0; | ||
@@ -95,2 +60,3 @@ this.playedTimePercentage = 0; | ||
this.firstTimePlayed = true; | ||
this.isConnectToPlayerGain = false; | ||
if (!Array.isArray(soundAttributes.source)) { | ||
@@ -152,2 +118,8 @@ this.source = [soundAttributes.source]; | ||
} | ||
if (typeof soundAttributes.onSeeking === 'function') { | ||
this.onSeeking = soundAttributes.onSeeking; | ||
} | ||
else { | ||
this.onSeeking = null; | ||
} | ||
if (soundAttributes.arrayBuffer instanceof ArrayBuffer) { | ||
@@ -164,7 +136,7 @@ this.arrayBuffer = soundAttributes.arrayBuffer; | ||
} | ||
PlayerSound.prototype.getCurrentTime = function () { | ||
var currentTime; | ||
getCurrentTime() { | ||
let currentTime; | ||
if (this.sourceNode !== null) { | ||
if (this.sourceNode instanceof AudioBufferSourceNode) { | ||
currentTime = this.sourceNode.context.currentTime; | ||
currentTime = (this.sourceNode.context.currentTime - this.startTime) + this.elapsedPlayTime; | ||
} | ||
@@ -175,9 +147,10 @@ else if (this.sourceNode instanceof MediaElementAudioSourceNode) { | ||
} | ||
return currentTime; | ||
}; | ||
PlayerSound.prototype.getDuration = function () { | ||
var duration; | ||
const currentTimeRounded = Math.round((currentTime + Number.EPSILON) * 100) / 100; | ||
return currentTimeRounded; | ||
} | ||
getDuration() { | ||
let duration; | ||
if (this.sourceNode !== null) { | ||
if (this.sourceNode instanceof AudioBufferSourceNode) { | ||
duration = this.sourceNode.buffer.duration; | ||
duration = this.audioBuffer.duration; | ||
} | ||
@@ -188,26 +161,16 @@ else if (this.sourceNode instanceof MediaElementAudioSourceNode) { | ||
} | ||
return duration; | ||
}; | ||
PlayerSound.prototype._generateSoundId = function () { | ||
const durationRounded = Math.round((duration + Number.EPSILON) * 100) / 100; | ||
return durationRounded; | ||
} | ||
_generateSoundId() { | ||
return Date.now().toString(36) + Math.random().toString(36).substring(2); | ||
}; | ||
PlayerSound.SOUND_STATE_STOPPED = 'sound_state_stopped'; | ||
PlayerSound.SOUND_STATE_PAUSED = 'sound_state_paused'; | ||
PlayerSound.SOUND_STATE_PLAYING = 'sound_state_playing'; | ||
return PlayerSound; | ||
}()); | ||
var PlayerError = (function (_super) { | ||
__extends(PlayerError, _super); | ||
function PlayerError(message, code) { | ||
var _this = _super.call(this, message) || this; | ||
_this.code = code || null; | ||
Object.setPrototypeOf(_this, PlayerError.prototype); | ||
return _this; | ||
} | ||
return PlayerError; | ||
}(Error)); | ||
} | ||
PlayerSound.SOUND_STATE_STOPPED = 'sound_state_stopped'; | ||
PlayerSound.SOUND_STATE_PAUSED = 'sound_state_paused'; | ||
PlayerSound.SOUND_STATE_PLAYING = 'sound_state_playing'; | ||
PlayerSound.SOUND_STATE_SEEKING = 'sound_state_seeking'; | ||
var PlayerAudio = (function () { | ||
function PlayerAudio(options) { | ||
class PlayerAudio { | ||
constructor(options) { | ||
this._audioContext = null; | ||
@@ -218,84 +181,105 @@ this._volume = null; | ||
}; | ||
this._audioElement = null; | ||
this._mediaElementAudioSourceNode = null; | ||
this._isAudioUnlocked = false; | ||
this._options = options; | ||
this._initialize(); | ||
} | ||
PlayerAudio.prototype._initialize = function () { | ||
_initialize() { | ||
if (this._options.createAudioContextOnFirstUserInteraction) { | ||
this._addAutoCreateAudioContextOnFirstUserInteractionEventListeners(); | ||
this._addFirstUserInteractionEventListeners(); | ||
} | ||
}; | ||
PlayerAudio.prototype.decodeAudio = function (arrayBuffer) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var audioContext, audioBufferPromise; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4, this.getAudioContext()]; | ||
case 1: | ||
audioContext = _a.sent(); | ||
return [4, audioContext.decodeAudioData(arrayBuffer)]; | ||
case 2: | ||
audioBufferPromise = _a.sent(); | ||
return [2, Promise.resolve(audioBufferPromise)]; | ||
} | ||
}); | ||
} | ||
getAudioNodes() { | ||
return this._audioNodes; | ||
} | ||
decodeAudio(arrayBuffer) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const audioContext = yield this.getAudioContext(); | ||
return yield audioContext.decodeAudioData(arrayBuffer); | ||
}); | ||
}; | ||
PlayerAudio.prototype._createAudioContext = function () { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { | ||
if (_this._audioContext instanceof AudioContext) { | ||
resolve(); | ||
} | ||
var WebAudioContext = window.AudioContext || window.webkitAudioContext; | ||
try { | ||
if (_this._options.audioContext !== null) { | ||
_this._audioContext = _this._options.audioContext; | ||
} | ||
else { | ||
_this._audioContext = new WebAudioContext(); | ||
} | ||
resolve(); | ||
} | ||
catch (error) { | ||
reject(error); | ||
} | ||
}); | ||
}; | ||
PlayerAudio.prototype._addAutoCreateAudioContextOnFirstUserInteractionEventListeners = function () { | ||
} | ||
_createAudioContext() { | ||
if (this._audioContext instanceof AudioContext) { | ||
return; | ||
} | ||
const WebAudioContext = window.AudioContext || window.webkitAudioContext; | ||
if (this._options.audioContext !== null) { | ||
this._audioContext = this._options.audioContext; | ||
} | ||
else { | ||
this._audioContext = new WebAudioContext(); | ||
} | ||
} | ||
_addFirstUserInteractionEventListeners() { | ||
if (this._options.createAudioContextOnFirstUserInteraction) { | ||
document.addEventListener('touchstart', this.getAudioContext.bind(this)); | ||
document.addEventListener('touchend', this.getAudioContext.bind(this)); | ||
document.addEventListener('mousedown', this.getAudioContext.bind(this)); | ||
document.addEventListener('touchstart', this._unlockAudio.bind(this)); | ||
document.addEventListener('touchend', this._unlockAudio.bind(this)); | ||
document.addEventListener('mousedown', this._unlockAudio.bind(this)); | ||
} | ||
}; | ||
PlayerAudio.prototype._removeAutoCreateAudioContextOnFirstUserInteractionEventListeners = function () { | ||
} | ||
_removeFirstUserInteractionEventListeners() { | ||
if (this._options.createAudioContextOnFirstUserInteraction) { | ||
document.removeEventListener('touchstart', this.getAudioContext.bind(this)); | ||
document.removeEventListener('touchend', this.getAudioContext.bind(this)); | ||
document.removeEventListener('mousedown', this.getAudioContext.bind(this)); | ||
document.removeEventListener('touchstart', this._unlockAudio.bind(this)); | ||
document.removeEventListener('touchend', this._unlockAudio.bind(this)); | ||
document.removeEventListener('mousedown', this._unlockAudio.bind(this)); | ||
} | ||
}; | ||
PlayerAudio.prototype.getAudioContext = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(this._audioContext === null)) return [3, 2]; | ||
return [4, this._createAudioContext()]; | ||
case 1: | ||
_a.sent(); | ||
return [3, 4]; | ||
case 2: | ||
if (!(this._audioContext.state === 'suspended')) return [3, 4]; | ||
return [4, this._unfreezeAudioContext()]; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: return [2, this._audioContext]; | ||
} | ||
_unlockAudio() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._isAudioUnlocked) { | ||
return; | ||
} | ||
yield this.getAudioContext(); | ||
const placeholderBuffer = this._audioContext.createBuffer(1, 1, 22050); | ||
let bufferSource = this._audioContext.createBufferSource(); | ||
bufferSource.onended = () => { | ||
bufferSource.disconnect(0); | ||
this._isAudioUnlocked = true; | ||
this._removeFirstUserInteractionEventListeners(); | ||
bufferSource.disconnect(0); | ||
bufferSource.buffer = null; | ||
bufferSource = null; | ||
}; | ||
bufferSource.buffer = placeholderBuffer; | ||
bufferSource.connect(this._audioContext.destination); | ||
bufferSource.start(0); | ||
if (this._options.loadPlayerMode === 'player_mode_audio') { | ||
this._createAudioElement(); | ||
this._createMediaElementAudioSourceNode(); | ||
} | ||
}); | ||
} | ||
_createAudioElement() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._audioElement === null) { | ||
const audioElement = new Audio(); | ||
audioElement.controls = false; | ||
audioElement.autoplay = false; | ||
audioElement.preload = 'metadata'; | ||
audioElement.volume = 1; | ||
audioElement.id = 'web-audio-api-player'; | ||
this._audioElement = audioElement; | ||
if (this._options.addAudioElementsToDom) { | ||
document.body.appendChild(audioElement); | ||
} | ||
}); | ||
} | ||
}); | ||
}; | ||
PlayerAudio.prototype._unfreezeAudioContext = function () { | ||
if (typeof this._audioContext.suspend === 'undefined') { | ||
} | ||
getAudioElement() { | ||
return this._audioElement; | ||
} | ||
getAudioContext() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._audioContext === null || this._audioContext.state === 'closed') { | ||
yield this._createAudioContext(); | ||
} | ||
else if (this._audioContext.state === 'suspended') { | ||
yield this.unfreezeAudioContext(); | ||
} | ||
return this._audioContext; | ||
}); | ||
} | ||
unfreezeAudioContext() { | ||
if (typeof this._audioContext.resume === 'undefined') { | ||
return Promise.resolve(); | ||
@@ -306,4 +290,4 @@ } | ||
} | ||
}; | ||
PlayerAudio.prototype.freezeAudioContext = function () { | ||
} | ||
freezeAudioContext() { | ||
if (typeof this._audioContext.suspend === 'undefined') { | ||
@@ -315,5 +299,8 @@ return Promise.resolve(); | ||
} | ||
}; | ||
PlayerAudio.prototype.detectAudioContextSupport = function () { | ||
var audioContextSupported = false; | ||
} | ||
isAudioContextFrozen() { | ||
return this._audioContext.state === 'suspended' ? true : false; | ||
} | ||
detectAudioContextSupport() { | ||
let audioContextSupported = false; | ||
if (typeof window.webkitAudioContext !== 'undefined') { | ||
@@ -326,183 +313,147 @@ audioContextSupported = true; | ||
return audioContextSupported; | ||
}; | ||
PlayerAudio.prototype.detectAudioElementSupport = function () { | ||
} | ||
detectAudioElementSupport() { | ||
return !!document.createElement('audio').canPlayType; | ||
}; | ||
PlayerAudio.prototype.shutDown = function (songsQueue) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
this._removeAutoCreateAudioContextOnFirstUserInteractionEventListeners(); | ||
songsQueue.forEach(function (sound) { | ||
if (sound.sourceNode !== null) { | ||
if (sound.sourceNode instanceof MediaElementAudioSourceNode) { | ||
if (typeof sound.sourceNode.mediaElement !== 'undefined') { | ||
sound.sourceNode.mediaElement.remove(); | ||
} | ||
} | ||
sound.sourceNode.disconnect(); | ||
} | ||
}); | ||
this._disconnectPlayerGainNode(); | ||
return [4, this._destroyAudioContext()]; | ||
case 1: | ||
_a.sent(); | ||
return [2]; | ||
} | ||
}); | ||
} | ||
_createAudioBufferSourceNode() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const audioContext = yield this.getAudioContext(); | ||
return audioContext.createBufferSource(); | ||
}); | ||
}; | ||
PlayerAudio.prototype._destroyAudioContext = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(this._audioContext !== null)) return [3, 2]; | ||
return [4, this._audioContext.close()]; | ||
case 1: | ||
_a.sent(); | ||
this._audioContext = null; | ||
_a.label = 2; | ||
case 2: return [2]; | ||
} | ||
}); | ||
} | ||
_createMediaElementAudioSourceNode() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._mediaElementAudioSourceNode === null) { | ||
const audioContext = yield this.getAudioContext(); | ||
this._mediaElementAudioSourceNode = audioContext.createMediaElementSource(this._audioElement); | ||
} | ||
}); | ||
}; | ||
PlayerAudio.prototype.createAudioBufferSourceNode = function (audioBufferSourceOptions, sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var audioContext, audioBufferSourceNode; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4, this.getAudioContext()]; | ||
case 1: | ||
audioContext = _a.sent(); | ||
audioBufferSourceNode = audioContext.createBufferSource(); | ||
sound.sourceNode = audioBufferSourceNode; | ||
audioBufferSourceNode.loop = audioBufferSourceOptions.loop; | ||
sound.gainNode = audioBufferSourceNode.context.createGain(); | ||
sound.gainNode.gain.value = 1; | ||
audioBufferSourceNode.connect(sound.gainNode); | ||
audioBufferSourceNode.onended = function (event) { | ||
audioBufferSourceOptions.onSourceNodeEnded(event); | ||
}; | ||
return [2]; | ||
} | ||
}); | ||
} | ||
_destroyMediaElementAudioSourceNode() { | ||
if (this._mediaElementAudioSourceNode !== null) { | ||
if (typeof this._mediaElementAudioSourceNode.mediaElement !== 'undefined') { | ||
this._mediaElementAudioSourceNode.mediaElement.remove(); | ||
} | ||
this._mediaElementAudioSourceNode.disconnect(); | ||
this._mediaElementAudioSourceNode = null; | ||
} | ||
} | ||
_destroyAudioBufferSourceNode() { | ||
if (this._mediaElementAudioSourceNode !== null) { | ||
this._mediaElementAudioSourceNode.disconnect(); | ||
} | ||
} | ||
_destroyAudioContext() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._audioContext !== null && this._audioContext.state !== 'closed') { | ||
yield this._audioContext.close(); | ||
this._audioContext = null; | ||
} | ||
}); | ||
}; | ||
PlayerAudio.prototype.createMediaElementSourceNode = function (sourceNodeOptions, sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var mediaElementAudioSourceNode, audioContext; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(sound.sourceNode === null)) return [3, 2]; | ||
return [4, this.getAudioContext()]; | ||
case 1: | ||
audioContext = _a.sent(); | ||
try { | ||
mediaElementAudioSourceNode = audioContext.createMediaElementSource(sourceNodeOptions.mediaElement); | ||
} | ||
catch (error) { | ||
throw new PlayerError(error); | ||
} | ||
mediaElementAudioSourceNode.mediaElement.loop = sourceNodeOptions.loop; | ||
sound.gainNode = mediaElementAudioSourceNode.context.createGain(); | ||
sound.gainNode.gain.value = 1; | ||
mediaElementAudioSourceNode.connect(sound.gainNode); | ||
mediaElementAudioSourceNode.mediaElement.onended = function () { return __awaiter(_this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
sourceNodeOptions.onSourceNodeEnded(); | ||
return [2]; | ||
}); | ||
}); }; | ||
sound.sourceNode = mediaElementAudioSourceNode; | ||
_a.label = 2; | ||
case 2: return [2]; | ||
} | ||
} | ||
shutDown(songsQueue) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this._removeFirstUserInteractionEventListeners(); | ||
songsQueue.forEach((sound) => { | ||
this.disconnectSound(sound); | ||
}); | ||
this._destroyMediaElementAudioSourceNode(); | ||
this._destroyAudioBufferSourceNode(); | ||
this._disconnectPlayerGainNode(); | ||
yield this._destroyAudioContext(); | ||
}); | ||
}; | ||
PlayerAudio.prototype._getPlayerGainNode = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var gainNode, audioContext; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(this._audioNodes.gainNode instanceof GainNode)) return [3, 1]; | ||
gainNode = this._audioNodes.gainNode; | ||
return [3, 3]; | ||
case 1: return [4, this.getAudioContext()]; | ||
case 2: | ||
audioContext = _a.sent(); | ||
gainNode = audioContext.createGain(); | ||
gainNode.connect(audioContext.destination); | ||
this._audioNodes.gainNode = gainNode; | ||
_a.label = 3; | ||
case 3: | ||
this._initializeVolume(); | ||
return [2, gainNode]; | ||
} | ||
}); | ||
} | ||
_getPlayerGainNode() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let gainNode; | ||
if (this._audioNodes.gainNode instanceof GainNode) { | ||
gainNode = this._audioNodes.gainNode; | ||
} | ||
else { | ||
const audioContext = yield this.getAudioContext(); | ||
gainNode = audioContext.createGain(); | ||
this._initializeVolume(gainNode); | ||
gainNode.connect(audioContext.destination); | ||
this._audioNodes.gainNode = gainNode; | ||
} | ||
return gainNode; | ||
}); | ||
}; | ||
PlayerAudio.prototype._disconnectPlayerGainNode = function () { | ||
} | ||
_disconnectPlayerGainNode() { | ||
if (this._audioNodes.gainNode !== null) { | ||
this._audioNodes.gainNode.disconnect(); | ||
this._audioNodes.gainNode = null; | ||
} | ||
this._audioNodes.gainNode = null; | ||
}; | ||
PlayerAudio.prototype.connectSound = function (sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var playerGainNode, soundGainNode; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4, this._getPlayerGainNode()]; | ||
case 1: | ||
playerGainNode = _a.sent(); | ||
soundGainNode = sound.gainNode; | ||
if (soundGainNode !== null) { | ||
soundGainNode.connect(playerGainNode); | ||
} | ||
return [2]; | ||
} | ||
}); | ||
} | ||
connectSound(sound, onEndedCallback) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (sound.isConnectToPlayerGain) { | ||
return; | ||
} | ||
if (this._options.loadPlayerMode === 'player_mode_ajax') { | ||
const audioBufferSourceNode = yield this._createAudioBufferSourceNode(); | ||
sound.gainNode = audioBufferSourceNode.context.createGain(); | ||
audioBufferSourceNode.connect(sound.gainNode); | ||
audioBufferSourceNode.loop = sound.loop; | ||
audioBufferSourceNode.onended = onEndedCallback; | ||
sound.sourceNode = audioBufferSourceNode; | ||
} | ||
else if (this._options.loadPlayerMode === 'player_mode_audio') { | ||
sound.gainNode = this._mediaElementAudioSourceNode.context.createGain(); | ||
this._mediaElementAudioSourceNode.connect(sound.gainNode); | ||
this._mediaElementAudioSourceNode.mediaElement.loop = sound.loop; | ||
this._mediaElementAudioSourceNode.mediaElement.onended = onEndedCallback; | ||
sound.sourceNode = this._mediaElementAudioSourceNode; | ||
} | ||
sound.gainNode.gain.value = 1; | ||
const playerGainNode = yield this._getPlayerGainNode(); | ||
sound.gainNode.connect(playerGainNode); | ||
sound.isConnectToPlayerGain = true; | ||
}); | ||
}; | ||
PlayerAudio.prototype.cleanUpAudiBufferSourceNode = function (sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
if (sound.sourceNode instanceof AudioBufferSourceNode) { | ||
sound.sourceNode = null; | ||
} | ||
disconnectSound(sound) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!sound.isConnectToPlayerGain) { | ||
return; | ||
} | ||
if (sound.sourceNode !== null) { | ||
sound.sourceNode.disconnect(); | ||
sound.sourceNode = null; | ||
} | ||
if (sound.gainNode !== null) { | ||
sound.gainNode.disconnect(); | ||
sound.gainNode = null; | ||
sound.isConnectToPlayerGain = false; | ||
} | ||
if (sound.audioElement !== null) { | ||
sound.audioElement = null; | ||
} | ||
}); | ||
} | ||
_changePlayerGainValue(gainValue) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._audioNodes.gainNode instanceof GainNode) { | ||
const audioContext = yield this.getAudioContext(); | ||
this._audioNodes.gainNode.gain.setTargetAtTime(gainValue, audioContext.currentTime, 0.1); | ||
} | ||
}); | ||
} | ||
setVolume(volume, forceUpdateUserVolume = true) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._options.persistVolume && forceUpdateUserVolume) { | ||
localStorage.setItem('WebAudioAPIPlayerVolume', volume.toString()); | ||
} | ||
const newGainValue = volume / 100; | ||
if (this._audioNodes.gainNode instanceof GainNode) { | ||
const currentGainRounded = Math.round((this._audioNodes.gainNode.gain.value + Number.EPSILON) * 100) / 100; | ||
if (newGainValue !== currentGainRounded) { | ||
yield this._changePlayerGainValue(newGainValue); | ||
} | ||
return [2]; | ||
}); | ||
} | ||
this._volume = volume; | ||
return volume; | ||
}); | ||
}; | ||
PlayerAudio.prototype._changePlayerGainValue = function (gainValue) { | ||
if (this._audioNodes.gainNode instanceof GainNode) { | ||
this._audioNodes.gainNode.gain.value = gainValue; | ||
} | ||
}; | ||
PlayerAudio.prototype._roundGainTwoDecimals = function (rawGainValue) { | ||
return Math.round((rawGainValue + Number.EPSILON) * 100) / 100; | ||
}; | ||
PlayerAudio.prototype.setVolume = function (volume, forceUpdateUserVolume) { | ||
if (forceUpdateUserVolume === void 0) { forceUpdateUserVolume = true; } | ||
if (this._options.persistVolume && forceUpdateUserVolume) { | ||
localStorage.setItem('WebAudioAPIPlayerVolume', volume.toString()); | ||
} | ||
var gainValue = volume / 100; | ||
if (this._audioNodes.gainNode instanceof GainNode) { | ||
var roundedGain = this._roundGainTwoDecimals(this._audioNodes.gainNode.gain.value); | ||
if (roundedGain !== this._volume) { | ||
this._changePlayerGainValue(gainValue); | ||
} | ||
} | ||
this._volume = volume; | ||
}; | ||
PlayerAudio.prototype.getVolume = function () { | ||
var volume; | ||
} | ||
getVolume() { | ||
let volume; | ||
if (this._volume !== null) { | ||
@@ -513,3 +464,3 @@ volume = this._volume; | ||
if (this._options.persistVolume) { | ||
var userVolumeInPercent = parseInt(localStorage.getItem('WebAudioAPIPlayerVolume')); | ||
const userVolumeInPercent = parseInt(localStorage.getItem('WebAudioAPIPlayerVolume')); | ||
if (!isNaN(userVolumeInPercent)) { | ||
@@ -522,25 +473,27 @@ volume = userVolumeInPercent; | ||
} | ||
this._volume = volume; | ||
} | ||
return volume; | ||
}; | ||
PlayerAudio.prototype._initializeVolume = function () { | ||
} | ||
_initializeVolume(gainNode) { | ||
if (this._options.persistVolume) { | ||
var userVolumeInPercent = parseInt(localStorage.getItem('WebAudioAPIPlayerVolume')); | ||
const userVolumeInPercent = parseInt(localStorage.getItem('WebAudioAPIPlayerVolume')); | ||
const gainValue = userVolumeInPercent / 100; | ||
if (!isNaN(userVolumeInPercent)) { | ||
this.setVolume(userVolumeInPercent, false); | ||
gainNode.gain.value = gainValue; | ||
} | ||
this._volume = userVolumeInPercent; | ||
} | ||
if (this._volume === null) { | ||
this.setVolume(this._options.volume, false); | ||
const gainValue = this._options.volume / 100; | ||
gainNode.gain.value = gainValue; | ||
this._volume = this._options.volume; | ||
} | ||
}; | ||
return PlayerAudio; | ||
}()); | ||
} | ||
} | ||
var PlayerRequest = (function () { | ||
function PlayerRequest() { | ||
} | ||
PlayerRequest.prototype.getArrayBuffer = function (requested) { | ||
class PlayerRequest { | ||
getArrayBuffer(requested) { | ||
return new Promise(function (resolve, reject) { | ||
var xhr = new XMLHttpRequest(); | ||
const xhr = new XMLHttpRequest(); | ||
xhr.open('GET', requested.url, true); | ||
@@ -553,39 +506,52 @@ xhr.responseType = 'arraybuffer'; | ||
else { | ||
reject(new PlayerError(xhr.statusText, xhr.status)); | ||
reject(new Error(xhr.statusText + '(status:' + xhr.status + ')')); | ||
} | ||
}; | ||
xhr.onprogress = function (event) { | ||
var percentage = 100 / (event.total / event.loaded); | ||
requested.loadingProgress = percentage; | ||
const percentage = 100 / (event.total / event.loaded); | ||
const percentageRounded = Math.round((percentage + Number.EPSILON) * 100) / 100; | ||
requested.loadingProgress = percentageRounded; | ||
if (requested.onLoading !== null) { | ||
requested.onLoading(percentage, event.total, event.loaded); | ||
requested.onLoading(percentageRounded, event.total, event.loaded); | ||
} | ||
}; | ||
xhr.onerror = function () { | ||
reject(new PlayerError('xhr network error')); | ||
xhr.onerror = function (error) { | ||
reject(error); | ||
}; | ||
xhr.send(); | ||
}); | ||
}; | ||
return PlayerRequest; | ||
}()); | ||
} | ||
} | ||
var PLAYER_MODE_AUDIO = 'player_mode_audio'; | ||
var WHERE_IN_QUEUE_AT_END = 'append'; | ||
var PlayerCore = (function () { | ||
function PlayerCore(playerOptions) { | ||
var _this = this; | ||
if (playerOptions === void 0) { playerOptions = {}; } | ||
const PLAYER_MODE_AUDIO = 'player_mode_audio'; | ||
const WHERE_IN_QUEUE_AT_END = 'append'; | ||
class PlayerCore { | ||
constructor(playerOptions = {}) { | ||
this._playingProgressRequestId = null; | ||
this._playingProgressPreviousTimestamp = 0; | ||
this._progressTrigger = function (sound, timestamp) { | ||
if ((timestamp - _this._playingProgressPreviousTimestamp) >= _this._options.playingProgressIntervalTime) { | ||
_this._playingProgress(sound); | ||
_this._playingProgressPreviousTimestamp = timestamp; | ||
this._postMuteVolume = null; | ||
this._progressTrigger = (sound, timestamp) => { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (sound.id !== currentSound.id || currentSound.state !== PlayerSound.SOUND_STATE_PLAYING) { | ||
return; | ||
} | ||
_this._playingProgressRequestId = window.requestAnimationFrame(function (timestamp) { | ||
_this._progressTrigger(sound, timestamp); | ||
if ((timestamp - this._playingProgressPreviousTimestamp) >= this._options.playingProgressIntervalTime) { | ||
const currentTime = sound.getCurrentTime(); | ||
const duration = sound.getDuration(); | ||
if (!isNaN(currentTime) && !isNaN(duration)) { | ||
let playingPercentage = 0; | ||
if (currentTime !== 0) { | ||
const playingPercentageRaw = (currentTime / duration) * 100; | ||
playingPercentage = Math.round(playingPercentageRaw); | ||
} | ||
sound.playedTimePercentage = playingPercentage; | ||
sound.playTime = currentTime; | ||
sound.onPlaying(playingPercentage, duration, currentTime); | ||
this._playingProgressPreviousTimestamp = timestamp; | ||
} | ||
} | ||
this._playingProgressRequestId = window.requestAnimationFrame((timestamp) => { | ||
this._progressTrigger(sound, timestamp); | ||
}); | ||
}; | ||
var defaultOptions = { | ||
const defaultOptions = { | ||
volume: 80, | ||
@@ -603,11 +569,13 @@ loopQueue: false, | ||
audioContext: null, | ||
addAudioElementsToDom: false, | ||
}; | ||
var options = Object.assign({}, defaultOptions, playerOptions); | ||
const options = Object.assign({}, defaultOptions, playerOptions); | ||
this._queue = []; | ||
this._currentIndex = null; | ||
this._currentIndex = 0; | ||
this._options = options; | ||
this._playingProgressPreviousTimestamp = 0; | ||
this._initialize(); | ||
} | ||
PlayerCore.prototype._initialize = function () { | ||
var audioOptions = this._audioOptions(); | ||
_initialize() { | ||
const audioOptions = this._audioOptions(); | ||
this._playerAudio = new PlayerAudio(audioOptions); | ||
@@ -617,6 +585,6 @@ switch (this._options.loadPlayerMode) { | ||
if (!this._playerAudio.detectAudioContextSupport()) { | ||
throw new PlayerError('audio context is not supported by this device'); | ||
throw new Error('audio context is not supported by this device'); | ||
} | ||
if (!this._playerAudio.detectAudioElementSupport()) { | ||
throw new PlayerError('audio element is not supported by this device'); | ||
throw new Error('audio element is not supported by this device'); | ||
} | ||
@@ -626,9 +594,9 @@ break; | ||
if (!this._playerAudio.detectAudioContextSupport()) { | ||
throw new PlayerError('audio context is not supported by this device'); | ||
throw new Error('audio context is not supported by this device'); | ||
} | ||
break; | ||
} | ||
}; | ||
PlayerCore.prototype._audioOptions = function () { | ||
var audioOptions = { | ||
} | ||
_audioOptions() { | ||
const audioOptions = { | ||
audioContext: this._options.audioContext, | ||
@@ -638,8 +606,9 @@ createAudioContextOnFirstUserInteraction: this._options.createAudioContextOnFirstUserInteraction, | ||
persistVolume: this._options.persistVolume, | ||
loadPlayerMode: this._options.loadPlayerMode, | ||
addAudioElementsToDom: this._options.addAudioElementsToDom, | ||
}; | ||
return audioOptions; | ||
}; | ||
PlayerCore.prototype.addSoundToQueue = function (_a) { | ||
var soundAttributes = _a.soundAttributes, _b = _a.whereInQueue, whereInQueue = _b === void 0 ? WHERE_IN_QUEUE_AT_END : _b; | ||
var sound = new PlayerSound(soundAttributes); | ||
} | ||
addSoundToQueue({ soundAttributes, whereInQueue = WHERE_IN_QUEUE_AT_END }) { | ||
const sound = new PlayerSound(soundAttributes); | ||
switch (whereInQueue) { | ||
@@ -654,169 +623,181 @@ case PlayerCore.WHERE_IN_QUEUE_AT_END: | ||
return sound; | ||
}; | ||
PlayerCore.prototype._appendSoundToQueue = function (sound) { | ||
} | ||
_appendSoundToQueue(sound) { | ||
this._queue.push(sound); | ||
}; | ||
PlayerCore.prototype._prependSoundToQueue = function (sound) { | ||
} | ||
_prependSoundToQueue(sound) { | ||
this._queue.unshift(sound); | ||
}; | ||
PlayerCore.prototype.resetQueue = function () { | ||
if (this._options.stopOnReset) { | ||
this.stop(); | ||
} | ||
this._queue = []; | ||
}; | ||
PlayerCore.prototype.reset = function () { | ||
this.resetQueue(); | ||
}; | ||
PlayerCore.prototype.getQueue = function () { | ||
} | ||
resetQueue() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._options.stopOnReset) { | ||
yield this.stop(); | ||
} | ||
this._queue.forEach((sound) => { | ||
this._playerAudio.disconnectSound(sound); | ||
}); | ||
this._queue = []; | ||
}); | ||
} | ||
reset() { | ||
this.resetQueue().catch((error) => { | ||
console.error(error); | ||
}); | ||
} | ||
getQueue() { | ||
return this._queue; | ||
}; | ||
PlayerCore.prototype.setVolume = function (volume) { | ||
this._playerAudio.setVolume(volume); | ||
}; | ||
PlayerCore.prototype.getVolume = function () { | ||
} | ||
setVolume(volume) { | ||
this._playerAudio.setVolume(volume).catch((error) => { | ||
console.error(error); | ||
}); | ||
} | ||
getVolume() { | ||
return this._playerAudio.getVolume(); | ||
}; | ||
PlayerCore.prototype.setLoopQueue = function (loppQueue) { | ||
} | ||
setLoopQueue(loppQueue) { | ||
this._options.loopQueue = loppQueue; | ||
}; | ||
PlayerCore.prototype.getLoopQueue = function () { | ||
} | ||
getLoopQueue() { | ||
return this._options.loopQueue; | ||
}; | ||
PlayerCore.prototype.mute = function () { | ||
var currentVolume = this.getVolume(); | ||
} | ||
mute() { | ||
const currentVolume = this.getVolume(); | ||
this._playerAudio.setVolume(0, false).catch((error) => { | ||
console.error(error); | ||
}); | ||
this._postMuteVolume = currentVolume; | ||
this._playerAudio.setVolume(0, false); | ||
}; | ||
PlayerCore.prototype.unMute = function () { | ||
this._playerAudio.setVolume(this._postMuteVolume, false); | ||
} | ||
unMute() { | ||
this._playerAudio.setVolume(this._postMuteVolume, false).catch((error) => { | ||
console.error(error); | ||
}); | ||
this._postMuteVolume = null; | ||
}; | ||
PlayerCore.prototype.isMuted = function () { | ||
return this._postMuteVolume === null ? true : false; | ||
}; | ||
PlayerCore.prototype.setPosition = function (soundPositionInPercent) { | ||
var _this = this; | ||
var currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound !== null) { | ||
if (currentSound.duration === null || isNaN(currentSound.duration)) { | ||
this._loadSound(currentSound) | ||
.then(function (sound) { | ||
var soundPositionInSeconds = (sound.duration / 100) * soundPositionInPercent; | ||
_this.setPositionInSeconds(soundPositionInSeconds); | ||
}).catch(function (error) { | ||
throw error; | ||
}); | ||
} | ||
else { | ||
var soundPositionInSeconds = (currentSound.duration / 100) * soundPositionInPercent; | ||
} | ||
isMuted() { | ||
return this._postMuteVolume === null ? false : true; | ||
} | ||
setPosition(soundPositionInPercent) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound !== null) { | ||
let duration = currentSound.getDuration(); | ||
if (duration === null || isNaN(duration)) { | ||
yield this._loadSound(currentSound); | ||
duration = currentSound.getDuration(); | ||
} | ||
const soundPositionInSeconds = (duration / 100) * soundPositionInPercent; | ||
this.setPositionInSeconds(soundPositionInSeconds); | ||
} | ||
} | ||
}; | ||
PlayerCore.prototype.setPositionInSeconds = function (soundPositionInSeconds) { | ||
var currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound !== null) { | ||
if (currentSound.state === PlayerSound.SOUND_STATE_PLAYING) { | ||
this.play({ whichSound: currentSound.id, playTimeOffset: soundPositionInSeconds }); | ||
}); | ||
} | ||
setPositionInSeconds(soundPositionInSeconds) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound !== null) { | ||
if (currentSound.onSeeking !== null) { | ||
const playTime = soundPositionInSeconds; | ||
const duration = currentSound.getDuration(); | ||
const seekingPercentageRaw = (playTime / duration) * 100; | ||
const seekingPercentage = Math.round(seekingPercentageRaw); | ||
currentSound.onSeeking(seekingPercentage, duration, playTime); | ||
} | ||
if (currentSound.state === PlayerSound.SOUND_STATE_PLAYING) { | ||
currentSound.playTime = soundPositionInSeconds; | ||
if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AJAX) { | ||
currentSound.elapsedPlayTime = soundPositionInSeconds; | ||
yield this._stop(currentSound, PlayerSound.SOUND_STATE_SEEKING); | ||
} | ||
else if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AUDIO) { | ||
currentSound.state = PlayerSound.SOUND_STATE_SEEKING; | ||
yield this._play(currentSound); | ||
} | ||
} | ||
else { | ||
currentSound.playTime = soundPositionInSeconds; | ||
currentSound.state = PlayerSound.SOUND_STATE_SEEKING; | ||
} | ||
} | ||
else { | ||
currentSound.playTimeOffset = soundPositionInSeconds; | ||
}); | ||
} | ||
_loadSound(sound) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
switch (this._options.loadPlayerMode) { | ||
case PlayerCore.PLAYER_MODE_AUDIO: | ||
yield this._loadSoundUsingAudioElement(sound); | ||
break; | ||
case PlayerCore.PLAYER_MODE_AJAX: | ||
yield this._loadSoundUsingRequest(sound); | ||
break; | ||
case PlayerCore.PLAYER_MODE_FETCH: | ||
console.warn(PlayerCore.PLAYER_MODE_FETCH + ' is not implemented yet'); | ||
} | ||
} | ||
else { | ||
throw new PlayerError('position change called, but no current sound found'); | ||
} | ||
}; | ||
PlayerCore.prototype._loadSound = function (sound) { | ||
var loadSoundPromise; | ||
var notImplementedError; | ||
switch (this._options.loadPlayerMode) { | ||
case PlayerCore.PLAYER_MODE_AUDIO: | ||
loadSoundPromise = this._loadSoundUsingAudioElement(sound); | ||
break; | ||
case PlayerCore.PLAYER_MODE_AJAX: | ||
loadSoundPromise = this._loadSoundUsingRequest(sound); | ||
break; | ||
case PlayerCore.PLAYER_MODE_FETCH: | ||
notImplementedError = new PlayerError(PlayerCore.PLAYER_MODE_FETCH + ' is not implemented yet', 1); | ||
loadSoundPromise = Promise.reject(notImplementedError); | ||
break; | ||
} | ||
return loadSoundPromise; | ||
}; | ||
PlayerCore.prototype._loadSoundUsingAudioElement = function (sound) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { | ||
var _a = _this._findBestSource(sound.source), url = _a.url, _b = _a.codec, codec = _b === void 0 ? null : _b; | ||
}); | ||
} | ||
_loadSoundUsingAudioElement(sound) { | ||
return new Promise((resolve, reject) => { | ||
const { url, codec = null } = this._findBestSource(sound.source); | ||
sound.url = url; | ||
sound.codec = codec; | ||
sound.arrayBuffer = null; | ||
if (sound.url !== null) { | ||
var audioElement_1 = new Audio(); | ||
audioElement_1.crossOrigin = 'anonymous'; | ||
audioElement_1.src = sound.url; | ||
audioElement_1.controls = false; | ||
audioElement_1.autoplay = false; | ||
audioElement_1.id = 'web_audio_api_player_sound_' + sound.id.toString(); | ||
document.body.appendChild(audioElement_1); | ||
sound.audioElement = audioElement_1; | ||
sound.isReadyToPLay = true; | ||
_this._initializeAudioElementListeners(sound); | ||
var canplaythroughListener_1 = function () { | ||
sound.audioElement.removeEventListener('canplaythrough', canplaythroughListener_1); | ||
if (!isNaN(audioElement_1.duration)) { | ||
sound.duration = audioElement_1.duration; | ||
sound.audioElement = this._playerAudio.getAudioElement(); | ||
const canPlayThroughHandler = () => __awaiter(this, void 0, void 0, function* () { | ||
sound.audioElement.removeEventListener('canplaythrough', canPlayThroughHandler); | ||
sound.isReadyToPLay = true; | ||
if (!isNaN(sound.audioElement.duration)) { | ||
sound.duration = sound.audioElement.duration; | ||
} | ||
resolve(sound); | ||
resolve(); | ||
}); | ||
sound.audioElement.addEventListener('canplaythrough', canPlayThroughHandler); | ||
sound.audioElement.onprogress = () => { | ||
if (sound.audioElement.buffered.length) { | ||
const duration = sound.getDuration(); | ||
const buffered = sound.audioElement.buffered.end(0); | ||
const percentage = 100 / (duration / buffered); | ||
sound.loadingProgress = percentage; | ||
if (sound.onLoading !== null) { | ||
sound.onLoading(percentage, duration, buffered); | ||
} | ||
sound.duration = sound.audioElement.duration; | ||
if (percentage === 100) { | ||
sound.isBuffering = false; | ||
sound.isBuffered = true; | ||
sound.audioBufferDate = new Date(); | ||
} | ||
} | ||
}; | ||
sound.audioElement.addEventListener('canplaythrough', canplaythroughListener_1); | ||
var errorListener_1 = function () { | ||
sound.audioElement.removeEventListener('error', errorListener_1); | ||
var soundLoadingError = new PlayerError('loading sound failed'); | ||
reject(soundLoadingError); | ||
}; | ||
sound.audioElement.addEventListener('error', errorListener_1); | ||
sound.audioElement.crossOrigin = 'anonymous'; | ||
sound.audioElement.src = sound.url; | ||
sound.audioElement.load(); | ||
} | ||
else { | ||
var noUrlError = new PlayerError('sound has no url', 1); | ||
reject(noUrlError); | ||
reject(new Error('sound has no url')); | ||
} | ||
}); | ||
}; | ||
PlayerCore.prototype._loadSoundUsingRequest = function (sound) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { | ||
var _a = _this._findBestSource(sound.source), url = _a.url, _b = _a.codec, codec = _b === void 0 ? null : _b; | ||
} | ||
_loadSoundUsingRequest(sound) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (sound.arrayBuffer !== null) { | ||
return yield this._decodeSound({ sound }); | ||
} | ||
const { url, codec = null } = this._findBestSource(sound.source); | ||
sound.url = url; | ||
sound.codec = codec; | ||
if (sound.url !== null) { | ||
var request = new PlayerRequest(); | ||
const request = new PlayerRequest(); | ||
sound.isBuffering = true; | ||
request.getArrayBuffer(sound).then(function (arrayBuffer) { | ||
sound.arrayBuffer = arrayBuffer; | ||
_this._decodeSound({ sound: sound }).then(function (sound) { | ||
resolve(sound); | ||
}).catch(reject); | ||
}).catch(function (requestError) { | ||
reject(requestError); | ||
}); | ||
const arrayBuffer = yield request.getArrayBuffer(sound); | ||
sound.arrayBuffer = arrayBuffer; | ||
yield this._decodeSound({ sound }); | ||
} | ||
else { | ||
var noUrlError = new PlayerError('sound has no url', 1); | ||
reject(noUrlError); | ||
throw new Error('sound has no url'); | ||
} | ||
}); | ||
}; | ||
PlayerCore.prototype._initializeAudioElementListeners = function (sound) { | ||
sound.audioElement.addEventListener('progress', function () { | ||
sound.loadingProgress = sound.audioElement.duration; | ||
}); | ||
sound.audioElement.addEventListener('timeupdate', function () { | ||
sound.duration = sound.audioElement.duration; | ||
}); | ||
}; | ||
PlayerCore.prototype._decodeSound = function (_a) { | ||
var sound = _a.sound; | ||
return this._playerAudio.decodeAudio(sound.arrayBuffer).then(function (audioBuffer) { | ||
} | ||
_decodeSound({ sound }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const arrayBufferCopy = sound.arrayBuffer.slice(0); | ||
const audioBuffer = yield this._playerAudio.decodeAudio(arrayBufferCopy); | ||
sound.audioBuffer = audioBuffer; | ||
@@ -828,187 +809,127 @@ sound.isBuffering = false; | ||
sound.isReadyToPLay = true; | ||
return sound; | ||
}).catch(function (decodeAudioError) { | ||
throw decodeAudioError; | ||
}); | ||
}; | ||
PlayerCore.prototype._cloneAudioBuffer = function (fromAudioBuffer) { | ||
var audioBuffer = new AudioBuffer({ | ||
length: fromAudioBuffer.length, | ||
numberOfChannels: fromAudioBuffer.numberOfChannels, | ||
sampleRate: fromAudioBuffer.sampleRate | ||
}); | ||
for (var channelI = 0; channelI < audioBuffer.numberOfChannels; ++channelI) { | ||
var samples = fromAudioBuffer.getChannelData(channelI); | ||
audioBuffer.copyToChannel(samples, channelI); | ||
} | ||
return audioBuffer; | ||
}; | ||
PlayerCore.prototype.play = function (_a) { | ||
var _this = this; | ||
var _b = _a === void 0 ? {} : _a, whichSound = _b.whichSound, playTimeOffset = _b.playTimeOffset; | ||
return new Promise(function (resolve, reject) { | ||
var currentSound = _this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
var sound = _this._getSoundFromQueue({ whichSound: whichSound, updateIndex: true }); | ||
} | ||
play({ whichSound, playTimeOffset } = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
const sound = this._getSoundFromQueue({ whichSound, updateIndex: true }); | ||
if (sound === null) { | ||
throw new Error('no more sounds in array'); | ||
console.warn('no more sounds in array'); | ||
return sound; | ||
} | ||
if (currentSound !== null | ||
&& (currentSound.state === PlayerSound.SOUND_STATE_PLAYING) | ||
&& (currentSound.id === sound.id)) { | ||
if (!isNaN(playTimeOffset)) { | ||
this.setPositionInSeconds(playTimeOffset); | ||
return sound; | ||
} | ||
else { | ||
return sound; | ||
} | ||
} | ||
if (currentSound !== null | ||
&& (currentSound.state === PlayerSound.SOUND_STATE_PLAYING || currentSound.state === PlayerSound.SOUND_STATE_PAUSED) | ||
&& (currentSound.id !== sound.id)) { | ||
_this._stop(currentSound, PlayerSound.SOUND_STATE_STOPPED); | ||
yield this._stop(currentSound, PlayerSound.SOUND_STATE_STOPPED); | ||
} | ||
if (currentSound !== null | ||
&& (currentSound.state === PlayerSound.SOUND_STATE_PLAYING) | ||
&& (currentSound.id === sound.id)) { | ||
_this._stop(currentSound, PlayerSound.SOUND_STATE_PAUSED); | ||
if (!isNaN(playTimeOffset)) { | ||
sound.playTimeOffset = playTimeOffset; | ||
} | ||
if (currentSound === null || (currentSound !== null && (currentSound.id !== sound.id))) { | ||
sound.firstTimePlayed = true; | ||
} | ||
else { | ||
sound.firstTimePlayed = false; | ||
sound.playTimeOffset = 0; | ||
} | ||
if (playTimeOffset !== undefined) { | ||
sound.playTimeOffset = playTimeOffset; | ||
if (sound.sourceNode === null) { | ||
yield this._playerAudio.connectSound(sound, () => { | ||
this._onEnded(); | ||
}); | ||
} | ||
if (!sound.isReadyToPLay) { | ||
_this._loadSound(sound).then(function () { | ||
_this._play(sound).then(resolve).catch(reject); | ||
}).catch(reject); | ||
yield this._loadSound(sound); | ||
yield this._play(sound); | ||
} | ||
else { | ||
if (sound.audioBuffer !== null) { | ||
sound.audioBuffer = _this._cloneAudioBuffer(sound.audioBuffer); | ||
} | ||
_this._play(sound).then(resolve).catch(reject); | ||
yield this._play(sound); | ||
} | ||
return sound; | ||
}); | ||
}; | ||
PlayerCore.prototype._play = function (sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(sound.audioBuffer !== null)) return [3, 2]; | ||
return [4, this._playAudioBuffer(sound)]; | ||
case 1: | ||
_a.sent(); | ||
return [3, 4]; | ||
case 2: return [4, this._playMediaElementAudio(sound)]; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: | ||
sound.state = PlayerSound.SOUND_STATE_PLAYING; | ||
sound.startTime = sound.getCurrentTime(); | ||
sound = this._triggerSoundCallbacks(sound); | ||
return [2]; | ||
} | ||
}); | ||
} | ||
_play(sound) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._playerAudio.isAudioContextFrozen()) { | ||
yield this._playerAudio.unfreezeAudioContext(); | ||
} | ||
if (sound.playTimeOffset > 0) { | ||
sound.playTime = sound.playTimeOffset; | ||
} | ||
if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AJAX) { | ||
yield this._playAudioBuffer(sound); | ||
} | ||
else if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AUDIO) { | ||
yield this._playMediaElementAudio(sound); | ||
} | ||
sound.state = PlayerSound.SOUND_STATE_PLAYING; | ||
this._triggerSoundCallbacks(sound); | ||
}); | ||
}; | ||
PlayerCore.prototype._playAudioBuffer = function (sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var sourceOptions, error_1; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(sound.sourceNode === null)) return [3, 4]; | ||
sourceOptions = { | ||
loop: sound.loop, | ||
onSourceNodeEnded: function () { | ||
_this._onEnded(); | ||
} | ||
}; | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
return [4, this._playerAudio.createAudioBufferSourceNode(sourceOptions, sound)]; | ||
case 2: | ||
_a.sent(); | ||
return [3, 4]; | ||
case 3: | ||
error_1 = _a.sent(); | ||
throw new PlayerError(error_1); | ||
case 4: | ||
if (!(sound.sourceNode instanceof AudioBufferSourceNode)) return [3, 6]; | ||
sound.sourceNode.buffer = sound.audioBuffer; | ||
return [4, this._playerAudio.connectSound(sound)]; | ||
case 5: | ||
_a.sent(); | ||
try { | ||
if (sound.playTimeOffset !== undefined) { | ||
sound.sourceNode.start(0, sound.playTimeOffset); | ||
} | ||
else { | ||
sound.sourceNode.start(); | ||
} | ||
} | ||
_playAudioBuffer(sound) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (sound.sourceNode instanceof AudioBufferSourceNode) { | ||
sound.startTime = sound.sourceNode.context.currentTime; | ||
sound.sourceNode.buffer = sound.audioBuffer; | ||
try { | ||
if (sound.state === PlayerSound.SOUND_STATE_SEEKING) { | ||
sound.sourceNode.start(0, sound.playTime); | ||
} | ||
else if (sound.state === PlayerSound.SOUND_STATE_PAUSED && sound.playTimeOffset === 0) { | ||
sound.sourceNode.start(0, sound.playTime); | ||
} | ||
else { | ||
if (sound.playTimeOffset > 0) { | ||
sound.elapsedPlayTime = sound.playTimeOffset; | ||
sound.sourceNode.start(0, sound.playTimeOffset); | ||
} | ||
catch (error) { | ||
throw new PlayerError(error); | ||
else { | ||
sound.sourceNode.start(); | ||
} | ||
_a.label = 6; | ||
case 6: return [2]; | ||
} | ||
} | ||
}); | ||
catch (error) { | ||
throw new Error(error); | ||
} | ||
} | ||
}); | ||
}; | ||
PlayerCore.prototype._playMediaElementAudio = function (sound) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var sourceOptions, error_2; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(sound.sourceNode === null)) return [3, 4]; | ||
sourceOptions = { | ||
loop: sound.loop, | ||
onSourceNodeEnded: function () { | ||
_this._onEnded(); | ||
}, | ||
mediaElement: sound.audioElement | ||
}; | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
return [4, this._playerAudio.createMediaElementSourceNode(sourceOptions, sound)]; | ||
case 2: | ||
_a.sent(); | ||
return [3, 4]; | ||
case 3: | ||
error_2 = _a.sent(); | ||
throw new PlayerError(error_2); | ||
case 4: | ||
if (!(sound.sourceNode instanceof MediaElementAudioSourceNode)) return [3, 6]; | ||
return [4, this._playerAudio.connectSound(sound)]; | ||
case 5: | ||
_a.sent(); | ||
if (sound.playTimeOffset !== undefined && !isNaN(sound.playTimeOffset)) { | ||
sound.audioElement.currentTime = sound.playTimeOffset; | ||
} | ||
try { | ||
sound.sourceNode.mediaElement.play(); | ||
} | ||
catch (error) { | ||
throw new PlayerError(error); | ||
} | ||
_a.label = 6; | ||
case 6: return [2]; | ||
} | ||
_playMediaElementAudio(sound) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (sound.sourceNode instanceof MediaElementAudioSourceNode) { | ||
if (sound.state === PlayerSound.SOUND_STATE_SEEKING) { | ||
sound.audioElement.currentTime = sound.playTime; | ||
} | ||
}); | ||
else if (sound.state === PlayerSound.SOUND_STATE_PAUSED && sound.playTimeOffset === 0) { | ||
sound.audioElement.currentTime = sound.playTime; | ||
} | ||
else { | ||
if (sound.playTimeOffset > 0) { | ||
sound.audioElement.currentTime = sound.playTimeOffset; | ||
} | ||
else { | ||
sound.audioElement.currentTime = 0; | ||
} | ||
} | ||
yield sound.audioElement.play(); | ||
} | ||
}); | ||
}; | ||
PlayerCore.prototype._triggerSoundCallbacks = function (sound) { | ||
var _this = this; | ||
} | ||
_triggerSoundCallbacks(sound) { | ||
if (sound.onResumed !== null && !sound.firstTimePlayed) { | ||
sound.onResumed(sound.playTimeOffset); | ||
sound.onResumed(sound.playTime); | ||
} | ||
if (sound.onStarted !== null && sound.firstTimePlayed) { | ||
sound.firstTimePlayed = false; | ||
sound.onStarted(sound.playTimeOffset); | ||
} | ||
if (sound.onPlaying !== null) { | ||
this._playingProgressRequestId = window.requestAnimationFrame(function (timestamp) { | ||
_this._progressTrigger(sound, timestamp); | ||
}); | ||
this._playingProgressPreviousTimestamp = 0; | ||
this._progressTrigger(sound, 0); | ||
} | ||
@@ -1018,95 +939,90 @@ else { | ||
} | ||
return sound; | ||
}; | ||
PlayerCore.prototype._onEnded = function () { | ||
var currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound !== null && currentSound.state === PlayerSound.SOUND_STATE_PLAYING) { | ||
var nextSound = this._getSoundFromQueue({ whichSound: PlayerCore.PLAY_SOUND_NEXT, updateIndex: false }); | ||
if (currentSound.onEnded !== null) { | ||
var willPlayNext = false; | ||
if (nextSound !== null && this._options.playNextOnEnded) { | ||
willPlayNext = true; | ||
return; | ||
} | ||
_onEnded() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._options.playNextOnEnded) { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound !== null) { | ||
if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AUDIO || | ||
(this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AJAX && currentSound.state === PlayerSound.SOUND_STATE_PLAYING)) { | ||
const nextSound = this._getSoundFromQueue({ whichSound: PlayerCore.PLAY_SOUND_NEXT }); | ||
let willPlayNext = false; | ||
if (nextSound !== null) { | ||
willPlayNext = true; | ||
} | ||
if (!willPlayNext) { | ||
yield this._playerAudio.freezeAudioContext(); | ||
} | ||
if (currentSound.onEnded !== null) { | ||
currentSound.onEnded(willPlayNext); | ||
} | ||
try { | ||
yield this.next(); | ||
} | ||
catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AJAX && currentSound.state === PlayerSound.SOUND_STATE_SEEKING) { | ||
try { | ||
yield this.play(currentSound); | ||
} | ||
catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
} | ||
if (this._options.loopQueue) { | ||
willPlayNext = true; | ||
} | ||
if (!willPlayNext) { | ||
this._playerAudio.freezeAudioContext(); | ||
} | ||
currentSound.onEnded(willPlayNext); | ||
} | ||
currentSound.firstTimePlayed = true; | ||
currentSound.playTimeOffset = 0; | ||
this._stop(currentSound, PlayerSound.SOUND_STATE_STOPPED); | ||
if (nextSound !== null) { | ||
if (this._options.playNextOnEnded) { | ||
this.play({ whichSound: PlayerCore.PLAY_SOUND_NEXT }); | ||
} | ||
} | ||
else { | ||
this._currentIndex = 0; | ||
if (this._options.loopQueue) { | ||
this.play(); | ||
} | ||
} | ||
} | ||
}; | ||
PlayerCore.prototype._getSoundFromQueue = function (_a) { | ||
var _b; | ||
var _c = _a === void 0 ? {} : _a, whichSound = _c.whichSound, _d = _c.updateIndex, updateIndex = _d === void 0 ? false : _d; | ||
var sound = null; | ||
var soundIndex = null; | ||
}); | ||
} | ||
_getSoundFromQueue({ whichSound, updateIndex = false } = {}) { | ||
let sound = null; | ||
let soundIndex = null; | ||
if (this._queue.length === 0) { | ||
return sound; | ||
} | ||
if (whichSound === undefined) { | ||
soundIndex = 0; | ||
if (this._currentIndex !== null) { | ||
if (typeof whichSound === 'undefined') { | ||
whichSound = PlayerCore.CURRENT_SOUND; | ||
} | ||
switch (whichSound) { | ||
case PlayerCore.CURRENT_SOUND: | ||
soundIndex = this._currentIndex; | ||
} | ||
sound = this._queue[soundIndex]; | ||
sound = this._queue[soundIndex]; | ||
break; | ||
case PlayerCore.PLAY_SOUND_NEXT: | ||
if (this._queue[this._currentIndex + 1] !== undefined) { | ||
soundIndex = this._currentIndex + 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
else if (this._options.loopQueue) { | ||
soundIndex = 0; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_PREVIOUS: | ||
if (this._queue[this._currentIndex - 1] !== undefined) { | ||
soundIndex = this._currentIndex - 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
else if (this._options.loopQueue) { | ||
soundIndex = this._queue.length - 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_FIRST: | ||
if (this._queue.length > 0) { | ||
soundIndex = 0; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_LAST: | ||
if (this._queue.length > 0) { | ||
soundIndex = this._queue.length - 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
default: | ||
[sound, soundIndex] = this._findSoundById({ soundId: whichSound }); | ||
} | ||
else { | ||
switch (whichSound) { | ||
case PlayerCore.CURRENT_SOUND: | ||
if (this._currentIndex !== null) { | ||
sound = this._queue[this._currentIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_NEXT: | ||
if (this._queue[this._currentIndex + 1] !== undefined) { | ||
soundIndex = this._currentIndex + 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
else if (this._options.loopQueue) { | ||
soundIndex = 0; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_PREVIOUS: | ||
if (this._queue[this._currentIndex - 1] !== undefined) { | ||
soundIndex = this._currentIndex - 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
else if (this._options.loopQueue) { | ||
soundIndex = this._queue.length - 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_FIRST: | ||
if (this._queue.length > 0) { | ||
soundIndex = 0; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
case PlayerCore.PLAY_SOUND_LAST: | ||
if (this._queue.length > 0) { | ||
soundIndex = this._queue.length - 1; | ||
sound = this._queue[soundIndex]; | ||
} | ||
break; | ||
default: | ||
_b = this._findSoundById({ soundId: whichSound }), sound = _b[0], soundIndex = _b[1]; | ||
} | ||
} | ||
if (soundIndex !== null && updateIndex) { | ||
@@ -1116,8 +1032,7 @@ this._currentIndex = soundIndex; | ||
return sound; | ||
}; | ||
PlayerCore.prototype._findSoundById = function (_a) { | ||
var soundId = _a.soundId; | ||
var sound = null; | ||
var soundIndex = 0; | ||
this._queue.some(function (soundFromQueue, index) { | ||
} | ||
_findSoundById({ soundId }) { | ||
let sound = null; | ||
let soundIndex = 0; | ||
this._queue.some((soundFromQueue, index) => { | ||
if (soundFromQueue.id === soundId) { | ||
@@ -1130,9 +1045,9 @@ sound = soundFromQueue; | ||
return [sound, soundIndex]; | ||
}; | ||
PlayerCore.prototype._findBestSource = function (soundSource) { | ||
var bestSource = { | ||
} | ||
_findBestSource(soundSource) { | ||
const bestSource = { | ||
url: null, | ||
codec: null | ||
}; | ||
var sources; | ||
let sources; | ||
if (!Array.isArray(soundSource)) { | ||
@@ -1144,6 +1059,6 @@ sources = [soundSource]; | ||
} | ||
var i = 0; | ||
let i = 0; | ||
while (i < sources.length) { | ||
var source = sources[i]; | ||
var soundUrl = ''; | ||
const source = sources[i]; | ||
let soundUrl = ''; | ||
if (this._options.soundsBaseUrl !== '') { | ||
@@ -1153,3 +1068,3 @@ soundUrl = this._options.soundsBaseUrl; | ||
soundUrl += source.url; | ||
var isCodecSupported = true; | ||
let isCodecSupported = true; | ||
if (source.codec !== null) { | ||
@@ -1172,6 +1087,6 @@ isCodecSupported = this._checkCodecSupport(source.codec); | ||
return bestSource; | ||
}; | ||
PlayerCore.prototype._checkCodecSupport = function (codec) { | ||
var mediaMimeTypes; | ||
var error = ''; | ||
} | ||
_checkCodecSupport(codec) { | ||
let mediaMimeTypes; | ||
let error = ''; | ||
switch (codec) { | ||
@@ -1217,11 +1132,11 @@ case 'ogg': | ||
if (error) { | ||
throw new PlayerError(error); | ||
throw new Error(error); | ||
} | ||
return this._checkMimeTypesSupport(mediaMimeTypes); | ||
}; | ||
PlayerCore.prototype._checkMimeTypesSupport = function (mediaMimeTypes) { | ||
var deviceAudio = new Audio(); | ||
var isSupported = false; | ||
mediaMimeTypes.forEach(function (mediaMimeType) { | ||
var isMediaTypeSupported = deviceAudio.canPlayType(mediaMimeType).replace(/^no$/, ''); | ||
} | ||
_checkMimeTypesSupport(mediaMimeTypes) { | ||
const deviceAudio = new Audio(); | ||
let isSupported = false; | ||
mediaMimeTypes.forEach((mediaMimeType) => { | ||
const isMediaTypeSupported = deviceAudio.canPlayType(mediaMimeType).replace(/^no$/, ''); | ||
if (isMediaTypeSupported) { | ||
@@ -1232,75 +1147,89 @@ isSupported = true; | ||
return isSupported; | ||
}; | ||
PlayerCore.prototype.pause = function () { | ||
var currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound === null) { | ||
return; | ||
} | ||
if (currentSound.state === PlayerSound.SOUND_STATE_PAUSED) { | ||
return; | ||
} | ||
var timeAtPause = currentSound.getCurrentTime(); | ||
currentSound.playTimeOffset += timeAtPause - currentSound.startTime; | ||
if (currentSound.onPaused !== null) { | ||
currentSound.onPaused(currentSound.playTimeOffset); | ||
} | ||
this._stop(currentSound, PlayerSound.SOUND_STATE_PAUSED); | ||
}; | ||
PlayerCore.prototype.stop = function () { | ||
var currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound === null) { | ||
return; | ||
} | ||
if (currentSound.state === PlayerSound.SOUND_STATE_STOPPED) { | ||
return; | ||
} | ||
this._playerAudio.freezeAudioContext(); | ||
var timeAtStop = currentSound.getCurrentTime(); | ||
currentSound.playTimeOffset += timeAtStop - currentSound.startTime; | ||
if (currentSound.onStopped !== null) { | ||
currentSound.onStopped(currentSound.playTimeOffset); | ||
} | ||
this._stop(currentSound, PlayerSound.SOUND_STATE_STOPPED); | ||
}; | ||
PlayerCore.prototype._stop = function (sound, soundState) { | ||
if (soundState === PlayerSound.SOUND_STATE_STOPPED) { | ||
sound.playTimeOffset = 0; | ||
sound.firstTimePlayed = true; | ||
} | ||
if (sound.sourceNode !== null) { | ||
if (sound.sourceNode instanceof AudioBufferSourceNode) { | ||
sound.sourceNode.stop(0); | ||
} | ||
pause() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound === null) { | ||
return; | ||
} | ||
else if (sound.sourceNode instanceof MediaElementAudioSourceNode) { | ||
sound.sourceNode.mediaElement.pause(); | ||
if (currentSound.state === PlayerSound.SOUND_STATE_PAUSED) { | ||
return; | ||
} | ||
this._playerAudio.cleanUpAudiBufferSourceNode(sound); | ||
sound.state = soundState; | ||
const currentTime = currentSound.getCurrentTime(); | ||
currentSound.playTime = currentTime; | ||
if (this._options.loadPlayerMode === PlayerCore.PLAYER_MODE_AJAX) { | ||
currentSound.elapsedPlayTime = currentTime; | ||
} | ||
if (currentSound.onPaused !== null) { | ||
currentSound.onPaused(currentSound.playTime); | ||
} | ||
yield this._stop(currentSound, PlayerSound.SOUND_STATE_PAUSED); | ||
return currentSound; | ||
}); | ||
} | ||
stop() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const currentSound = this._getSoundFromQueue({ whichSound: PlayerCore.CURRENT_SOUND }); | ||
if (currentSound === null) { | ||
return; | ||
} | ||
if (currentSound.state === PlayerSound.SOUND_STATE_STOPPED) { | ||
return; | ||
} | ||
yield this._playerAudio.freezeAudioContext(); | ||
if (currentSound.onStopped !== null) { | ||
currentSound.onStopped(currentSound.playTime); | ||
} | ||
yield this._stop(currentSound, PlayerSound.SOUND_STATE_STOPPED); | ||
return currentSound; | ||
}); | ||
} | ||
_stop(sound, soundState) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._playingProgressRequestId !== null) { | ||
cancelAnimationFrame(this._playingProgressRequestId); | ||
this._playingProgressPreviousTimestamp = 0; | ||
this._playingProgressRequestId = null; | ||
} | ||
} | ||
}; | ||
PlayerCore.prototype.next = function () { | ||
this.play({ whichSound: PlayerCore.PLAY_SOUND_NEXT }); | ||
}; | ||
PlayerCore.prototype.previous = function () { | ||
this.play({ whichSound: PlayerCore.PLAY_SOUND_PREVIOUS }); | ||
}; | ||
PlayerCore.prototype.first = function () { | ||
this.play({ whichSound: PlayerCore.PLAY_SOUND_FIRST }); | ||
}; | ||
PlayerCore.prototype.last = function () { | ||
this.play({ whichSound: PlayerCore.PLAY_SOUND_LAST }); | ||
}; | ||
PlayerCore.prototype._playingProgress = function (sound) { | ||
var timeNow = sound.getCurrentTime(); | ||
sound.playTime = (timeNow - sound.startTime) + sound.playTimeOffset; | ||
var duration = sound.getDuration(); | ||
var playingPercentage = (sound.playTime / duration) * 100; | ||
sound.playedTimePercentage = playingPercentage; | ||
sound.onPlaying(playingPercentage, duration, sound.playTime); | ||
}; | ||
PlayerCore.prototype.setVisibilityAutoMute = function (visibilityAutoMute) { | ||
sound.state = soundState; | ||
if (sound.sourceNode !== null) { | ||
if (sound.sourceNode instanceof AudioBufferSourceNode) { | ||
sound.sourceNode.stop(0); | ||
yield this._playerAudio.disconnectSound(sound); | ||
} | ||
if (sound.sourceNode instanceof MediaElementAudioSourceNode) { | ||
sound.audioElement.pause(); | ||
} | ||
} | ||
if (soundState === PlayerSound.SOUND_STATE_STOPPED) { | ||
sound.isReadyToPLay = false; | ||
sound.firstTimePlayed = true; | ||
sound.startTime = 0; | ||
sound.elapsedPlayTime = 0; | ||
sound.playTime = 0; | ||
sound.playedTimePercentage = 0; | ||
yield this._playerAudio.disconnectSound(sound); | ||
} | ||
}); | ||
} | ||
next() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.play({ whichSound: PlayerCore.PLAY_SOUND_NEXT }); | ||
}); | ||
} | ||
previous() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.play({ whichSound: PlayerCore.PLAY_SOUND_PREVIOUS }); | ||
}); | ||
} | ||
first() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.play({ whichSound: PlayerCore.PLAY_SOUND_FIRST }); | ||
}); | ||
} | ||
last() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.play({ whichSound: PlayerCore.PLAY_SOUND_LAST }); | ||
}); | ||
} | ||
setVisibilityAutoMute(visibilityAutoMute) { | ||
this._options.visibilityAutoMute = visibilityAutoMute; | ||
@@ -1313,8 +1242,8 @@ if (visibilityAutoMute) { | ||
} | ||
}; | ||
PlayerCore.prototype.getVisibilityAutoMute = function () { | ||
} | ||
getVisibilityAutoMute() { | ||
return this._options.visibilityAutoMute; | ||
}; | ||
PlayerCore.prototype._handleVisibilityChange = function () { | ||
var hiddenKeyword; | ||
} | ||
_handleVisibilityChange() { | ||
let hiddenKeyword; | ||
if (typeof document.hidden !== 'undefined') { | ||
@@ -1335,46 +1264,31 @@ hiddenKeyword = 'hidden'; | ||
} | ||
}; | ||
PlayerCore.prototype.disconnect = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (this._playingProgressRequestId !== null) { | ||
cancelAnimationFrame(this._playingProgressRequestId); | ||
} | ||
return [4, this._playerAudio.shutDown(this._queue)]; | ||
case 1: | ||
_a.sent(); | ||
return [2]; | ||
} | ||
}); | ||
} | ||
disconnect() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._playingProgressRequestId !== null) { | ||
cancelAnimationFrame(this._playingProgressRequestId); | ||
this._playingProgressRequestId = null; | ||
} | ||
yield this._playerAudio.shutDown(this._queue); | ||
}); | ||
}; | ||
PlayerCore.prototype.getAudioContext = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var audioContext; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4, this._playerAudio.getAudioContext()]; | ||
case 1: | ||
audioContext = _a.sent(); | ||
return [2, audioContext]; | ||
} | ||
}); | ||
} | ||
getAudioContext() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const audioContext = yield this._playerAudio.getAudioContext(); | ||
return audioContext; | ||
}); | ||
}; | ||
PlayerCore.WHERE_IN_QUEUE_AT_END = 'append'; | ||
PlayerCore.WHERE_IN_QUEUE_AT_START = 'prepend'; | ||
PlayerCore.PLAY_SOUND_NEXT = 'next'; | ||
PlayerCore.PLAY_SOUND_PREVIOUS = 'previous'; | ||
PlayerCore.PLAY_SOUND_FIRST = 'first'; | ||
PlayerCore.PLAY_SOUND_LAST = 'last'; | ||
PlayerCore.CURRENT_SOUND = 'current'; | ||
PlayerCore.PLAYER_MODE_AUDIO = 'player_mode_audio'; | ||
PlayerCore.PLAYER_MODE_AJAX = 'player_mode_ajax'; | ||
PlayerCore.PLAYER_MODE_FETCH = 'player_mode_fetch'; | ||
return PlayerCore; | ||
}()); | ||
} | ||
} | ||
PlayerCore.WHERE_IN_QUEUE_AT_END = 'append'; | ||
PlayerCore.WHERE_IN_QUEUE_AT_START = 'prepend'; | ||
PlayerCore.PLAY_SOUND_NEXT = 'next'; | ||
PlayerCore.PLAY_SOUND_PREVIOUS = 'previous'; | ||
PlayerCore.PLAY_SOUND_FIRST = 'first'; | ||
PlayerCore.PLAY_SOUND_LAST = 'last'; | ||
PlayerCore.CURRENT_SOUND = 'current'; | ||
PlayerCore.PLAYER_MODE_AUDIO = 'player_mode_audio'; | ||
PlayerCore.PLAYER_MODE_AJAX = 'player_mode_ajax'; | ||
PlayerCore.PLAYER_MODE_FETCH = 'player_mode_fetch'; | ||
export { PlayerCore, PlayerSound }; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
var e=function(t,o){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o])},e(t,o)};function t(e,t,o,n){return new(o||(o=Promise))((function(i,u){function r(e){try{a(n.next(e))}catch(e){u(e)}}function s(e){try{a(n.throw(e))}catch(e){u(e)}}function a(e){var t;e.done?i(e.value):(t=e.value,t instanceof o?t:new o((function(e){e(t)}))).then(r,s)}a((n=n.apply(e,t||[])).next())}))}function o(e,t){var o,n,i,u,r={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return u={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(u[Symbol.iterator]=function(){return this}),u;function s(s){return function(a){return function(s){if(o)throw new TypeError("Generator is already executing.");for(;u&&(u=0,s[0]&&(r=0)),r;)try{if(o=1,n&&(i=2&s[0]?n.return:s[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,s[1])).done)return i;switch(n=0,i&&(s=[2&s[0],i.value]),s[0]){case 0:case 1:i=s;break;case 4:return r.label++,{value:s[1],done:!1};case 5:r.label++,n=s[1],s=[0];continue;case 7:s=r.ops.pop(),r.trys.pop();continue;default:if(!(i=r.trys,(i=i.length>0&&i[i.length-1])||6!==s[0]&&2!==s[0])){r=0;continue}if(3===s[0]&&(!i||s[1]>i[0]&&s[1]<i[3])){r.label=s[1];break}if(6===s[0]&&r.label<i[1]){r.label=i[1],i=s;break}if(i&&r.label<i[2]){r.label=i[2],r.ops.push(s);break}i[2]&&r.ops.pop(),r.trys.pop();continue}s=t.call(e,r)}catch(e){s=[6,e],n=0}finally{o=i=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,a])}}}var n=function(){function e(e){this.url=null,this.codec=null,this.sourceNode=null,this.gainNode=null,this.isReadyToPLay=!1,this.isBuffered=!1,this.isBuffering=!1,this.audioElement=null,this.audioBuffer=null,this.arrayBuffer=null,this.audioBufferDate=null,this.playTimeOffset=0,this.startTime=0,this.playTime=0,this.playedTimePercentage=0,this.state="sound_state_stopped",this.loadingProgress=0,this.duration=null,this.firstTimePlayed=!0,Array.isArray(e.source)?this.source=e.source:this.source=[e.source],void 0!==e.id?this.id=e.id:this.id=this._generateSoundId(),this.loop=e.loop||!1,this.duration=e.duration||null,"function"==typeof e.onLoading?this.onLoading=e.onLoading:this.onLoading=null,"function"==typeof e.onPlaying?this.onPlaying=e.onPlaying:this.onPlaying=null,"function"==typeof e.onStarted?this.onStarted=e.onStarted:this.onStarted=null,"function"==typeof e.onEnded?this.onEnded=e.onEnded:this.onEnded=null,"function"==typeof e.onStopped?this.onStopped=e.onStopped:this.onStopped=null,"function"==typeof e.onPaused?this.onPaused=e.onPaused:this.onPaused=null,"function"==typeof e.onResumed?this.onResumed=e.onResumed:this.onResumed=null,e.arrayBuffer instanceof ArrayBuffer&&(this.arrayBuffer=e.arrayBuffer),e.audioBuffer instanceof AudioBuffer&&(this.audioBuffer=e.audioBuffer,this.isBuffering=!1,this.isBuffered=!0,this.audioBufferDate=new Date,this.duration=this.getDuration())}return e.prototype.getCurrentTime=function(){var e;return null!==this.sourceNode&&(this.sourceNode instanceof AudioBufferSourceNode?e=this.sourceNode.context.currentTime:this.sourceNode instanceof MediaElementAudioSourceNode&&(e=this.audioElement.currentTime)),e},e.prototype.getDuration=function(){var e;return null!==this.sourceNode&&(this.sourceNode instanceof AudioBufferSourceNode?e=this.sourceNode.buffer.duration:this.sourceNode instanceof MediaElementAudioSourceNode&&(e=this.audioElement.duration)),e},e.prototype._generateSoundId=function(){return Date.now().toString(36)+Math.random().toString(36).substring(2)},e.SOUND_STATE_STOPPED="sound_state_stopped",e.SOUND_STATE_PAUSED="sound_state_paused",e.SOUND_STATE_PLAYING="sound_state_playing",e}(),i=function(t){function o(e,n){var i=t.call(this,e)||this;return i.code=n||null,Object.setPrototypeOf(i,o.prototype),i}return function(t,o){if("function"!=typeof o&&null!==o)throw new TypeError("Class extends value "+String(o)+" is not a constructor or null");function n(){this.constructor=t}e(t,o),t.prototype=null===o?Object.create(o):(n.prototype=o.prototype,new n)}(o,t),o}(Error),u=function(){function e(e){this._audioContext=null,this._volume=null,this._audioNodes={gainNode:null},this._options=e,this._initialize()}return e.prototype._initialize=function(){this._options.createAudioContextOnFirstUserInteraction&&this._addAutoCreateAudioContextOnFirstUserInteractionEventListeners()},e.prototype.decodeAudio=function(e){return t(this,void 0,void 0,(function(){var t;return o(this,(function(o){switch(o.label){case 0:return[4,this.getAudioContext()];case 1:return[4,o.sent().decodeAudioData(e)];case 2:return t=o.sent(),[2,Promise.resolve(t)]}}))}))},e.prototype._createAudioContext=function(){var e=this;return new Promise((function(t,o){e._audioContext instanceof AudioContext&&t();var n=window.AudioContext||window.webkitAudioContext;try{null!==e._options.audioContext?e._audioContext=e._options.audioContext:e._audioContext=new n,t()}catch(e){o(e)}}))},e.prototype._addAutoCreateAudioContextOnFirstUserInteractionEventListeners=function(){this._options.createAudioContextOnFirstUserInteraction&&(document.addEventListener("touchstart",this.getAudioContext.bind(this)),document.addEventListener("touchend",this.getAudioContext.bind(this)),document.addEventListener("mousedown",this.getAudioContext.bind(this)))},e.prototype._removeAutoCreateAudioContextOnFirstUserInteractionEventListeners=function(){this._options.createAudioContextOnFirstUserInteraction&&(document.removeEventListener("touchstart",this.getAudioContext.bind(this)),document.removeEventListener("touchend",this.getAudioContext.bind(this)),document.removeEventListener("mousedown",this.getAudioContext.bind(this)))},e.prototype.getAudioContext=function(){return t(this,void 0,void 0,(function(){return o(this,(function(e){switch(e.label){case 0:return null!==this._audioContext?[3,2]:[4,this._createAudioContext()];case 1:return e.sent(),[3,4];case 2:return"suspended"!==this._audioContext.state?[3,4]:[4,this._unfreezeAudioContext()];case 3:e.sent(),e.label=4;case 4:return[2,this._audioContext]}}))}))},e.prototype._unfreezeAudioContext=function(){return void 0===this._audioContext.suspend?Promise.resolve():this._audioContext.resume()},e.prototype.freezeAudioContext=function(){return void 0===this._audioContext.suspend?Promise.resolve():this._audioContext.suspend()},e.prototype.detectAudioContextSupport=function(){var e=!1;return(void 0!==window.webkitAudioContext||"undefined"!=typeof AudioContext)&&(e=!0),e},e.prototype.detectAudioElementSupport=function(){return!!document.createElement("audio").canPlayType},e.prototype.shutDown=function(e){return t(this,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return this._removeAutoCreateAudioContextOnFirstUserInteractionEventListeners(),e.forEach((function(e){null!==e.sourceNode&&(e.sourceNode instanceof MediaElementAudioSourceNode&&void 0!==e.sourceNode.mediaElement&&e.sourceNode.mediaElement.remove(),e.sourceNode.disconnect())})),this._disconnectPlayerGainNode(),[4,this._destroyAudioContext()];case 1:return t.sent(),[2]}}))}))},e.prototype._destroyAudioContext=function(){return t(this,void 0,void 0,(function(){return o(this,(function(e){switch(e.label){case 0:return null===this._audioContext?[3,2]:[4,this._audioContext.close()];case 1:e.sent(),this._audioContext=null,e.label=2;case 2:return[2]}}))}))},e.prototype.createAudioBufferSourceNode=function(e,n){return t(this,void 0,void 0,(function(){var t,i;return o(this,(function(o){switch(o.label){case 0:return[4,this.getAudioContext()];case 1:return t=o.sent(),i=t.createBufferSource(),n.sourceNode=i,i.loop=e.loop,n.gainNode=i.context.createGain(),n.gainNode.gain.value=1,i.connect(n.gainNode),i.onended=function(t){e.onSourceNodeEnded(t)},[2]}}))}))},e.prototype.createMediaElementSourceNode=function(e,n){return t(this,void 0,void 0,(function(){var u,r,s=this;return o(this,(function(a){switch(a.label){case 0:return null!==n.sourceNode?[3,2]:[4,this.getAudioContext()];case 1:r=a.sent();try{u=r.createMediaElementSource(e.mediaElement)}catch(e){throw new i(e)}u.mediaElement.loop=e.loop,n.gainNode=u.context.createGain(),n.gainNode.gain.value=1,u.connect(n.gainNode),u.mediaElement.onended=function(){return t(s,void 0,void 0,(function(){return o(this,(function(t){return e.onSourceNodeEnded(),[2]}))}))},n.sourceNode=u,a.label=2;case 2:return[2]}}))}))},e.prototype._getPlayerGainNode=function(){return t(this,void 0,void 0,(function(){var e,t;return o(this,(function(o){switch(o.label){case 0:return this._audioNodes.gainNode instanceof GainNode?(e=this._audioNodes.gainNode,[3,3]):[3,1];case 1:return[4,this.getAudioContext()];case 2:t=o.sent(),(e=t.createGain()).connect(t.destination),this._audioNodes.gainNode=e,o.label=3;case 3:return this._initializeVolume(),[2,e]}}))}))},e.prototype._disconnectPlayerGainNode=function(){null!==this._audioNodes.gainNode&&this._audioNodes.gainNode.disconnect(),this._audioNodes.gainNode=null},e.prototype.connectSound=function(e){return t(this,void 0,void 0,(function(){var t,n;return o(this,(function(o){switch(o.label){case 0:return[4,this._getPlayerGainNode()];case 1:return t=o.sent(),null!==(n=e.gainNode)&&n.connect(t),[2]}}))}))},e.prototype.cleanUpAudiBufferSourceNode=function(e){return t(this,void 0,void 0,(function(){return o(this,(function(t){return e.sourceNode instanceof AudioBufferSourceNode&&(e.sourceNode=null),[2]}))}))},e.prototype._changePlayerGainValue=function(e){this._audioNodes.gainNode instanceof GainNode&&(this._audioNodes.gainNode.gain.value=e)},e.prototype._roundGainTwoDecimals=function(e){return Math.round(100*(e+Number.EPSILON))/100},e.prototype.setVolume=function(e,t){void 0===t&&(t=!0),this._options.persistVolume&&t&&localStorage.setItem("WebAudioAPIPlayerVolume",e.toString());var o=e/100;this._audioNodes.gainNode instanceof GainNode&&(this._roundGainTwoDecimals(this._audioNodes.gainNode.gain.value)!==this._volume&&this._changePlayerGainValue(o));this._volume=e},e.prototype.getVolume=function(){var e;if(null!==this._volume)e=this._volume;else{if(this._options.persistVolume){var t=parseInt(localStorage.getItem("WebAudioAPIPlayerVolume"));isNaN(t)||(e=t)}void 0===e&&(e=this._options.volume)}return e},e.prototype._initializeVolume=function(){if(this._options.persistVolume){var e=parseInt(localStorage.getItem("WebAudioAPIPlayerVolume"));isNaN(e)||this.setVolume(e,!1)}null===this._volume&&this.setVolume(this._options.volume,!1)},e}(),r=function(){function e(){}return e.prototype.getArrayBuffer=function(e){return new Promise((function(t,o){var n=new XMLHttpRequest;n.open("GET",e.url,!0),n.responseType="arraybuffer",n.onload=function(){200===n.status?t(n.response):o(new i(n.statusText,n.status))},n.onprogress=function(t){var o=100/(t.total/t.loaded);e.loadingProgress=o,null!==e.onLoading&&e.onLoading(o,t.total,t.loaded)},n.onerror=function(){o(new i("xhr network error"))},n.send()}))},e}(),s=function(){function e(e){var t=this;void 0===e&&(e={}),this._playingProgressRequestId=null,this._playingProgressPreviousTimestamp=0,this._progressTrigger=function(e,o){o-t._playingProgressPreviousTimestamp>=t._options.playingProgressIntervalTime&&(t._playingProgress(e),t._playingProgressPreviousTimestamp=o),t._playingProgressRequestId=window.requestAnimationFrame((function(o){t._progressTrigger(e,o)}))};var o={volume:80,loopQueue:!1,loopSong:!1,soundsBaseUrl:"",playingProgressIntervalTime:200,playNextOnEnded:!0,stopOnReset:!0,visibilityAutoMute:!1,createAudioContextOnFirstUserInteraction:!0,persistVolume:!0,loadPlayerMode:"player_mode_audio",audioContext:null},n=Object.assign({},o,e);this._queue=[],this._currentIndex=null,this._options=n,this._initialize()}return e.prototype._initialize=function(){var t=this._audioOptions();switch(this._playerAudio=new u(t),this._options.loadPlayerMode){case e.PLAYER_MODE_AUDIO:if(!this._playerAudio.detectAudioContextSupport())throw new i("audio context is not supported by this device");if(!this._playerAudio.detectAudioElementSupport())throw new i("audio element is not supported by this device");break;case e.PLAYER_MODE_AJAX:if(!this._playerAudio.detectAudioContextSupport())throw new i("audio context is not supported by this device")}},e.prototype._audioOptions=function(){return{audioContext:this._options.audioContext,createAudioContextOnFirstUserInteraction:this._options.createAudioContextOnFirstUserInteraction,volume:this._options.volume,persistVolume:this._options.persistVolume}},e.prototype.addSoundToQueue=function(t){var o=t.soundAttributes,i=t.whereInQueue,u=void 0===i?"append":i,r=new n(o);switch(u){case e.WHERE_IN_QUEUE_AT_END:this._appendSoundToQueue(r);break;case e.WHERE_IN_QUEUE_AT_START:this._prependSoundToQueue(r)}return r},e.prototype._appendSoundToQueue=function(e){this._queue.push(e)},e.prototype._prependSoundToQueue=function(e){this._queue.unshift(e)},e.prototype.resetQueue=function(){this._options.stopOnReset&&this.stop(),this._queue=[]},e.prototype.reset=function(){this.resetQueue()},e.prototype.getQueue=function(){return this._queue},e.prototype.setVolume=function(e){this._playerAudio.setVolume(e)},e.prototype.getVolume=function(){return this._playerAudio.getVolume()},e.prototype.setLoopQueue=function(e){this._options.loopQueue=e},e.prototype.getLoopQueue=function(){return this._options.loopQueue},e.prototype.mute=function(){var e=this.getVolume();this._postMuteVolume=e,this._playerAudio.setVolume(0,!1)},e.prototype.unMute=function(){this._playerAudio.setVolume(this._postMuteVolume,!1),this._postMuteVolume=null},e.prototype.isMuted=function(){return null===this._postMuteVolume},e.prototype.setPosition=function(t){var o=this,n=this._getSoundFromQueue({whichSound:e.CURRENT_SOUND});if(null!==n)if(null===n.duration||isNaN(n.duration))this._loadSound(n).then((function(e){var n=e.duration/100*t;o.setPositionInSeconds(n)})).catch((function(e){throw e}));else{var i=n.duration/100*t;this.setPositionInSeconds(i)}},e.prototype.setPositionInSeconds=function(t){var o=this._getSoundFromQueue({whichSound:e.CURRENT_SOUND});if(null===o)throw new i("position change called, but no current sound found");o.state===n.SOUND_STATE_PLAYING?this.play({whichSound:o.id,playTimeOffset:t}):o.playTimeOffset=t},e.prototype._loadSound=function(t){var o,n;switch(this._options.loadPlayerMode){case e.PLAYER_MODE_AUDIO:o=this._loadSoundUsingAudioElement(t);break;case e.PLAYER_MODE_AJAX:o=this._loadSoundUsingRequest(t);break;case e.PLAYER_MODE_FETCH:n=new i(e.PLAYER_MODE_FETCH+" is not implemented yet",1),o=Promise.reject(n)}return o},e.prototype._loadSoundUsingAudioElement=function(e){var t=this;return new Promise((function(o,n){var u=t._findBestSource(e.source),r=u.url,s=u.codec,a=void 0===s?null:s;if(e.url=r,e.codec=a,e.arrayBuffer=null,null!==e.url){var d=new Audio;d.crossOrigin="anonymous",d.src=e.url,d.controls=!1,d.autoplay=!1,d.id="web_audio_api_player_sound_"+e.id.toString(),document.body.appendChild(d),e.audioElement=d,e.isReadyToPLay=!0,t._initializeAudioElementListeners(e);var c=function(){e.audioElement.removeEventListener("canplaythrough",c),isNaN(d.duration)||(e.duration=d.duration),o(e)};e.audioElement.addEventListener("canplaythrough",c);var l=function(){e.audioElement.removeEventListener("error",l);var t=new i("loading sound failed");n(t)};e.audioElement.addEventListener("error",l)}else{var p=new i("sound has no url",1);n(p)}}))},e.prototype._loadSoundUsingRequest=function(e){var t=this;return new Promise((function(o,n){var u=t._findBestSource(e.source),s=u.url,a=u.codec,d=void 0===a?null:a;if(e.url=s,e.codec=d,null!==e.url){var c=new r;e.isBuffering=!0,c.getArrayBuffer(e).then((function(i){e.arrayBuffer=i,t._decodeSound({sound:e}).then((function(e){o(e)})).catch(n)})).catch((function(e){n(e)}))}else{var l=new i("sound has no url",1);n(l)}}))},e.prototype._initializeAudioElementListeners=function(e){e.audioElement.addEventListener("progress",(function(){e.loadingProgress=e.audioElement.duration})),e.audioElement.addEventListener("timeupdate",(function(){e.duration=e.audioElement.duration}))},e.prototype._decodeSound=function(e){var t=e.sound;return this._playerAudio.decodeAudio(t.arrayBuffer).then((function(e){return t.audioBuffer=e,t.isBuffering=!1,t.isBuffered=!0,t.audioBufferDate=new Date,t.duration=e.duration,t.isReadyToPLay=!0,t})).catch((function(e){throw e}))},e.prototype._cloneAudioBuffer=function(e){for(var t=new AudioBuffer({length:e.length,numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate}),o=0;o<t.numberOfChannels;++o){var n=e.getChannelData(o);t.copyToChannel(n,o)}return t},e.prototype.play=function(t){var o=this,i=void 0===t?{}:t,u=i.whichSound,r=i.playTimeOffset;return new Promise((function(t,i){var s=o._getSoundFromQueue({whichSound:e.CURRENT_SOUND}),a=o._getSoundFromQueue({whichSound:u,updateIndex:!0});if(null===a)throw new Error("no more sounds in array");null===s||s.state!==n.SOUND_STATE_PLAYING&&s.state!==n.SOUND_STATE_PAUSED||s.id===a.id||o._stop(s,n.SOUND_STATE_STOPPED),null!==s&&s.state===n.SOUND_STATE_PLAYING&&s.id===a.id&&o._stop(s,n.SOUND_STATE_PAUSED),null===s||null!==s&&s.id!==a.id?a.firstTimePlayed=!0:a.firstTimePlayed=!1,void 0!==r&&(a.playTimeOffset=r),a.isReadyToPLay?(null!==a.audioBuffer&&(a.audioBuffer=o._cloneAudioBuffer(a.audioBuffer)),o._play(a).then(t).catch(i)):o._loadSound(a).then((function(){o._play(a).then(t).catch(i)})).catch(i)}))},e.prototype._play=function(e){return t(this,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return null===e.audioBuffer?[3,2]:[4,this._playAudioBuffer(e)];case 1:return t.sent(),[3,4];case 2:return[4,this._playMediaElementAudio(e)];case 3:t.sent(),t.label=4;case 4:return e.state=n.SOUND_STATE_PLAYING,e.startTime=e.getCurrentTime(),e=this._triggerSoundCallbacks(e),[2]}}))}))},e.prototype._playAudioBuffer=function(e){return t(this,void 0,void 0,(function(){var t,n,u=this;return o(this,(function(o){switch(o.label){case 0:if(null!==e.sourceNode)return[3,4];t={loop:e.loop,onSourceNodeEnded:function(){u._onEnded()}},o.label=1;case 1:return o.trys.push([1,3,,4]),[4,this._playerAudio.createAudioBufferSourceNode(t,e)];case 2:return o.sent(),[3,4];case 3:throw n=o.sent(),new i(n);case 4:return e.sourceNode instanceof AudioBufferSourceNode?(e.sourceNode.buffer=e.audioBuffer,[4,this._playerAudio.connectSound(e)]):[3,6];case 5:o.sent();try{void 0!==e.playTimeOffset?e.sourceNode.start(0,e.playTimeOffset):e.sourceNode.start()}catch(e){throw new i(e)}o.label=6;case 6:return[2]}}))}))},e.prototype._playMediaElementAudio=function(e){return t(this,void 0,void 0,(function(){var t,n,u=this;return o(this,(function(o){switch(o.label){case 0:if(null!==e.sourceNode)return[3,4];t={loop:e.loop,onSourceNodeEnded:function(){u._onEnded()},mediaElement:e.audioElement},o.label=1;case 1:return o.trys.push([1,3,,4]),[4,this._playerAudio.createMediaElementSourceNode(t,e)];case 2:return o.sent(),[3,4];case 3:throw n=o.sent(),new i(n);case 4:return e.sourceNode instanceof MediaElementAudioSourceNode?[4,this._playerAudio.connectSound(e)]:[3,6];case 5:o.sent(),void 0===e.playTimeOffset||isNaN(e.playTimeOffset)||(e.audioElement.currentTime=e.playTimeOffset);try{e.sourceNode.mediaElement.play()}catch(e){throw new i(e)}o.label=6;case 6:return[2]}}))}))},e.prototype._triggerSoundCallbacks=function(e){var t=this;return null===e.onResumed||e.firstTimePlayed||e.onResumed(e.playTimeOffset),null!==e.onStarted&&e.firstTimePlayed&&e.onStarted(e.playTimeOffset),null!==e.onPlaying?this._playingProgressRequestId=window.requestAnimationFrame((function(o){t._progressTrigger(e,o)})):this._playingProgressRequestId=null,e},e.prototype._onEnded=function(){var t=this._getSoundFromQueue({whichSound:e.CURRENT_SOUND});if(null!==t&&t.state===n.SOUND_STATE_PLAYING){var o=this._getSoundFromQueue({whichSound:e.PLAY_SOUND_NEXT,updateIndex:!1});if(null!==t.onEnded){var i=!1;null!==o&&this._options.playNextOnEnded&&(i=!0),this._options.loopQueue&&(i=!0),i||this._playerAudio.freezeAudioContext(),t.onEnded(i)}t.firstTimePlayed=!0,t.playTimeOffset=0,this._stop(t,n.SOUND_STATE_STOPPED),null!==o?this._options.playNextOnEnded&&this.play({whichSound:e.PLAY_SOUND_NEXT}):(this._currentIndex=0,this._options.loopQueue&&this.play())}},e.prototype._getSoundFromQueue=function(t){var o,n=void 0===t?{}:t,i=n.whichSound,u=n.updateIndex,r=void 0!==u&&u,s=null,a=null;if(0===this._queue.length)return s;if(void 0===i)a=0,null!==this._currentIndex&&(a=this._currentIndex),s=this._queue[a];else switch(i){case e.CURRENT_SOUND:null!==this._currentIndex&&(s=this._queue[this._currentIndex]);break;case e.PLAY_SOUND_NEXT:void 0!==this._queue[this._currentIndex+1]?(a=this._currentIndex+1,s=this._queue[a]):this._options.loopQueue&&(a=0,s=this._queue[a]);break;case e.PLAY_SOUND_PREVIOUS:void 0!==this._queue[this._currentIndex-1]?(a=this._currentIndex-1,s=this._queue[a]):this._options.loopQueue&&(a=this._queue.length-1,s=this._queue[a]);break;case e.PLAY_SOUND_FIRST:this._queue.length>0&&(a=0,s=this._queue[a]);break;case e.PLAY_SOUND_LAST:this._queue.length>0&&(a=this._queue.length-1,s=this._queue[a]);break;default:s=(o=this._findSoundById({soundId:i}))[0],a=o[1]}return null!==a&&r&&(this._currentIndex=a),s},e.prototype._findSoundById=function(e){var t=e.soundId,o=null,n=0;return this._queue.some((function(e,i){if(e.id===t)return o=e,n=i,!0})),[o,n]},e.prototype._findBestSource=function(e){var t,o={url:null,codec:null};t=Array.isArray(e)?e:[e];for(var n=0;n<t.length;){var i=t[n],u="";""!==this._options.soundsBaseUrl&&(u=this._options.soundsBaseUrl),u+=i.url;var r=!0;if(null!==i.codec&&(r=this._checkCodecSupport(i.codec)),r){if(i.isPreferred){o.url=u,o.codec=i.codec;break}o.url=u,o.codec=i.codec}n++}return o},e.prototype._checkCodecSupport=function(e){var t,o="";switch(e){case"ogg":case"oga":t=['audio/ogg; codecs="vorbis"'];break;case"mp3":t=['audio/mpeg; codecs="mp3"'];break;case"opus":t=['audio/ogg; codecs="opus"','audio/webm; codecs="opus"'];break;case"wav":t=['audio/wav; codecs="1"'];break;case"m4a":t=["audio/m4a;","audio/x-m4a;"];break;case"m4p":t=["audio/m4p;","audio/x-m4p;"];break;case"caf":t=["audio/x-caf;"];break;case"aac":t=["audio/aac;"];break;case"weba":case"webm":t=['audio/webm; codecs="vorbis"'];break;case"flac":t=["audio/flac;","audio/x-flac;"];break;default:o="unrecognised codec"}if(o)throw new i(o);return this._checkMimeTypesSupport(t)},e.prototype._checkMimeTypesSupport=function(e){var t=new Audio,o=!1;return e.forEach((function(e){t.canPlayType(e).replace(/^no$/,"")&&(o=!0)})),o},e.prototype.pause=function(){var t=this._getSoundFromQueue({whichSound:e.CURRENT_SOUND});if(null!==t&&t.state!==n.SOUND_STATE_PAUSED){var o=t.getCurrentTime();t.playTimeOffset+=o-t.startTime,null!==t.onPaused&&t.onPaused(t.playTimeOffset),this._stop(t,n.SOUND_STATE_PAUSED)}},e.prototype.stop=function(){var t=this._getSoundFromQueue({whichSound:e.CURRENT_SOUND});if(null!==t&&t.state!==n.SOUND_STATE_STOPPED){this._playerAudio.freezeAudioContext();var o=t.getCurrentTime();t.playTimeOffset+=o-t.startTime,null!==t.onStopped&&t.onStopped(t.playTimeOffset),this._stop(t,n.SOUND_STATE_STOPPED)}},e.prototype._stop=function(e,t){t===n.SOUND_STATE_STOPPED&&(e.playTimeOffset=0,e.firstTimePlayed=!0),null!==e.sourceNode&&(e.sourceNode instanceof AudioBufferSourceNode?e.sourceNode.stop(0):e.sourceNode instanceof MediaElementAudioSourceNode&&e.sourceNode.mediaElement.pause(),this._playerAudio.cleanUpAudiBufferSourceNode(e),e.state=t,null!==this._playingProgressRequestId&&(cancelAnimationFrame(this._playingProgressRequestId),this._playingProgressPreviousTimestamp=0))},e.prototype.next=function(){this.play({whichSound:e.PLAY_SOUND_NEXT})},e.prototype.previous=function(){this.play({whichSound:e.PLAY_SOUND_PREVIOUS})},e.prototype.first=function(){this.play({whichSound:e.PLAY_SOUND_FIRST})},e.prototype.last=function(){this.play({whichSound:e.PLAY_SOUND_LAST})},e.prototype._playingProgress=function(e){var t=e.getCurrentTime();e.playTime=t-e.startTime+e.playTimeOffset;var o=e.getDuration(),n=e.playTime/o*100;e.playedTimePercentage=n,e.onPlaying(n,o,e.playTime)},e.prototype.setVisibilityAutoMute=function(e){this._options.visibilityAutoMute=e,e?document.addEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1):document.removeEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1)},e.prototype.getVisibilityAutoMute=function(){return this._options.visibilityAutoMute},e.prototype._handleVisibilityChange=function(){var e;void 0!==document.hidden?e="hidden":void 0!==document.msHidden?e="msHidden":void 0!==document.webkitHidden&&(e="webkitHidden"),document[e]?this.mute():this.unMute()},e.prototype.disconnect=function(){return t(this,void 0,void 0,(function(){return o(this,(function(e){switch(e.label){case 0:return null!==this._playingProgressRequestId&&cancelAnimationFrame(this._playingProgressRequestId),[4,this._playerAudio.shutDown(this._queue)];case 1:return e.sent(),[2]}}))}))},e.prototype.getAudioContext=function(){return t(this,void 0,void 0,(function(){return o(this,(function(e){switch(e.label){case 0:return[4,this._playerAudio.getAudioContext()];case 1:return[2,e.sent()]}}))}))},e.WHERE_IN_QUEUE_AT_END="append",e.WHERE_IN_QUEUE_AT_START="prepend",e.PLAY_SOUND_NEXT="next",e.PLAY_SOUND_PREVIOUS="previous",e.PLAY_SOUND_FIRST="first",e.PLAY_SOUND_LAST="last",e.CURRENT_SOUND="current",e.PLAYER_MODE_AUDIO="player_mode_audio",e.PLAYER_MODE_AJAX="player_mode_ajax",e.PLAYER_MODE_FETCH="player_mode_fetch",e}();export{s as PlayerCore,n as PlayerSound}; | ||
function e(e,t,i,o){return new(i||(i=Promise))((function(n,s){function u(e){try{r(o.next(e))}catch(e){s(e)}}function d(e){try{r(o.throw(e))}catch(e){s(e)}}function r(e){var t;e.done?n(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(u,d)}r((o=o.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class t{constructor(e){this.url=null,this.codec=null,this.loop=!1,this.sourceNode=null,this.gainNode=null,this.isReadyToPLay=!1,this.isBuffered=!1,this.isBuffering=!1,this.audioElement=null,this.audioBuffer=null,this.arrayBuffer=null,this.audioBufferDate=null,this.playTimeOffset=0,this.startTime=0,this.elapsedPlayTime=0,this.playTime=0,this.playedTimePercentage=0,this.state="sound_state_stopped",this.loadingProgress=0,this.duration=null,this.firstTimePlayed=!0,this.isConnectToPlayerGain=!1,Array.isArray(e.source)?this.source=e.source:this.source=[e.source],void 0!==e.id?this.id=e.id:this.id=this._generateSoundId(),this.loop=e.loop||!1,this.duration=e.duration||null,"function"==typeof e.onLoading?this.onLoading=e.onLoading:this.onLoading=null,"function"==typeof e.onPlaying?this.onPlaying=e.onPlaying:this.onPlaying=null,"function"==typeof e.onStarted?this.onStarted=e.onStarted:this.onStarted=null,"function"==typeof e.onEnded?this.onEnded=e.onEnded:this.onEnded=null,"function"==typeof e.onStopped?this.onStopped=e.onStopped:this.onStopped=null,"function"==typeof e.onPaused?this.onPaused=e.onPaused:this.onPaused=null,"function"==typeof e.onResumed?this.onResumed=e.onResumed:this.onResumed=null,"function"==typeof e.onSeeking?this.onSeeking=e.onSeeking:this.onSeeking=null,e.arrayBuffer instanceof ArrayBuffer&&(this.arrayBuffer=e.arrayBuffer),e.audioBuffer instanceof AudioBuffer&&(this.audioBuffer=e.audioBuffer,this.isBuffering=!1,this.isBuffered=!0,this.audioBufferDate=new Date,this.duration=this.getDuration())}getCurrentTime(){let e;null!==this.sourceNode&&(this.sourceNode instanceof AudioBufferSourceNode?e=this.sourceNode.context.currentTime-this.startTime+this.elapsedPlayTime:this.sourceNode instanceof MediaElementAudioSourceNode&&(e=this.audioElement.currentTime));return Math.round(100*(e+Number.EPSILON))/100}getDuration(){let e;null!==this.sourceNode&&(this.sourceNode instanceof AudioBufferSourceNode?e=this.audioBuffer.duration:this.sourceNode instanceof MediaElementAudioSourceNode&&(e=this.audioElement.duration));return Math.round(100*(e+Number.EPSILON))/100}_generateSoundId(){return Date.now().toString(36)+Math.random().toString(36).substring(2)}}t.SOUND_STATE_STOPPED="sound_state_stopped",t.SOUND_STATE_PAUSED="sound_state_paused",t.SOUND_STATE_PLAYING="sound_state_playing",t.SOUND_STATE_SEEKING="sound_state_seeking";class i{constructor(e){this._audioContext=null,this._volume=null,this._audioNodes={gainNode:null},this._audioElement=null,this._mediaElementAudioSourceNode=null,this._isAudioUnlocked=!1,this._options=e,this._initialize()}_initialize(){this._options.createAudioContextOnFirstUserInteraction&&this._addFirstUserInteractionEventListeners()}getAudioNodes(){return this._audioNodes}decodeAudio(t){return e(this,void 0,void 0,(function*(){const e=yield this.getAudioContext();return yield e.decodeAudioData(t)}))}_createAudioContext(){if(this._audioContext instanceof AudioContext)return;const e=window.AudioContext||window.webkitAudioContext;null!==this._options.audioContext?this._audioContext=this._options.audioContext:this._audioContext=new e}_addFirstUserInteractionEventListeners(){this._options.createAudioContextOnFirstUserInteraction&&(document.addEventListener("touchstart",this._unlockAudio.bind(this)),document.addEventListener("touchend",this._unlockAudio.bind(this)),document.addEventListener("mousedown",this._unlockAudio.bind(this)))}_removeFirstUserInteractionEventListeners(){this._options.createAudioContextOnFirstUserInteraction&&(document.removeEventListener("touchstart",this._unlockAudio.bind(this)),document.removeEventListener("touchend",this._unlockAudio.bind(this)),document.removeEventListener("mousedown",this._unlockAudio.bind(this)))}_unlockAudio(){return e(this,void 0,void 0,(function*(){if(this._isAudioUnlocked)return;yield this.getAudioContext();const e=this._audioContext.createBuffer(1,1,22050);let t=this._audioContext.createBufferSource();t.onended=()=>{t.disconnect(0),this._isAudioUnlocked=!0,this._removeFirstUserInteractionEventListeners(),t.disconnect(0),t.buffer=null,t=null},t.buffer=e,t.connect(this._audioContext.destination),t.start(0),"player_mode_audio"===this._options.loadPlayerMode&&(this._createAudioElement(),this._createMediaElementAudioSourceNode())}))}_createAudioElement(){return e(this,void 0,void 0,(function*(){if(null===this._audioElement){const e=new Audio;e.controls=!1,e.autoplay=!1,e.preload="metadata",e.volume=1,e.id="web-audio-api-player",this._audioElement=e,this._options.addAudioElementsToDom&&document.body.appendChild(e)}}))}getAudioElement(){return this._audioElement}getAudioContext(){return e(this,void 0,void 0,(function*(){return null===this._audioContext||"closed"===this._audioContext.state?yield this._createAudioContext():"suspended"===this._audioContext.state&&(yield this.unfreezeAudioContext()),this._audioContext}))}unfreezeAudioContext(){return void 0===this._audioContext.resume?Promise.resolve():this._audioContext.resume()}freezeAudioContext(){return void 0===this._audioContext.suspend?Promise.resolve():this._audioContext.suspend()}isAudioContextFrozen(){return"suspended"===this._audioContext.state}detectAudioContextSupport(){let e=!1;return(void 0!==window.webkitAudioContext||"undefined"!=typeof AudioContext)&&(e=!0),e}detectAudioElementSupport(){return!!document.createElement("audio").canPlayType}_createAudioBufferSourceNode(){return e(this,void 0,void 0,(function*(){return(yield this.getAudioContext()).createBufferSource()}))}_createMediaElementAudioSourceNode(){return e(this,void 0,void 0,(function*(){if(null===this._mediaElementAudioSourceNode){const e=yield this.getAudioContext();this._mediaElementAudioSourceNode=e.createMediaElementSource(this._audioElement)}}))}_destroyMediaElementAudioSourceNode(){null!==this._mediaElementAudioSourceNode&&(void 0!==this._mediaElementAudioSourceNode.mediaElement&&this._mediaElementAudioSourceNode.mediaElement.remove(),this._mediaElementAudioSourceNode.disconnect(),this._mediaElementAudioSourceNode=null)}_destroyAudioBufferSourceNode(){null!==this._mediaElementAudioSourceNode&&this._mediaElementAudioSourceNode.disconnect()}_destroyAudioContext(){return e(this,void 0,void 0,(function*(){null!==this._audioContext&&"closed"!==this._audioContext.state&&(yield this._audioContext.close(),this._audioContext=null)}))}shutDown(t){return e(this,void 0,void 0,(function*(){this._removeFirstUserInteractionEventListeners(),t.forEach((e=>{this.disconnectSound(e)})),this._destroyMediaElementAudioSourceNode(),this._destroyAudioBufferSourceNode(),this._disconnectPlayerGainNode(),yield this._destroyAudioContext()}))}_getPlayerGainNode(){return e(this,void 0,void 0,(function*(){let e;if(this._audioNodes.gainNode instanceof GainNode)e=this._audioNodes.gainNode;else{const t=yield this.getAudioContext();e=t.createGain(),this._initializeVolume(e),e.connect(t.destination),this._audioNodes.gainNode=e}return e}))}_disconnectPlayerGainNode(){null!==this._audioNodes.gainNode&&(this._audioNodes.gainNode.disconnect(),this._audioNodes.gainNode=null)}connectSound(t,i){return e(this,void 0,void 0,(function*(){if(t.isConnectToPlayerGain)return;if("player_mode_ajax"===this._options.loadPlayerMode){const e=yield this._createAudioBufferSourceNode();t.gainNode=e.context.createGain(),e.connect(t.gainNode),e.loop=t.loop,e.onended=i,t.sourceNode=e}else"player_mode_audio"===this._options.loadPlayerMode&&(t.gainNode=this._mediaElementAudioSourceNode.context.createGain(),this._mediaElementAudioSourceNode.connect(t.gainNode),this._mediaElementAudioSourceNode.mediaElement.loop=t.loop,this._mediaElementAudioSourceNode.mediaElement.onended=i,t.sourceNode=this._mediaElementAudioSourceNode);t.gainNode.gain.value=1;const e=yield this._getPlayerGainNode();t.gainNode.connect(e),t.isConnectToPlayerGain=!0}))}disconnectSound(t){return e(this,void 0,void 0,(function*(){t.isConnectToPlayerGain&&(null!==t.sourceNode&&(t.sourceNode.disconnect(),t.sourceNode=null),null!==t.gainNode&&(t.gainNode.disconnect(),t.gainNode=null,t.isConnectToPlayerGain=!1),null!==t.audioElement&&(t.audioElement=null))}))}_changePlayerGainValue(t){return e(this,void 0,void 0,(function*(){if(this._audioNodes.gainNode instanceof GainNode){const e=yield this.getAudioContext();this._audioNodes.gainNode.gain.setTargetAtTime(t,e.currentTime,.1)}}))}setVolume(t,i=!0){return e(this,void 0,void 0,(function*(){this._options.persistVolume&&i&&localStorage.setItem("WebAudioAPIPlayerVolume",t.toString());const e=t/100;if(this._audioNodes.gainNode instanceof GainNode){e!==Math.round(100*(this._audioNodes.gainNode.gain.value+Number.EPSILON))/100&&(yield this._changePlayerGainValue(e))}return this._volume=t,t}))}getVolume(){let e;if(null!==this._volume)e=this._volume;else{if(this._options.persistVolume){const t=parseInt(localStorage.getItem("WebAudioAPIPlayerVolume"));isNaN(t)||(e=t)}void 0===e&&(e=this._options.volume),this._volume=e}return e}_initializeVolume(e){if(this._options.persistVolume){const t=parseInt(localStorage.getItem("WebAudioAPIPlayerVolume")),i=t/100;isNaN(t)||(e.gain.value=i),this._volume=t}if(null===this._volume){const t=this._options.volume/100;e.gain.value=t,this._volume=this._options.volume}}}class o{getArrayBuffer(e){return new Promise((function(t,i){const o=new XMLHttpRequest;o.open("GET",e.url,!0),o.responseType="arraybuffer",o.onload=function(){200===o.status?t(o.response):i(new Error(o.statusText+"(status:"+o.status+")"))},o.onprogress=function(t){const i=100/(t.total/t.loaded),o=Math.round(100*(i+Number.EPSILON))/100;e.loadingProgress=o,null!==e.onLoading&&e.onLoading(o,t.total,t.loaded)},o.onerror=function(e){i(e)},o.send()}))}}class n{constructor(e={}){this._playingProgressRequestId=null,this._postMuteVolume=null,this._progressTrigger=(e,i)=>{const o=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND});if(e.id===o.id&&o.state===t.SOUND_STATE_PLAYING){if(i-this._playingProgressPreviousTimestamp>=this._options.playingProgressIntervalTime){const t=e.getCurrentTime(),o=e.getDuration();if(!isNaN(t)&&!isNaN(o)){let n=0;if(0!==t){const e=t/o*100;n=Math.round(e)}e.playedTimePercentage=n,e.playTime=t,e.onPlaying(n,o,t),this._playingProgressPreviousTimestamp=i}}this._playingProgressRequestId=window.requestAnimationFrame((t=>{this._progressTrigger(e,t)}))}};const i={volume:80,loopQueue:!1,loopSong:!1,soundsBaseUrl:"",playingProgressIntervalTime:200,playNextOnEnded:!0,stopOnReset:!0,visibilityAutoMute:!1,createAudioContextOnFirstUserInteraction:!0,persistVolume:!0,loadPlayerMode:"player_mode_audio",audioContext:null,addAudioElementsToDom:!1},o=Object.assign({},i,e);this._queue=[],this._currentIndex=0,this._options=o,this._playingProgressPreviousTimestamp=0,this._initialize()}_initialize(){const e=this._audioOptions();switch(this._playerAudio=new i(e),this._options.loadPlayerMode){case n.PLAYER_MODE_AUDIO:if(!this._playerAudio.detectAudioContextSupport())throw new Error("audio context is not supported by this device");if(!this._playerAudio.detectAudioElementSupport())throw new Error("audio element is not supported by this device");break;case n.PLAYER_MODE_AJAX:if(!this._playerAudio.detectAudioContextSupport())throw new Error("audio context is not supported by this device")}}_audioOptions(){return{audioContext:this._options.audioContext,createAudioContextOnFirstUserInteraction:this._options.createAudioContextOnFirstUserInteraction,volume:this._options.volume,persistVolume:this._options.persistVolume,loadPlayerMode:this._options.loadPlayerMode,addAudioElementsToDom:this._options.addAudioElementsToDom}}addSoundToQueue({soundAttributes:e,whereInQueue:i="append"}){const o=new t(e);switch(i){case n.WHERE_IN_QUEUE_AT_END:this._appendSoundToQueue(o);break;case n.WHERE_IN_QUEUE_AT_START:this._prependSoundToQueue(o)}return o}_appendSoundToQueue(e){this._queue.push(e)}_prependSoundToQueue(e){this._queue.unshift(e)}resetQueue(){return e(this,void 0,void 0,(function*(){this._options.stopOnReset&&(yield this.stop()),this._queue.forEach((e=>{this._playerAudio.disconnectSound(e)})),this._queue=[]}))}reset(){this.resetQueue().catch((e=>{}))}getQueue(){return this._queue}setVolume(e){this._playerAudio.setVolume(e).catch((e=>{}))}getVolume(){return this._playerAudio.getVolume()}setLoopQueue(e){this._options.loopQueue=e}getLoopQueue(){return this._options.loopQueue}mute(){const e=this.getVolume();this._playerAudio.setVolume(0,!1).catch((e=>{})),this._postMuteVolume=e}unMute(){this._playerAudio.setVolume(this._postMuteVolume,!1).catch((e=>{})),this._postMuteVolume=null}isMuted(){return null!==this._postMuteVolume}setPosition(t){return e(this,void 0,void 0,(function*(){const e=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND});if(null!==e){let i=e.getDuration();(null===i||isNaN(i))&&(yield this._loadSound(e),i=e.getDuration());const o=i/100*t;this.setPositionInSeconds(o)}}))}setPositionInSeconds(i){return e(this,void 0,void 0,(function*(){const e=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND});if(null!==e){if(null!==e.onSeeking){const t=i,o=e.getDuration(),n=t/o*100,s=Math.round(n);e.onSeeking(s,o,t)}e.state===t.SOUND_STATE_PLAYING?(e.playTime=i,this._options.loadPlayerMode===n.PLAYER_MODE_AJAX?(e.elapsedPlayTime=i,yield this._stop(e,t.SOUND_STATE_SEEKING)):this._options.loadPlayerMode===n.PLAYER_MODE_AUDIO&&(e.state=t.SOUND_STATE_SEEKING,yield this._play(e))):(e.playTime=i,e.state=t.SOUND_STATE_SEEKING)}}))}_loadSound(t){return e(this,void 0,void 0,(function*(){switch(this._options.loadPlayerMode){case n.PLAYER_MODE_AUDIO:yield this._loadSoundUsingAudioElement(t);break;case n.PLAYER_MODE_AJAX:yield this._loadSoundUsingRequest(t);case n.PLAYER_MODE_FETCH:}}))}_loadSoundUsingAudioElement(t){return new Promise(((i,o)=>{const{url:n,codec:s=null}=this._findBestSource(t.source);if(t.url=n,t.codec=s,null!==t.url){t.audioElement=this._playerAudio.getAudioElement();const o=()=>e(this,void 0,void 0,(function*(){t.audioElement.removeEventListener("canplaythrough",o),t.isReadyToPLay=!0,isNaN(t.audioElement.duration)||(t.duration=t.audioElement.duration),i()}));t.audioElement.addEventListener("canplaythrough",o),t.audioElement.onprogress=()=>{if(t.audioElement.buffered.length){const e=t.getDuration(),i=t.audioElement.buffered.end(0),o=100/(e/i);t.loadingProgress=o,null!==t.onLoading&&t.onLoading(o,e,i),t.duration=t.audioElement.duration,100===o&&(t.isBuffering=!1,t.isBuffered=!0,t.audioBufferDate=new Date)}},t.audioElement.crossOrigin="anonymous",t.audioElement.src=t.url,t.audioElement.load()}else o(new Error("sound has no url"))}))}_loadSoundUsingRequest(t){return e(this,void 0,void 0,(function*(){if(null!==t.arrayBuffer)return yield this._decodeSound({sound:t});const{url:e,codec:i=null}=this._findBestSource(t.source);if(t.url=e,t.codec=i,null===t.url)throw new Error("sound has no url");{const e=new o;t.isBuffering=!0;const i=yield e.getArrayBuffer(t);t.arrayBuffer=i,yield this._decodeSound({sound:t})}}))}_decodeSound({sound:t}){return e(this,void 0,void 0,(function*(){const e=t.arrayBuffer.slice(0),i=yield this._playerAudio.decodeAudio(e);t.audioBuffer=i,t.isBuffering=!1,t.isBuffered=!0,t.audioBufferDate=new Date,t.duration=i.duration,t.isReadyToPLay=!0}))}play({whichSound:i,playTimeOffset:o}={}){return e(this,void 0,void 0,(function*(){const e=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND}),s=this._getSoundFromQueue({whichSound:i,updateIndex:!0});return null===s?s:null!==e&&e.state===t.SOUND_STATE_PLAYING&&e.id===s.id?(isNaN(o)||this.setPositionInSeconds(o),s):(null===e||e.state!==t.SOUND_STATE_PLAYING&&e.state!==t.SOUND_STATE_PAUSED||e.id===s.id||(yield this._stop(e,t.SOUND_STATE_STOPPED)),isNaN(o)?s.playTimeOffset=0:s.playTimeOffset=o,null===s.sourceNode&&(yield this._playerAudio.connectSound(s,(()=>{this._onEnded()}))),s.isReadyToPLay||(yield this._loadSound(s)),yield this._play(s),s)}))}_play(i){return e(this,void 0,void 0,(function*(){this._playerAudio.isAudioContextFrozen()&&(yield this._playerAudio.unfreezeAudioContext()),i.playTimeOffset>0&&(i.playTime=i.playTimeOffset),this._options.loadPlayerMode===n.PLAYER_MODE_AJAX?yield this._playAudioBuffer(i):this._options.loadPlayerMode===n.PLAYER_MODE_AUDIO&&(yield this._playMediaElementAudio(i)),i.state=t.SOUND_STATE_PLAYING,this._triggerSoundCallbacks(i)}))}_playAudioBuffer(i){return e(this,void 0,void 0,(function*(){if(i.sourceNode instanceof AudioBufferSourceNode){i.startTime=i.sourceNode.context.currentTime,i.sourceNode.buffer=i.audioBuffer;try{i.state===t.SOUND_STATE_SEEKING||i.state===t.SOUND_STATE_PAUSED&&0===i.playTimeOffset?i.sourceNode.start(0,i.playTime):i.playTimeOffset>0?(i.elapsedPlayTime=i.playTimeOffset,i.sourceNode.start(0,i.playTimeOffset)):i.sourceNode.start()}catch(e){throw new Error(e)}}}))}_playMediaElementAudio(i){return e(this,void 0,void 0,(function*(){i.sourceNode instanceof MediaElementAudioSourceNode&&(i.state===t.SOUND_STATE_SEEKING||i.state===t.SOUND_STATE_PAUSED&&0===i.playTimeOffset?i.audioElement.currentTime=i.playTime:i.playTimeOffset>0?i.audioElement.currentTime=i.playTimeOffset:i.audioElement.currentTime=0,yield i.audioElement.play())}))}_triggerSoundCallbacks(e){null===e.onResumed||e.firstTimePlayed||e.onResumed(e.playTime),null!==e.onStarted&&e.firstTimePlayed&&(e.firstTimePlayed=!1,e.onStarted(e.playTimeOffset)),null!==e.onPlaying?(this._playingProgressPreviousTimestamp=0,this._progressTrigger(e,0)):this._playingProgressRequestId=null}_onEnded(){return e(this,void 0,void 0,(function*(){if(this._options.playNextOnEnded){const e=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND});if(null!==e){if(this._options.loadPlayerMode===n.PLAYER_MODE_AUDIO||this._options.loadPlayerMode===n.PLAYER_MODE_AJAX&&e.state===t.SOUND_STATE_PLAYING){let t=!1;null!==this._getSoundFromQueue({whichSound:n.PLAY_SOUND_NEXT})&&(t=!0),t||(yield this._playerAudio.freezeAudioContext()),null!==e.onEnded&&e.onEnded(t);try{yield this.next()}catch(e){}}if(this._options.loadPlayerMode===n.PLAYER_MODE_AJAX&&e.state===t.SOUND_STATE_SEEKING)try{yield this.play(e)}catch(e){}}}}))}_getSoundFromQueue({whichSound:e,updateIndex:t=!1}={}){let i=null,o=null;if(0===this._queue.length)return i;switch(void 0===e&&(e=n.CURRENT_SOUND),e){case n.CURRENT_SOUND:o=this._currentIndex,i=this._queue[o];break;case n.PLAY_SOUND_NEXT:void 0!==this._queue[this._currentIndex+1]?(o=this._currentIndex+1,i=this._queue[o]):this._options.loopQueue&&(o=0,i=this._queue[o]);break;case n.PLAY_SOUND_PREVIOUS:void 0!==this._queue[this._currentIndex-1]?(o=this._currentIndex-1,i=this._queue[o]):this._options.loopQueue&&(o=this._queue.length-1,i=this._queue[o]);break;case n.PLAY_SOUND_FIRST:this._queue.length>0&&(o=0,i=this._queue[o]);break;case n.PLAY_SOUND_LAST:this._queue.length>0&&(o=this._queue.length-1,i=this._queue[o]);break;default:[i,o]=this._findSoundById({soundId:e})}return null!==o&&t&&(this._currentIndex=o),i}_findSoundById({soundId:e}){let t=null,i=0;return this._queue.some(((o,n)=>{if(o.id===e)return t=o,i=n,!0})),[t,i]}_findBestSource(e){const t={url:null,codec:null};let i;i=Array.isArray(e)?e:[e];let o=0;for(;o<i.length;){const e=i[o];let n="";""!==this._options.soundsBaseUrl&&(n=this._options.soundsBaseUrl),n+=e.url;let s=!0;if(null!==e.codec&&(s=this._checkCodecSupport(e.codec)),s){if(e.isPreferred){t.url=n,t.codec=e.codec;break}t.url=n,t.codec=e.codec}o++}return t}_checkCodecSupport(e){let t,i="";switch(e){case"ogg":case"oga":t=['audio/ogg; codecs="vorbis"'];break;case"mp3":t=['audio/mpeg; codecs="mp3"'];break;case"opus":t=['audio/ogg; codecs="opus"','audio/webm; codecs="opus"'];break;case"wav":t=['audio/wav; codecs="1"'];break;case"m4a":t=["audio/m4a;","audio/x-m4a;"];break;case"m4p":t=["audio/m4p;","audio/x-m4p;"];break;case"caf":t=["audio/x-caf;"];break;case"aac":t=["audio/aac;"];break;case"weba":case"webm":t=['audio/webm; codecs="vorbis"'];break;case"flac":t=["audio/flac;","audio/x-flac;"];break;default:i="unrecognised codec"}if(i)throw new Error(i);return this._checkMimeTypesSupport(t)}_checkMimeTypesSupport(e){const t=new Audio;let i=!1;return e.forEach((e=>{t.canPlayType(e).replace(/^no$/,"")&&(i=!0)})),i}pause(){return e(this,void 0,void 0,(function*(){const e=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND});if(null===e)return;if(e.state===t.SOUND_STATE_PAUSED)return;const i=e.getCurrentTime();return e.playTime=i,this._options.loadPlayerMode===n.PLAYER_MODE_AJAX&&(e.elapsedPlayTime=i),null!==e.onPaused&&e.onPaused(e.playTime),yield this._stop(e,t.SOUND_STATE_PAUSED),e}))}stop(){return e(this,void 0,void 0,(function*(){const e=this._getSoundFromQueue({whichSound:n.CURRENT_SOUND});if(null!==e&&e.state!==t.SOUND_STATE_STOPPED)return yield this._playerAudio.freezeAudioContext(),null!==e.onStopped&&e.onStopped(e.playTime),yield this._stop(e,t.SOUND_STATE_STOPPED),e}))}_stop(i,o){return e(this,void 0,void 0,(function*(){null!==this._playingProgressRequestId&&(cancelAnimationFrame(this._playingProgressRequestId),this._playingProgressRequestId=null),i.state=o,null!==i.sourceNode&&(i.sourceNode instanceof AudioBufferSourceNode&&(i.sourceNode.stop(0),yield this._playerAudio.disconnectSound(i)),i.sourceNode instanceof MediaElementAudioSourceNode&&i.audioElement.pause()),o===t.SOUND_STATE_STOPPED&&(i.isReadyToPLay=!1,i.firstTimePlayed=!0,i.startTime=0,i.elapsedPlayTime=0,i.playTime=0,i.playedTimePercentage=0,yield this._playerAudio.disconnectSound(i))}))}next(){return e(this,void 0,void 0,(function*(){return yield this.play({whichSound:n.PLAY_SOUND_NEXT})}))}previous(){return e(this,void 0,void 0,(function*(){return yield this.play({whichSound:n.PLAY_SOUND_PREVIOUS})}))}first(){return e(this,void 0,void 0,(function*(){return yield this.play({whichSound:n.PLAY_SOUND_FIRST})}))}last(){return e(this,void 0,void 0,(function*(){return yield this.play({whichSound:n.PLAY_SOUND_LAST})}))}setVisibilityAutoMute(e){this._options.visibilityAutoMute=e,e?document.addEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1):document.removeEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1)}getVisibilityAutoMute(){return this._options.visibilityAutoMute}_handleVisibilityChange(){let e;void 0!==document.hidden?e="hidden":void 0!==document.msHidden?e="msHidden":void 0!==document.webkitHidden&&(e="webkitHidden"),document[e]?this.mute():this.unMute()}disconnect(){return e(this,void 0,void 0,(function*(){null!==this._playingProgressRequestId&&(cancelAnimationFrame(this._playingProgressRequestId),this._playingProgressRequestId=null),yield this._playerAudio.shutDown(this._queue)}))}getAudioContext(){return e(this,void 0,void 0,(function*(){return yield this._playerAudio.getAudioContext()}))}}n.WHERE_IN_QUEUE_AT_END="append",n.WHERE_IN_QUEUE_AT_START="prepend",n.PLAY_SOUND_NEXT="next",n.PLAY_SOUND_PREVIOUS="previous",n.PLAY_SOUND_FIRST="first",n.PLAY_SOUND_LAST="last",n.CURRENT_SOUND="current",n.PLAYER_MODE_AUDIO="player_mode_audio",n.PLAYER_MODE_AJAX="player_mode_ajax",n.PLAYER_MODE_FETCH="player_mode_fetch";export{n as PlayerCore,t as PlayerSound}; | ||
//# sourceMappingURL=index.min.js.map |
import { ISound } from './sound'; | ||
type OnEndedCallbackType = (event: Event) => void; | ||
export interface IAudioOptions { | ||
@@ -7,2 +8,4 @@ audioContext: AudioContext; | ||
persistVolume: boolean; | ||
loadPlayerMode: string; | ||
addAudioElementsToDom: boolean; | ||
} | ||
@@ -24,12 +27,2 @@ export interface IAudioNodes { | ||
} | ||
interface IOnSourceNodeEnded { | ||
(event?: Event): void; | ||
} | ||
export interface IAudioBufferSourceOptions extends AudioBufferSourceOptions { | ||
onSourceNodeEnded: IOnSourceNodeEnded; | ||
} | ||
export interface IMediaElementAudioSourceOptions extends MediaElementAudioSourceOptions { | ||
onSourceNodeEnded: IOnSourceNodeEnded; | ||
loop: boolean; | ||
} | ||
export declare class PlayerAudio { | ||
@@ -40,27 +33,36 @@ protected _options: IAudioOptions; | ||
protected _audioNodes: IAudioNodes; | ||
protected _audioElement: HTMLAudioElement; | ||
protected _mediaElementAudioSourceNode: MediaElementAudioSourceNode; | ||
protected _isAudioUnlocked: boolean; | ||
constructor(options: IAudioOptions); | ||
protected _initialize(): void; | ||
getAudioNodes(): IAudioNodes; | ||
decodeAudio(arrayBuffer: ArrayBuffer): Promise<AudioBuffer>; | ||
protected _createAudioContext(): Promise<void>; | ||
protected _addAutoCreateAudioContextOnFirstUserInteractionEventListeners(): void; | ||
protected _removeAutoCreateAudioContextOnFirstUserInteractionEventListeners(): void; | ||
protected _addFirstUserInteractionEventListeners(): void; | ||
protected _removeFirstUserInteractionEventListeners(): void; | ||
protected _unlockAudio(): Promise<void>; | ||
protected _createAudioElement(): Promise<void>; | ||
getAudioElement(): HTMLAudioElement; | ||
getAudioContext(): Promise<AudioContext>; | ||
protected _unfreezeAudioContext(): Promise<void>; | ||
unfreezeAudioContext(): Promise<void>; | ||
freezeAudioContext(): Promise<void>; | ||
isAudioContextFrozen(): boolean; | ||
detectAudioContextSupport(): boolean; | ||
detectAudioElementSupport(): boolean; | ||
protected _createAudioBufferSourceNode(): Promise<AudioBufferSourceNode>; | ||
protected _createMediaElementAudioSourceNode(): Promise<void>; | ||
protected _destroyMediaElementAudioSourceNode(): void; | ||
protected _destroyAudioBufferSourceNode(): void; | ||
protected _destroyAudioContext(): Promise<void>; | ||
shutDown(songsQueue: ISound[]): Promise<void>; | ||
protected _destroyAudioContext(): Promise<void>; | ||
createAudioBufferSourceNode(audioBufferSourceOptions: IAudioBufferSourceOptions, sound: ISound): Promise<void>; | ||
createMediaElementSourceNode(sourceNodeOptions: IMediaElementAudioSourceOptions, sound: ISound): Promise<void>; | ||
protected _getPlayerGainNode(): Promise<GainNode>; | ||
protected _disconnectPlayerGainNode(): void; | ||
connectSound(sound: ISound): Promise<void>; | ||
cleanUpAudiBufferSourceNode(sound: ISound): Promise<void>; | ||
protected _changePlayerGainValue(gainValue: number): void; | ||
protected _roundGainTwoDecimals(rawGainValue: number): number; | ||
setVolume(volume: number, forceUpdateUserVolume?: boolean): void; | ||
connectSound(sound: ISound, onEndedCallback: OnEndedCallbackType): Promise<void>; | ||
disconnectSound(sound: ISound): Promise<void>; | ||
protected _changePlayerGainValue(gainValue: number): Promise<void>; | ||
setVolume(volume: number, forceUpdateUserVolume?: boolean): Promise<number>; | ||
getVolume(): number; | ||
protected _initializeVolume(): void; | ||
protected _initializeVolume(gainNode: GainNode): void; | ||
} | ||
export {}; |
import { ISound, ISoundAttributes, ISoundSource, typeSoundStates } from './sound'; | ||
import { PlayerAudio, IAudioOptions } from './audio'; | ||
import { PlayerError } from './error'; | ||
declare const PLAYER_MODE_AUDIO = "player_mode_audio"; | ||
@@ -24,2 +23,3 @@ declare const PLAYER_MODE_AJAX = "player_mode_ajax"; | ||
audioContext?: AudioContext; | ||
addAudioElementsToDom?: boolean; | ||
} | ||
@@ -70,5 +70,5 @@ export interface ISoundsQueueOptions { | ||
addSoundToQueue({ soundAttributes, whereInQueue }: ISoundsQueueOptions): ISound; | ||
_appendSoundToQueue(sound: ISound): void; | ||
_prependSoundToQueue(sound: ISound): void; | ||
resetQueue(): void; | ||
protected _appendSoundToQueue(sound: ISound): void; | ||
protected _prependSoundToQueue(sound: ISound): void; | ||
resetQueue(): Promise<void>; | ||
reset(): void; | ||
@@ -83,17 +83,15 @@ getQueue(): ISound[]; | ||
isMuted(): boolean; | ||
setPosition(soundPositionInPercent: number): void; | ||
setPositionInSeconds(soundPositionInSeconds: number): void; | ||
protected _loadSound(sound: ISound): Promise<ISound | PlayerError>; | ||
protected _loadSoundUsingAudioElement(sound: ISound): Promise<ISound | PlayerError>; | ||
protected _loadSoundUsingRequest(sound: ISound): Promise<ISound | PlayerError>; | ||
protected _initializeAudioElementListeners(sound: ISound): void; | ||
protected _decodeSound({ sound }: IDecodeSoundOptions): Promise<ISound>; | ||
protected _cloneAudioBuffer(fromAudioBuffer: AudioBuffer): AudioBuffer; | ||
play({ whichSound, playTimeOffset }?: IPlayOptions): Promise<void>; | ||
setPosition(soundPositionInPercent: number): Promise<void>; | ||
setPositionInSeconds(soundPositionInSeconds: number): Promise<void>; | ||
protected _loadSound(sound: ISound): Promise<void>; | ||
protected _loadSoundUsingAudioElement(sound: ISound): Promise<void>; | ||
protected _loadSoundUsingRequest(sound: ISound): Promise<void>; | ||
protected _decodeSound({ sound }: IDecodeSoundOptions): Promise<void>; | ||
play({ whichSound, playTimeOffset }?: IPlayOptions): Promise<ISound>; | ||
protected _play(sound: ISound): Promise<void>; | ||
protected _playAudioBuffer(sound: ISound): Promise<void>; | ||
protected _playMediaElementAudio(sound: ISound): Promise<void>; | ||
protected _triggerSoundCallbacks(sound: ISound): ISound; | ||
protected _triggerSoundCallbacks(sound: ISound): void; | ||
protected _progressTrigger: (sound: ISound, timestamp: DOMHighResTimeStamp) => void; | ||
protected _onEnded(): void; | ||
protected _onEnded(): Promise<void>; | ||
protected _getSoundFromQueue({ whichSound, updateIndex }?: IGetSoundFromQueue): ISound; | ||
@@ -104,10 +102,9 @@ protected _findSoundById({ soundId }: IFindSoundById): [ISound, number]; | ||
protected _checkMimeTypesSupport(mediaMimeTypes: string[]): boolean; | ||
pause(): void; | ||
stop(): void; | ||
protected _stop(sound: ISound, soundState: typeSoundStates): void; | ||
next(): void; | ||
previous(): void; | ||
first(): void; | ||
last(): void; | ||
protected _playingProgress(sound: ISound): void; | ||
pause(): Promise<ISound>; | ||
stop(): Promise<ISound>; | ||
protected _stop(sound: ISound, soundState: typeSoundStates): Promise<void>; | ||
next(): Promise<ISound>; | ||
previous(): Promise<ISound>; | ||
first(): Promise<ISound>; | ||
last(): Promise<ISound>; | ||
setVisibilityAutoMute(visibilityAutoMute: boolean): void; | ||
@@ -114,0 +111,0 @@ getVisibilityAutoMute(): boolean; |
declare const SOUND_STATE_STOPPED = "sound_state_stopped"; | ||
declare const SOUND_STATE_PAUSED = "sound_state_paused"; | ||
declare const SOUND_STATE_PLAYING = "sound_state_playing"; | ||
export type typeSoundStates = typeof SOUND_STATE_STOPPED | typeof SOUND_STATE_PAUSED | typeof SOUND_STATE_PLAYING; | ||
declare const SOUND_STATE_SEEKING = "sound_state_seeking"; | ||
export type typeSoundStates = typeof SOUND_STATE_STOPPED | typeof SOUND_STATE_PAUSED | typeof SOUND_STATE_PLAYING | typeof SOUND_STATE_SEEKING; | ||
export interface IOnProgress { | ||
(progress: number, maximumValue: number, currentValue: number): void; | ||
(playingPercentage: number, duration: number, playTime: number): void; | ||
} | ||
@@ -11,5 +12,17 @@ export interface IOnEnded { | ||
} | ||
export interface IOnAnyAction { | ||
export interface IOnStarted { | ||
(playTimeOffset: number): void; | ||
} | ||
export interface IOnPaused { | ||
(playTime: number): void; | ||
} | ||
export interface IOnResumed { | ||
(playTime: number): void; | ||
} | ||
export interface IOnStopped { | ||
(playTime: number): void; | ||
} | ||
export interface IOnSeeking { | ||
(seekingPercentage: number, duration: number, playTime: number): void; | ||
} | ||
export interface ISoundSource { | ||
@@ -30,6 +43,7 @@ url: string; | ||
onEnded?: IOnEnded; | ||
onStarted?: IOnAnyAction; | ||
onStopped?: IOnAnyAction; | ||
onPaused?: IOnAnyAction; | ||
onResumed?: IOnAnyAction; | ||
onStarted?: IOnStarted; | ||
onStopped?: IOnStopped; | ||
onPaused?: IOnPaused; | ||
onResumed?: IOnResumed; | ||
onSeeking?: IOnSeeking; | ||
} | ||
@@ -47,2 +61,3 @@ export interface ISound extends ISoundAttributes, ISoundSource { | ||
playTime: number; | ||
elapsedPlayTime: number; | ||
playedTimePercentage: number; | ||
@@ -52,2 +67,3 @@ state: typeSoundStates; | ||
firstTimePlayed: boolean; | ||
isConnectToPlayerGain: boolean; | ||
getCurrentTime(): number; | ||
@@ -60,2 +76,3 @@ getDuration(): number; | ||
static readonly SOUND_STATE_PLAYING = "sound_state_playing"; | ||
static readonly SOUND_STATE_SEEKING = "sound_state_seeking"; | ||
source: (ISoundSource)[] | ISoundSource; | ||
@@ -77,2 +94,3 @@ url: string; | ||
startTime: number; | ||
elapsedPlayTime: number; | ||
playTime: number; | ||
@@ -84,9 +102,11 @@ playedTimePercentage: number; | ||
firstTimePlayed: boolean; | ||
isConnectToPlayerGain: boolean; | ||
onLoading: IOnProgress; | ||
onPlaying: IOnProgress; | ||
onEnded: IOnEnded; | ||
onStarted: IOnAnyAction; | ||
onStopped: IOnAnyAction; | ||
onPaused: IOnAnyAction; | ||
onResumed: IOnAnyAction; | ||
onStarted: IOnStarted; | ||
onStopped: IOnStopped; | ||
onPaused: IOnPaused; | ||
onResumed: IOnResumed; | ||
onSeeking?: IOnSeeking; | ||
constructor(soundAttributes: ISoundAttributes); | ||
@@ -93,0 +113,0 @@ getCurrentTime(): number; |
{ | ||
"name": "web-audio-api-player", | ||
"version": "5.0.4", | ||
"version": "5.1.0-beta.1", | ||
"description": "web audio api player", | ||
@@ -43,8 +43,8 @@ "keywords": [ | ||
"@rollup/plugin-terser": "0.4.3", | ||
"@typescript-eslint/eslint-plugin": "6.7.0", | ||
"@typescript-eslint/parser": "6.7.0", | ||
"eslint": "8.49.0", | ||
"@typescript-eslint/eslint-plugin": "6.7.3", | ||
"@typescript-eslint/parser": "6.7.3", | ||
"eslint": "8.50.0", | ||
"eslint-plugin-import": "2.28.1", | ||
"rollup": "3.29.2", | ||
"rollup-plugin-typescript2": "0.35.0", | ||
"rollup": "3.29.4", | ||
"rollup-plugin-typescript2": "0.36.0", | ||
"typescript": "5.2.2" | ||
@@ -51,0 +51,0 @@ }, |
195
README.md
@@ -114,4 +114,4 @@ [![npm version](https://img.shields.io/npm/v/web-audio-api-player.svg?style=flat)](https://www.npmjs.com/package/web-audio-api-player) | ||
}, | ||
onPlaying: (playingProgress, maximumValue, currentValue) => { | ||
console.log('onPlaying (playingProgress, maximumValue, currentValue): ', playingProgress, maximumValue, currentValue) | ||
onPlaying: (playingPercentage, duration, playTime) => { | ||
console.log('onPlaying (playingPercentage, duration, playTime): ', playingPercentage, duration, playTime) | ||
}, | ||
@@ -121,14 +121,17 @@ onStarted: (playTimeOffset) => { | ||
}, | ||
onPaused: (playTimeOffset) => { | ||
console.log('onPaused (playTimeOffset): ', playTimeOffset) | ||
onPaused: (playTime) => { | ||
console.log('onPaused (playTime): ', playTime) | ||
}, | ||
onStopped: (playTimeOffset) => { | ||
console.log('onStopped (playTimeOffset): ', playTimeOffset) | ||
onStopped: (playTime) => { | ||
console.log('onStopped (playTime): ', playTime) | ||
}, | ||
onResumed: (playTimeOffset) => { | ||
console.log('onResumed (playTimeOffset): ', playTimeOffset) | ||
onResumed: (playTime) => { | ||
console.log('onResumed (playTime): ', playTime) | ||
}, | ||
onEnded: (willPlayNext) => { | ||
console.log('onEnded (willPlayNext): ', willPlayNext) | ||
} | ||
}, | ||
onSeeking: (seekingPercentage, duration, playTime) => { | ||
console.log('onPlaying (seekingPercentage, duration, playTime): ', seekingPercentage, duration, playTime) | ||
}, | ||
} | ||
@@ -228,2 +231,3 @@ ``` | ||
* audioContext: [AudioContext] (default: null) a custom [audiocontext](https://developer.mozilla.org/en-US/docs/Web/API/AudioContext) you inject to replace the default audiocontext of the player | ||
* addAudioElementsToDom: [boolean] (default: false) when audio elements get created, they are by default offscreen (not added to the DOM), if you want the audio elements to be added to the DOM set this option to true | ||
@@ -248,10 +252,86 @@ ### sound attributes | ||
* onLoading: [function] (optional) a callback funtion that will get triggered at intervals during the loading process of a sound | ||
* onPlaying: [function] (optional) a callback funtion that will get triggered at intervals while the sound is playing | ||
* onEnded: [function] (optional) a callback funtion that will get triggered when the end of the sound is reached | ||
* onStarted: [function] (optional) a callback funtion that will get triggered when the sound playback starts | ||
* onStopped: [function] (optional) a callback funtion that will get triggered when the sound playback is stopped (the difference between pause and stop is that stop will free the resources needed to play a song) | ||
* onPaused: [function] (optional) a callback funtion that will get triggered when the sound playback is being paused (use pause instead of stop if there is a reason to assume that the playback will be resumed at anytime, if this can't be assumed it is recommended to call stop) | ||
* onResumed: [function] (optional) a callback funtion that will get triggered when the sound playback gets resumed after if got set to pause | ||
* onLoading(loadingPercentage, total, loaded): [function] (optional) a callback funtion that will get triggered at intervals during the loading process of a sound, the interval duration can be changed using the [player option "playingProgressIntervalTime"](#player-options), the callback has three parameters, **loadingPercentage** is the percentage that has been loaded so far (number ranging from 0 to 100) | ||
* if the player mode is [PLAYER_MODE_AUDIO](#player_mode_audio), then **total** is an integer telling you the total song duration in seconds ([MDN HTMLMediaElement duration](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration)), **loaded** is an integer that tells you the amount that already got loaded (buffered end) in seconds ([MDN HTMLMediaElement timerange end](https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges/end)), if you prefer to use the raw values I recommend you use the **sound.audioElement.buffered** and read them perciodically yourself | ||
* if the player mode is [PLAYER_MODE_AJAX](#player_mode_ajax), then **total** is an integer telling you the total bytes that will get loaded ([MDN ProgressEvent total](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/total)), **loaded** is an integer that tells you the amount of bytes that already got loaded ([MDN ProgressEvent loaded](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/loaded)) | ||
* onPlaying(playingPercentage, duration, playTime)): [function] (optional) a callback funtion that will get triggered at intervals while the sound is playing, the callback has three parameters, **playingPercentage** is the percentage that has been played so far (number ranging from 0 to 100), **duration** is the total song duration, playTime is the current time in seconds that have been played | ||
* onEnded(willPlayNext): [function] (optional) a callback funtion that will get triggered when the end of the sound is reached, returns one parameter **willPlayNext** which is a boolean, true if there is a next song in the internal queue that will get played or false if no next sound will get played | ||
* onStarted(playTimeOffset): [function] (optional) a callback funtion that will get triggered when the sound playback starts, returned value is the playTimeOffset of the song, usually playTimeOffset is zero unless you explicitly set it to be something else | ||
* onStopped(playTime): [function] (optional) a callback funtion that will get triggered when the sound playback is stopped (the difference between pause and stop is that stop will free the resources needed to play a song), returns one parameter **playTime** which is the current sound position in seconds | ||
* onPaused(playTime): [function] (optional) a callback funtion that will get triggered when the sound playback is being paused (use pause instead of stop if there is a reason to assume that the playback will be resumed at anytime, if this can't be assumed it is recommended to call stop), returns one parameter **playTime** which is the current sound position in seconds | ||
* onResumed(playTime): [function] (optional) a callback funtion that will get triggered when the sound playback gets resumed after if got set to pause, returns one parameter **playTime** which is the current sound position in seconds | ||
### player functions | ||
Note: all player functions a promise, I recommend using a try catch and await the promise or call promise.catch to fetch eventual errors thrown by the player, like so: | ||
```ts | ||
async function foo(): Promise<void> { | ||
try { | ||
await player.play() | ||
} catch (error) { | ||
console.error(error) | ||
} | ||
} | ||
foo() | ||
``` | ||
or like so: | ||
```ts | ||
function bar(): void { | ||
player.play().catch((error) => { | ||
console.error(error) | ||
}) | ||
} | ||
bar() | ||
``` | ||
* play() [optional property IPlayOptions] (default {}) **starts playback** of a sound, returns a promise that when resolved returns the current sound | ||
```ts | ||
IPlayOptions { | ||
whichSound: accepted values: song ID (number or string) OR one of these 4 constants: PlayerCore.PLAY_SOUND_NEXT, PlayerCore.PLAY_SOUND_PREVIOUS, PlayerCore.PLAY_SOUND_FIRST, PlayerCore.PLAY_SOUND_LAST | ||
playTimeOffset: the time at which you want the sound to start (in seconds), usually the song would start at zero but if you set this it will start at playTimeOffset | ||
} | ||
``` | ||
Note: the playTimeOffset (if set) will always get honored, so if you want to resume after a pause don't set the playTimeOffset, if playTimeOffset is set the song will start at the specified position, if no playTimeOffset is set the player will use the songs playTime value, which is 0 for a song that gets played for the first time or a value > 0 for a song that was paused | ||
* pause() **pauses playback**, returns a promise that when resolved returns the current sound | ||
* stop() **stops playback**, returns a promise that when resolved returns the current sound | ||
* next() used to play the **next** sound from the internal queue, returns a promise that when resolved returns the current sound | ||
* previous() used to play the **previous** sound from the internal queue, returns a promise that when resolved returns the current sound | ||
* first() used to play the **first** sound from the internal queue, returns a promise that when resolved returns the current sound | ||
* last() used to play the **last** sound from the internal queue, returns a promise that when resolved returns the current sound | ||
* addSoundToQueue() [ISoundsQueueOptions] (default { soundAttributes, whereInQueue? }) adds a new sound to the queue, it returns a sound (ISound) object | ||
* addSoundToQueue has a single parameter **soundsQueueOptions** is an object of type ISoundsQueueOptions, it has two properties **soundAttribtes** (object) and **whereInQueue** (string) | ||
* the soundAttribtes property you probably want to set is **source**, source is either a single ISoundSource object or an array of ISoundSource objects and the second property you may want to set is **id** (string or number), if you set it you will be able to play sounds by id, however if you don't set it the player will create an id | ||
* an ISoundSource object has two required properties **url** (string) and a **codec** (string), the third property **isPreferred** is optional, it can be used to tell the player which source is preferred (if you set two sources, one with the codec mp3 and another source for that same song but with the codec ogg and both codecs are supported then the player will take the one that is marked as preferred and if none is marked as preferred it will take the first one that has a codec which is supported) | ||
* the other property **whereInQueue** is optional and tells the player to put the sound at the beginning or the end of the queue, use the constants PlayerCore.WHERE_IN_QUEUE_AT_START or PlayerCore.WHERE_IN_QUEUE_AT_END, if you don't specify a constant the sound will be put at the end of the queue | ||
* for some sample code check out [building a simple player guide](#guide-to-building-a-simple-audio-player-ui) or for a working example have a look at [simple player example](./examples/simple-player/README.md) source code in the file bootstrap.ts, or use this basic example to get started: | ||
```ts | ||
const mySoundAttributes = { | ||
source: [{ url: 'https://example.com/mySound.mp3', codec: 'mp3' }], | ||
} | ||
player.addSoundToQueue({ soundAttributes: mySoundAttributes }) | ||
``` | ||
* resetQueue() (or reset()) removes all sounds from the queue | ||
* getQueue() returns the an array of sounds currently in the queue | ||
* setVolume(volume: number) sets to the volume in percent, so a number ranging from 0 to 100 | ||
* getVolume() returns the current volume | ||
* setLoopQueue(loppQueue: boolean) to let the player know it should loop the queue, meaning that after the last song in the queue finished playing it will play the first sound in the queue, set to false to just stop at the last song in queue | ||
* getLoopQueue() get the current boolean value to which **loopQueue** is set | ||
* mute() sets the volume to 0 | ||
* unMute() resets the volume to it's previous value | ||
* isMuted() a boolean value, true if the volume is currently muted else false | ||
* setPosition(soundPositionInPercent: number) used to change the position of the song that is currently playing in percent, so a number ranging from 0 to 100, returns a promise | ||
* setPositionInSeconds(soundPositionInSeconds: number): used to change the position of the song that is currently playing in seconds, the number should be smaller than the duration of the song, returns a promise | ||
* setVisibilityAutoMute(visibilityAutoMute: boolean) a boolean value to change the **visibilityAutoMute** option of the player, if true the player will be muted when the visibility API [MDN visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) notices that the browser is in the background, will get unmuted when the visibility API notices that the browser is in the foreground again, if false the volume will not be automatically muted when the visibility changes | ||
* getVisibilityAutoMute() get the current boolean value that is set for the **visibilityAutoMute** option | ||
* disconnect() disconnects the player and destroys all songs in the queue, this function should get called for example in react when a component unmounts, call this function when you don't need the player anymore to free memory | ||
* getAudioContext() get the current audioContext that is being used by the player [MDN audiocontext](https://developer.mozilla.org/en-US/docs/Web/API/AudioContext) | ||
### modes extended knowledge | ||
@@ -285,12 +365,4 @@ | ||
You can inject your own, if you want to reuse an existing one your app already created: | ||
You can inject your own using the **audioContext** [player option](#player-options), if you want to reuse an existing one your app already created | ||
TODO: add example | ||
You can also take the one created by the library and alter it the way you want: | ||
TODO: add example | ||
#### You can create and then inject your own AudioGraph (audio routing graph) | ||
This is especially useful if you want to add your own nodes to the AudioGraph (audio routing graph). For example you may want to add an [AnalyserNode](https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode) or a pannerNode, delayNode or any other node that is available in the web audio API. | ||
@@ -304,2 +376,3 @@ | ||
* [MDN "The Embed Audio element" page](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio) | ||
* [MDN webaudio examples repository on github](https://github.com/mdn/webaudio-examples/) | ||
* Support tables for audio features, [caniuse: web audio API / audio element / formats ...](https://caniuse.com/#search=audio) | ||
@@ -343,21 +416,2 @@ | ||
## notes about problems I encountered during development | ||
### web audio api typings notes | ||
As of the 25.05.2019 the web audio api typings seem to be included in lib.d.ts, so removing them from package.json: | ||
```json | ||
"dependencies": { | ||
"@types/webaudioapi": "0.0.27" | ||
}, | ||
``` | ||
Unfortunately (as of 06/2019) the defined window does not have AudioContext: | ||
* check out [github ticket](https://github.com/microsoft/TypeScript/issues/31686) | ||
* the current [dom.d.ts on github](https://github.com/microsoft/TypeScript/blob/master/src/lib/dom.generated.d.ts) | ||
This is fixed, as of now (20.02.2023) the AudioContext is now defined properly | ||
## Changelog | ||
@@ -389,25 +443,22 @@ | ||
* add a shuffle songs feature | ||
* add a loop song (<https://webaudio.github.io/web-audio-api/#looping-AudioBufferSourceNode>) feature (actually maybe this already works today, need to verify) | ||
* add a shuffle songs feature, I thought about adding a PLAY_SHUFFLE(D) option for the play() function but then only the first song would be a random pick, so the player itself needs a shuffle mode which also shuffles the next songs, you need to be able to turn it on / off at any time | ||
* add a loop song (<https://webaudio.github.io/web-audio-api/#looping-AudioBufferSourceNode>) feature (actually maybe this already works today, need to verify this), same for loop playlist (need to verify it works well before I remove this item from the TODOS) | ||
* we have sound events, but would player event be useful, like onVolumeChange? | ||
* allow to play starting at a certain position other then the beginning (or allow to set position while song is not playing? but probably not a good idea as sound is not loaded yet) | ||
* add (stereo) panning | ||
* use service worker to cache ajax requests when the player mode is ajax (audio buffer) <https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API> | ||
* it would probably be useful to have a duration change callback (onDurationChange) for songs | ||
* add sound option to set the initial gain value of a sound, for now it is always 1 (1 = no change to loudness), (optional method that lets you define a modifier (or coefficient) per song by which the gain will be changed), useful if some songs are louder than others and you want to normalize the volume of all songs in a playlist to be similar | ||
* add a song feature to fade out (current song) / fade in (next song) maybe two new options fadeInDuration and fadeOutDuration would be enough | ||
* instead of having sound properties like "isReadyToPLay, isBuffered, isBuffering" it would be better to use the SOUND_STATE_XXX constants | ||
* add (stereo) panning (maybe add an example of how to do it by injecting an audiocontext that has the panningnode attached already) <https://developer.mozilla.org/en-US/docs/Web/API/StereoPannerNode> | ||
* allow to add an array of sounds to queue all at once | ||
* allow to add sound to queue after a sound by id (not just at beginning or end, as it is as of now) | ||
* for position and volume, allow to use a percentage or a value, for volume (gain) allow values beyond 0 to 1 to amplify wave or invert it? | ||
* for volume (gain) allow values beyond 0 to 1 to amplify wave or invert it? | ||
* add improve UI style of the "simple" example(s) (or any new example) and then add a screenshot of it to the readme to show what can be achieved | ||
* destroy the audiocontext at some point, to release memory? | ||
* feature to use the browser notification system to alert which song is being played | ||
* preload AudioBuffers into indexeddb (first song, next song, current song if loop or previous is triggered ...), let the developer set the amount of preloaded AudioBuffers, remove from "cache" by least used and by date when "cache" is full, maybe do such work using this browser feature [requestidlecallback](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback) (when available) | ||
* cache songs for offline mode? indexeddb is not very big (filesystem?), check if doable because saving a playlist of songs might exhaust the free space (depending on the playlist size) | ||
* opt in feature to use the browser notification system to alert which song is being played (?) | ||
* preload ArrayBuffers (or the audio buffer instead of array buffer) into indexeddb (first song, next song, current song if loop or previous is triggered ...), let the developer set the amount of preloaded ArrayBuffers, remove from "cache" by least used and by date when "cache" is full, maybe do such work using this browser feature [requestidlecallback](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback) (when available) | ||
* cache songs for offline mode? indexeddb is not very big (filesystem?), check if doable because saving a playlist of songs might exhaust the free space (depending on the playlist size), maybe using service worker? | ||
* some methods return a promise others don't, use promises for all to make it more consistent? | ||
* write more documentation | ||
* make a list of all possible errors (set a distinct code for each error), handle all error cases that are still unhandled | ||
* [abort](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort) the loading of the sound if the user clicks play and then pause (or stop / next / previous) before the end of the buffering process | ||
* add new loadPlayerMode similar to XMLHttpRequest but that uses [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to get the sound / song data from server, fetch as of now is still young, it is not yet possible to get the loading progress (<https://stackoverflow.com/a/69400632/656689>) | ||
* add feature to crossfade two songs "on end" (if there is a the next song in a playlist) or just fade out (current song) / fade in (next song) | ||
* add sound option to set the initial gain value of a sound, for now it is always 1 (1 = no change to loudness), (optional method that lets you define a modifier (or coefficient) per song by which the gain will be changed), useful if some songs are louder than others and you want to normalize the volume of all songs in a playlist to be similar | ||
* currently the "find song in queue" can't retrieve songs by queue index, is this useful anyway? | ||
* use suspend and resume if for some time no sound was played? ... to free device resources. As suspend returns a promise, does this mean suspending and resuming takes time? if so how much time does it take, based on that information we can decide after how much time it makes sense to suspend the ctx to save device resources, should this be an event of the player so that user can attach a callback to show a dialog like netflix (still wathcing?) | ||
* use suspend (audioContext) if for some time no sound was played? (and then resume needed?) ... to free device resources. As suspend returns a promise, does this mean suspending and resuming takes time? if so how much time does it take, based on that information we can decide after how much time it makes sense to suspend the ctx to save device resources, should this be an event of the player so that user can attach a callback to show a dialog like netflix (still wathcing?) | ||
* use web workers, especially for the decoding of the ArrayBuffer into an AudioBuffer, to not block the main thread while decoding? | ||
@@ -419,4 +470,3 @@ * add support for more codecs? Note: the player should check which codecs are supported by the browser and compare that list with the ones defined in the sound sources, then the player should use the first codec that is supported and that is marked as "isPreferred", if none is marked as "isPreferred" use the first sources codec that is supported | ||
* add live demo (via github pages?) for people to see how the player works | ||
* add hooks to the sound object for all the native source node events [AudioBufferSourceNode](https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode) | ||
* create a react example | ||
* create a react example (vite server?) | ||
* create a vue.js example | ||
@@ -436,20 +486,23 @@ * create an example using the (browser) fileReader, something like: | ||
## note to self: publish package on npmjs.com | ||
## notes about problems I encountered during development | ||
login to npmjs.com | ||
### web audio api typings notes | ||
`npm login` | ||
As of the 25.05.2019 the web audio api typings seem to be included in lib.d.ts, so removing them from package.json: | ||
to make a publishing test (without actually publishing) use: | ||
```json | ||
"dependencies": { | ||
"@types/webaudioapi": "0.0.27" | ||
}, | ||
``` | ||
`npm publish --dry-run` | ||
Unfortunately (as of 06/2019) the defined window does not have AudioContext: | ||
!!! before using the next the command ensure the version of your package in the package.json has been updated | ||
* check out [github ticket](https://github.com/microsoft/TypeScript/issues/31686) | ||
* the current [dom.d.ts on github](https://github.com/microsoft/TypeScript/blob/master/src/lib/dom.generated.d.ts) | ||
publish a new version on npmjs | ||
This is fixed, as of now (20.02.2023) the AudioContext is now defined properly | ||
`npm publish` | ||
## License | ||
[MIT](LICENSE) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
331639
499
12
1642
1
1