Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 101 additions & 16 deletions js/rpg_core/WebAudio.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,17 @@ WebAudio.prototype.clear = function() {
this._sourceNode = null;
this._gainNode = null;
this._pannerNode = null;
this._partialArray = null;
this._wholeArray = null;
this._chunkGainRate = 5;
this._chunkSize = 75 * 1024;
this._loadedSize = 0;
this._totalTime = 0;
this._sampleRate = 0;
this._loopStart = 0;
this._loopLength = 0;
this._startTime = 0;
this._offset = 0;
this._volume = 1;
this._pitch = 1;
this._pan = 0;
Expand Down Expand Up @@ -357,7 +363,7 @@ Object.defineProperty(WebAudio.prototype, 'pan', {
* @return {Boolean} True if the audio data is ready to play
*/
WebAudio.prototype.isReady = function() {
return !!this._buffer;
return !!this._buffer && this._buffer.duration >= this._offset;
};

/**
Expand Down Expand Up @@ -388,8 +394,8 @@ WebAudio.prototype.isPlaying = function() {
* @param {Number} offset The start position to play in seconds
*/
WebAudio.prototype.play = function(loop, offset) {
this._offset = offset = offset || 0;
if (this.isReady()) {
offset = offset || 0;
this._startPlaying(loop, offset);
} else if (WebAudio._context) {
this._autoPlay = true;
Expand Down Expand Up @@ -504,6 +510,9 @@ WebAudio.prototype._load = function(url) {
var xhr = new XMLHttpRequest();
if(Decrypter.hasEncryptedAudio) url = Decrypter.extToEncryptExt(url);
xhr.open('GET', url);
if (typeof require === 'undefined') {
xhr.setRequestHeader('Range', 'bytes=' + this._loadedSize + '-' + (this._loadedSize + this._chunkSize - 1));
}
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
if (xhr.status < 400) {
Expand All @@ -521,21 +530,89 @@ WebAudio.prototype._load = function(url) {
* @private
*/
WebAudio.prototype._onXhrLoad = function(xhr) {
if (xhr.status === 206) {
this._onPartialLoad(xhr);
} else {
this._onWholeLoad(xhr.response);
}
};

/**
* @method _onPartialLoad
* @param {XMLHttpRequest} xhr
* @private
*/
WebAudio.prototype._onPartialLoad = function(xhr) {
var array = xhr.response;
if(Decrypter.hasEncryptedAudio) array = Decrypter.decryptArrayBuffer(array);
if (!this._partialArray) {
this._partialArray = new Uint8Array(+xhr.getResponseHeader('Content-Range').split('/').pop());
this._chunkSize *= this._chunkGainRate - 1;
} else {
this._chunkSize = this._partialArray.byteLength;
}
this._partialArray.set(new Uint8Array(array), this._loadedSize);
this._loadedSize += array.byteLength;
if (this._loadedSize < this._partialArray.byteLength) {
array = this._partialArray.buffer.slice(0, this._loadedSize);
this._load(this._url);
} else {
array = this._partialArray.buffer;
this._partialArray = null;
}
if (Decrypter.hasEncryptedAudio) {
array = Decrypter.decryptArrayBuffer(array);
}
this._readLoopComments(new Uint8Array(array));
WebAudio._context.decodeAudioData(array, function(buffer) {
WebAudio._context.decodeAudioData(array, this._onDecode.bind(this));
};

/**
* @method _onWholeLoad
* @param {ArrayBuffer} array
* @private
*/
WebAudio.prototype._onWholeLoad = function(array) {
if (array) {
if (Decrypter.hasEncryptedAudio) {
array = Decrypter.decryptArrayBuffer(array);
}
this._readLoopComments(new Uint8Array(array));
if (this._chunkSize < array.byteLength) {
this._wholeArray = array;
array = this._wholeArray.slice(0, this._chunkSize);
this._chunkSize *= this._chunkGainRate;
}
} else if (this._chunkSize < this._wholeArray.byteLength) {
array = this._wholeArray.slice(0, this._chunkSize);
this._chunkSize = this._wholeArray.byteLength;
} else {
array = this._wholeArray;
this._wholeArray = null;
}
WebAudio._context.decodeAudioData(array, this._onDecode.bind(this), function() {
this._onWholeLoad();
}.bind(this));
};

/**
* @method _onDecode
* @param {AudioBuffer} buffer
* @private
*/
WebAudio.prototype._onDecode = function(buffer) {
if (!this._buffer || this._buffer.length < buffer.length) {
this._buffer = buffer;
this._totalTime = buffer.duration;
if (this._loopLength > 0 && this._sampleRate > 0) {
this._loopStart /= this._sampleRate;
this._loopLength /= this._sampleRate;
} else {
this._loopStart = 0;
this._loopLength = this._totalTime;
if (this.isPlaying()) {
this._startPlaying(this._sourceNode.loop, this.seek());
}
this._onLoad();
}.bind(this));
if (this.isReady()) {
this._onLoad();
}
if (this._wholeArray) {
this._onWholeLoad();
}
}
};

/**
Expand Down Expand Up @@ -563,8 +640,10 @@ WebAudio.prototype._createNodes = function() {
var context = WebAudio._context;
this._sourceNode = context.createBufferSource();
this._sourceNode.buffer = this._buffer;
this._sourceNode.loopStart = this._loopStart;
this._sourceNode.loopEnd = this._loopStart + this._loopLength;
if (this._buffer.duration > this._loopStart) {
this._sourceNode.loopStart = this._loopStart;
this._sourceNode.loopEnd = this._loopStart + this._loopLength;
}
this._sourceNode.playbackRate.setValueAtTime(this._pitch, context.currentTime);
this._gainNode = context.createGain();
this._gainNode.gain.setValueAtTime(this._volume, context.currentTime);
Expand Down Expand Up @@ -650,8 +729,14 @@ WebAudio.prototype._onLoad = function() {
* @private
*/
WebAudio.prototype._readLoopComments = function(array) {
this._readOgg(array);
this._readMp4(array);
if (this._sampleRate === 0) {
this._readOgg(array);
this._readMp4(array);
if (this._loopLength > 0 && this._sampleRate > 0) {
this._loopStart /= this._sampleRate;
this._loopLength /= this._sampleRate;
}
}
};

/**
Expand Down
2 changes: 1 addition & 1 deletion js/rpg_managers/AudioManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ AudioManager.updateBufferParameters = function(buffer, configVolume, audio) {
};

AudioManager.audioFileExt = function() {
if (WebAudio.canPlayOgg() && !Utils.isMobileDevice()) {
if (WebAudio.canPlayOgg()) {
return '.ogg';
} else {
return '.m4a';
Expand Down
149 changes: 149 additions & 0 deletions plugins/Debug_ReportSound.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*:
* @plugindesc Show the process of loading sounds.
* @author RM CoreScript team
*
* @param chunkSize
* @type number
* @desc the size of first loading (KB)
* @default 75
*
* @param chunkGainRate
* @type number
* @desc the size of second loading (per chunkSize)
* @default 5
*
*/

/*:ja
* @plugindesc 音声読み込みの様子を表示します。
* @author RM CoreScript team
*
* @param chunkSize
* @type number
* @desc 一回目の分割読み込みのサイズ(KB)
* @default 75
*
* @param chunkGainRate
* @type number
* @desc 二回目の分割読み込みのサイズ(一回目の何倍のサイズかで表す)
* @default 5
*
*/

(function(){
'use strict';
function isNumber(str) {
return !!str && !isNaN(str);
}

function toNumber(str, def) {
return isNumber(str) ? +str : def;
}

function updateInfo() {
var loadTime = info.loadTime.map(function(time) {
return time < 0 ? '(progress)' : time;
});
var decodeTime = info.decodeTime.map(function(time) {
return time < 0 ? '(progress)' : time;
});
var content = 'name: ' + info.url + '<br>';
content += 'loadingMode: ' + info.loadingMode + '<br>';
content += 'loadTime: ' + loadTime + '<br>';
content += 'decodeTime: ' + decodeTime + '<br>';

if (div.innerHTML !== content) div.innerHTML = content;
div.style.zIndex = 11;
}

var parameters = PluginManager.parameters('Debug_ReportSound');
var chunkSize = toNumber(parameters['chunkSize'], 75) * 1024;
var chunkGainRate = toNumber(parameters['chunkGainRate'], 5);
var info;

var div = document.createElement('div');
div.style.backgroundColor = 'AliceBlue';
div.style.position = 'fixed';
div.style.right = 0;
div.style.bottom = 0;
document.body.appendChild(div);

var _WebAudio_clear = WebAudio.prototype.clear;
WebAudio.prototype.clear = function() {
_WebAudio_clear.apply(this, arguments);
info = {
fastLoadEnabled: !!this._chunkSize,
rangeEnabled: null,
loadingMode: '',
url: '',
loadTime: [],
decodeTime: []
};
this._chunkSize = chunkSize;
this._chunkGainRate = chunkGainRate;
};

var _WebAudio__load = WebAudio.prototype._load;
WebAudio.prototype._load = function(url) {
_WebAudio__load.apply(this, arguments);
info.url = info.url || url;
if (url === info.url) {
info.loadTime.push(-Date.now());
}
};

if (WebAudio.prototype._onPartialLoad && WebAudio.prototype._onWholeLoad && WebAudio.prototype._onDecode) {
var _WebAudio__onPartialLoad = WebAudio.prototype._onPartialLoad;
WebAudio.prototype._onPartialLoad = function(xhr) {
if (this._url === info.url) {
info.loadingMode = 'Range Enabled<br>(load & decode multiply)';
info.loadTime[info.loadTime.length - 1] += Date.now();
info.decodeTime.push(-Date.now());
updateInfo();
}
_WebAudio__onPartialLoad.apply(this, arguments);
};

var _WebAudio__onWholeLoad = WebAudio.prototype._onWholeLoad;
WebAudio.prototype._onWholeLoad = function(array) {
if (this._url === info.url) {
info.loadingMode = 'Range Disabled<br>(load once, decode multiply)';
if (info.decodeTime.length === 0) {
info.loadTime[0] += Date.now();
}
info.decodeTime.push(-Date.now());
updateInfo();
}
_WebAudio__onWholeLoad.apply(this, arguments);
};

var _WebAudio__onDecode = WebAudio.prototype._onDecode;
WebAudio.prototype._onDecode = function(buffer) {
if (this._url === info.url && info.decodeTime[info.decodeTime.length - 1] < 0) {
info.decodeTime[info.decodeTime.length - 1] += Date.now();
updateInfo();
}
_WebAudio__onDecode.apply(this, arguments);
};
} else {
var _WebAudio__onXhrLoad = WebAudio.prototype._onXhrLoad;
WebAudio.prototype._onXhrLoad = function(xhr) {
if (this._url === info.url) {
info.loadingMode = 'Legacy<br>(load & decode once)';
info.loadTime[0] += Date.now();
info.decodeTime.push(-Date.now());
updateInfo();
}
_WebAudio__onXhrLoad.apply(this, arguments);
};

var _WebAudio__onLoad = WebAudio.prototype._onLoad;
WebAudio.prototype._onLoad = function() {
if (this._url === info.url && info.decodeTime[info.decodeTime.length - 1] < 0) {
info.decodeTime[info.decodeTime.length - 1] += Date.now();
updateInfo();
}
_WebAudio__onLoad.apply(this, arguments);
};
}
})();