@skyway-sdk/core
Version:
The official Next Generation JavaScript SDK for SkyWay
81 lines • 3.72 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AudioLevel = void 0;
/**@internal */
class AudioLevel {
constructor(audioStreamTrack) {
// ChromeのAudioLevelに近い挙動とするために取得範囲と更新周期を100msとする
this.LEVEL_RANGE_MS = 100;
// ChromeのAudioLevelに近い挙動とするために100ms毎に1/4減衰させる
this.DECAY_FACTOR = 0.25; // 1/4
this.DECAY_INTERVAL_MS = 100;
// 使用する環境によってサンプリングレートは8000〜48000Hzまで様々であるため、中間値24000Hzを想定したデフォルト値を設定する
this.DEFAULT_BUFFER_SIZE = 24000 * (this.LEVEL_RANGE_MS / 1000);
this.currentMaxLevel = 0;
this.audioContext = new AudioContext();
this.analyser = this.setupAnalyser(audioStreamTrack);
this.decayTimer = this.setDecayTimer();
}
[Symbol.dispose]() {
return __awaiter(this, void 0, void 0, function* () {
yield this.dispose();
});
}
calculate() {
// マイクの切り替えを考慮して毎回AudioContextからsampleRateを取得する
const sampleRate = this.audioContext.sampleRate;
// LEVEL_RANGE_MS分の音声サンプルを取得する
const duration = this.LEVEL_RANGE_MS / 1000;
const bufferLength = sampleRate
? sampleRate * duration
: this.DEFAULT_BUFFER_SIZE;
const timeDomainData = new Float32Array(bufferLength);
this.analyser.getFloatTimeDomainData(timeDomainData);
let level = Math.max(...timeDomainData);
// 大きな音が発生した場合その影響を残すために保持する
const _currentMaxLevel = this.currentMaxLevel;
if (level > _currentMaxLevel) {
this.currentMaxLevel = level;
}
else {
level = _currentMaxLevel;
}
return this.clamp(level, 0, 1);
}
setupAnalyser(audioStreamTrack) {
const mediaStream = new MediaStream([audioStreamTrack]);
const source = this.audioContext.createMediaStreamSource(mediaStream);
const analyser = this.audioContext.createAnalyser();
source.connect(analyser);
return analyser;
}
setDecayTimer() {
// 100ms毎に現在の最大レベルを減衰させて一時的なピークの影響を抑える
return setInterval(() => {
this.currentMaxLevel = this.currentMaxLevel * this.DECAY_FACTOR;
}, this.DECAY_INTERVAL_MS);
}
clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
dispose() {
return __awaiter(this, void 0, void 0, function* () {
if (this.decayTimer) {
clearInterval(this.decayTimer);
this.decayTimer = null;
}
yield this.audioContext.close();
});
}
}
exports.AudioLevel = AudioLevel;
//# sourceMappingURL=audioLevel.js.map