danoniplus 49.0.0 → 49.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/danoni_main.js +74 -26
- package/package.json +1 -1
package/js/danoni_main.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Source by tickle
|
|
6
6
|
* Created : 2018/10/08
|
|
7
|
-
* Revised : 2026/
|
|
7
|
+
* Revised : 2026/07/02
|
|
8
8
|
*
|
|
9
9
|
* https://github.com/cwtickle/danoniplus
|
|
10
10
|
*/
|
|
11
|
-
const g_version = `Ver 49.
|
|
12
|
-
const g_revisedDate = `2026/
|
|
11
|
+
const g_version = `Ver 49.1.0`;
|
|
12
|
+
const g_revisedDate = `2026/07/02`;
|
|
13
13
|
|
|
14
14
|
// カスタム用バージョン (danoni_custom.js 等で指定可)
|
|
15
15
|
let g_localVersion = ``;
|
|
@@ -2514,7 +2514,7 @@ const drawTitleResultMotion = _displayName =>
|
|
|
2514
2514
|
// WebAudioAPIでAudio要素風に再生するクラス
|
|
2515
2515
|
class AudioPlayer {
|
|
2516
2516
|
constructor() {
|
|
2517
|
-
this._context =
|
|
2517
|
+
this._context = getSharedAudioContext();
|
|
2518
2518
|
this._gain = this._context.createGain();
|
|
2519
2519
|
this._gain.connect(this._context.destination);
|
|
2520
2520
|
this._startTime = 0;
|
|
@@ -2562,11 +2562,8 @@ class AudioPlayer {
|
|
|
2562
2562
|
}
|
|
2563
2563
|
|
|
2564
2564
|
close() {
|
|
2565
|
-
if (this._context) {
|
|
2566
|
-
this._context.close()?.catch(() => {/* ignore double-close */ });
|
|
2567
|
-
this._buffer = null;
|
|
2568
|
-
}
|
|
2569
2565
|
if (this._source) {
|
|
2566
|
+
this._source.stop(0);
|
|
2570
2567
|
this._source.disconnect(this._gain);
|
|
2571
2568
|
this._source = null;
|
|
2572
2569
|
}
|
|
@@ -2641,10 +2638,33 @@ class AudioPlayer {
|
|
|
2641
2638
|
this._eventListeners[_type] = this._eventListeners[_type].filter(_element => _element !== _listener);
|
|
2642
2639
|
}
|
|
2643
2640
|
|
|
2641
|
+
getBuffer() {
|
|
2642
|
+
return this._buffer;
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
setBuffer(_buffer) {
|
|
2646
|
+
this._buffer = _buffer;
|
|
2647
|
+
this._duration = _buffer.duration;
|
|
2648
|
+
this._eventListeners[`canplaythrough`]?.forEach(_listener => _listener());
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2644
2651
|
load() { }
|
|
2645
2652
|
dispatchEvent() { }
|
|
2646
2653
|
}
|
|
2647
2654
|
|
|
2655
|
+
// グローバルで1つだけ保持(遅延生成)
|
|
2656
|
+
let g_sharedAudioContext = null;
|
|
2657
|
+
const getSharedAudioContext = () => {
|
|
2658
|
+
if (!g_sharedAudioContext) {
|
|
2659
|
+
g_sharedAudioContext = new AudioContext();
|
|
2660
|
+
}
|
|
2661
|
+
// タブのバックグラウンド化等でsuspendedになることがあるため念のためresume
|
|
2662
|
+
if (g_sharedAudioContext.state === `suspended`) {
|
|
2663
|
+
g_sharedAudioContext.resume();
|
|
2664
|
+
}
|
|
2665
|
+
return g_sharedAudioContext;
|
|
2666
|
+
};
|
|
2667
|
+
|
|
2648
2668
|
/**
|
|
2649
2669
|
* クリップボードコピー関数
|
|
2650
2670
|
* 入力値をクリップボードへコピーし、メッセージを表示
|
|
@@ -6370,23 +6390,22 @@ const playBGM = async (_num, _currentLoopNum = g_settings.musicLoopNum) => {
|
|
|
6370
6390
|
|
|
6371
6391
|
if (encodeFlg) {
|
|
6372
6392
|
try {
|
|
6373
|
-
|
|
6374
|
-
if (
|
|
6375
|
-
|
|
6393
|
+
closeExistingAudio();
|
|
6394
|
+
if (g_audioBufferCache.has(url)) {
|
|
6395
|
+
const tmpAudio = new AudioPlayer();
|
|
6396
|
+
tmpAudio.setBuffer(g_audioBufferCache.get(url)); // 新設メソッド、decode不要
|
|
6397
|
+
g_audioForMS = tmpAudio;
|
|
6398
|
+
} else {
|
|
6376
6399
|
await loadScript2(url);
|
|
6377
6400
|
musicInit();
|
|
6378
|
-
if (!isTitle()) {
|
|
6379
|
-
|
|
6380
|
-
return;
|
|
6381
|
-
}
|
|
6401
|
+
if (!isTitle()) { g_musicdata = ``; return; }
|
|
6402
|
+
|
|
6382
6403
|
const tmpAudio = new AudioPlayer();
|
|
6383
|
-
const array =
|
|
6404
|
+
const array = base64ToUint8Array(g_musicdata);
|
|
6384
6405
|
await tmpAudio.init(array.buffer);
|
|
6385
|
-
if (!isTitle()) {
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
return;
|
|
6389
|
-
}
|
|
6406
|
+
if (!isTitle()) { g_musicdata = ``; tmpAudio.close(); return; }
|
|
6407
|
+
|
|
6408
|
+
cacheAudioBuffer(url, tmpAudio.getBuffer());
|
|
6390
6409
|
g_audioForMS = tmpAudio;
|
|
6391
6410
|
}
|
|
6392
6411
|
g_audioForMS.volume = g_stateObj.bgmVolume / 100;
|
|
@@ -11969,7 +11988,7 @@ const loadMusic = () => {
|
|
|
11969
11988
|
const blobUrl = URL.createObjectURL(request.response);
|
|
11970
11989
|
createEmptySprite(divRoot, `loader`, g_windowObj.loader);
|
|
11971
11990
|
lblLoading.textContent = g_lblNameObj.pleaseWait;
|
|
11972
|
-
setAudio(blobUrl);
|
|
11991
|
+
setAudio(blobUrl, url);
|
|
11973
11992
|
} else {
|
|
11974
11993
|
makeWarningWindow(`${g_msgInfoObj.E_0041.split('{0}').join(getFullPath(url))}<br>(${request.status} ${request.statusText})`, { backBtnUse: true });
|
|
11975
11994
|
}
|
|
@@ -12001,8 +12020,9 @@ const loadMusic = () => {
|
|
|
12001
12020
|
* 音楽データの設定
|
|
12002
12021
|
* iOSの場合はAudioタグによる再生
|
|
12003
12022
|
* @param {string} _url
|
|
12023
|
+
* @param {string} _cacheKey
|
|
12004
12024
|
*/
|
|
12005
|
-
const setAudio = async (_url) => {
|
|
12025
|
+
const setAudio = async (_url, _cacheKey = _url) => {
|
|
12006
12026
|
|
|
12007
12027
|
const loadMp3 = () => {
|
|
12008
12028
|
if (g_isFile) {
|
|
@@ -12034,7 +12054,7 @@ const setAudio = async (_url) => {
|
|
|
12034
12054
|
await loadScript2(_url);
|
|
12035
12055
|
if (typeof musicInit === C_TYP_FUNCTION) {
|
|
12036
12056
|
musicInit();
|
|
12037
|
-
readyToStart(() => initWebAudioAPIfromBase64(g_musicdata));
|
|
12057
|
+
readyToStart(() => initWebAudioAPIfromBase64(g_musicdata, _cacheKey));
|
|
12038
12058
|
} else {
|
|
12039
12059
|
makeWarningWindow(g_msgInfoObj.E_0031);
|
|
12040
12060
|
musicAfterLoaded();
|
|
@@ -12045,11 +12065,19 @@ const setAudio = async (_url) => {
|
|
|
12045
12065
|
};
|
|
12046
12066
|
|
|
12047
12067
|
// Base64から音声データに変換してWebAudioAPIで再生する準備
|
|
12048
|
-
const initWebAudioAPIfromBase64 = async (_base64) => {
|
|
12068
|
+
const initWebAudioAPIfromBase64 = async (_base64, _cacheKey) => {
|
|
12049
12069
|
g_audio = new AudioPlayer();
|
|
12050
12070
|
musicAfterLoaded();
|
|
12051
|
-
|
|
12071
|
+
|
|
12072
|
+
if (_cacheKey && g_audioBufferCache.has(_cacheKey)) {
|
|
12073
|
+
g_audio.setBuffer(g_audioBufferCache.get(_cacheKey)); // デコード完全スキップ
|
|
12074
|
+
return;
|
|
12075
|
+
}
|
|
12076
|
+
const array = base64ToUint8Array(_base64);
|
|
12052
12077
|
await g_audio.init(array.buffer);
|
|
12078
|
+
if (_cacheKey) {
|
|
12079
|
+
cacheAudioBuffer(_cacheKey, g_audio.getBuffer());
|
|
12080
|
+
}
|
|
12053
12081
|
};
|
|
12054
12082
|
|
|
12055
12083
|
// 音声ファイルを読み込んでWebAudioAPIで再生する準備
|
|
@@ -12061,6 +12089,26 @@ const initWebAudioAPIfromURL = async (_url) => {
|
|
|
12061
12089
|
await g_audio.init(arrayBuffer);
|
|
12062
12090
|
};
|
|
12063
12091
|
|
|
12092
|
+
const g_audioBufferCache = new Map();
|
|
12093
|
+
const AUDIO_CACHE_MAX = 5;
|
|
12094
|
+
|
|
12095
|
+
const cacheAudioBuffer = (_key, _buffer) => {
|
|
12096
|
+
g_audioBufferCache.set(_key, _buffer);
|
|
12097
|
+
if (g_audioBufferCache.size > AUDIO_CACHE_MAX) {
|
|
12098
|
+
g_audioBufferCache.delete(g_audioBufferCache.keys().next().value); // 古い順に破棄
|
|
12099
|
+
}
|
|
12100
|
+
};
|
|
12101
|
+
|
|
12102
|
+
const base64ToUint8Array = (_base64Str) => {
|
|
12103
|
+
const binaryStr = atob(_base64Str);
|
|
12104
|
+
const len = binaryStr.length;
|
|
12105
|
+
const array = new Uint8Array(len);
|
|
12106
|
+
for (let i = 0; i < len; i++) {
|
|
12107
|
+
array[i] = binaryStr.charCodeAt(i);
|
|
12108
|
+
}
|
|
12109
|
+
return array;
|
|
12110
|
+
};
|
|
12111
|
+
|
|
12064
12112
|
const musicAfterLoaded = () => {
|
|
12065
12113
|
g_audio.load();
|
|
12066
12114
|
|