Compute multitrack mixdown gain from peaks and relative levels
This multitrack mixdown level calculator turns measured peak levels and creative balance weights into a precise gain setting for every track.
Run — free
Enter each peak in dBFS and assign a non-negative weight that describes how loud its final peak should be relative to the others. The calculator normalizes the largest weight to 0 dBFS, converts every other ratio into decibels, and reports the required gain or attenuation. The result gives engineers, editors, podcasters, and automated audio pipelines a consistent starting balance without guessing at fader moves.
Describe the source peaks and the intended balance
Begin with a reliable peak reading for every track before adding mix-bus processing. Enter that value as peak_dbfs, using zero for digital full scale and negative values for peaks below it. Then assign each track a weight. A weight is a ratio, not a decibel value and not a percentage that must total one. For example, weights of 1, 0.5, and 0.25 ask for final linear peaks in a four-to-two-to-one relationship. Doubling every weight produces exactly the same balance because only their ratios matter. Names are preserved in the output so the settings can be mapped back to channels without relying on row positions. At least two tracks are required, and at least one weight must be positive. A zero weight deliberately mutes a track. Negative weights are invalid because a signed amplitude does not represent a usable level preference. Measure peaks over representative program material: an unrepresentative short section can produce mathematically correct settings that do not express the balance wanted across the full song, episode, or scene.
Understand how each gain value is calculated
The largest positive weight becomes the reference and receives a normalized weight of one. Its target peak is therefore 0 dBFS. Every other positive weight is divided by that maximum, and the resulting linear amplitude ratio is converted to decibels with 20 times the base-ten logarithm. The required gain is the target peak minus the measured input peak. Consider a track peaking at -6 dBFS with the largest weight: its target is 0 dBFS, so the reported gain is +6 dB. A track assigned half that weight has a target near -6.0206 dBFS; if it currently peaks at -3 dBFS, its gain is about -3.0206 dB. Values are rounded to six decimal places for stable, reproducible output. A zero-weight track is returned with muted set to true and no fictitious infinite decibel value. Because this method aligns peak amplitudes rather than loudness, it does not claim that two tracks with matching peaks will sound equally loud. Spectral density, dynamics, duration, and human perception still influence the artistic result.
Apply the settings safely in a real mixdown
Apply each reported gain_db as a trim before summing, or translate it into an equivalent fader adjustment when the signal path makes that more practical. The loudest requested individual peak lands at 0 dBFS, while the others land below it according to their weights. That normalization maximizes individual peak use, but it does not guarantee that the combined waveform will remain below full scale: simultaneous tracks add together, and correlated material can create a bus peak above any individual target. Preserve mix-bus headroom by lowering all non-muted tracks by the same additional amount after calculation, or use the result as a relative starting point and set the master gain during playback. Lowering every result equally retains the computed balance. Review the mix with meters and ears, especially when limiters, compressors, automation, or phase relationships follow the trim stage. For repeatable pipelines, store the original peaks, weights, and returned gains together. The API costs $0.002 per request, while the browser version can perform the same deterministic calculation locally. No audio file is uploaded or analyzed because the input is already-measured numeric data.
What you can do with it
Set an initial music mix balance
Convert peak scans and producer-supplied ratios into repeatable trim values before detailed automation begins.
Balance podcast stems
Place voices, music, and room tone at defined relative peak targets before applying shared bus headroom.
Automate batch mix preparation
Generate deterministic per-track gains from measurements produced earlier in an offline audio workflow.
FAQ
Do the weights need to add up to one?
No. Only the ratios matter. Weights of 1, 0.5, and 0.25 produce the same result as 4, 2, and 1.
What happens when a weight is zero?
That track is marked as muted. The response omits target and gain values instead of representing negative infinity as JSON.
Why are negative weights rejected?
A balance weight represents a non-negative amplitude ratio. A negative value cannot describe a conventional target peak level.
Will the summed mix stay below 0 dBFS?
Not necessarily. Several tracks can peak together and exceed the individual reference, so apply common bus headroom without changing their relative gains.
Does this calculate perceived loudness?
No. It balances measured peak amplitudes. Use LUFS measurements and listening review when perceived loudness is the goal.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/audio/multi-track-mixdown-levels \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"tracks":[{"name":"Lead vocal","peak_dbfs":-6,"weight":1},{"name":"Music bed","peak_dbfs":-3,"weight":0.5},{"name":"Room","peak_dbfs":-12,"weight":0.25}]}'const res = await fetch("https://api.kit.forhosting.com/audio/multi-track-mixdown-levels", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"tracks": [
{
"name": "Lead vocal",
"peak_dbfs": -6,
"weight": 1
},
{
"name": "Music bed",
"peak_dbfs": -3,
"weight": 0.5
},
{
"name": "Room",
"peak_dbfs": -12,
"weight": 0.25
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/audio/multi-track-mixdown-levels",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"tracks": [
{
"name": "Lead vocal",
"peak_dbfs": -6,
"weight": 1
},
{
"name": "Music bed",
"peak_dbfs": -3,
"weight": 0.5
},
{
"name": "Room",
"peak_dbfs": -12,
"weight": 0.25
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/audio/multi-track-mixdown-levels", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"tracks":[{"name":"Lead vocal","peak_dbfs":-6,"weight":1},{"name":"Music bed","peak_dbfs":-3,"weight":0.5},{"name":"Room","peak_dbfs":-12,"weight":0.25}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"tracks":[{"name":"Lead vocal","peak_dbfs":-6,"weight":1},{"name":"Music bed","peak_dbfs":-3,"weight":0.5},{"name":"Room","peak_dbfs":-12,"weight":0.25}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/audio/multi-track-mixdown-levels", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"tracks": [
{
"name": "Lead vocal",
"peak_dbfs": -6,
"weight": 1
},
{
"name": "Music bed",
"peak_dbfs": -3,
"weight": 0.5
},
{
"name": "Room",
"peak_dbfs": -12,
"weight": 0.25
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "audio.multi_track_mixdown_levels",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 200 |
max_minutes | 180 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |