title: audioop.rms() - why does it differ from normal RMS?
body: <p>I am writing a python function to return the loudness of a .wav file. RMS seems to be best the metric for this, <a href="https://stackoverflow.com/questions/2668442/detect-and-record-a-sound-with-python">Detect and record a sound with python</a>. 
  <code>audioop.rms()</code> does the trick, but I'd like to avoid audioop as a dependency, and I already import numpy. but I'm not getting the same RMS values, and would appreciate help in understanding what is going on.</p>
  
  <p>From the <a href="http://docs.python.org/library/audioop.html" rel="nofollow noreferrer">audioop page</a>, it says that the rms calculation is just what you'd expect, namely <code>sqrt(sum(S_i^2)/n)</code>, where, <code>S_i</code> is the <code>i</code>-th sample of the sound. Seems like its not rocket science.</p>
  
  <p>To use numpy, I first convert the sound to a numpy array, and always see identical min / max, and the same length of the data (so the conversion seems fine).</p>
  
  <pre><code>&gt;&gt;&gt; d = np.frombuffer(data, np.int16)
  &gt;&gt;&gt; print (min(d), max(d)), audioop.minmax(data,2)
  (-2593, 2749) (-2593, 2749)
  </code></pre>
  
  <p>but I get very different RMS values, not even ball-park close:</p>
  
  <pre><code>&gt;&gt;&gt; numpy_rms = np.sqrt(sum(d*d)/len(d))
  &gt;&gt;&gt; print numpy_rms, audioop.rms(data, 2)
  41.708703254716383, 120
  </code></pre>
  
  <p>The difference between them is variable, no obvious pattern I can see, eg, I also get:</p>
  
  <pre><code>63.786714248938772, 402
  62.779300661773405, 148
  </code></pre>
  
  <p>My numpy RMS code gives identical output to the one here: <a href="https://stackoverflow.com/questions/8245687/numpy-root-mean-squared-rms-smoothing-of-a-signal">Numpy Root-Mean-Squared (RMS) smoothing of a signal</a></p>
  
  <p>I don't see where I am going wrong, but something is off. Any help much appreciated.</p>
  
  <hr>
  
  <p>EDITED / UPDATE:</p>
  
  <p>In case its useful, here's the code I ended up with. Its not quite as fast as audioop but is still plenty fast, good enough for my purpose. Of note, using np.mean() makes it MUCH faster (~100x) than my version using python sum().</p>
  
  <pre><code>def np_audioop_rms(data, width):
      """audioop.rms() using numpy; avoids another dependency for app"""
      #_checkParameters(data, width)
      if len(data) == 0: return None
      fromType = (np.int8, np.int16, np.int32)[width//2]
      d = np.frombuffer(data, fromType).astype(np.float)
      rms = np.sqrt( np.mean(d**2) )
      return int( rms )
  </code></pre>