Conversation
- Modify `JsPreprocessor.computeRawMel` to accept `startFrame` to skip redundant STFT/Mel computations for cached prefixes. - Update `IncrementalMelProcessor.process` to utilize `startFrame` for a ~3x speedup in streaming scenarios (26ms vs 78ms). - Refactor `IncrementalMelProcessor.process` non-cached path to avoid double computation, yielding a ~2x speedup (78ms vs 153ms). Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
📝 WalkthroughWalkthroughThe changes enable partial Mel feature extraction by adding an optional Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)✅ Unit Test PR creation complete.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/mel.js (1)
556-578:⚠️ Potential issue | 🟡 MinorPotential out-of-bounds cache copy if the audio window shrinks between calls.
safeFramesis bounded bythis._cachedFeaturesLen(from the previous call), but the new call'snFramescould be smaller if the current audio is shorter. In that case, the copy loop at lines 575–576 writes torawMel[m * nFrames + t]wheretcan reachsafeFrames - 1 >= nFrames, silently overwriting the start of the next mel bin's row in the flat array (or writing past the end for the last bin). In JavaScript typed arrays, indices beyond the buffer length are silently ignored, so there's no crash — but the resulting features would be silently corrupted.If the streaming contract guarantees non-shrinking windows, a comment or assertion documenting that assumption would be valuable. Otherwise, clamp
safeFramesagainst the newnFrames/featuresLen.🛡️ Proposed fix — clamp safeFrames against the new frame count
const { rawMel, nFrames, featuresLen } = this.preprocessor.computeRawMel(audio, safeFrames); + // Ensure safeFrames doesn't exceed new frame dimensions + const clampedSafeFrames = Math.min(safeFrames, featuresLen, nFrames); + // Replace first safeFrames with cached values (they're identical) - if (safeFrames > 0 && this._cachedRawMel) { + if (clampedSafeFrames > 0 && this._cachedRawMel) { for (let m = 0; m < this.nMels; m++) { const srcBase = m * this._cachedNFrames; const dstBase = m * nFrames; - for (let t = 0; t < safeFrames; t++) { + for (let t = 0; t < clampedSafeFrames; t++) { rawMel[dstBase + t] = this._cachedRawMel[srcBase + t]; } } }Also update the return value to use
clampedSafeFramesfor thecachedFramesandnewFramescounts.
🧹 Nitpick comments (2)
src/mel.js (2)
359-398: Consider adding a bounds check forstartFrame.If a caller passes a
startFramethat exceedsnFrames, the loop silently produces an all-zerorawMel. A negativestartFramewould causeoffset = t * HOP_LENGTHto index intopaddedat negative offsets, producingNaN. While current internal callers always pass a non-negative, bounded value (viaMath.max(0, ...)), a defensive clamp would protect this public method.🛡️ Proposed defensive clamp
computeRawMel(audio, startFrame = 0) { + startFrame = Math.max(0, Math.min(startFrame, Number.MAX_SAFE_INTEGER)); const N = audio.length;And after
nFramesis computed:const nFrames = Math.floor((paddedLen - N_FFT) / HOP_LENGTH) + 1; const featuresLen = Math.floor(N / HOP_LENGTH); + startFrame = Math.min(startFrame, nFrames);
497-502:reset()andclear()are identical — consider removing one.Both methods set the exact same four fields to the same default values. Having two public methods with the same behavior is confusing for consumers. Consider keeping one (e.g.,
reset()) and removing the other, or having one delegate to the other.Also applies to: 606-611
|
Note Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it. Generating unit tests... This may take up to 20 minutes. |
1 similar comment
|
Note Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it. Generating unit tests... This may take up to 20 minutes. |
|
Failed to clone repository into sandbox. |
|
Note Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it. Generating unit tests... This may take up to 20 minutes. |
|
Failed to clone repository into sandbox. |
|
✅ Created PR with unit tests: #33 |
ysdede
left a comment
There was a problem hiding this comment.
Summary: Adds startFrame support and avoids double compute in incremental mel; full path now normalizes raw mel once.
Recommendation: Ready to merge.
Tests: npm test
|
Handled in PR#34 (release branch). Closing superseded PR. |
Understood. Acknowledging that this work is now superseded by PR#34 and stopping work on this task. |
This PR optimizes the
IncrementalMelProcessorinsrc/mel.jsto significantly improve performance for streaming audio processing.Key Changes
JsPreprocessor.computeRawMel: Added astartFrameparameter. When provided, the STFT/Mel loop starts from this frame index, leaving earlier frames as zeros (which are later filled from cache). This avoids recomputing frames that are already known.IncrementalMelProcessor.process(Incremental Path): When a valid cache prefix is found (safeFrames > 0),computeRawMelis called withstartFrame = safeFrames. This skips the heavy computation for the overlapping part of the window.IncrementalMelProcessor.process(Full Path): Refactored the logic when no cache is available. Previously, it calledprocess(compute features) ANDcomputeRawMel(compute raw for cache), doubling the work. Now it computes raw mel once, normalizes it, and updates the cache.Performance Impact
Benchmarks on
tests/mel.test.mjsshow significant improvements:These changes make the processor much more efficient for real-time applications.
PR created automatically by Jules for task 5930782711649377570 started by @ysdede
Summary by CodeRabbit
New Features
Performance Improvements