@maddeye/pi-voice 1.0.0 → 1.1.0

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.
@@ -93,6 +93,11 @@ export function pcmToFloat32(frames: Int16Array[]): Float32Array {
93
93
  return audio;
94
94
  }
95
95
 
96
+ export function waveformBar(frame: Int16Array): string {
97
+ const rms = Math.sqrt(frame.reduce((sum, sample) => sum + sample * sample, 0) / frame.length) / 32768;
98
+ return rms <= 0.002 ? "·" : "▁▂▃▄▅▆▇█"[Math.min(7, Math.floor(rms * 400))];
99
+ }
100
+
96
101
  async function loadConfig(): Promise<VoiceConfig> {
97
102
  try {
98
103
  const raw = JSON.parse(await readFile(CONFIG_PATH, "utf8"));
@@ -160,6 +165,7 @@ async function record(ctx: ExtensionContext, config: VoiceConfig): Promise<Float
160
165
 
161
166
  const recorder = new PvRecorder(512, deviceIndex);
162
167
  const frames: Int16Array[] = [];
168
+ const waveform = Array(15).fill("·") as string[];
163
169
  let capturing = true;
164
170
  let captureFailure: unknown;
165
171
  let cleanupFailure: unknown;
@@ -176,7 +182,12 @@ async function record(ctx: ExtensionContext, config: VoiceConfig): Promise<Float
176
182
  recorder.start();
177
183
  capture = (async () => {
178
184
  try {
179
- while (capturing && frames.length * recorder.frameLength < maxSamples) frames.push(await recorder.read());
185
+ while (capturing && frames.length * recorder.frameLength < maxSamples) {
186
+ const frame = await recorder.read();
187
+ frames.push(frame);
188
+ waveform.push(waveformBar(frame));
189
+ waveform.shift();
190
+ }
180
191
  if (capturing) finish(true);
181
192
  } catch (error) {
182
193
  if (capturing) {
@@ -194,7 +205,7 @@ async function record(ctx: ExtensionContext, config: VoiceConfig): Promise<Float
194
205
  render(width: number) {
195
206
  const seconds = ((Date.now() - started) / 1000).toFixed(1);
196
207
  return [
197
- truncateToWidth(theme.fg("error", theme.bold(`● Recording ${seconds}s`)), width),
208
+ truncateToWidth(theme.fg("error", theme.bold(`${waveform.join("")} ${seconds}s`)), width),
198
209
  truncateToWidth(theme.fg("dim", "Enter stop and transcribe • Esc cancel"), width),
199
210
  ];
200
211
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maddeye/pi-voice",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Private, cross-platform voice prompt input for pi using local Whisper",
5
5
  "license": "MIT",
6
6
  "author": "maddeye",