Audio Waveform Plot — Apache ECharts

A time-domain visualization of audio amplitude that displays the raw waveform shape as seen in digital audio workstations (DAWs). The plot shows positive and negative amplitude symmetrically around a zero baseline, with time on the x-axis and normalized amplitude (-1 to +1) on the y-axis. This is the fundamental representation for inspecting audio signals, revealing dynamics, clipping, silence, and transient characteristics at a glance.

Audio Waveform Plot rendered with Apache ECharts

Renders

JavaScript source (Apache ECharts)

// anyplot.ai
// waveform-audio: Audio Waveform Plot
// Library: echarts 5.5.1 | JavaScript 22.22.3
// Quality: 92/100 | Created: 2026-06-03
//# anyplot-orientation: landscape

const t = window.ANYPLOT_TOKENS;

// Inline RGB components for gradient stops (palette[0] = #009E73)
const waveColor = t.palette[0];
const wR = parseInt(waveColor.slice(1, 3), 16);
const wG = parseInt(waveColor.slice(3, 5), 16);
const wB = parseInt(waveColor.slice(5, 7), 16);

// Synthetic speech-like waveform: 5000 samples over 1 second
const N = 5000;
const duration = 1.0;
const rawData = [];

for (let i = 0; i < N; i++) {
    const time = (i / N) * duration;
    // Three Gaussian syllabic envelopes at 0.14 s, 0.47 s, 0.81 s
    const env1 = Math.exp(-32 * Math.pow(time - 0.14, 2));
    const env2 = Math.exp(-28 * Math.pow(time - 0.47, 2));
    const env3 = Math.exp(-38 * Math.pow(time - 0.81, 2));
    const envelope = (env1 + 0.88 * env2 + 0.72 * env3) * 0.85;
    // 175 Hz fundamental with four harmonics
    const f0 = 175;
    const carrier =
        0.48 * Math.sin(2 * Math.PI * f0 * time) +
        0.26 * Math.sin(2 * Math.PI * 2 * f0 * time) +
        0.14 * Math.sin(2 * Math.PI * 3 * f0 * time) +
        0.09 * Math.sin(2 * Math.PI * 4 * f0 * time) +
        0.03 * Math.sin(2 * Math.PI * 5 * f0 * time);
    rawData.push(Math.max(-1, Math.min(1, carrier * envelope)));
}

// Downsample to 300-bin min/max envelope to avoid aliasing
const BINS = 300;
const binSize = Math.floor(N / BINS);
const maxEnv = [], minEnv = [];
for (let b = 0; b < BINS; b++) {
    const start = b * binSize;
    const end = Math.min(start + binSize, N);
    const tCenter = ((start + end) / 2 / N) * duration;
    let bMax = -Infinity, bMin = Infinity;
    for (let k = start; k < end; k++) {
        if (rawData[k] > bMax) bMax = rawData[k];
        if (rawData[k] < bMin) bMin = rawData[k];
    }
    maxEnv.push([tCenter, bMax]);
    minEnv.push([tCenter, bMin]);
}

const chart = echarts.init(document.getElementById("container"));

chart.setOption({
    animation: false,
    backgroundColor: "transparent",
    title: {
        text: "waveform-audio · javascript · echarts · anyplot.ai",
        left: "center",
        top: 18,
        textStyle: { color: t.ink, fontSize: 22, fontWeight: "bold" }
    },
    grid: { left: 95, right: 50, top: 80, bottom: 85, containLabel: true },
    xAxis: {
        type: "value",
        name: "Time (s)",
        nameLocation: "middle",
        nameGap: 46,
        nameTextStyle: { color: t.inkSoft, fontSize: 18 },
        axisLabel: {
            color: t.inkSoft,
            fontSize: 14,
            formatter: (v) => (v === 0 ? "0" : v.toFixed(2))
        },
        axisLine: { show: true, lineStyle: { color: t.inkSoft } },
        axisTick: { lineStyle: { color: t.inkSoft } },
        splitLine: { show: false },
        min: 0,
        max: 1.0
    },
    yAxis: {
        type: "value",
        name: "Amplitude",
        nameLocation: "middle",
        nameGap: 52,
        nameTextStyle: { color: t.inkSoft, fontSize: 18 },
        axisLabel: {
            color: t.inkSoft,
            fontSize: 14,
            formatter: (v) => (v === 0 ? "0" : v.toFixed(1))
        },
        axisLine: { show: true, lineStyle: { color: t.inkSoft } },
        axisTick: { lineStyle: { color: t.inkSoft } },
        splitLine: { lineStyle: { color: t.grid } },
        min: -1.0,
        max: 1.0
    },
    series: [
        {
            // Upper envelope: max amplitude per bin
            type: "line",
            data: maxEnv,
            symbol: "none",
            smooth: false,
            lineStyle: { color: waveColor, width: 0.8, opacity: 0.9 },
            areaStyle: {
                origin: 0,
                color: {
                    type: "linear",
                    x: 0, y: 0, x2: 0, y2: 1,
                    colorStops: [
                        { offset: 0, color: `rgba(${wR},${wG},${wB},0.62)` },
                        { offset: 1, color: `rgba(${wR},${wG},${wB},0.05)` }
                    ]
                }
            },
            markLine: {
                silent: true,
                data: [{ yAxis: 0 }],
                lineStyle: { color: t.inkSoft, width: 1.5, type: "solid", opacity: 0.5 },
                label: { show: false },
                symbol: ["none", "none"]
            },
            markArea: {
                silent: true,
                label: {
                    show: true,
                    position: "insideTop",
                    color: t.inkSoft,
                    fontSize: 12
                },
                itemStyle: {
                    color: `rgba(${wR},${wG},${wB},0.07)`,
                    borderColor: `rgba(${wR},${wG},${wB},0.22)`,
                    borderWidth: 1
                },
                data: [
                    [{ name: "Syllable 1", xAxis: 0.05 }, { xAxis: 0.24 }],
                    [{ name: "Syllable 2", xAxis: 0.36 }, { xAxis: 0.58 }],
                    [{ name: "Syllable 3", xAxis: 0.70 }, { xAxis: 0.92 }]
                ]
            }
        },
        {
            // Lower envelope: min amplitude per bin
            type: "line",
            data: minEnv,
            symbol: "none",
            smooth: false,
            lineStyle: { color: waveColor, width: 0.8, opacity: 0.9 },
            areaStyle: {
                origin: 0,
                color: {
                    type: "linear",
                    x: 0, y: 0, x2: 0, y2: 1,
                    colorStops: [
                        { offset: 0, color: `rgba(${wR},${wG},${wB},0.05)` },
                        { offset: 1, color: `rgba(${wR},${wG},${wB},0.62)` }
                    ]
                }
            }
        }
    ]
});

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/waveform-audio/echarts/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "waveform-audio",
  "language": "javascript",
  "library": "echarts",
  "page": "https://anyplot.ai/waveform-audio/javascript/echarts",
  "hub": "https://anyplot.ai/waveform-audio",
  "code_json": "https://api.anyplot.ai/specs/waveform-audio/echarts/code",
  "spec_json": "https://api.anyplot.ai/specs/waveform-audio",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/waveform-audio/javascript/echarts/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/waveform-audio/javascript/echarts/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/waveform-audio/javascript/echarts/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/waveform-audio/javascript/echarts/plot-dark.html",
  "quality_score": 92.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Audio Waveform Plot on anyplot.ai.

Other implementations