@momo2555/koppeliajs 0.0.172 → 0.0.174
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/README.md +80 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -1
- package/dist/scripts/device.d.ts +22 -0
- package/dist/scripts/device.js +49 -0
- package/dist/scripts/errors.d.ts +3 -0
- package/dist/scripts/errors.js +6 -0
- package/dist/scripts/koppelia.js +2 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -151,6 +151,13 @@ The `Device` class is your bridge to the physical world. Instead of dealing with
|
|
|
151
151
|
* `onCursor(callback(x, y))`: Translates IMU spatial movement into 2D coordinates.
|
|
152
152
|
* `onBiking(callback(speed))`: Reads data if the modular controller is clipped to a physical exercise bike pedal.
|
|
153
153
|
|
|
154
|
+
**Available Microphone Methods:**
|
|
155
|
+
* `enableMic()`: Enables real-time microphone streaming for this device. Returns a `Promise<void>`.
|
|
156
|
+
* `disableMic()`: Stops microphone streaming and removes the audio sink from Maestro.
|
|
157
|
+
* `setMicConfig({ volume, effect, intensity })`: Updates playback volume and optional voice effects.
|
|
158
|
+
|
|
159
|
+
Filarmonic enforces a maximum of 5 active microphones at the same time. If the limit is reached, `enableMic()` rejects with `MicLimitError`.
|
|
160
|
+
|
|
154
161
|
#### Example
|
|
155
162
|
```typescript
|
|
156
163
|
import { Koppelia, Device } from "@momo2555/koppeliajs";
|
|
@@ -182,6 +189,78 @@ koppelia.onReady(async () => {
|
|
|
182
189
|
|
|
183
190
|
---
|
|
184
191
|
|
|
192
|
+
### 3.1. Real-Time Microphone Streaming
|
|
193
|
+
|
|
194
|
+
#### How it works & Capabilities
|
|
195
|
+
The controller microphone can be streamed in real time to the console speakers. This is designed for games where the animator wants to temporarily amplify a resident, apply a playful voice effect, or create call-and-response mechanics.
|
|
196
|
+
|
|
197
|
+
The audio path is intentionally low-latency:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
nRF52840 controller mic -> BLE audio characteristic -> AllegroLink -> UDP -> Maestro -> speakers
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Filarmonic stays in the control path, not the audio path. It enables/disables the mic module, enforces the 5-mic limit, and forwards configuration commands to Maestro. The audio itself bypasses Filarmonic to avoid extra latency.
|
|
204
|
+
|
|
205
|
+
**Configuration:**
|
|
206
|
+
* `volume`: Number from `0` to `100`.
|
|
207
|
+
* `effect`: `"echo"`, `"reverb"`, or `null`.
|
|
208
|
+
* `intensity`: Number from `0.0` to `1.0`.
|
|
209
|
+
|
|
210
|
+
Use microphone audio carefully in games: TV speakers can feed back into the controller microphone if the device is too close to the sound output. Prefer short push-to-talk interactions, moderate volume, and no effect by default.
|
|
211
|
+
|
|
212
|
+
#### Example
|
|
213
|
+
```typescript
|
|
214
|
+
import { Koppelia, Device, MicLimitError, type MicConfig } from "@momo2555/koppeliajs";
|
|
215
|
+
|
|
216
|
+
let koppelia = Koppelia.instance;
|
|
217
|
+
|
|
218
|
+
koppelia.onReady(async () => {
|
|
219
|
+
const devices: Device[] = await koppelia.getDevices();
|
|
220
|
+
const device = devices[0];
|
|
221
|
+
|
|
222
|
+
const config: MicConfig = {
|
|
223
|
+
volume: 70,
|
|
224
|
+
effect: null,
|
|
225
|
+
intensity: 0.5,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
await device.enableMic();
|
|
230
|
+
device.setMicConfig(config);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (error instanceof MicLimitError) {
|
|
233
|
+
console.warn("Too many microphones are already active.");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Stop streaming when the microphone is no longer needed.
|
|
240
|
+
setTimeout(() => {
|
|
241
|
+
device.disableMic();
|
|
242
|
+
}, 10000);
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### Push-To-Talk Pattern
|
|
247
|
+
For most games, prefer a short-lived mic session controlled by the animator:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
async function startTalking(device: Device) {
|
|
251
|
+
await device.enableMic();
|
|
252
|
+
device.setMicConfig({ volume: 60, effect: null });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function stopTalking(device: Device) {
|
|
256
|
+
device.disableMic();
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Avoid leaving multiple microphones open during normal gameplay. If you use `"echo"` or `"reverb"`, keep `volume` lower because effects increase the risk of acoustic feedback.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
185
264
|
### 4. Remote Procedure Calls (`CustomCallbacks`)
|
|
186
265
|
|
|
187
266
|
#### How it works & Capabilities
|
|
@@ -465,4 +544,4 @@ Here is a comprehensive example demonstrating how Routing, State, Hardware, and
|
|
|
465
544
|
padding: 20px;
|
|
466
545
|
}
|
|
467
546
|
</style>
|
|
468
|
-
```
|
|
547
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -7,10 +7,13 @@ import { Koppelia } from "./scripts/koppelia.js";
|
|
|
7
7
|
import { Console } from "./scripts/console.js";
|
|
8
8
|
import { Message } from "./scripts/message.js";
|
|
9
9
|
import { Device } from "./scripts/device.js";
|
|
10
|
+
import { MicLimitError } from "./scripts/errors.js";
|
|
10
11
|
import { Play } from "./scripts/play.js";
|
|
11
12
|
import { Resident } from "./scripts/resident.js";
|
|
12
13
|
import { Song } from "./scripts/song.js";
|
|
14
|
+
import type { MicConfig, MicEffect } from "./scripts/device.js";
|
|
13
15
|
import { updateRoute, routeType } from './stores/routeStore.js';
|
|
14
16
|
import { audioManager, AudioManager } from './stores/audioManager.js';
|
|
15
17
|
export { KBase, GrowableElement, Button, ResizableText };
|
|
16
|
-
export { updateRoute, routeType, Koppelia, Console, Message, Device, Play, Song, audioManager, Resident, AudioManager };
|
|
18
|
+
export { updateRoute, routeType, Koppelia, Console, Message, Device, Play, Song, audioManager, Resident, AudioManager, MicLimitError };
|
|
19
|
+
export type { MicConfig, MicEffect };
|
package/dist/index.js
CHANGED
|
@@ -8,10 +8,11 @@ import { Koppelia } from "./scripts/koppelia.js";
|
|
|
8
8
|
import { Console } from "./scripts/console.js";
|
|
9
9
|
import { Message } from "./scripts/message.js";
|
|
10
10
|
import { Device } from "./scripts/device.js";
|
|
11
|
+
import { MicLimitError } from "./scripts/errors.js";
|
|
11
12
|
import { Play } from "./scripts/play.js";
|
|
12
13
|
import { Resident } from "./scripts/resident.js";
|
|
13
14
|
import { Song } from "./scripts/song.js";
|
|
14
15
|
import { updateRoute, routeType } from './stores/routeStore.js';
|
|
15
16
|
import { audioManager, AudioManager } from './stores/audioManager.js';
|
|
16
17
|
export { KBase, GrowableElement, Button, ResizableText }; // Compoenents
|
|
17
|
-
export { updateRoute, routeType, Koppelia, Console, Message, Device, Play, Song, audioManager, Resident, AudioManager }; // libraries and store
|
|
18
|
+
export { updateRoute, routeType, Koppelia, Console, Message, Device, Play, Song, audioManager, Resident, AudioManager, MicLimitError }; // libraries and store
|
package/dist/scripts/device.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ type Color = {
|
|
|
7
7
|
lon?: number;
|
|
8
8
|
loff?: number;
|
|
9
9
|
};
|
|
10
|
+
export type MicEffect = "echo" | "reverb" | null;
|
|
11
|
+
export type MicConfig = {
|
|
12
|
+
volume: number;
|
|
13
|
+
effect?: MicEffect;
|
|
14
|
+
intensity?: number;
|
|
15
|
+
};
|
|
10
16
|
/**
|
|
11
17
|
* Represents a physical or logical device connected to the console.
|
|
12
18
|
* Handles device-specific commands like LEDs, vibrations, and hardware module subscriptions.
|
|
@@ -61,6 +67,22 @@ export declare class Device {
|
|
|
61
67
|
* @param moduleName The name of the module to enable (Note: retains original code spelling).
|
|
62
68
|
*/
|
|
63
69
|
private _enableModule;
|
|
70
|
+
/**
|
|
71
|
+
* Enables the microphone module on this device.
|
|
72
|
+
* Filarmonic enforces a maximum of 5 simultaneous mic modules.
|
|
73
|
+
* @throws {MicLimitError} if the 5-mic limit has been reached.
|
|
74
|
+
*/
|
|
75
|
+
enableMic(): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Disables the microphone module on this device and removes its audio sink in Maestro.
|
|
78
|
+
*/
|
|
79
|
+
disableMic(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Configures the audio sink for this device's microphone.
|
|
82
|
+
* Must be called after enableMic() succeeds.
|
|
83
|
+
* @param config The microphone sink configuration.
|
|
84
|
+
*/
|
|
85
|
+
setMicConfig(config: MicConfig): void;
|
|
64
86
|
/**
|
|
65
87
|
* Changes the current LED color of the device.
|
|
66
88
|
* @param color The RGB color configuration to apply.
|
package/dist/scripts/device.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Console } from "./console.js";
|
|
2
|
+
import { MicLimitError } from "./errors.js";
|
|
2
3
|
import { Message, MessageType, PeerType } from "./message.js";
|
|
3
4
|
import { Resident } from "./resident.js";
|
|
4
5
|
/**
|
|
@@ -133,6 +134,54 @@ export class Device {
|
|
|
133
134
|
request.setRequest("enableModule");
|
|
134
135
|
this._console.sendMessage(request);
|
|
135
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Enables the microphone module on this device.
|
|
139
|
+
* Filarmonic enforces a maximum of 5 simultaneous mic modules.
|
|
140
|
+
* @throws {MicLimitError} if the 5-mic limit has been reached.
|
|
141
|
+
*/
|
|
142
|
+
enableMic() {
|
|
143
|
+
return new Promise((resolve, reject) => {
|
|
144
|
+
let request = new Message();
|
|
145
|
+
request.addParam("module", "mic");
|
|
146
|
+
request.setDestination(PeerType.DEVICE, this._address);
|
|
147
|
+
request.setRequest("enableModule");
|
|
148
|
+
this._console.sendMessage(request, (response) => {
|
|
149
|
+
if (response.getType() === MessageType.ERROR) {
|
|
150
|
+
const errMsg = response.getParam("error") ?? "Failed to enable mic module";
|
|
151
|
+
reject(new MicLimitError(errMsg));
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
resolve();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Disables the microphone module on this device and removes its audio sink in Maestro.
|
|
161
|
+
*/
|
|
162
|
+
disableMic() {
|
|
163
|
+
let request = new Message();
|
|
164
|
+
request.addParam("module", "mic");
|
|
165
|
+
request.setDestination(PeerType.DEVICE, this._address);
|
|
166
|
+
request.setRequest("disableModule");
|
|
167
|
+
this._console.sendMessage(request);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Configures the audio sink for this device's microphone.
|
|
171
|
+
* Must be called after enableMic() succeeds.
|
|
172
|
+
* @param config The microphone sink configuration.
|
|
173
|
+
*/
|
|
174
|
+
setMicConfig(config) {
|
|
175
|
+
let request = new Message();
|
|
176
|
+
request.setDestination(PeerType.DEVICE, this._address);
|
|
177
|
+
request.setRequest("setMicConfig");
|
|
178
|
+
request.addParam("volume", config.volume);
|
|
179
|
+
if (config.effect !== undefined)
|
|
180
|
+
request.addParam("effect", config.effect);
|
|
181
|
+
if (config.intensity !== undefined)
|
|
182
|
+
request.addParam("intensity", config.intensity);
|
|
183
|
+
this._console.sendMessage(request);
|
|
184
|
+
}
|
|
136
185
|
/**
|
|
137
186
|
* Changes the current LED color of the device.
|
|
138
187
|
* @param color The RGB color configuration to apply.
|
package/dist/scripts/koppelia.js
CHANGED
|
@@ -303,11 +303,8 @@ export class Koppelia {
|
|
|
303
303
|
getCurrentPlaysRequest.setRequest("getCurrentPlays");
|
|
304
304
|
getCurrentPlaysRequest.setDestination(PeerType.MASTER, "");
|
|
305
305
|
this._console.sendMessage(getCurrentPlaysRequest, (response) => {
|
|
306
|
-
let playsRawList = response.getParam("plays",
|
|
307
|
-
let plays =
|
|
308
|
-
for (let playId in playsRawList) {
|
|
309
|
-
plays.push(new Play(this._console, playId, playsRawList[playId]));
|
|
310
|
-
}
|
|
306
|
+
let playsRawList = response.getParam("plays", []);
|
|
307
|
+
let plays = playsRawList.map((playData) => new Play(this._console, playData.id, playData));
|
|
311
308
|
resolve(plays);
|
|
312
309
|
});
|
|
313
310
|
});
|