Exponential Audio Unmute

Jeff T August 7, 2011 Coded in Matlab

Sometimes "unmuting" audio can appear to be a simple task on the surface.  However, if you are not careful you can end up with artifacts that are commonly referred to as pops and clicks.  This is both an auditory response and a speaker response.


Remember, the audio you are controlling is ultimately driving a speaker which has it's own suspension and compliance to control how the cone moves.  So as much as you may want the sound pressure waves traveling to the listeners ear to suddenly start... the speaker physics has something completely different in mind.


The most common way to unmute audio is to exponentially ramp up the signal at a slow enough rate to allow the speaker to begin moving and not minize any audible high frequency effect caused by ramping.  The code below will accept your matlab signal and apply a unmute at the desired index (typically the beginning).  So if you have a 10sec audio signal and want to apply it at the 2 sec mark, simply apply the proper index for the unmuting to begin.  Below is an example of a noise input being unmuted half-way through the signal.


Unmuting a noise source

function [y] = signal_unmute(x, index, duration, Fs)
% Return the input vector with a unmute that occurs at a specific
% index and with an exponential ramp-up to reduce "pop" sounds.
% The output will start off at -100dB gain and end at 0dB gain.
% Usage: y = SIGNAL_UNMUTE(x, index, duration, Fs);
%        X is your one-dimensional input array
%        INDEX is where in the input signal you want the unmute to begin
%        DURATION is how long (in seconds) to exponentially ramp up the
%           input signal. 100ms is recommended.
%        FS is the sample rate
% Example: 
%        You want to unmute your signal at 0.5sec with a duration of 100ms 
%        and with a 48k Fs. (signal is unmuted completely at 0.6sec)
%        y = signal_mute(x, 24000, 0.1, 48000);
% Author: sparafucile17 7/29/2003

% Input must have some length
if(length(x) == 1)
    error('ERROR: input signal must have more than one element');

% This function only supports one-dimensional arrays
if((size(x, 2) ~= 1) && (size(x, 1) ~= 1))
    error('ERROR: Input must be one-dimensional');

% Make sure there are enough samples to complete the mute
if(length(x) < (index + duration*Fs))
    error(['There are not enough samples in X to complete the unmute.  '  ...
           'Either change the mute duration or move the index back.' ]);

% Flip vector (temporarily)
if((size(x, 2) ~= 1))
    x = x';
    flip_back = true;
    flip_back = false;

% Calculate exponential coefficient
dB_atten  = -100; %What do we consider "muted" to be in decibels
decayrate = -dB_atten / duration;
coeff = 1.0 - 10^(-decayrate/(20.0*Fs));

% Build the Gain array
gain = [zeros(index, 1); ones((length(x)-index), 1);];
b = [ coeff  0];
a = [ 1 (-1*(1-coeff))];
gain  = filter(b,a,gain);

% Apply Mute (gain) to the input signal
y = gain .* x;

% Flip the vector (if required)
if(flip_back == true);
    y = y';