UNPKG

@ekx/auph

Version:

[![Build](https://github.com/eliasku/auph/actions/workflows/build.yml/badge.svg)](https://github.com/eliasku/auph/actions/workflows/build.yml) [![Version](https://img.shields.io/npm/v/auph)](https://www.npmjs.com/package/auph) [![Downloads](https://img.sh

382 lines 12.3 kB
import { audioContextPause, audioContextResume, closeContext, getAudioContextObject, getContext, getContextState, initContext } from "./Mixer"; import { _getVoiceObj, _voiceApplyPitch, _voiceChangeDestination, _voicePrepareBuffer, _voiceSetLoop, _voiceSetRunning, _voiceStartBuffer, _voiceStop, createVoiceObj, voicePool } from "./Voice"; import { _getBus, _getBusGain, _setBusConnected, busLine, initBusPool, termBusPool } from "./Bus"; import { setError, warn } from "./debug"; import { DefaultBus, iMask, Mixer, tMask, Unit } from "../protocol/interface"; import { _buffer_set_callback, _bufferDestroy, _bufferLoad, _bufferMemory, _getBufferObj, buffers, getNextBufferObj } from "./Buffer"; import { connectAudioNode, len, resize, setAudioParamValue } from "./common"; export function setup() { var ctx = initContext(); if (ctx) { initBusPool(ctx); } } export function shutdown() { var ctx = getContext(); if (ctx) { termBusPool(); resize(voicePool, 1); resize(buffers, 1); closeContext(ctx); } } export function load(filepath, flags) { var handle = getNextBufferObj(); if (handle) { var ctx = getAudioContextObject(); if (!ctx) { setError(24 /* NotInitialized */); return 0; } var obj = buffers[handle & iMask]; _bufferLoad(obj, ctx, filepath, flags); } return handle; } export function loadMemory(data, flags) { var handle = getNextBufferObj(); if (handle) { var ctx = getAudioContextObject(); if (!ctx) { setError(24 /* NotInitialized */); return 0; } var obj = buffers[handle & iMask]; _bufferMemory(obj, ctx, data, flags); } return handle; } export function load_callback(p_callback, p_userdata) { var handle = getNextBufferObj(); if (handle) { var ctx = getAudioContextObject(); if (!ctx) { setError(24 /* NotInitialized */); return 0; } var obj = buffers[handle & iMask]; _buffer_set_callback(obj, ctx, p_callback, p_userdata); } return handle; } export function unload(name) { var obj = _getBufferObj(name); if (obj) { stop(name); _bufferDestroy(obj); } } /*** * * @param buffer * @param gain * @param pan * @param rate * @param flags * @param bus */ export function voice(buffer, gain, pan, rate, flags, bus) { // arguments check debug if (flags & ~(2 /* Running */ | 4 /* Loop */)) { setError(22 /* InvalidArguments */); return 0; } /// var ctx = getAudioContextObject(); if (!ctx || ctx.state !== "running") { setError(23 /* InvalidMixerState */, ctx === null || ctx === void 0 ? void 0 : ctx.state); return 0; } var bufferObj = _getBufferObj(buffer); if (!bufferObj) { setError(15 /* BufferNotFound */); return 0; } if (!(bufferObj.s & 2 /* Loaded */)) { setError(16 /* BufferIsNotLoaded */); return 0; } if (!bufferObj.b) { setError(17 /* BufferNoData */); return 0; } var targetNode = _getBusGain(bus ? bus : DefaultBus); if (!targetNode) { setError(21 /* BusNotFound */); return 0; } var voice = createVoiceObj(ctx); if (voice === 0) { setError(12 /* Warning_NoFreeVoices */); return 0; } var voiceObj = _getVoiceObj(voice); voiceObj.s = 1 /* Active */ | flags; voiceObj.bf = buffer; voiceObj.G = gain; voiceObj.P = pan; voiceObj.R = rate; setAudioParamValue(voiceObj.g.gain, gain / Unit); setAudioParamValue(voiceObj.p.pan, pan / Unit - 1); // TODO: streamed decoding //if (bufferObj.s & Flag.Stream) { if (bufferObj.s & 16 /* Callback */) { // const _play_next_chunk = () => { // _voicePrepareBuffer(voiceObj, ctx, bufferObj.b as AudioBuffer); // voiceObj.sn!.loop = false; // const ptr = _auph_read_to_buffer(bufferObj._u, bufferObj._f); // (bufferObj.b as AudioBuffer).copyToChannel(HEAPF32.subarray(ptr >>> 2, 8192 + (ptr >>> 2)), 0, 0); // (bufferObj.b as AudioBuffer).copyToChannel(HEAPF32.subarray(8192 + (ptr >>> 2), (2 * 8192) + (ptr >>> 2)), 1, 0); // voiceObj.sn!.onended = _play_next_chunk; // voiceObj.sn!.start(); // }; // _play_next_chunk(); //_voicePrepareBuffer(voiceObj, ctx, bufferObj.b as AudioBuffer); if (flags & 2 /* Running */) { // _voiceStartBuffer(voiceObj); voiceObj._s = 1; //voiceObj.sn!.loop = true; var processor = ctx.createScriptProcessor(8192, 0, 2); processor.onaudioprocess = function (ev) { // The output buffer contains the samples that will be modified and played var outputBuffer = ev.outputBuffer; // Loop through the output channels (in this case there is only one) var ptr = _auph_read_to_buffer(bufferObj._u, bufferObj._f); var output0 = outputBuffer.getChannelData(0); var output1 = outputBuffer.getChannelData(1); output0.set(HEAPF32.subarray(ptr >>> 2, 8192 + (ptr >>> 2))); output1.set(HEAPF32.subarray(8192 + (ptr >>> 2), (2 * 8192) + (ptr >>> 2))); }; //disconnectAudioNode(voiceObj.sn!, voiceObj.p); // connectAudioNode(voiceObj.sn!, processor); connectAudioNode(processor, voiceObj.p); //voiceObj.sn!.start(); voiceObj.pr = processor; } } else { _voicePrepareBuffer(voiceObj, ctx, bufferObj.b); if (flags & 2 /* Running */) { _voiceStartBuffer(voiceObj); } } // maybe we need to set target before `startBuffer()` _voiceChangeDestination(voiceObj, targetNode); _voiceApplyPitch(voiceObj, rate); return voice; } export function stop(name) { if (name === 0) { return; } var type = name & tMask; if (type === 805306368 /* Voice */) { var obj = _getVoiceObj(name); if (obj) { _voiceStop(obj); } } else if (type === 536870912 /* Buffer */) { var obj = _getBufferObj(name); if (obj) { for (var i = 1; i < len(voicePool); ++i) { var v = voicePool[i]; if (v.bf === name) { _voiceStop(v); } } } else { setError(15 /* BufferNotFound */); } } } export function set(name, param, value) { if (name === 0) { return; } if (name === Mixer && (param & 128 /* Flags */) && (param & 2 /* Running */)) { var ctx = getContext(); if (ctx) { if (value && ctx.state === "suspended") { audioContextResume(ctx); } else if (!value && ctx.state === "running") { audioContextPause(ctx); } } } var type = name & tMask; if (type === 805306368 /* Voice */) { var obj = _getVoiceObj(name); if (obj) { if (param & 128 /* Flags */) { var enabled = value !== 0; if (param & 2 /* Running */) { _voiceSetRunning(obj, enabled); } else if (param & 4 /* Loop */) { _voiceSetLoop(obj, enabled); } } else { if (param === 1 /* Gain */) { if (obj.G !== value) { obj.G = value; setAudioParamValue(obj.g.gain, value / Unit); } } else if (param === 2 /* Pan */) { if (obj.P !== value) { obj.P = value; setAudioParamValue(obj.p.pan, value / Unit - 1); } } else if (param === 3 /* Rate */) { if (obj.R !== value) { obj.R = value; _voiceApplyPitch(obj, value); } } else if (param === 4 /* CurrentTime */) { // TODO: } } } } else if (type === 268435456 /* Bus */) { var obj = _getBus(name); if (obj) { if (param & 128 /* Flags */) { if (param & 2 /* Running */) { _setBusConnected(obj, !!value); } } else { if (param === 1 /* Gain */) { if (obj.G !== value) { setAudioParamValue(obj.g.gain, value / Unit); obj.G = value; } } else { } } } } } export function get(name, param) { var result = 0; if (name === Mixer) { var ctx = getAudioContextObject(); if (ctx) { if (param === 0 /* State */) { result = getContextState(ctx); } else if (param === 5 /* SampleRate */) { result = ctx.sampleRate | 0; } } return result; } var type = name & tMask; if ((param & 256 /* Count */) && !(name & iMask)) { var stateMask = param & 127 /* StateMask */; if (type === 805306368 /* Voice */) { result = _countObjectsWithFlags(voicePool, stateMask); } else if (type === 268435456 /* Bus */) { result = _countObjectsWithFlags(busLine, stateMask); } else if (type === 536870912 /* Buffer */) { result = _countObjectsWithFlags(buffers, stateMask); } return result; } if (type === 805306368 /* Voice */) { var obj = _getVoiceObj(name); if (obj) { if (param === 0 /* State */) { result = obj.s; } else if (param === 1 /* Gain */) { result = obj.G; } else if (param === 2 /* Pan */) { result = obj.P; } else if (param === 3 /* Rate */) { result = obj.R; } else if (param === 6 /* Duration */) { if (obj.sn && obj.sn.buffer) { result = (obj.sn.buffer.duration * Unit) | 0; } } else if (param === 4 /* CurrentTime */) { if (obj.sn && obj.sn.buffer) { // TODO: :( } } else { warn(1 /* NotSupported */); } } return result; } if (type === 268435456 /* Bus */) { var obj = _getBus(name); if (obj) { if (param === 0 /* State */) { result = obj.s; } else if (param === 1 /* Gain */) { result = obj.G; } else { warn(1 /* NotSupported */); } } return result; } if (type === 536870912 /* Buffer */) { var obj = _getBufferObj(name); if (obj) { if (param === 0 /* State */) { result = obj.s; } else if (param === 6 /* Duration */) { if (obj.b) { result = (obj.b.duration * Unit) | 0; } } else { warn(1 /* NotSupported */); } } } return result; } export function vibrate(durationMillis) { try { if (navigator.vibrate) { return navigator.vibrate(durationMillis) ? 0 : 1; } } catch (_a) { } return 1; } /** private helpers **/ function _countObjectsWithFlags(arr, mask) { var cnt = 0; var size = len(arr); for (var i = 1; i < size; ++i) { var obj = arr[i]; if (obj && (obj.s & mask) === mask) { ++cnt; } } return cnt; } //# sourceMappingURL=index.js.map