title: From Amplitude or FFT to dB
body: <p>I've a Python code which performs FFT on a wav file and plot the amplitude vs time / amplitude vs freq graphs. I want to calculate dB from these graphs (they are long arrays). I do not want to calculate exact dBA, I just want to see a linear relationship after my calculations. I've dB meter, I will compare it. Here is my code:</p>
  
  <pre><code>#!/usr/bin/env python
  # -*- coding: utf-8 -*-
  
  from __future__ import print_function
  import scipy.io.wavfile as wavfile
  import scipy
  import scipy.fftpack
  import numpy as np
  from matplotlib import pyplot as plt
  
  fs_rate, signal = wavfile.read("output.wav")
  print ("Frequency sampling", fs_rate)
  l_audio = len(signal.shape)
  print ("Channels", l_audio)
  if l_audio == 2:
      signal = signal.sum(axis=1) / 2
  N = signal.shape[0]
  print ("Complete Samplings N", N)
  secs = N / float(fs_rate)
  print ("secs", secs)
  Ts = 1.0/fs_rate # sampling interval in time
  print ("Timestep between samples Ts", Ts)
  t = scipy.arange(0, secs, Ts) # time vector as scipy arange field / numpy.ndarray
  FFT = abs(scipy.fft(signal))
  FFT_side = FFT[range(N//4)] # one side FFT range
  freqs = scipy.fftpack.fftfreq(signal.size, t[1]-t[0])
  fft_freqs = np.array(freqs)
  freqs_side = freqs[range(N//4)] # one side frequency range
  fft_freqs_side = np.array(freqs_side)
  
  makespositive = signal[44100:]*(-1)
  logal = np.log10(makespositive)
  
  sn1 = np.mean(logal[1:44100])
  sn2 = np.mean(logal[44100:88200])
  sn3 = np.mean(logal[88200:132300])
  sn4 = np.mean(logal[132300:176400])
  
  print(sn1)
  print(sn2)
  print(sn3)
  print(sn4)
  
  abs(FFT_side)
  for a in range(500):
      FFT_side[a] = 0
  
  plt.subplot(311)
  p1 = plt.plot(t[44100:], signal[44100:], "g") # plotting the signal
  plt.xlabel('Time')
  plt.ylabel('Amplitude')
  
  plt.subplot(312)
  p1 = plt.plot(t[44100:], logal, "r") # plotting the signal
  plt.xlabel('Time')
  plt.ylabel('Amplitude')
  
  plt.subplot(313)
  p3 = plt.plot(freqs_side, abs(FFT_side), "b") # plotting the positive fft spectrum
  plt.xlabel('Frequency (Hz)')
  plt.ylabel('Count single-sided')
  plt.show()
  </code></pre>
  
  <p>First plot is amplitude vs time, second one is logarithm of previous graph and the last one is FFT.
  In sn1,sn2 part I tried to calculate dB from signal. First I took log and then calculated mean value for each second. It did not give me a clear relationship. I also tried this and did not worked.</p>
  
  <pre><code>import numpy as np
  import matplotlib.pyplot as plt
  import scipy.io.wavfile as wf
  
  fs, signal = wf.read('output.wav')  # Load the file
  ref = 32768  # 0 dBFS is 32678 with an int16 signal
  
  N = 8192
  win = np.hamming(N)                                                       
  x = signal[0:N] * win                             # Take a slice and multiply by a window
  sp = np.fft.rfft(x)                               # Calculate real FFT
  s_mag = np.abs(sp) * 2 / np.sum(win)              # Scale the magnitude of FFT by window and factor of 2,
                                                    # because we are using half of FFT spectrum
  s_dbfs = 20 * np.log10(s_mag / ref)               # Convert to dBFS
  freq = np.arange((N / 2) + 1) / (float(N) / fs)   # Frequency axis
  plt.plot(freq, s_dbfs)
  plt.grid(True)
  </code></pre>
  
  <p>So which steps should I perform? (Sum/mean all freq amplitudes then take log or reverse, or perform it for signal etc.)</p>
  
  <pre><code>import numpy as np
  import matplotlib.pyplot as plt
  import scipy.io.wavfile as wf
  
  fs, signal = wf.read('db1.wav') 
  
  signal2 = signal[44100:]
  chunk_size = 44100
  num_chunk  = len(signal2) // chunk_size
  sn = []
  for chunk in range(0, num_chunk):
      sn.append(np.mean(signal2[chunk*chunk_size:(chunk+1)*chunk_size].astype(float)**2))
  
  print(sn)
  
  logsn = 20*np.log10(sn)
  
  print(logsn)
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>[4.6057844427695475e+17, 5.0025315250895744e+17, 5.028593412665193e+17, 4.910948397471887e+17]
  [353.26607217 353.98379668 354.02893044 353.82330741]
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/r87na.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/r87na.jpg" alt="revised plot"></a></p>