@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 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
@@ -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.
@@ -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.
@@ -0,0 +1,3 @@
1
+ export declare class MicLimitError extends Error {
2
+ constructor(message?: string);
3
+ }
@@ -0,0 +1,6 @@
1
+ export class MicLimitError extends Error {
2
+ constructor(message = "Maximum of 5 mic modules can be active simultaneously") {
3
+ super(message);
4
+ this.name = "MicLimitError";
5
+ }
6
+ }
@@ -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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo2555/koppeliajs",
3
- "version": "0.0.172",
3
+ "version": "0.0.174",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run package",