• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

DecayCore — Free FIR room correction with temporal decay control, automatic optimization and measurement workflow

Hello @VilhoValittu,
Thanks so much for putting this together and making it free!

Running measurements on Ubuntu 26.04 and getting error / notification "Impulse peak arrived unusually early. Check pre-silence length or latency settings. Detected recording clock drift from chirp spacing (+657 ppm).Applied chirp-based drift correction before sweep deconvolution."

Where to check those things?

Marko
Thanks for reporting this. “Check pre-silence length or latency settings” is a development-only message accidentally left in the release. I will remove it at next update.

The detected drift is usually caused by a small clock-rate difference between the playback and recording devices, especially when using separate audio devices. DecayCore detected and corrected it automatically before processing the measurement.
 
It's very pleasing to see that the author keeps working on improving DecayCore.

My new monitors – Edifier MR4.5 – arrived, and I decided to use DecayCore for their correction. However, some roughness when running under Arch Linux prevented me from doing that, so I limited myself to REW correction.

The author quickly fixed the issues, and I was able to perform measurements. One of the correction options…

When I later felt like tweaking the settings a bit, I found another difficulty in the program's operation. The author sorted that out promptly as well. So I could make new measurements and create yet another correction profile.

In all cases I chose to use the "Auto" mode, but with a selected target curve.

And here's the result… The last correction profile turned out to be the most "musical" for my room. Compared to the previous ones, it sounded "light" but not "thin", with more than enough bass but without boominess. And it is a much "better" option than both the uncorrected response and the REW correction.

Frankly speaking – I'm satisfied.

Attached is a measurement in RTA mode with ERB smoothing. Yes, the smoothing is heavy, but this measurement is not for analysis or creating a correction – it's just to get a rough idea of what is actually heard in the end.

Aug 30 +6.png
 
Earlier in this thread, there was support for doing subwoofer integration to main speakers as a base layer, followed by DecayCore on top of that base layer. I'm wondering what can and cannot be changed after DecayCore. With DC-derived FIR active, is it defensible to adjust some delays to achieve time and phase alignment between channels for low frequency (LF) content? [main question of this post, everything below has to do with this question]

I have some doubt about this, thus the question, but I believe the answer is 'yes' based on measurement and analysis. The reason I ask is because some low frequency (LF) time alignment between channels that I set in the sub integration stage became misaligned following DecayCore (through no fault of DC which only takes in speaker pairs, there is no cross-channel coordination say between L-R and center).

Measurements for input into DecayCore have the subwoofer integrated with the other speakers in a 7.1 speaker system. By "sub integration" I mean that I have:
1) determined crossover frequency for each channel sending LF content to the subwoofer
2) adjusted subwoofer gain to level match front L and front R in the context of my chosen target curve (Harman 6dB or Harman 8dB)
3) time aligned the subwoofer to L+R (sub polarity determined at this step as well)
4) time aligned low frequency (LF) content from center, surround, and LFE channels (XO for center and surrounds, no XO for LFE), to arrive at the sub the same time as LF content from L+R. This is needed because front, center, and surrounds are different speakers with different crossover frequencies. This in turn impacts the timing of arrival of LF content to the sub.
(Steps 3 and 4 described in detail: https://www.audiosciencereview.com/...ubwoofer-s-to-mains-how-to.15269/post-2662112)

Once I have done steps 1-4 and all of that is active, I take measurements for DecayCore, one speaker pair at a time. So I do 5 separate DC runs for: L-R, Center-Center, SL-SR, BL-BR, LFE-LFE. LFE-LFE and Center-Center go in as identical twins just because DC expects a pair. I leave bass management in DC off because my sub is already integrated: when I take a measurement of "L" in REW for input into DC, both my front L and sub make sound. The XO tab has the sub crossover frequency plus the within-speaker crossover(s), except for the LFE channel which has the XO tab blank. All of this is consistent with the plan to have sub integration as a base layer, and then DC on top of that base layer.

After DC and with FIR and IIR outputs from DC active (summaries included here), I repeated my sweeps to check for phase alignment. For step 3 above, in REW, I take two sweeps, both driven by "L+R": Sweep 1) with L and R speakers off, the sub on, crossover active, and Sweep 2) with L and R speakers on, the sub off, crossover active. Before DC, I had found a 17ms delay to L and R speakers would result in impulse and phase alignment at the 40 hz crossover, and just slightly different following DC, close to natural variance with replicate experiments. This makes sense to me because the same DC-based FIR is applied to both HF and LF content together before my crossover split. Step 4 was a different story. In Step 4, I take the sub only driven by L+R (Sweep #1 above) and align to sub only driven by Center, Surround, and LFE. In these cases time alignment was completely off, which makes sense to me because FIR for each channel was derived by DC independent of any other channel set. Unlike step 3, in step 4 the alignment tool in REW is comparing a pair of channels that each have a different FIR set applied. I believe step 4 is important for overall 7.1 system coherence in LF content.

Figures 1 and 2 below show phase relationships following DC:
Figure 1 after DecayCore, a 17.19ms delay on L+R (delay_mains, dark blue, sub off) results in phase alignment at 40hz (XO) with sub driven by L+R (red).
No delay (0 ms delay_mains, light blue) on L+R shown for comparison.
phase-align-LR-sub-post-DC.jpg

phase-align-LR-sub-post-DC.jpg



Figure 2. After DC, phase curves for sub only (driven by L+R, red, same as in Figure 1) are mis-aligned with those for sub only driven by Center (light blue), Surround L (green), and LFE (black). They were phase-aligned before DC, by adjusting time of arrival of LF content from these channels to the sub. Alignment is done at 25hz which is far from the crossover frequencies of 40hz (L-R), 110hz (Center), and 100hz (surrounds).

phase-misalign-sub-C-SL-LFE-post-DC.jpg



What is the risk if I do steps 3 (to make a small adjustment to delay of mains to phase align with sub) and 4 (delay LF content derived from different channels to arrive at the sub at the same time) again after DC, that I will invalidate the FIR filters generated in DC? After DC is it ok and desired to phase align the sub with main speakers for a second time (Figure 3) and phase align all of the LF content from each channel destined for the subwoofer for a second time(Figure 4)?

Although I perceive a risk of invalidating FIR filters by changing timing, I think that it is needed for overall 7.1 system LF coherence, which DC cannot address given that it deals with pairs of speakers and not the system as a whole. So I proceed with a second round of time alignment for subwoofer, following DC.

Figures 3 and 4 below show phase relationships following DC and a second round of time aligning:
Figure 3 after DecayCore and a second round aligning L&R speakers with sub (both driven by L+R), a 19.83ms delay on L+R (delay_mains, dark blue, sub off) results in phase alignment with sub driven by L+R (red). The delay in Figure 1 was 17.19ms, and that is the case here too, the remaining difference here is to deal with time aligning LF content going to sub from different channels. If I only had a sub and L and R speakers, the delay would be 17.19ms here. Alignment is done at 40hz, the L-R crossover to sub.
phase-align-LR-sub-postDC-postSI.jpg


Figure 4. After DC and a second round of sub-bus time alignment, phase curves for sub only (driven by L+R, red, same as in Figure 3) are aligned with those for sub only driven by Center (light blue), Surround L (green), and LFE (black). This alignment is accomplished by adjusting time of arrival of LF content from these channels to the sub (delay_sub_C, delay_sub_surrounds, delay_sub_LFE parameters). Alignment is done at 25hz which is far from the crossover frequencies.

phase-align-LRsub-C-SL-LFE-postDC-postSI.jpg


You can see in Figure 4 that the sub, driven by 1) L+R, 2) Center speaker, 3) Surround L, or 4) LFE are in phase with matching slopes at the 25hz alignment frequency and quite close as they approach 100hz. I will do one more verification in an upcoming post.

For reference, here is my CamillaDSP pipeline (delay_sub is zero; time alignment of sub with main speakers done through delay_mains):
pipeline:
# Step 1: Master gain + FIR room correction (full range, before crossover split)
- type: Filter
channels: [0]
names: [master_gain, fir_FL]
- type: Filter
channels: [1]
names: [master_gain, hybrid_iir_1_FR, fir_FR]
- type: Filter
channels: [2]
names: [master_gain, hybrid_iir_1_LFE, hybrid_iir_2_LFE, fir_LFE]
- type: Filter
channels: [3]
names: [master_gain, fir_FC]
- type: Filter
channels: [4]
names: [master_gain, fir_SL]
- type: Filter
channels: [5]
names: [master_gain, fir_SR]
- type: Filter
channels: [6]
names: [master_gain, hybrid_iir_1_BL, fir_BL]
- type: Filter
channels: [7]
names: [master_gain, fir_BR]


# Step 2: Expand to 15 channels for bass management
- type: Mixer
name: expand_to_15

# Step 3: Highpass main speaker channels
- type: Filter
channels: [0, 1]
names: [hp_40hz]

- type: Filter
channels: [3]
names: [hp_110hz]

- type: Filter
channels: [4, 5, 6, 7]
names: [hp_100hz]

# Step 4: Lowpass duplicated channels (for sub) and delays for L&R, Center, surrounds, and LFE
- type: Filter
channels: [2]
names: [delay_sub_LFE]

- type: Filter
channels: [8, 9]
names: [lp_40hz, delay_sub_LR]

- type: Filter
channels: [10]
names: [lp_110hz, delay_sub_C]

- type: Filter
channels: [11, 12, 13, 14]
names: [lp_100hz, delay_sub_surr]

# Step 5: Collapse back to 8 channels
- type: Mixer
name: collapse_to_8

# Step 6: Speaker delays and level trims
- type: Filter
channels: [0]
names: [delay_mains, delay_FL, gain_FL]
- type: Filter
channels: [1]
names: [delay_mains, delay_FR, gain_FR]
- type: Filter
channels: [3]
names: [delay_mains, delay_C, gain_C]
- type: Filter
channels: [4]
names: [delay_mains, delay_SL, gain_SL]
- type: Filter
channels: [5]
names: [delay_mains, delay_SR, gain_SR]
- type: Filter
channels: [6]
names: [delay_mains, delay_BL, gain_BL]
- type: Filter
channels: [7]
names: [delay_mains, delay_BR, gain_BR]

# Step 7: Sub delay and gain
- type: Filter
channels: [2]
names: [delay_sub, gain_sub]


Parameter explanations:
master_gain: set at -6dB for safety, per DC output.

fir_FL, fir_FR, fir_C, fir_SL, fir_SR, fir_BL, fir_BR, fir_LFE: FIR derived from DC.

hybrid_iir_1_FR, etc: IIR derived from DC.

delay_FL, delay_FR, delay_C, delay_SL, delay_SR, delay_BL, delay_BR: speaker delays to time align in midrange, done before any sub integration.

gain_FL, gain_FR, gain_C, gain_SL, gain_SR, gain_BL, gain_BR: speaker gains to level match in midrange, done before any sub integration.

delay_mains: derived in my sub integration #3 way above. This is derived from L+R driven sweeps in REW, but applied to all 7 main speakers. This is to time align sub and L+R. The other main speakers have to go along for the ride so that inter-channel timing is coherent.

delay_sub_LR, delay_sub_C, delay_sub_LFE, delay_sub_surrounds: delay applied to LF content destined for subwoofer so that such content arrives at the sub at the same time and in phase. After DC, LFE was the slowest, and so that delay was set to zero and all others were delayed based on that reference and by comparing in REW alignment tool sub only (L+R driven) with sub only driven by Center, Surround, and LFE.

delay_sub: used to delay sub for alignment with L+R (set to zero)

gain_sub: subwoofer gain to level match with L and R.
 

Attachments

As further verification following DC and a second round of time-alignment with sub, I next did predicted vector sum vs actual measurement for sweeps 10hz-250hz. For L+R, Center, and SL: captured 1) sub only, crossover active, driven by that channel, speaker off (blue), 2) speaker alone, crossover active, sub off (red), 3) Vector-summed (1)+(2) in REW to get a predicted combined response (black), then compared against 4) a real simultaneous measurement of speaker+sub together (green). Predicted and actual overlap almost exactly in both SPL and phase, through each group's own crossover region and into the comb-filter zone above it, for all three groups tested.

Graphs attached:

  • [LR/Center/SL] SPL: predicted sum vs. actual — black (predicted) and green (actual) overlap closely across the full 10-250 Hz range shown, including through each crossover.
  • [LR/Center/SL] Phase: predicted sum vs. actual — same close overlap in phase.
Figure 1 F+R SPL
LRsub-verify.jpg



Figure 2 L+R phase
LRsub-verify-phase.jpg


Figure 3
Center SPL

Csub-verify.jpg


Figure 4
Center phase
Csub-verify-phase.jpg


Figure 5
Surround L SPL
SLsub-verify.jpg


Figure 6
Surround L phase
SLsub-verify-phase.jpg



So the predicted vector sum (black) overlaps with actual measurement (green) for L+R, Center, and Surround L, in both the SPL and phase graphs. Note that in the phase graph the speaker alone (red) is aligned to sub (blue) only in L+R, as one cannot (as far as I know) phase align the sub with each speaker.

For Discussion
  • If you generate DecayCore (or similar independently-optimized per-channel) FIR filters after completing sub-to-mains and internal sub-bus time alignment, don't assume that alignment is still valid once the filters are loaded. Each filter can independently shift phase near its own crossover by a non-trivial amount.
  • Re-measuring and correcting only the delay values (not regenerating the FIR filters) is sufficient to fix this, since delay is a pure time shift and doesn't interact with the correction the FIR filter is providing (this is a question, per immediate previous post above).
  • Predicted-sum-vs-actual-measurement is an additional validation step — it directly tests whether corrected delays produce genuine constructive summation in practice, rather than relying solely on Alignment Tool readings.
So this is further evidence that time alignment following DC can be beneficial. I don't see a downside, but perhaps there is one.
 
Finally, here are some overlay plots of full range sweeps comparing 1) sub-integrated before DC (green), 2) post-DC (blue), 3) post-DC with second time alignment (red) for a few speakers. On SPL overlays, the second time alignment post-DC (3) improved some dips compared to post-DC (2) such as around 110hz in R and LFE and especially SL, and around 180hz in Center. All the SPL overlays show DC did a good job attenuating some bass.

R-SI-DC-SI-spl.jpg



C-SI-DC-SI-spl.jpg


LFE-SI-DC-SI-spl.jpg



SL-SI-DC-SI-spl.jpg



The SL big dip around 102hz and the Center big dip at 180hz were greatly reduced following the second time-alignment. However, DC must have helped too because both big dips were also present before DC despite good initial phase alignment. This makes me think that DC and the second time alignment are synergistic. Much appreciation again to VilhoValittu for making DC available and working to improve it.

Summarizing these last 3 posts, time-aligning the sub following DecayCore:
1) maintained phase alignment of L+R with subwoofer
2) maintained syncronization of LF content from speaker channels (L-R, center, surround, LFE) going to the subwoofer
3) corrected delays produced constructive summation, demonstrated by vector summing speaker only + sub only and showing equivalence with sweep of speaker + sub.
4) further corrected some dips as shown in this post.

Based on 1-4, I believe doing a second time-alignment following DecayCore is warranted. If there are disadvantages, please say so, but it seems like it was needed and advantageous. I think the first time-alignment during initial sub-integration is still needed to deliver good measurements for DecayCore, and cannot be avoided to reduce work.

I started with an ideal of sub-integration as a base layer and then placing DecayCore on top of that base layer, and then mistakenly thought I was done. In practice for a multichannel system, a second time alignment is likely needed (or at least a check) following DC.
 
Last edited:
First of all, @SoundsGood64 , thanks for the effort you put into those posts. Glad to see such passion.

I think your observation is valid.

I would not call this a DecayCore bug, though. The different channel groups were processed in separate runs, so their FIRs are not phase-coordinated with each other across the whole system.

Re-measuring after DC and fine-tuning delays can therefore make sense in a multichannel setup like this. Adding pure delay does not change the FIR magnitude correction or TDC itself, but it does change the phase relationship between the speaker and subwoofer, so the final crossover summation can improve or worsen.

The only part I would be cautious about is aligning all sub feeds at 25 Hz, as you already noted yourself, that is quite far from the crossover region.

For multichannel/movie use, my personal preference would be to align the subwoofer primarily with the center channel around its crossover region. Center carries a very large share of the important content in a typical movie mix, so to me that is the most logical reference.

In the end, measure the final system, adjust delays if needed, play your favourite demo clip and judge the result with your ears. That is what matters most.
 
Iterative cycling between bass management crossovers and DRC / tackling modes adds a lot of work.

I am planning on LCR co-located "stacks", each having their own channel-specific bass, and then treat those as if big floorstanders when (trying) to use tools not designed for the full "big picture"

Gets more complicated when I think about also having mono trueSub(s) freely placed to tackle room modes below Schröder, say MSO managed separately?

Chicken, eggs...

Wohld be nice to get a workflow - ordered checklizt built to handle all that, bding able to test and compare those tools really designed around Stereo only
 
Iterative cycling between bass management crossovers and DRC / tackling modes adds a lot of work.

I am planning on LCR co-located "stacks", each having their own channel-specific bass, and then treat those as if big floorstanders when (trying) to use tools not designed for the full "big picture"

Gets more complicated when I think about also having mono trueSub(s) freely placed to tackle room modes below Schröder, say MSO managed separately?

Chicken, eggs...

Wohld be nice to get a workflow - ordered checklizt built to handle all that, bding able to test and compare those tools really designed around Stereo only
IMO :

  1. Get the physical bass system working first: placement, MSO, delays, gains
  2. Set the crossover regions and align each main channel with the bass system around its actual XO region.
  3. Only after that run FIR correction on the resulting acoustic system.
  4. Finally re-measure the complete system and make only small delay/gain adjustments if needed.
  5. You have do this everytime, when you move system
Main reason is that DRC should ideally correct a system which bas topology is already stable. If you change sub delays, gains, MSO filters or crossover behaviour afterwards, you also change the acoustic transfer function that the FIR was designed for.

Stereo-oriented tools can still work in a multichannel system, but only if the larger bass-management problem is solved first and each correction step is treated as part of the final signal chain rather than isolated operation.
 
First of all, @SoundsGood64 , thanks for the effort you put into those posts. Glad to see such passion.

I think your observation is valid.

I would not call this a DecayCore bug, though. The different channel groups were processed in separate runs, so their FIRs are not phase-coordinated with each other across the whole system.

Re-measuring after DC and fine-tuning delays can therefore make sense in a multichannel setup like this. Adding pure delay does not change the FIR magnitude correction or TDC itself, but it does change the phase relationship between the speaker and subwoofer, so the final crossover summation can improve or worsen.

The only part I would be cautious about is aligning all sub feeds at 25 Hz, as you already noted yourself, that is quite far from the crossover region.

For multichannel/movie use, my personal preference would be to align the subwoofer primarily with the center channel around its crossover region. Center carries a very large share of the important content in a typical movie mix, so to me that is the most logical reference.

In the end, measure the final system, adjust delays if needed, play your favourite demo clip and judge the result with your ears. That is what matters most.
Thanks @VilhoValittu. 100% agree this issue is not a DecayCore bug; I should have clearly re-stated that in the above post in a prominent spot (was buried in the details), and glad to read that you agree doing some fine tuning on delays after DecayCore is appropriate.

For phase-aligning L+R to sub, it's clear to me that the alignment should be done at the crossover point, which for my case is 40hz. An additional and different step is to align LF content from each channel going to the sub such that they arrive at the same time, allowing for overall coherence in the 7.1 system. I didn't know what frequency I should align at, and chose 25hz for each sub feed because of a thought (maybe wrong) that it would be best to stay away from the crossover points (center 110hz, surrounds 100hz), and of course LFE channel has no crossover. Can you suggest an alignment frequency for the LF feeds to the sub for this multichannel setup, and what is the physical/engineering basis for that suggestion? Should that frequency be the same for all the feeds or differ according to channel? Is there some aspect of the DecayCore summary that I should consider to inform this choice?

This DSP pipeline is 100% for music (no movies, no video), and 94% of the music library enters CamillaDSP as streams derived from CD (44100hz) or SACD (DSD64, transcoded to PCM), and the vast majority is classical or jazz. Based on that, L+R, rather than center, is the appropriate reference for sub integration in this specific context. Of course CD is 2ch only, and there is a lot of LF content in L and R channels in SACD probably more so in 5.0 mixes (more of those) compared to 5.1 mixes (less common). That I'm listening to classical and jazz, it also makes me wonder if 25hz is the correct alignment frequency for the sub bus, because few instruments get down that low. The rationale behind the 88200hz processing frequency is based on the music library content, with 88200hz staying in the same frequency family as CD and DSD64 (even multiple or division with no remainder, 94% of collection), as opposed to the other family of 48,96, or 192khz (non-integer multiple or division has remainders). No video means I can be more relaxed on latency, so linear phase filters are ok.

On listening to the system-- It's hard for me to be objective when I listen to music through this system because I put so much work into it. Subjectively it sounds SUPER, and maybe it's the work that makes it feel so great, and i mean that in two ways 1) the work resulted in physical changes to make the system more coherent and 2) the emotional connection of being actively invested in something. Both are at play and disentangling 1 vs 2 is difficult. An audio engineer who was not invested in the process listened to music on this system without post-DC time-alignment, and he heard no problems. The measurements and analysis above help bring some objectivity especically if in moments 2>1 remains true. Overall, I've never been happier with sitting down and listening to a piece of music. Lately it's been Sibelius: Symphony 7 (5.0ch), Saint-Saens: Symphony 3 (5.0ch), Mahler: Symphony 2 (5.0ch), and Touba from Uneasy (2ch, Vijay Iyer, Linda May Han Oh, and Tyshawn Sorey), all with beautiful bass notes that need to be well taken care of in the signal pipeline.
 
That context changes my earlier center-channel comment. For music, L+R is clearly the appropriate reference.

I would keep two tasks separate:

  • Align each main speaker with the sub around its own crossover.
  • Align the sub-only feeds with each other over a shared band below the lowest crossover.
With 40 Hz as the lowest crossover, I would compare roughly 25–35 Hz rather than forcing an exact match at 25 Hz. Use the same comparison band for all feeds, but allow different delay values, wit the L+R sub feed as reference. Then re-check every main+sub combination around its own crossover; good crossover summation should take priority if objectives conflict.

DC's summaries cannot fully determine this because equal FIR length and nominal latency do not guarantee equal low-frequency phase between independent runs. Measuring the final CamillaDSP pipeline, as you did, is the reliable method.

Regarding sample rates, previously mentioned CamillaDSP $samplerate$ substitution can select matching FIR files and avoid unnecessary resampling altogether.
 
I've never seen new versions of a program be worse than the old ones.
And why does import only stereo, where is the import of the subwoofer channel if this function is advertised?

1788388330470.png


In the measurement section, similarly - there is no "Apply as subwoofer measurement" button.

1788388537236.png
 
And why does import only stereo, where is the import of the subwoofer channel if this function is advertised?
Enable Bass Integration and those fields come up.

I've never seen new versions of a program be worse than the old ones.
You don't have to use DC if you don't like it.
 
Enable Bass Integration and those fields come up.
This option doesn't work, the corresponding field "Apply as sub measurement" don't appear.
Sorry, are you making your program without being a programmer, using AI?
Very much bugs


1788420736405.gif
 
This option doesn't work, the corresponding field "Apply as sub measurement" don't appear.
Did you make measurement?


Sorry, are you making your program without being a programmer, using AI?
No and yes, programming has been hobby of mine over 30 years. I have tried Codex and I'm very impressed about it performance. It always find improvements to my code when I use it to review.


Very much bugs
If you found real bug, please report it here DC issues
 
This option doesn't work, the corresponding field "Apply as sub measurement" don't appear.
Sorry, are you making your program without being a programmer, using AI?
Very much bugs


View attachment 556164
To be candid, your communication style comes across as abrasive, and this isn't limited to this thread. Vilho has shown a great deal of patience. Had it been my application, I probably would have told you to take your concerns elsewhere.
 
And so what if he was using AI for programming ? Many users have including myself have gotten it to work and have successful results...
 
I've used it and got working code. Why not? It's interesting to see different solutions.
 

[1.2.8] - 4-9-2026​

Export​

A user-defined Filter name field is now available in the export settings on
the Files tab. The name is included in ZIP, CamillaDSP, main, sub, config,
summary and IIR filenames.

Target-curve names and timestamps are now also included in sub and CamillaDSP
filenames.

UI​

The Measurement preview section is now hidden when no measurement result is
available and appears automatically after a successful measurement.

v1.2.8


Phase and group-delay (GD) correction use a new algorithm since v1.2.7. Feedback on the perceived soundstage would be appreciated.
 
Back
Top Bottom