PyAudio Input overflowed

后端 未结 9 1550
长发绾君心
长发绾君心 2020-11-30 04:04

I\'m trying to make real-time plotting sound in python. I need to get chunks from my microphone.

Using PyAudio, try to use

import pyaudio
import wav         


        
相关标签:
9条回答
  • 2020-11-30 04:16

    I got the same error when I ran your code. I looked at the default sample rate of my default audio device, my macbook's internal microphone, it was 48000Hz not 44100Hz.

    p.get_device_info_by_index(0)['defaultSampleRate']
    Out[12]: 48000.0
    

    When I changed RATE to this value, it worked.

    0 讨论(0)
  • 2020-11-30 04:18

    I had the same issue on the really slow raspberry pi, but I was able to solve it (for most cases) by using the faster array module for storing the data.

    import array
    import pyaudio 
    
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    INPUT_CHANNEL=2
    RATE = 48000
    CHUNK = 512
    
    p = pyaudio.PyAudio()
    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=INPUT_CHANNEL,
                    frames_per_buffer =CHUNK)
    
    print("* recording")
    
    
    try:
        data = array.array('h')
        for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
            data.fromstring(stream.read(CHUNK))
    finally:
        stream.stop_stream()
        stream.close()
        p.terminate()
    
    print("* done recording")
    

    The content of data is rather binary afterwards. But you can use numpy.array(data, dtype='i') to get a numpy array of intergers.

    0 讨论(0)
  • 2020-11-30 04:19

    pyaudio.Stream.read() has a keyword parameter exception_on_overflow, set this to False.

    For your sample code that would look like:

    import pyaudio
    import wave
    import sys
    
    chunk = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 44100
    RECORD_SECONDS = 5
    WAVE_OUTPUT_FILENAME = "output.wav"
    
    p = pyaudio.PyAudio()
    
    stream = p.open(format = FORMAT,
                    channels = CHANNELS,
                    rate = RATE,
                    input = True,
                    frames_per_buffer = chunk)
    
    print "* recording"
    all = []
    for i in range(0, RATE / chunk * RECORD_SECONDS):
        data = stream.read(chunk, exception_on_overflow = False)
        all.append(data)
    print "* done recording"
    
    stream.close()
    p.terminate()
    

    See the PyAudio documentation for more details.

    0 讨论(0)
  • 2020-11-30 04:21

    This was helpful for me:

    input_ = stream.read(chunk, exception_on_overflow=False)
    exception_on_overflow = False
    
    0 讨论(0)
  • 2020-11-30 04:28
    FORMAT = pyaudio.paInt16
    

    Make sure to set the correct format, my internal microphone was set to 24 Bit (see Audio-Midi-Setup application).

    0 讨论(0)
  • 2020-11-30 04:33

    It seems like a lot of people are encountering this issue. I dug a bit into it and I think it means that between the previous call to stream.read() and this current call, data from the stream was lost (i.e. the buffer filled up faster than you cleared it).

    From the doc for Pa_ReadStream() (the PortAudio function that stream.read() eventually ends up calling):

    @return On success PaNoError will be returned, or PaInputOverflowed if
    input data was discarded by PortAudio after the previous call and
    before this call.
    

    (PaInputOverflowed then causes an IOError in the pyaudio wrapper).

    If it's OK for you to not capture every single frame, then you may ignore this error. If it's absolutely critical for you to have every frame, then you'll need to find a way to increase the priority of your application. I'm not familiar enough with Python to know a pythonic way to do this, but it's worth trying a simple nice command, or changing the scheduling policy to SCHED_DEADLINE.

    Edit:

    One issue right now is that when IOError is thrown, you lose all the frames collected in that call. To instead ignore the overflow and just return what we have, you can apply the patch below, which will cause stream.read() to ignore output underrun and input overflow errors from PortAudio (but still throw something if a different error occurred). A better way would be to make this behaviour (throw/no throw) customizable depending on your needs.

    diff --git a/src/_portaudiomodule.c b/src/_portaudiomodule.c
    index a8f053d..0878e74 100644
    --- a/src/_portaudiomodule.c
    +++ b/src/_portaudiomodule.c
    @@ -2484,15 +2484,15 @@ pa_read_stream(PyObject *self, PyObject *args)
         } else {
           /* clean up */
           _cleanup_Stream_object(streamObject);
    +
    +      /* free the string buffer */
    +      Py_XDECREF(rv);
    +
    +      PyErr_SetObject(PyExc_IOError,
    +                       Py_BuildValue("(s,i)",
    +                                     Pa_GetErrorText(err), err));
    +      return NULL;
         }
    -
    -    /* free the string buffer */
    -    Py_XDECREF(rv);
    -
    -    PyErr_SetObject(PyExc_IOError,
    -                   Py_BuildValue("(s,i)",
    -                                 Pa_GetErrorText(err), err));
    -    return NULL;
       }
    
       return rv;
    
    0 讨论(0)
提交回复
热议问题