audio - How to amplify sounds without distortion in Python -
i trying naive volume adjustment of sound file. using python 2.7 , following
libraries:
import numpy np import scipy.io.wavfile wv import matplotlib.pyplot plt import pyaudio import wave i have tried 2 approaches, trying amplify sound 2, ie. n=2. first altered dyanmic range limiter approach here (http://bastibe.de/2012-11-02-real-time-signal-processing-in-python.html):
def limiter(self, n): #best version far signal=self.snd_array attack_coeff = 0.01 framemax=2**15-1 threshold=framemax in np.arange(len(signal)): #if amplitude value * amplitude gain factor > threshold set interval decrease amplitude if signal[i]*n > threshold: gain=1 jmin=0 jmax=0 if i-100>0: jmin=i-100 else: jmin=0 if i+100<len(signal): jmax=i+100 else: jmax=len(signal) j in range(jmin,jmax): #target gain amplitude factor times exponential smoothly decrease amp factor (n) target_gain = n*np.exp(-10*(j-jmin)) gain = (gain*attack_coeff + target_gain*(1-attack_coeff)) signal[j]=signal[j]*gain else: signal[i] = signal[i]*n print max(signal),min(signal) plt.figure(3) plt.plot(signal) return signal the second method hard knee compression decrease amplitude of sound values above threshold , amplify whole signal amplitude gain factor.
def compress(self,n): print 'start compress' threshold=2**15/n+1000 #compress values above threshold, therefore limiting audio amplitude range in np.arange(len(self.snd_array)): if abs(self.snd_array[i])>threshold: factor=1+(threshold-abs(self.snd_array[i]))/threshold else: factor=1.0 #apply compression factor , amp gain factor (n) self.snd_array[i] = self.snd_array[i]*factor*n print np.min(self.snd_array),np.max(self.snd_array) plt.figure(2) plt.plot(self.snd_array,'k') return self.snd_array in both methods file sounds distorted. @ points amplitudes near threshold music sounds clipped , crackly. think because "flattens" out near threshold value. tried applying exponential in limiter function not remove crackling sound when make decrease quickly. if change n=1.5 sound not distorted. if give me pointers on how remove crackling distortion or links other volume modulation code appreciated.
it might not 100% on topic, maybe interesting anyway. if not need real time processing, things can made more easy. limiting , dynamic compression can seen applying dynamic transfer function. function maps input output values. linear function returns original audio , "curved" function compression or expansion. applying transfer function simple as
import numpy np scipy.interpolate import interp1d scipy.io import wavfile def apply_transfer(signal, transfer, interpolation='linear'): constant = np.linspace(-1, 1, len(transfer)) interpolator = interp1d(constant, transfer, interpolation) return interpolator(signal) limiting or compression case of choosing different transfer function:
# hard limiting def limiter(x, treshold=0.8): transfer_len = 1000 transfer = np.concatenate([ np.repeat(-1, int(((1-treshold)/2)*transfer_len)), np.linspace(-1, 1, int(treshold*transfer_len)), np.repeat(1, int(((1-treshold)/2)*transfer_len)) ]) return apply_transfer(x, transfer) # smooth compression: if factor small, near linear, bigger # stronger compression def arctan_compressor(x, factor=2): constant = np.linspace(-1, 1, 1000) transfer = np.arctan(factor * constant) transfer /= np.abs(transfer).max() return apply_transfer(x, transfer) this example assumes 16 bit mono wav files input:
sr, x = wavfile.read("input.wav") x = x / np.abs(x).max() # x scale between -1 , 1 x2 = limiter(x) x2 = np.int16(x2 * 32767) wavfile.write("output_limit.wav", sr, x2) x3 = arctan_compressor(x) x3 = np.int16(x3 * 32767) wavfile.write("output_comp.wav", sr, x3) maybe clean offline code helps benchmark realtime code.
Comments
Post a Comment