CorentinJ/Real-Time-Voice-Cloning · error · ValueError

Both increase only and decrease only are set

Error message

Both increase only and decrease only are set

What it means

Raised by normalize_volume() in encoder/audio.py when both `increase_only` and `decrease_only` keyword arguments are True. These flags are mutually exclusive: increase_only means 'only amplify quiet audio', decrease_only means 'only attenuate loud audio'. Setting both is a contradictory request (the function would have to both apply and skip any gain change), so it fails fast with a ValueError before touching the waveform.

Source

Thrown at encoder/audio.py:113

    def moving_average(array, width):
        array_padded = np.concatenate((np.zeros((width - 1) // 2), array, np.zeros(width // 2)))
        ret = np.cumsum(array_padded, dtype=float)
        ret[width:] = ret[width:] - ret[:-width]
        return ret[width - 1:] / width
    
    audio_mask = moving_average(voice_flags, vad_moving_average_width)
    audio_mask = np.round(audio_mask).astype(bool)
    
    # Dilate the voiced regions
    audio_mask = binary_dilation(audio_mask, np.ones(vad_max_silence_length + 1))
    audio_mask = np.repeat(audio_mask, samples_per_window)
    
    return wav[audio_mask == True]


def normalize_volume(wav, target_dBFS, increase_only=False, decrease_only=False):
    if increase_only and decrease_only:
        raise ValueError("Both increase only and decrease only are set")
    dBFS_change = target_dBFS - 10 * np.log10(np.mean(wav ** 2))
    if (dBFS_change < 0 and increase_only) or (dBFS_change > 0 and decrease_only):
        return wav
    return wav * (10 ** (dBFS_change / 20))

View on GitHub (pinned to 890f3a0318)

Solutions

  1. Pass at most one of increase_only / decrease_only (both False is valid and applies the gain unconditionally).
  2. If the two flags come from a config object, validate them together at config load time and fail with a clearer message naming the config keys.
  3. If you want a deadband (neither boost nor cut), that is not what these flags do — clamp dBFS_change yourself before calling with both flags False.

Example fix

// before
normalize_volume(wav, -30, increase_only=True, decrease_only=True)

// after
normalize_volume(wav, -30, increase_only=True)
Defensive patterns

Strategy: validation

Validate before calling

def safe_normalize(wav, target_dbfs, increase_only=False, decrease_only=False):
    if increase_only and decrease_only:
        raise ValueError("increase_only and decrease_only are mutually exclusive")
    return normalize_volume(wav, target_dbfs, increase_only, decrease_only)

Try / catch

try:
    out = normalize_volume(wav, -30, increase_only=boost, decrease_only=cut)
except ValueError as e:
    if "increase only" in str(e):
        boost = boost and not cut  # resolve conflict, prefer decrease_only
        out = normalize_volume(wav, -30, increase_only=boost, decrease_only=cut)
    else:
        raise

Prevention

When it happens

Trigger: Calling normalize_volume(wav, target_dBFS, increase_only=True, decrease_only=True). In this codebase the caller is encoder_preprocess.py's preprocess_wav path (volume normalization during trimming); in user code, any direct call passing both flags or a config that maps two independent booleans onto these parameters.

Common situations: A wrapper/config that exposes separate 'allow_boost' and 'allow_cut' options and forwards them verbatim; copying example code and flipping flags without reading the semantics; defaulting both parameters to True 'to be safe'.

Related errors


AI-assisted analysis of CorentinJ/Real-Time-Voice-Cloning@890f3a0318 (2026-08-15). Data as JSON: /api/errors/cac01154cb328c08. Report an issue: GitHub.