Skip to content

Optimize audio buffer handling to avoid repeated copies#48

Open
wpflueger wants to merge 1 commit intomainfrom
fix/audio-buffer-optimization
Open

Optimize audio buffer handling to avoid repeated copies#48
wpflueger wants to merge 1 commit intomainfrom
fix/audio-buffer-optimization

Conversation

@wpflueger
Copy link
Owner

Summary

  • Replaced Buffer.concat([buffer, chunk]) on every PortAudio data event (O(n^2) worst-case) with a remainder-based approach
  • The new code only concatenates the small leftover bytes (always < 1 frame = 640 bytes) with incoming chunks, not the entire accumulated buffer
  • Functionally identical behavior — same frame extraction, same flush-on-stop logic

Test plan

  • Record a dictation and verify audio frames are sent correctly (transcription works)
  • Verify the remaining partial frame at end-of-stream is still flushed with silence padding
  • No regressions in audio quality or timing

Closes #35

🤖 Generated with Claude Code

Replace Buffer.concat([buffer, chunk]) on every data event with a
remainder-based approach. The old pattern copied the entire accumulated
buffer (~O(n^2)); the new approach only concatenates the small remainder
(always < one frame = 640 bytes) with the incoming chunk.

Closes #35

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 9, 2026 03:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Optimizes Electron audio capture buffering in createAudioStream to avoid repeated full-buffer concatenations on each PortAudio data event, reducing worst-case time complexity and copy overhead while preserving frame extraction and stop-flush behavior.

Changes:

  • Replaced “grow-the-entire-buffer” concatenation with a small remainder-based buffering approach.
  • Extracts frames via an offset into the current chunk (plus small remainder) and stores only leftover bytes for the next event.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +80 to +83
let offset = 0;
while (offset + frameBytes <= data.length) {
const frame = data.subarray(offset, offset + frameBytes);
offset += frameBytes;
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop will never terminate if frameBytes is 0 (e.g., options.frameMs <= 0 or options.channels <= 0), because offset never advances. Please add input validation (throw early) or guard here to ensure frameBytes > 0 before entering the while loop.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +95
// Keep only the leftover bytes (always < frameBytes)
remainder = offset < data.length ? data.subarray(offset) : Buffer.alloc(0);
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remainder is assigned as a subarray view into data. When data is chunk (or a large concat), this keeps the entire underlying buffer alive until the next data event even though only < frameBytes are needed. Consider copying the leftover bytes into a new small Buffer (bounded to < frameBytes) to avoid retaining potentially large backing buffers and to avoid relying on the lifetime/mutability of the native chunk buffer across async boundaries.

Suggested change
// Keep only the leftover bytes (always < frameBytes)
remainder = offset < data.length ? data.subarray(offset) : Buffer.alloc(0);
// Keep only the leftover bytes (always < frameBytes), copying them into a new Buffer
if (offset < data.length) {
const remaining = data.length - offset;
const newRemainder = Buffer.alloc(remaining);
data.copy(newRemainder, 0, offset, data.length);
remainder = newRemainder;
} else {
remainder = Buffer.alloc(0);
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimize audio buffer handling to avoid repeated copies

2 participants