* Normalize unvoiced RMS using peak normalization (BlueWizard RMSNormalizer.m lines 24-37) * Finds max RMS across all unvoiced frames and scales to unvoicedRMSLimit * IMPORTANT: Excludes SILENCE frames (RMS < silenceThreshold) from normalization to preserve them
(frames: FrameData[])
| 592 | * IMPORTANT: Excludes SILENCE frames (RMS < silenceThreshold) from normalization to preserve them |
| 593 | */ |
| 594 | private normalizeUnvoicedRMS(frames: FrameData[]): void { |
| 595 | // Find maximum RMS across all unvoiced frames (excluding SILENCE frames) |
| 596 | let max = 0.0; |
| 597 | for (const frame of frames) { |
| 598 | if ( |
| 599 | frame.reflector.isUnvoiced() && |
| 600 | frame.reflector.rms >= this.settings.silenceThreshold && |
| 601 | frame.reflector.rms > max |
| 602 | ) { |
| 603 | max = frame.reflector.rms; |
| 604 | } |
| 605 | } |
| 606 | |
| 607 | if (max <= 0.0) return; |
| 608 | |
| 609 | // Calculate scale factor to reach unvoicedRMSLimit |
| 610 | const limitIndex = Math.min(this.settings.unvoicedRmsLimit, this.codingTable.rms.length - 1); |
| 611 | const scale = this.codingTable.rms[limitIndex] / max; |
| 612 | |
| 613 | // Scale all unvoiced frames (excluding SILENCE frames) |
| 614 | for (const frame of frames) { |
| 615 | if (frame.reflector.isUnvoiced() && frame.reflector.rms >= this.settings.silenceThreshold) { |
| 616 | frame.reflector.rms = frame.reflector.rms * scale; |
| 617 | } |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | /** |
| 622 | * Apply unvoiced multiplier to all unvoiced frames (BlueWizard RMSNormalizer.m lines 39-44) |