API
0.3.0 の @debuffjp/earshot のすべてのエクスポートです。印のないものは 0.2 より前からあります。
サウンド
createListener
ts
function createListener(ctx: BaseAudioContext, options: ListenerOptions): Listener;
interface ListenerOptions {
output?: AudioNode;
tile?: number;
world?: World;
params?: Partial<Params>;
materials?: Record<string, Material>;
reverbs?: Record<string, Reverb>;
pos(): Point;
}
interface Listener {
readonly params: Params;
readonly materials: Record<string, Material>;
readonly reverbs: Record<string, Reverb>;
source(input: AudioNode, options: SourceOptions): Source;
voice(stream: MediaStream, options: VoiceOptions): Voice;
update(): void;
dispose(): void;
}voice は 0.2 で追加しました。リスナーを見てください。
World
ts
interface World {
wallsBetween?(a: Point, b: Point): readonly string[];
reverbAt?(p: Point): string | null | undefined;
}座標はタイル単位です。
Source
ts
interface SourceOptions { pos(): Point }
type SourceState = "audible" | "out-of-range" | "muted";
interface Source {
readonly state: SourceState;
readonly mix: Mix | null;
readonly reverb: string | null;
muted: boolean;
remove(): void;
}0.3 で変更:新しい音源はフェードインせず、最初からミックスどおりの状態で始まります。
Point, Material, Reverb, Params
ts
interface Point { x: number; y: number }
interface Material { hz: number; db: number }
interface Reverb { seconds: number; wetDb: number }
interface Params {
fullRadius: number;
silentRadius: number;
panWidth: number;
panRange: number;
smoothing: number;
multiWall: Material;
}デフォルト値
ts
const DEFAULT_PARAMS: Readonly<Params>;
const DEFAULT_MATERIALS: Readonly<Record<string, Material>>;
const DEFAULT_REVERBS: Readonly<Record<string, Reverb>>;wallsOnGrid
ts
function wallsOnGrid(tiles: ReadonlyArray<ReadonlyArray<string | null | undefined>>, a: Point, b: Point): string[];タイル座標の 2 点の間にある壁を返します。tiles[y][x] には素材の名前を入れるか、何も入れません。
wallsAlong
0.3 で追加しました。
ts
function wallsAlong(at: (x: number, y: number) => string | null | undefined, a: Point, b: Point): string[];入れ子の配列ではないマップ向けの wallsOnGrid です。
distanceGain
ts
function distanceGain(d: number, full: number, silent: number): number;full の内側で 1、silent からちょうど 0、その間は smoothstep です。
computeMix と Mix
ts
function computeMix(
listener: Point,
source: Point,
walls: readonly string[],
params: Params,
materials: Readonly<Record<string, Material>>,
): Mix;
interface Mix {
distance: number;
gain: number;
cutoff: number;
pan: number;
walls: readonly string[];
}判断の全体を数値で返します。座標はタイル単位です。未知の素材の壁が 1 枚だけあると例外を投げます。
ラウドネス
createLoudness
ts
function createLoudness(ctx: AudioContext, options?: LoudnessOptions): Loudness;
interface LoudnessOptions extends DetectorOptions {
calibrateMs?: number;
browserProcessing?: boolean;
}
interface Loudness {
readonly level: LoudLevel;
readonly micStatus: MicStatus;
readonly overFloorDb: number | null;
readonly applied: MediaTrackSettings | null;
press(level: LoudLevel): void;
enableMic(): Promise<MicResult>;
recalibrate(): Promise<void>;
disableMic(): void;
onLevel(callback: (level: LoudLevel) => void): () => void;
}
type LoudLevel = 0 | 1 | 2 | 3;
type MicStatus = "off" | "calibrating" | "on";
interface MicResult { ok: boolean; error?: string }ラウドネスを見てください。
createLevelDetector
ts
function createLevelDetector(options?: DetectorOptions): LevelDetector;
interface DetectorOptions {
steps?: readonly [number, number, number];
attackMs?: number;
releaseMs?: number;
hysteresisDb?: number;
}
interface LevelDetector {
readonly floor: number | null;
readonly level: LoudLevel;
calibrate(readings: readonly number[]): void;
update(db: number, dtMs: number): LoudLevel;
}heardDb
ts
function heardDb(level: number, mix: Pick<Mix, "gain">, levelDb?: readonly number[]): number;ある地点での音の大きさを dB で返します。levelDb のデフォルトは [-Infinity, 10, 20, 30] です。
ボイス
すべて 0.2 で追加しました。ボイスを見てください。
Voice 型
ts
interface VoiceOptions extends SourceOptions { speakingDb?: number }
interface Voice extends Source {
readonly levelDb: number;
readonly speaking: boolean;
}listener.voice() が返します。OfflineAudioContext では例外を投げます。
createVoiceMic
ts
function createVoiceMic(options: VoiceMicOptions): VoiceMic;
interface VoiceMicOptions {
canUseVoice(): boolean;
echoCancellation?: boolean | "all" | "remote-only";
pushToTalk?: boolean;
}
interface VoiceMic {
readonly stream: MediaStream | null;
readonly applied: MediaTrackSettings | null;
readonly live: boolean;
muted: boolean;
pushToTalk: boolean;
talk(held: boolean): void;
start(): Promise<MicResult>;
stop(): void;
}createRoomCode
ts
function createRoomCode(): string;128 ビットの乱数を URL セーフな base64 にしたものです。
joinVoiceRoom
ts
function joinVoiceRoom(options: VoiceRoomOptions): Promise<JoinResult>;
interface VoiceRoomOptions {
url: string;
code: string;
mic: VoiceMic;
listener: Listener;
ipPolicy: "relay" | "direct";
pos(peer: string): Point;
onPeer?(peer: string, voice: Voice): void;
onLeave?(peer: string): void;
onMessage?(peer: string, message: unknown): void;
}
interface VoiceRoom {
readonly id: string;
readonly peers: ReadonlyMap<string, Voice>;
connection(peer: string): RTCPeerConnectionState | null;
send(message: unknown): void;
leave(): void;
}
type JoinResult = { ok: true; room: VoiceRoom } | (MicResult & { ok: false; error: string });reject しません。接続とエラーを見てください。