jiaaro / pydub

Manipulate audio with a simple and easy high level interface
http://pydub.com
MIT License
8.96k stars 1.05k forks source link

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

Open aaronchantrill opened 11 months ago

aaronchantrill commented 11 months ago

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 https://github.com/jiaaro/pydub/issues/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

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

khoran commented 6 months ago

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.