Skip to main content
RapidDev - Software Development Agency
App Featuresscanning-devices19 min read

How to Add Noise Level Detection to Your App (Copy-Paste Prompts Included)

Noise level detection uses the browser's Web Audio API (or the noise_meter Flutter package on mobile) to read microphone amplitude, convert it to dBFS, and display a live meter. The whole client-side stack is free — Web Audio API is built into every modern browser, no library purchase required. Costs appear only if you log session data to Supabase (free tier handles most volumes) or need background monitoring on native mobile (requires custom dev).

4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members

Feature spec

Intermediate

Category

scanning-devices

Build with AI

4–8 hours with Lovable

Custom build

4–7 days custom dev

Running cost

$0/mo (client-side only) · $0–25/mo with Supabase session logging

Works on

WebMobile

Everything it takes to ship Noise Level Detection — parts, prompts, and real costs.

TL;DR

Noise level detection uses the browser's Web Audio API (or the noise_meter Flutter package on mobile) to read microphone amplitude, convert it to dBFS, and display a live meter. The whole client-side stack is free — Web Audio API is built into every modern browser, no library purchase required. Costs appear only if you log session data to Supabase (free tier handles most volumes) or need background monitoring on native mobile (requires custom dev).

What Noise Level Detection Actually Is

Noise level detection reads the microphone input, measures amplitude in real time, and converts it to a decibel value the app can display, log, or act on. Typical use cases include restaurant noise monitors, classroom focus tools, baby monitors, sound-triggered recording apps, and occupational health trackers. The browser's Web Audio API provides everything needed on web — no external SDK, no API key, no per-measurement fee. The engineering challenge is making the measurement loop fast enough to feel live (10+ fps), preventing the audio context from being blocked by browser autoplay policies, and deciding how much data to write to the database without overwhelming it.

What users consider table stakes in 2026

  • Decibel readout updates at least 10 times per second — anything slower feels laggy for a live meter
  • Visual gauge or waveform bar reacts immediately to changes in ambient sound, with distinct colour zones (green, amber, red)
  • Configurable alert threshold with a non-annoying notification when the level is exceeded (debounced to one alert per 5 seconds minimum)
  • Session start/stop controls so users can bracket a measurement period and review it later
  • Peak dB indicator that holds its maximum reading for 3 seconds before resetting
  • Microphone permission prompt with a clear fallback message explaining how to grant access if denied

Anatomy of the Feature

Six components. The dB computation engine and the high-frequency write strategy are where AI-built versions most commonly fail in production.

Layers:UIDataBackend

Microphone access layer

UI

Calls getUserMedia({audio: true}) to request microphone access and connects the resulting MediaStream to a Web Audio API AudioContext. On mobile, the same Web Audio API works on iOS Safari 14.5+ and Chrome Android. The AudioContext must be created or resumed inside a user gesture handler — component-mount creation causes a browser autoplay policy block.

Note: Requires HTTPS and a user gesture (button click) before the AudioContext is allowed to start. AI tools frequently create the AudioContext at module mount, causing a silent 'was not allowed to start' error.

dB computation engine

Backend

An AnalyserNode connected to the AudioContext reads time-domain data via getByteTimeDomainData() into a Uint8Array. A JavaScript loop computes RMS (root mean square) amplitude from the array and converts it to dBFS using 20 * Math.log10(rms). Output is clamped to the range -100 to 0 dBFS. The loop runs inside requestAnimationFrame at approximately 60fps, but meter updates are throttled to 10fps to reduce React re-renders.

Note: On iOS Safari 16, the AudioContext sometimes reports incorrect RMS at startup. Discard the first 30 frames (about 500ms) before showing values to the user.

Real-time meter UI

UI

A React component renders an SVG arc gauge or animated vertical bar using Framer Motion transitions or CSS custom properties driven by the current dBFS value. Three colour zones: green for levels below -40dBFS (quiet), amber for -40 to -20dBFS (moderate), red above -20dBFS (loud). A separate peak indicator element holds its position for 3 seconds then drops.

Note: Use CSS transitions for the bar fill rather than Framer Motion on every animation frame — animating at 60fps with Framer can cause jank on lower-end devices.

Threshold alert system

Backend

Compares the current dBFS reading to a user-configured threshold stored in component state. When the threshold is exceeded, triggers a browser Notification API alert or an in-app toast. A debounce guard (minimum 5 seconds between alerts) prevents repeated notifications during a sustained loud period.

Note: Browser Notifications require a separate permission request. In-app toasts require no extra permission and are the safer default for most use cases.

Session log storage

Data

Supabase tables noise_sessions and noise_readings persist measurement history. The client batches readings in memory and inserts an array every 5 seconds rather than on every animation frame — this keeps Supabase write volume manageable at scale. Session metadata (label, peak_db, avg_db) is written on session end.

Note: If you insert every reading at 60fps, a single user generates 3,600 rows per minute. Batch inserts every 5 seconds reduce that to 12 rows per minute per user.

Noise history chart

UI

A Recharts LineChart (web) or fl_chart (Flutter) renders db_value over recorded_at timestamps for the current session, showing the last 60 seconds of data on the visible x-axis. Supports zoom and pan for longer sessions. Colour fills match the three dBFS zones.

Note: Load chart data from Supabase only on session open — do not subscribe to real-time inserts for the chart, or you'll trigger a full re-render on every batch insert.

The data model

Two tables: sessions for metadata and batched readings for the time-series data. Run this in the Supabase SQL editor — it creates both tables with RLS and the composite index needed for fast chart queries.

schema.sql
1create table public.noise_sessions (
2 id uuid primary key default gen_random_uuid(),
3 user_id uuid references auth.users(id) on delete cascade not null,
4 label text,
5 started_at timestamptz not null default now(),
6 ended_at timestamptz,
7 peak_db numeric(6,2),
8 avg_db numeric(6,2)
9);
10
11alter table public.noise_sessions enable row level security;
12
13create policy "Users can manage own sessions"
14 on public.noise_sessions for all
15 using (auth.uid() = user_id)
16 with check (auth.uid() = user_id);
17
18create table public.noise_readings (
19 id uuid primary key default gen_random_uuid(),
20 session_id uuid references public.noise_sessions(id) on delete cascade not null,
21 db_value numeric(6,2) not null,
22 recorded_at timestamptz not null default now()
23);
24
25alter table public.noise_readings enable row level security;
26
27create policy "Users can manage own readings"
28 on public.noise_readings for all
29 using (
30 session_id in (
31 select id from public.noise_sessions where user_id = auth.uid()
32 )
33 )
34 with check (
35 session_id in (
36 select id from public.noise_sessions where user_id = auth.uid()
37 )
38 );
39
40create index noise_readings_session_time_idx
41 on public.noise_readings (session_id, recorded_at desc);

Heads up: The RLS policy on noise_readings checks ownership via the parent session — this is cleaner than duplicating user_id on every reading row. The index keeps chart queries fast even when a session accumulates thousands of rows.

Build it — pick your path

Each tool fits this feature differently. Switch tabs to compare fit, time, the exact steps, and a copy-paste prompt.

Hand-built by developersFit for this feature:

Custom development is required for calibrated SPL readings, background monitoring, raw audio export, or high-frequency time-series storage at scale.

Step by step

  1. 1Web: use Web Audio API with AudioWorklet for zero-latency processing in a separate thread; the main thread stays responsive during heavy measurement loops
  2. 2Mobile: flutter_sound or react-native-audio-toolkit for on-device processing; platform channel for native foreground services enabling background monitoring
  3. 3High-frequency write path: batch readings to a local buffer, write to TimescaleDB or InfluxDB for time-series queries optimised for sensor data at millions of rows
  4. 4Device-specific calibration: apply correction curves per device model using device_info_plus to convert dBFS to calibrated dB SPL values
  5. 5Export pipeline: write raw PCM audio alongside dB readings if compliance-grade evidence is required

Where this path bites

  • Most expensive path — only justified for compliance monitoring, IoT integration, or building-management system connectivity
  • AudioWorklet requires a separate worklet JavaScript file served from the same origin; incompatible with some CDN setups

Third-party services you'll need

The entire client-side processing stack is free. Costs appear only for data persistence:

ServiceWhat it doesFree tierPaid from
Web Audio APIBrowser-native microphone access, AnalyserNode for amplitude measurement — no library neededBuilt into all modern browsers, freeFree
noise_meter (Flutter pub.dev)Dart package providing a noise stream from the device microphone for Flutter appsOpen source, freeFree
Supabasenoise_sessions and noise_readings tables, RLS, and optional Realtime subscription for live session sharingFree tier: 2 projects, 500MB DB, 500K Edge Function invocations/moPro $25/mo (8GB DB)
RechartsReact charting library for noise history LineChart — open source, no API keyOpen source, freeFree

Swipe the table sideways to see pricing.

What it costs to run

Drag through the tiers to see how your monthly bill scales with users — no surprises later.

Estimated monthly running cost

$0/mo

Entirely client-side processing — no server costs for the meter itself. Supabase free tier handles session logs for 100 users with batched inserts comfortably.

Estimates use verified 2026 pricing and assume typical usage per user. Your real bill depends on activity, storage, and third-party plans.

What breaks when AI tools build this

The failures people actually hit on their first build — the symptom, why it happens, and the exact fix.

AudioContext blocked by browser autoplay policy

Symptom: Browsers throw 'AudioContext was not allowed to start' when AudioContext is created or .resume() is called before a user gesture. AI tools frequently create the AudioContext on component mount (inside useEffect) rather than inside a click handler, causing the noise meter to silently show zero dBFS at all times.

Fix: Create the AudioContext exclusively inside the Start button's onClick handler. If you need to store the context reference across renders, create it lazily — check if it exists before constructing. Alternatively, create it on mount in suspended state and call audioCtx.resume() inside the click handler.

Microphone access blocked in preview iframes

Symptom: getUserMedia({audio: true}) requires a secure context (HTTPS) and is rejected in the sandboxed iframes used by Lovable and v0 previews. The component renders, the Start button appears, but clicking it either shows nothing or throws a NotAllowedError that goes unhandled.

Fix: Test only on the published HTTPS URL. Add explicit error handling in the catch block of getUserMedia to render a permission-denied state with instructions — do not let the error silently disappear.

SSR crash with AudioContext in Next.js

Symptom: V0-generated Next.js code sometimes references AudioContext or navigator at module scope, causing 'window is not defined' or 'navigator is not defined' during server-side rendering. The build passes locally but crashes on Vercel at deployment.

Fix: Wrap every Web Audio API reference in typeof window !== 'undefined' guards. For the NoiseMeter component, add 'use client' at the top and import it with next/dynamic and ssr: false from a page that needs SSR.

High-frequency database writes overload Supabase free tier

Symptom: If the requestAnimationFrame loop triggers a Supabase insert on every frame (60 writes per second per user), the free tier rate limit is hit almost instantly, causing 429 errors and lost data. AI tools often wire the DB insert directly inside the animation loop.

Fix: Batch readings in a local JavaScript array. Set a setInterval at 5 seconds to flush the array as a single batch INSERT. Use a JSONB column or an array of row objects in a single Supabase call. This reduces DB writes from 3,600/min to 12/min per active user.

iOS Safari AudioContext sample rate reports incorrect RMS at startup

Symptom: On some iOS Safari 16 versions, the AudioContext initialises with a sample rate mismatch that causes the first 200–500ms of AnalyserNode readings to return near-zero values. This makes the meter look broken on first launch even though the microphone is working.

Fix: Add a 500ms warm-up delay before displaying meter values. Discard the first 30 frames from the requestAnimationFrame loop — set a frameCount counter and skip state updates until it reaches 30.

Best practices

1

Always create AudioContext inside a user gesture handler (button click), never on component mount — browser autoplay policy blocks silent creation

2

Batch Supabase inserts every 5 seconds instead of on every animation frame — one user's 30-minute session should produce 360 rows, not 108,000

3

Cap the meter update rate at 10fps for React state updates even though the AnalyserNode reads at 60fps — excessive re-renders cause jank without improving perceived responsiveness

4

Show a peak dB indicator that holds the maximum reading for 3 seconds — users often miss the peak reading on a live meter

5

Debounce threshold alerts to a minimum of 5 seconds between notifications — a sustained loud environment triggers alerts every frame without debouncing, which is unusable

6

Stop the microphone stream and close the AudioContext when the component unmounts — an active microphone indicator in the browser tab header causes user alarm

7

Provide a calibration note in the UI: dBFS is relative to the device's microphone sensitivity, not absolute dB SPL — set correct expectations so users do not report 'wrong' readings

When You Need Custom Development

Lovable and V0 handle noise monitoring for most consumer use cases. These requirements consistently exceed what AI-tool builds can deliver reliably:

  • Continuous background monitoring when the app is minimised — this requires a native foreground service on Android and a background audio session on iOS, both beyond FlutterFlow's visual tools
  • Calibrated SPL (dB SPL) readings with device-specific correction curves — dBFS values vary by device microphone sensitivity and require hardware calibration data
  • Exporting raw WAV audio alongside dB readings for compliance evidence in occupational health or noise enforcement contexts
  • Integration with building management systems, IoT sensors, or industrial noise monitoring hardware via MQTT or proprietary protocols

RapidDev builds these features for production

Real auth, database, and payments — fixed price, delivered in weeks. You own 100% of the code.

Get a fixed-price quote

Frequently asked questions

How do I access the microphone in a web app without writing native code?

Call navigator.mediaDevices.getUserMedia({audio: true}) inside a button click handler — this is the browser's standard Web Audio API, available in all modern browsers with no library or API key required. Connect the resulting MediaStream to an AudioContext and AnalyserNode to start reading amplitude values.

What is the difference between dBFS and dB SPL in a noise detection app?

dBFS (decibels relative to full scale) measures the digital amplitude of the audio signal, where 0dBFS is the maximum the microphone can record and -100dBFS is near silence. dB SPL (sound pressure level) measures physical air pressure and requires a calibrated microphone with a known sensitivity curve. Browser-based apps produce dBFS values. For consumer noise awareness features dBFS is sufficient; for compliance-grade occupational health monitoring you need calibrated dB SPL hardware.

Why does the noise meter not work in the Lovable or V0 preview?

Both preview environments use sandboxed iframes that block microphone access via getUserMedia(). This is a browser security restriction applied to the iframe, not a bug in your code. Publish the app and test the HTTPS URL on a real device to verify the meter works.

How do I prevent AudioContext from being blocked by the browser?

Create the AudioContext inside the Start button's onClick handler rather than on component mount. If the context already exists (user clicked start before), call audioCtx.resume() instead of creating a new one. Never create AudioContext in useEffect with an empty dependency array — that runs before any user interaction and triggers the autoplay block.

How many database writes does a noise monitoring session generate?

With naive implementation (one insert per animation frame at 60fps), a single 30-minute session generates 108,000 rows — enough to hit Supabase free tier limits within minutes across a handful of users. The correct approach is to batch readings in memory and insert an array every 5 seconds, which produces 360 rows for the same 30-minute session.

Can I build a noise level detector in FlutterFlow without writing any code?

Not fully. FlutterFlow does not have a built-in noise meter action. You need to add the noise_meter pub.dev package and write a Custom Action in Dart to subscribe to the noise stream and update an App State variable. The rest — gauge widget, colour zones, session controls — can be built visually once the Custom Action exists.

How do I add a threshold alert that notifies the user when it gets too loud?

In your requestAnimationFrame loop, compare the current dBFS reading to the user's threshold value. If exceeded, trigger a browser Notification (requires a separate permission) or an in-app toast. Store the time of the last alert in a ref and skip new alerts if less than 5 seconds have elapsed — without this debounce, a sustained loud environment fires hundreds of alerts per minute.

Can noise monitoring run in the background on mobile?

Not with a web app or a standard FlutterFlow build. Background audio processing on iOS requires a background audio session entitlement, and on Android it requires a foreground service with a persistent notification. Both are native capabilities that require custom Flutter or React Native code outside of visual AI builders.

RapidDev

Need this feature production-ready?

RapidDev builds noise level detection into real apps — auth, database, payments — at $13K–$25K.

Book a free consultation

30-min call. No commitment.

Want this built for you?

We ship production apps at a fixed price — $13K–$25K, 6–10 weeks, source code yours. You've seen what it takes; we do it every week.

Get a fixed-price quote

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.