How to Build Waveform Visualization with Peak and RMS Data in Clypra
Clypra generates waveform visualizations by creating buckets containing both peak and RMS amplitude values, then renders them using canvas utilities that support both thin peak bars and dense RMS fills.
Clypra is an open-source audio editing platform that provides precise visual feedback through dual-mode waveform rendering. To build waveform visualization with peak and RMS visualization in Clypra, you work with a bucket-based data structure that stores both instantaneous maximum levels and perceived loudness values. This architecture allows seamless switching between crisp peak indicators and dense RMS fills without regenerating underlying audio data.
Understanding the Waveform Data Model
The WaveformBucket Interface
According to the Clypra source code, the fundamental data structure is defined in src/types/index.ts as the WaveformBucket interface. Each bucket stores both amplitude measurements as a pair of floating-point values:
peak: The maximum absolute amplitude in the time window (instantaneous level)rms: The root-mean-square amplitude representing perceived loudness
This dual-storage approach enables the rendering layer to choose between visual styles without re-analyzing the source audio file.
Generating Buckets from Audio Files
The generateWaveform function in src/lib/audio/audioWaveformGenerator.ts processes audio files and returns an array of { peak, rms } objects. If the audio file cannot be processed, the generator falls back to a pseudo-random pattern while maintaining the same bucket structure.
// Generate waveform data when an audio file is imported
import { generateWaveform } from "../lib/audio/audioWaveformGenerator";
import type { WaveformBucket } from "../types";
async function getWaveform(path: string): Promise<WaveformBucket[]> {
// `generateWaveform` returns [{peak, rms}, …]
const buckets = await generateWaveform(path);
return buckets;
}
Rendering Peak and RMS Visualizations
Drawing Peak Bars with drawProfessionalWaveform
Located in src/lib/utils/canvasUtils.ts, the drawProfessionalWaveform function renders thin 1 px peak bars using the bucket.peak values. This creates the default visual style for audio clips, showing the maximum amplitude reached in each time window.
// Render the *peak* style in a React component
import { useEffect, useRef } from "react";
import { drawProfessionalWaveform } from "../lib/utils/canvasUtils";
interface Props {
buckets: WaveformBucket[];
colour?: string;
}
export function PeakWaveform({ buckets, colour = "#22d3ee" }: Props) {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
if (!canvasRef.current) return;
// Draw thin 1 px peak bars
drawProfessionalWaveform(canvasRef.current, buckets, colour);
}, [buckets, colour]);
return <canvas ref={canvasRef} width={300} height={60} />;
}
Converting Legacy RMS Data
For dense RMS visualization, the convertLegacyWaveform function (also in src/lib/utils/canvasUtils.ts) transforms RMS-only arrays into the standard WaveformBucket format. By treating the RMS values as peak amplitudes, you can reuse the same drawing routine while producing a filled waveform that reflects perceived loudness rather than instantaneous peaks.
// Render the *RMS* (dense) style
import { drawProfessionalWaveform, convertLegacyWaveform } from "../lib/utils/canvasUtils";
export function RmsWaveform({ rmsValues, colour }: { rmsValues: number[]; colour?: string }) {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
if (!canvasRef.current) return;
// Convert legacy RMS‑only array → {peak, rms}
const buckets = convertLegacyWaveform(rmsValues);
// Use the same drawing routine – RMS is now treated as the peak amplitude
drawProfessionalWaveform(canvasRef.current, buckets, colour ?? "#22d3ee");
}, [rmsValues, colour]);
return <canvas ref={canvasRef} width={300} height={60} />;
}
Implementation Summary
The Clypra waveform visualization pipeline follows three distinct stages:
- Analysis:
src/lib/audio/audioWaveformGenerator.tsanalyzes audio files and producesWaveformBucketarrays containing both peak and RMS values - Storage: The
WaveformBucketinterface insrc/types/index.tsensures type safety across the application - Rendering:
src/lib/utils/canvasUtils.tsprovidesdrawProfessionalWaveformfor peak visualization andconvertLegacyWaveformfor RMS compatibility
Summary
- Clypra stores dual amplitude values in each waveform bucket, allowing you to build waveform visualization with peak and RMS visualization without data regeneration
- Peak visualization uses
drawProfessionalWaveformdirectly with thin 1 px bars representing maximum instantaneous levels - RMS visualization requires
convertLegacyWaveformto transform RMS-only arrays into the bucket format, producing dense fills that reflect perceived loudness - Source files implementing this system include
src/lib/audio/audioWaveformGenerator.ts,src/types/index.ts, andsrc/lib/utils/canvasUtils.ts
Frequently Asked Questions
What is the difference between peak and RMS visualization in Clypra?
Peak visualization displays the maximum absolute amplitude reached in each time window using thin 1 px bars, showing instantaneous audio levels. RMS visualization displays root-mean-square values using dense fills, representing the perceived loudness and energy of the audio signal more accurately than peak levels alone.
How does Clypra handle audio files that cannot be processed?
When generateWaveform in src/lib/audio/audioWaveformGenerator.ts encounters an unreadable audio file, it automatically falls back to generating a pseudo-random pattern that maintains the same { peak, rms } bucket structure. This ensures the UI components can still render a representative waveform even when source analysis fails.
Can I switch between peak and RMS views without regenerating the waveform data?
Yes. Because the WaveformBucket interface stores both peak and rms values simultaneously, you can toggle between visualization styles by simply choosing which property to pass to the rendering function. For legacy RMS-only data, use convertLegacyWaveform in src/lib/utils/canvasUtils.ts to create compatible buckets without re-analyzing the audio file.
Which canvas utility should I use for legacy RMS-only data?
Use convertLegacyWaveform from src/lib/utils/canvasUtils.ts to transform legacy RMS-only arrays into the standard WaveformBucket format. This function maps the RMS values to both the peak and rms properties, allowing you to render dense RMS-style waveforms using the same drawProfessionalWaveform routine used for peak visualization.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →