Exponential Audio Mute
Sometimes "muting" 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 move. So as much as you may want the sound pressure waves traveling to the listeners ear to suddenly stop... the speaker physics has something completely different in mind.
The most common way to mute audio is to exponentially ramp down the signal at a slow enough rate to allow the speaker to slow down and not minize any audible high frequency effect caused by ramping. The code below will accept your matlab signal and apply a mute at the desired index. 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 muting to begin. Below is an example of a muted noise input.
function [y] = signal_mute(x, index, duration, Fs)
% Return the input vector with a mute that occurs at a specific
% index and with an exponential ramp-down to reduce "pop" sounds.
% The output will start off at 0dB gain and end at -100dB gain.
%
% Usage: y = SIGNAL_MUTE(x, index, duration, Fs);
%
% X is your one-dimensional input array
% INDEX is where in the input signal you want the mute to begin
% DURATION is how long (in seconds) to exponentially ramp down the
% input signal. 100ms is recommended.
% FS is the sample rate
%
% Example:
% You want to mute your signal at 0.5sec with a duration of 100ms
% and with a 48k Fs. (mute complete 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');
end
% This function only supports one-dimensional arrays
if((size(x, 2) ~= 1) && (size(x, 1) ~= 1))
error('ERROR: Input must be one-dimensional');
end
% 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 mute. ' ...
'Either change the mute duration or move the index back.' ]);
end
% Flip vector (temporarily)
if((size(x, 2) ~= 1))
x = x';
flip_back = true;
else
flip_back = false;
end
% Calculate exponential coefficient
dB_atten = -100; %How much attenuation will be at time: index + duration
decayrate = -dB_atten / duration;
coeff = 1.0 - 10^(-decayrate/(20.0*Fs));
% Build the Gain array
gain = [ones(index, 1); zeros((length(x)-index), 1);];
b = [ coeff 0];
a = [ 1 (-1*(1-coeff))];
gain = filter(b,a,gain, [1]);
% Remove minor overshoot at the beginning of gain vector
gain(find(gain > 1)) = 1;
% Apply Mute (gain) to the input signal
y = gain .* x;
% Flip the vector (if required)
if(flip_back == true);
y = y';
end