jiaaro/pydub

pyaudioop.rms() TypeError: 'float' object cannot be interpreted as an integer and NameError: name 'buffer' is not defined

aaronchantrill opened this issue · 1 comments

Steps to reproduce

I am attempting to use pyaudioop as a replacement for audioop which is deprecated and slated for removal in Python 3.13

I am using the rms method to get a volume level.

I found an issue here #725 that seems to address the change and recommends using pydub.pyaudioop as a substitute.

Unfortunately, pydub.pyaudioop makes heavy use of the buffer() function, which appears to have been removed from python 3 early in its development, so I'm not sure how it helps with the Python 3.13 transition.

Expected behavior

The rms function should return an integer

$ python
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pydub import pyaudioop as audioop
>>> print(audioop.rms(b'\x00'*960, 2))
0

Actual behavior

$ python
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pydub import pyaudioop as audioop
>>> print(audioop.rms(b'\x00'*960, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 149, in rms
    sum_squares = sum(sample**2 for sample in _get_samples(cp, size))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 149, in <genexpr>
    sum_squares = sum(sample**2 for sample in _get_samples(cp, size))
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 36, in _get_samples
    for i in range(_sample_count(cp, size)):
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'float' object cannot be interpreted as an integer

Now, the value being returned here is actually the floating point form of an integer (480.0), so if we wrap the _sample_count() in an int(), then we get:

$ python
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pydub import pyaudioop as audioop
>>> print(audioop.rms(b'\x00'*960, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 149, in rms
    sum_squares = sum(sample**2 for sample in _get_samples(cp, size))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 149, in <genexpr>
    sum_squares = sum(sample**2 for sample in _get_samples(cp, size))
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 37, in _get_samples
    yield _get_sample(cp, size, i, signed)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.virtualenvs/Naomi/lib/python3.11/site-packages/pydub/pyaudioop.py", line 53, in _get_sample
    return struct.unpack_from(fmt, buffer(cp)[start:end])[0]
                                   ^^^^^^
NameError: name 'buffer' is not defined

In my case, my data is being pulled from PyAudio or pyAlsaAudio is already in a bytes-like string, so I can just define buffer like:

def buffer(o):
    return o

and it works, but I have seen some different discussions of replacements for the buffer() function including memoryview() and bytes(). As far as I can tell, the purpose is to collapse an iterable object into a byte array so that slicing operations can be used on it.

Your System configuration

  • Python version: Python 3.11.2
  • Pydub version: 0.25.1 (installed via pip)
  • ffmpeg or avlib?: ffmpeg
  • ffmpeg/avlib version: 5.1.4-0

Is there an audio file you can include to help us reproduce?

This is not related to a specific audio file, but you can use the code above to verify

I'm also getting a similar error when using the audioop.max function:

Traceback (most recent call last):
  File "/opt/LED_VU.py", line 42, in <module>
    max_vol=audioop.max(data,2)
            ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pydub/pyaudioop.py", line 120, in max
    return builtin_max(abs(sample) for sample in _get_samples(cp, size))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pydub/pyaudioop.py", line 120, in <genexpr>
    return builtin_max(abs(sample) for sample in _get_samples(cp, size))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pydub/pyaudioop.py", line 36, in _get_samples
    for i in range(_sample_count(cp, size)):
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'float' object cannot be interpreted as an integer

data is from alsaaudio PCM.read.