<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Neural Sound</title>
    <description>The latest articles on DEV Community by Neural Sound (@neural_sound).</description>
    <link>https://dev.to/neural_sound</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4057259%2F73be7bac-1ae8-47e7-be79-34ff2e9067e5.jpeg</url>
      <title>DEV Community: Neural Sound</title>
      <link>https://dev.to/neural_sound</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/neural_sound"/>
    <language>en</language>
    <item>
      <title>Why Millisecond Timing Errors Can Ruin a Music Separation Benchmark</title>
      <dc:creator>Neural Sound</dc:creator>
      <pubDate>Wed, 05 Aug 2026 18:00:10 +0000</pubDate>
      <link>https://dev.to/neural_sound/why-millisecond-timing-errors-can-ruin-a-music-separation-benchmark-2lpj</link>
      <guid>https://dev.to/neural_sound/why-millisecond-timing-errors-can-ruin-a-music-separation-benchmark-2lpj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; This article is based on a benchmark conducted by the NeuralSound team. AI was used to help edit and structure the draft; the code, methodology, and technical claims were reviewed by the team before publication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vkaa8li8arsp2kxr0e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vkaa8li8arsp2kxr0e4.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A music source-separation model can sound good and still receive a surprisingly poor score.&lt;/p&gt;

&lt;p&gt;One common reason is not the model itself. It is timing. &lt;a href="https://neuralsound.org/" rel="noopener noreferrer"&gt;NeuralSound&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A cloud-based AI vocal remover may add a short delay, trim a few samples, pad silence, or export a file that is slightly shorter than the original. To a listener, a 10–30 ms offset may sound almost irrelevant. To sample-by-sample metrics such as SI-SDR, that same offset can create a large penalty.&lt;/p&gt;

&lt;p&gt;This tutorial explains how to detect and correct timing offsets before evaluating an AI stem splitter, vocal remover, acapella extractor, or background music remover.&lt;/p&gt;

&lt;p&gt;The examples come from our public AI vocal-remover benchmark, where the same five songs were processed by NeuralSound, Moises, and Fadr.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://neuralsound.org/compare/ai-vocal-remover-2026" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Play the full benchmark with 35 audio samples&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why timing matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose the reference vocal is:&lt;/p&gt;

&lt;p&gt;reference[n]&lt;/p&gt;

&lt;p&gt;and the estimated vocal is identical except that it starts 1,000 samples later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At 44.1 kHz, 1,000 samples are only about 22.7 ms.&lt;/p&gt;

&lt;p&gt;The audio may still sound almost identical. But a metric comparing reference[n] with estimate[n] sees different values at nearly every sample.&lt;/p&gt;

&lt;p&gt;That creates a false conclusion:&lt;/p&gt;

&lt;p&gt;“The separator is inaccurate.”&lt;/p&gt;

&lt;p&gt;The more accurate conclusion is:&lt;/p&gt;

&lt;p&gt;“The separator output and reference are not synchronized.”&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  Core rule: synchronize first, score second.
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What should be normalized before scoring?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A fair audio benchmark should make these conditions consistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sample rate;&lt;/li&gt;
&lt;li&gt;channel layout;&lt;/li&gt;
&lt;li&gt;start time;&lt;/li&gt;
&lt;li&gt;duration;&lt;/li&gt;
&lt;li&gt;stem definition;&lt;/li&gt;
&lt;li&gt;output format;&lt;/li&gt;
&lt;li&gt;quality tier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our two-stem benchmark, every evaluated output was synchronized at 44.1 kHz before scoring. The reference vocal came from the dataset’s ground-truth vocal stem, and the instrumental reference was calculated from the mixture minus vocals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Resample and convert to mono&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a controlled experiment, every waveform should use the same sample rate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gcd&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;scipy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_mono&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Convert mono or channel-last audio to one float64 waveform.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndim&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndim&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expected mono audio or channel-last stereo audio&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resample_audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;source_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Resample with a polyphase filter.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;source_rate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;target_rate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sample rates must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;source_rate&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;gcd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_rate&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;
    &lt;span class="n"&gt;down&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source_rate&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resample_poly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For a production benchmark, preserve the original stereo files separately. Mono conversion makes the timing example easier, but it does not evaluate spatial imaging or stereo artifacts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Estimate the lag with cross-correlation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cross-correlation asks:&lt;/p&gt;

&lt;p&gt;At what shift do these two signals match most strongly?&lt;/p&gt;

&lt;p&gt;A practical implementation should limit the search window. Songs contain repeated beats and repeated sections, so searching across the entire duration can match the wrong chorus or drum pattern.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;standardize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Remove the mean and scale variance for correlation only.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;centered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;std&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1e-12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot align a silent or near-silent waveform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;centered&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;estimate_lag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_lag_seconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Return the sample shift to apply to the estimate.

    Positive return value: shift estimate right.
    Negative return value: shift estimate left.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sample_rate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample_rate must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;standardize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;standardize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;correlation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;correlate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fft&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;correlation_lags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;max_lag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_lag_seconds&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;max_lag&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No candidate lags were available&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;candidate_corr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;correlation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;candidate_lags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;best_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate_corr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate_lags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;best_index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The function returns the shift that should be applied to the estimate.&lt;/p&gt;

&lt;p&gt;A negative lag means the estimate is delayed and should be moved left.&lt;/p&gt;

&lt;p&gt;A positive lag means it should be moved right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Apply the shift without changing content&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alignment should correct timing only.&lt;/p&gt;

&lt;p&gt;It should not denoise, equalize, compress, or otherwise “improve” one product’s output.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;shift_to_reference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;lag_samples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reference_length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Shift an estimate and return exactly reference_length samples.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reference_length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reference_length must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lag_samples&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;shifted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lag_samples&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;lag_samples&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lag_samples&lt;/span&gt;
        &lt;span class="n"&gt;shifted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;advance&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;shifted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;shifted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;reference_length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;shifted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;shifted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reference_length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;shifted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;shifted&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;reference_length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now combine the steps:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;align_for_evaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_lag_seconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Align estimate to reference and report the applied lag.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_mono&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_mono&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;lag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;estimate_lag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_lag_seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;max_lag_seconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shift_to_reference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;lag_samples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;reference_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lag&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 4: Verify the alignment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never assume the largest correlation peak is correct.&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the lag in samples;&lt;/li&gt;
&lt;li&gt;the lag in milliseconds;&lt;/li&gt;
&lt;li&gt;the correlation before and after;&lt;/li&gt;
&lt;li&gt;a short waveform overlay;&lt;/li&gt;
&lt;li&gt;a listening test around transients.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lag_in_milliseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;lag_samples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1000.0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;lag_samples&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;sample_rate&lt;/span&gt;


&lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;align_for_evaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reference_vocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;estimated_vocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;44_100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Applied lag:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;samples&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Applied lag:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;lag_in_milliseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;44_100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the reported shift is unexpectedly large, do not continue automatically. Investigate whether:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the wrong file was loaded;&lt;/li&gt;
&lt;li&gt;the stem starts at a different song section;&lt;/li&gt;
&lt;li&gt;the export was trimmed;&lt;/li&gt;
&lt;li&gt;there is a sample-rate mismatch;&lt;/li&gt;
&lt;li&gt;the signal contains long silence;&lt;/li&gt;
&lt;li&gt;repetitive music created a false correlation peak.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why alignment can still fail&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Repeated beats&lt;/p&gt;

&lt;p&gt;A steady kick pattern can create several strong peaks. Restrict the lag window and use a section with distinctive transients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long silence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Silence contains little information. Skip silent intros or align on an active excerpt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different source content&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If one tool removes part of the vocal or damages the transient structure, correlation may become less reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stereo phase differences&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Averaging stereo channels can cancel information. For stereo evaluation, consider aligning channels separately or using a carefully chosen mono reference only for timing estimation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variable delay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A constant shift cannot correct clock drift, time stretching, or nonlinear resampling. If the offset changes through the song, inspect the sample rates and processing pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where SI-SDR fits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After alignment, SI-SDR can answer the intended question:&lt;br&gt;
How closely does the estimated stem match its reference after accounting for scale?&lt;br&gt;
SI-SIR adds information about unwanted source leakage, while SI-SAR focuses on artifacts introduced by separation.&lt;/p&gt;

&lt;p&gt;A strong music-separation benchmark should report several metrics and also provide playable audio. One overall number cannot explain missing cymbals, metallic textures, damaged reverb, or vocal residue.&lt;/p&gt;

&lt;p&gt;Our five-song benchmark reported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://neuralsound.org/" rel="noopener noreferrer"&gt;NeuralSound&lt;/a&gt;: &lt;strong&gt;15.80 dB&lt;/strong&gt; overall SI-SDR;&lt;/li&gt;
&lt;li&gt;Moises: 14.47 dB;&lt;/li&gt;
&lt;li&gt;Fadr: 12.59 dB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those numbers are limited to the tested songs and configuration. They are not a universal ranking.&lt;br&gt;
You can inspect the per-track audio and methodology in the &lt;a href="https://neuralsound.org/compare/ai-vocal-remover-2026" rel="noopener noreferrer"&gt;NeuralSound vs Moises vs Fadr comparison&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A reproducibility checklist&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before comparing an AI vocal remover or stem separator, record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;input file hash;&lt;/li&gt;
&lt;li&gt;sample rate and channel count;&lt;/li&gt;
&lt;li&gt;product and plan;&lt;/li&gt;
&lt;li&gt;separation mode;&lt;/li&gt;
&lt;li&gt;test date;&lt;/li&gt;
&lt;li&gt;output format;&lt;/li&gt;
&lt;li&gt;estimated lag;&lt;/li&gt;
&lt;li&gt;duration correction;&lt;/li&gt;
&lt;li&gt;metric implementation;&lt;/li&gt;
&lt;li&gt;failures and retries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also publish the raw results when possible.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/neuralgpt407" rel="noopener noreferrer"&gt;
        neuralgpt407
      &lt;/a&gt; / &lt;a href="https://github.com/neuralgpt407/ai-vocal-remover-benchmark-2026" rel="noopener noreferrer"&gt;
        ai-vocal-remover-benchmark-2026
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.neuralsound.musicseparation" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Download NeuralSound for Android on Google Play" src="https://camo.githubusercontent.com/ca038abc27edb06b242ec05e5d6814397b172c38a0f9b565824e672a07ba7f07/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f416e64726f69642d476f6f676c655f506c61792d3431343134313f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65706c6179266c6f676f436f6c6f723d7768697465"&gt;&lt;/a&gt;
&lt;a href="https://neuralsound.org/tools/music-separation" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Open the NeuralSound web app" src="https://camo.githubusercontent.com/db21afd6fc65de34814584bdf7cd437179d02114ff51add5b1f1160338d01abb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5765622d4f70656e5f4e657572616c536f756e642d3743334145443f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c656368726f6d65266c6f676f436f6c6f723d7768697465"&gt;&lt;/a&gt;
&lt;a href="https://apps.apple.com/us/app/neuralsound-vocal-remover-ai/id6756906827" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Download NeuralSound for iPhone and iPad on the App Store" src="https://camo.githubusercontent.com/2dfaa7f494faf467059e5d4d359a6563c4013dee5b7da9d4b452e18a71071cf3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f694f532d4170705f53746f72652d3044393646363f7374796c653d666f722d7468652d6261646765266c6f676f3d6170706c65266c6f676f436f6c6f723d7768697465"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NeuralSound AI Vocal Remover Benchmark 2026&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;NeuralSound vs Moises vs Fadr&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A playable five-song comparison of AI vocal removal and two-stem music separation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/neuralgpt407/ai-vocal-remover-benchmark-2026#benchmark-results" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8832bdf701b68c798e102446f2783f36853b529cbc1e1a9ea6e5e8f2cf582572/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e657572616c536f756e642532306f766572616c6c25323053492d2d5344522d31352e383025323064422d313661333461" alt="Overall SI-SDR"&gt;&lt;/a&gt;
&lt;a href="https://github.com/neuralgpt407/ai-vocal-remover-benchmark-2026#benchmark-results" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3e31e866cce2c82866a185fa7461378210f9f3639adce6a0e9e6981a5ffb7f85/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646973706c617965642532306d657472696325323077696e732d33302532306f6625323033302d376333616564" alt="Displayed metric wins"&gt;&lt;/a&gt;
&lt;a href="https://github.com/neuralgpt407/ai-vocal-remover-benchmark-2026#play-and-download-every-audio-result" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/cc0e3f69f53ba6ddb595cddfee098edf0f2e9b51199f155714516159d1db703b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f736f6e67732532307465737465642d352d333334313535" alt="Songs tested"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About NeuralSound&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://neuralsound.org/" rel="nofollow noopener noreferrer"&gt;NeuralSound&lt;/a&gt; is an &lt;strong&gt;AI vocal remover, online music separator and multi-stem splitter&lt;/strong&gt; available on the web, Android, iPhone and iPad. It can separate a mixed song or video into clean &lt;strong&gt;vocals, drums, bass, guitar, piano and other instrument stems&lt;/strong&gt;, helping musicians, DJs, singers, producers and content creators work with individual parts of a recording.&lt;/p&gt;
&lt;p&gt;Use NeuralSound to &lt;a href="https://neuralsound.org/vocal-remover" rel="nofollow noopener noreferrer"&gt;remove vocals from a song&lt;/a&gt;, create an instrumental or backing track, &lt;a href="https://neuralsound.org/acapella-extractor" rel="nofollow noopener noreferrer"&gt;extract an acapella&lt;/a&gt;, &lt;a href="https://neuralsound.org/ai-music-separator" rel="nofollow noopener noreferrer"&gt;split music into stems&lt;/a&gt;, reduce music behind a voice with the &lt;a href="https://neuralsound.org/background-music-remover" rel="nofollow noopener noreferrer"&gt;background music remover&lt;/a&gt;, or prepare practice tracks with the &lt;a href="https://neuralsound.org/karaoke-maker" rel="nofollow noopener noreferrer"&gt;AI karaoke maker&lt;/a&gt;. NeuralSound also supports synchronized lyrics, pitch and tempo controls, stem mixing, audio/video input and downloadable separated tracks.&lt;/p&gt;
&lt;p&gt;This repository publishes original benchmark evidence for people…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/neuralgpt407/ai-vocal-remover-benchmark-2026" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The live benchmark provides the playable inputs and outputs, while the GitHub repository contains the public project resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product context without turning the article into an ad&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This post focuses on evaluation rather than product claims.&lt;/p&gt;

&lt;p&gt;For readers unfamiliar with the terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;a href="https://neuralsound.org/" rel="noopener noreferrer"&gt;AI vocal remover&lt;/a&gt; separates vocals and instrumental;&lt;/li&gt;
&lt;li&gt;an &lt;a href="https://neuralsound.org/tools/music-separation" rel="noopener noreferrer"&gt;AI music separator&lt;/a&gt; can additionally isolate drums, bass, guitar, piano, and other stems
.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The engineering lesson applies to any provider:&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  Synchronize first. Score second. Publish enough detail for others to reproduce the result.
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Final takeaway&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few milliseconds can make a good model look bad.&lt;/p&gt;

&lt;p&gt;Before trusting SI-SDR, SI-SIR, or SI-SAR:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;standardize the sample rate and channels;&lt;/li&gt;
&lt;li&gt;estimate a bounded timing offset;&lt;/li&gt;
&lt;li&gt;apply timing correction only;&lt;/li&gt;
&lt;li&gt;verify the shift visually and audibly;&lt;/li&gt;
&lt;li&gt;calculate multiple metrics;&lt;/li&gt;
&lt;li&gt;publish enough detail for others to reproduce the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That process creates a more honest music source-separation benchmark—and prevents timing errors from being mistaken for model errors.&lt;/p&gt;

&lt;p&gt;References&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MUSDB18 dataset documentation&lt;/li&gt;
&lt;li&gt;SDR — Half-baked or Well Done?&lt;/li&gt;
&lt;li&gt;Interactive NeuralSound benchmark&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>podcast</category>
      <category>ai</category>
    </item>
    <item>
      <title>How We Benchmarked 3 AI Vocal Removers with SI-SDR, SI-SIR, and SI-SAR</title>
      <dc:creator>Neural Sound</dc:creator>
      <pubDate>Fri, 31 Jul 2026 23:03:10 +0000</pubDate>
      <link>https://dev.to/neural_sound/how-we-benchmarked-3-ai-vocal-removers-with-si-sdr-si-sir-and-si-sar-3544</link>
      <guid>https://dev.to/neural_sound/how-we-benchmarked-3-ai-vocal-removers-with-si-sdr-si-sir-and-si-sar-3544</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; &lt;em&gt;&lt;strong&gt;NeuralSound designed and conducted this benchmark. Moises and Fadr did not review or approve the test. The same input files and evaluation pipeline were used for all three services.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Comparing AI vocal removers is harder than uploading one song and deciding which result sounds louder or cleaner.&lt;/p&gt;

&lt;p&gt;Cloud services may introduce timing offsets, export different file lengths, apply different output levels, and update their models without exposing a version number. A fair comparison therefore needs consistent inputs, reference stems, time alignment, objective metrics, and audible examples.&lt;/p&gt;

&lt;p&gt;We compared &lt;a href="https://neuralsound.org/" rel="noopener noreferrer"&gt;NeuralSound&lt;/a&gt;, &lt;a href="https://moises.ai/" rel="noopener noreferrer"&gt;Moises&lt;/a&gt;, and &lt;a href="https://fadr.com/" rel="noopener noreferrer"&gt;Fadr&lt;/a&gt; on the same five songs in two-stem mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;isolated vocals&lt;/li&gt;
&lt;li&gt;instrumental&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full interactive benchmark includes 35 playable previews and the complete per-track results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://neuralsound.org/compare/ai-vocal-remover-2026" rel="noopener noreferrer"&gt;▶️ Play the full benchmark&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The evaluation question&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For each product, we wanted to answer three separate questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How closely does the estimated stem match the   reference?&lt;/li&gt;
&lt;li&gt;How much of the unwanted source remains?&lt;/li&gt;
&lt;li&gt;How many artifacts were introduced by the separation process?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is why we used three related metrics instead of relying on one score:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SI-SDR for overall reconstruction quality&lt;/li&gt;
&lt;li&gt;SI-SIR for unwanted source interference&lt;/li&gt;
&lt;li&gt;SI-SAR for processing artifacts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Test setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We used the first five songs in the valid folder of the MUSDB18-HQ source used for this study.&lt;/p&gt;

&lt;p&gt;For every track:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The identical mixture was uploaded to all three services.&lt;/li&gt;
&lt;li&gt;Each service produced a vocal stem and an instrumental stem.&lt;/li&gt;
&lt;li&gt;The original vocal stem was used as the vocal reference.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The instrumental reference was calculated as:&lt;br&gt;
&lt;strong&gt;instrumental_reference = mixture - vocals&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evaluation signals were converted to mono at 44.1 kHz.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Estimated outputs were aligned with the references.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Timing and length differences were corrected only for synchronization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No denoising, EQ, or post-processing was applied before scoring.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why alignment matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even a good separation can score poorly if the estimate is shifted by a few milliseconds.&lt;/p&gt;

&lt;p&gt;A simplified alignment step looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;scipy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;align_estimate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Align an estimated mono waveform to a mono reference waveform.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndim&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndim&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reference and estimate must be mono waveforms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;waveforms must not be empty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;correlation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;correlate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fft&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;correlation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lag&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;lag&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lag&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only the alignment stage, not a complete source-separation evaluator. In a production benchmark, also validate sample rate, channel layout, clipping, silent references, and file integrity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the metrics measure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SI-SDR: overall reconstruction quality:&lt;/strong&gt;&lt;br&gt;
SI-SDR measures how closely an estimated stem matches its reference after accounting for a simple difference in scale.&lt;/p&gt;

&lt;p&gt;Higher is better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SI-SIR: unwanted source leakage:&lt;/strong&gt;&lt;br&gt;
SI-SIR focuses on interference from the wrong source.&lt;/p&gt;

&lt;p&gt;For an isolated vocal, a higher score generally means less accompaniment remains in the vocal. For an instrumental, it generally means less vocal residue remains in the music.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SI-SAR: processing artifacts:&lt;/strong&gt;&lt;br&gt;
SI-SAR focuses on artifacts introduced by the separation system.&lt;/p&gt;

&lt;p&gt;Listeners may hear these as metallic textures, unstable reverb, watery sounds, missing transients, or robotic vocal edges.&lt;/p&gt;

&lt;p&gt;The SI-SDR formulation was proposed as a simpler and more robust alternative to commonly misused SDR implementations in source-separation evaluation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmubakefsmf1hamn74iie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmubakefsmf1hamn74iie.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://neuralsound.org/" rel="noopener noreferrer"&gt;NeuralSound&lt;/a&gt; produced the highest average measured result in this five-song test.&lt;/p&gt;

&lt;p&gt;That statement is intentionally narrow. It does not mean NeuralSound will perform best on every song, genre, model version, or export setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Averages hide track-level variation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The per-track results were not equally difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The So So Glos — Emergency&lt;/strong&gt; produced the lowest average SI-SDR for all three services:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;NeuralSound: 12.31 dB&lt;/li&gt;
&lt;li&gt;Moises: 11.52 dB&lt;/li&gt;
&lt;li&gt;Fadr: 10.13 dB&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Wrong’Uns — Rothko&lt;/strong&gt; produced the highest average SI-SDR for all three:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;NeuralSound: 19.88 dB&lt;/li&gt;
&lt;li&gt;Moises: 18.11 dB&lt;/li&gt;
&lt;li&gt;Fadr: 14.97 dB&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is one reason a single aggregate number is not enough. Separation quality depends heavily on the source mix, vocal reverb, instrument overlap, distortion, and arrangement density.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Synchronization is part of evaluation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A timing offset can change the score even when the audio sounds similar. Alignment must be documented rather than treated as an invisible cleanup step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One metric cannot describe the whole result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A system can reduce interference while introducing artifacts. SI-SDR, SI-SIR, and SI-SAR should be interpreted together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Listening tests still matter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Objective metrics make the comparison reproducible, but they do not fully represent human preference.&lt;/p&gt;

&lt;p&gt;Listeners should still check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accompaniment inside the vocal&lt;/li&gt;
&lt;li&gt;lead-vocal residue inside the instrumental&lt;/li&gt;
&lt;li&gt;missing cymbals or guitar attacks&lt;/li&gt;
&lt;li&gt;phasey stereo effects&lt;/li&gt;
&lt;li&gt;unstable ambience&lt;/li&gt;
&lt;li&gt;damaged vocal texture and reverb&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This benchmark has several important limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;only five songs were tested&lt;/li&gt;
&lt;li&gt;only two-stem separation was evaluated&lt;/li&gt;
&lt;li&gt;there was no blind listening panel&lt;/li&gt;
&lt;li&gt;cloud services may update their models&lt;/li&gt;
&lt;li&gt;account tier and export format may affect  results&lt;/li&gt;
&lt;li&gt;NeuralSound conducted the study&lt;/li&gt;
&lt;li&gt;the result is not an official MUSDB18 leaderboard
A stronger follow-up should include more tracks, more genres, equivalent lossless exports, repeated processing runs, and a blind listening test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Reproduce or inspect the full benchmark&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The interactive page includes:&lt;/li&gt;
&lt;li&gt;five original mixtures&lt;/li&gt;
&lt;li&gt;15 vocal outputs&lt;/li&gt;
&lt;li&gt;15 instrumental outputs&lt;/li&gt;
&lt;li&gt;per-track SI-SDR, SI-SIR, and SI-SAR&lt;/li&gt;
&lt;li&gt;methodology and limitations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://neuralsound.org/compare/ai-vocal-remover-2026" rel="noopener noreferrer"&gt;▶️ Open the NeuralSound vs Moises vs Fadr benchmark&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;References&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sigsep.github.io/datasets/musdb.html" rel="noopener noreferrer"&gt;MUSDB18 dataset documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>python</category>
      <category>podcast</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
