Skip to main content

VNDecorrelate

VersionPyPITests

A Velvet-Noise Decorrelator for audio.

Decorrelation refers to the process of transforming an audio source signal into multiple output signals with different waveforms from each other, but with the same sound as the source signal [1].

In music production, decorrelation is typically applied to the left and right audio channels, creating the perception of stereo width and space. This, however, may come at the cost of potential coloration or transient smearing artifacts.

Velvet-Noise Decorrelation (VND) attempts to minimize these artifacts as well as computation cost while reducing the correlation of the outputs as much as possible [2].

Velvet Noise

Velvet Noise is a sparse noise sequence generated from randomly time-shifted impulses with a random value of either -1 or 1 [2]:

Basic Velvet Noise

To reduce transient smearing and frequency coloration you can apply a segmented decay envelope [2]:

Segmented Decaying Velvet Noise

As well as logarithmically distribute the impulses towards the start of the sequence [2]:

Segmented Decaying Log Distributed Velvet Noise

Quick Start

First install the package into your environment: pip install vndecorrelate

Then load an audio file.

import scipy.io.wavfile as wavfile
from vndecorrelate.decorrelation import *

fs, input_signal = wavfile.read("audio/viola.wav")

Then you can simply use the VelvetNoise class:

velvet_noise = VelvetNoise(
    sample_rate_hz=fs,
    duration_seconds=0.03,
    num_impulses=30,
)
output_signal = velvet_noise.decorrelate(input_signal)

Or:

# manually generate the velvet noise as numpy NDArrays
velvet_noise = generate_velvet_noise(
    duration_seconds=0.03,
    num_impulses=30,
)
# numerically equivalent to VelvetNoise.convolve
output_signal = convolve_velvet_noise(input_signal, velvet_noise)

Or you can create a chain of signal processors:

chain = (
    SignalChain(sample_rate_hz=fs)
    .velvet_noise(
        duration_seconds=0.03,
        num_impulses=30,
        log_distribution_strength=1.0,
        seed=1,
    )
    .haas_effect(
        delay_time_seconds=0.02,
        delayed_channel=1, # Right Channel
        mode='LR',
    )
)
# SignalChain is lazy, so instatiation of its signal processors happens here
output_signal = chain(input_signal)

To listen back to the processed audio, simply save to a wav file locally.

wavfile.write('audio/viola_out.wav', fs, output_signal)

Optimization

optimization.py contains functions for optimizing VelvetNoise or HaasEffect for maximizing stereo seperation while maintaining polar sample symmetry and mono compatiblilty.

optimize_velvet_noise optimizes the concentration of impulses towards the start of the filter referred to as log_distribution_strength:

Kappa

optimize_haas_delay optimizes the delay_time_seconds parameter:

Tau

symmetry_aware_objective takes the input signal and converts it to polar samples to compute the scalar objective function defined by:

Symmetry Aware Objective
where Alpha is the input scalar to optimize, each Moment is a moment of the polar sample distribution:
Weighted Angular Variance is the weighted angular variance
Centroid is the weighted mean (centroid)
Skewness is the skewness,
R is the correlation between the input left and right channels, Phi is the angle constraint threshold, and each Lambda is a penalty weight.

Visualization

Vectorscopes

Sample runs of VelvetNoise.decorrelate with unoptimized and optimized filters can be compared by their polar sample plots generated from plot_polar_sample:

VN Optimized Polar Sample

plot_polar_level:

VN Optimized Polar Level

or plot_lissajous:

VN Optimized Lissajous

These vectorscope functions loosely follow the design of Izotope's Ozone Imager [3], an industry standard stereo imager plugin for Digital Audio Workstations.

Correlograms

To provide further visualization of the effects decorrelation plot_correlogram is provided. Short windows of typically ~20ms are taken from two signals to calculate normalized cross-correlation values at various lag distances. sine_sweep can be used to generate a test signal that can be compared before and after applying a velvet noise decorrelation. Sine Sweep Signal We can use the auto correlogram as a baseline: Sine Sweep Auto Correlogram Plot the cross correlogram after filtering each channel with velvet noise: Velvet Noise Filtered Sine Sweep Cross Correlogram And compare to the behavior of filtering with white noise: White Noise Filtered Sine Sweep Cross Correlogram

References

[1] Sweetwater, “Decorrelation,” InSync, Dec. 17, 2004. https://www.sweetwater.com/insync/decorrelation/ (accessed May 15, 2026).

[2] B. Alary, A. Politis, and V. Välimäki, “VELVET-NOISE DECORRELATOR,” Proceedings of the 20th International Conference on Digital Audio Effects (DAFx-17), Edinburgh, UK, Sep. 2017. Accessed: May 15, 2026. [Online]. Available: http://www.dafx17.eca.ed.ac.uk/papers/DAFx17_paper_96.pdf

[3] “Ozone 8 Help Documentation,” Izotope.com, 2017. https://downloads.izotope.com/docs/ozone8/imager/index.html#vectorscope (accessed Jun. 15, 2026).

Metadata

Release files for vndecorrelate 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vndecorrelate 1.1.0
File Size Uploaded
vndecorrelate-1.1.0.tar.gz 17.7 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for vndecorrelate 1.1.0
File Interpreter ABI Platform
vndecorrelate-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.7 MB

Release files / vndecorrelate-1.1.0.tar.gz

Download URL vndecorrelate-1.1.0.tar.gz
Size 17.7 MB
Tags Source
SHA-256 checksum
How to use checksums
a3d5c175a57098f96fd58a532024f993c6155ccb1b8e1ddb38da27ea0d8436a1
BLAKE2b-256 checksum
How to use checksums
cfdbc1b18393e84ee2f226b420f6729ededd9450e5b55de7a4669d5fdd27ab71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.

Transparency log

Release files / vndecorrelate-1.1.0-py3-none-any.whl

Download URL vndecorrelate-1.1.0-py3-none-any.whl
Size 28.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b4fbcd4ddaeaa23602568a1eac70afbbf83fc8dff448a56e3000ac9e62140594
BLAKE2b-256 checksum
How to use checksums
1e51e091f9cf1e08a8553450bb982a142c0d1508a44fdbe8960035a764b81ee7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page