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

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

android - Keyboard hides my half of edit-text and button below it even in scroll view -

css - Make div keyboard-scrollable in jQuery Mobile? -