dlsauers 0 Newbie Poster

I am converting a program in python that is written and used on another OS that starts with the letter w.

The script as written works on that OS, but on Linux it seems to fall flat on its face.

First, I do not have access to any non Linux systems. I am strictly 100% Linux and Linux only. (Hence the need to correct this script.)

Second, I need to determine if a few things are even possible or I should just stop now and not waste my time trying to convert it.

a. - Can python via pyaudio listen to the mic/line in monitor for a trigger event, record audio after the trigger event, while still monitoring for additional trigger events that would trigger another recording, and playback whats being recorded while monitoring? All with a SINGLE audio card?

If the answer to the above is NO? Its interesting that this can be done on a non Linux system.

Third, right now I have 2 issues:

a) buffer overflow on reading

b) audio recorded sounds like a chipmunk with the audio recorded at about 20 times normal rate.

Lastly, I think most of these issues can be overcome on Linux, I don't know why not.

So some basic info. I program with all kinds of thinks from assembler to HTML, to PHP to SQL. Python is relatively new.

Development testing system is an old 32bit system using a Kubuntu Precise distro (its more that its customized to include tons of stuff that officially is not included like codex, java etc...)

Python and Tk is all the versions from the Kubuntu repos. Nothing compiled from sources, just apt-get install or synaptic.

I have added: Tk, ffmpeg, numpy, pyaudio, pyserial etc. as this required by this script, along with any dependencies they had to install.

NOTE: Pulseaudio is REMOVED on my distro and all other systems, I do not use it. Strictly just ALSA, and I don't want to make its use required. Nor require others to remove it. pyaudio should deal with that be it ALSA or whatever.

Bug #1: - IOError: [Errno Input overflowed] -9981

 Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1413, in __call__
    return self.func(*args)
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 498, in callit
    func(*args)
  File "T_mybeta.py", line 896, in start
    nextstate()
  File "T_mybeta.py", line 547, in Atone1
    data = record(.2,0,1)
  File "T_mybeta.py", line 341, in record
    data = stream.read(chunk)
  File "/usr/lib/pymodules/python2.7/pyaudio.py", line 564, in read
    return pa.read_stream(self._stream, num_frames)
IOError: [Errno Input overflowed] -9981

The code which causes this error:

ORIGINAL
def record(seconds,playback,chan):
#function to record audio
#inputs:  seconds - number of seconds to record, playback - value of 1 will send audio to output while recording, 0 will not
#outputs:  data - recorded audio data
    RECORD_SECONDS = seconds
    all = []
    global RATE
    for i in range(0, int(RATE / chunk * RECORD_SECONDS)):
        data = stream.read(chunk)
        if playback == 1:
            stream.write(data)
        all.append(data)
    data = ''.join(all)
    return data

MY ALTERATION to deal with the error:

def record(seconds,playback,chan):
#function to record audio
#inputs:  seconds - number of seconds to record, playback - value of 1 will send audio to output while recording, 0 will not
#outputs:  data - recorded audio data
    RECORD_SECONDS = seconds
    all = []
    global RATE
    for i in range(0, int(RATE / chunk * RECORD_SECONDS)):
        #print "i: ", i, "top",int(RATE / chunk * RECORD_SECONDS)
        try:
            data = stream.read(chunk)
        except IOError as ex:
               if ex[1] != pyaudio.paInputOverflowed:
               raise
               print "error read step 1"
               #time.sleep(0.05)
               wait_sec(0.05)
#              data = stream.read(chunk) # data = '\x00' * chunk
        if playback == 1:
            stream.write(data)
        all.append(data)
    data = ''.join(all)
    return data

I added a wait for the buffer to fill? via a function that was included in the code handle when time.sleep might get used in multiple sub-processes. I've had time.sleep in place of wait_sec.

It seems to handle the overflow.. but the delay causes the trigger mechanism to not trigger unless this error condition does not occur.

I tried to use larger buffer sizes, but it causes two issues, the script uses a FFT based on the chunk size and sample rate. Increasing the buffer past 2176 causes another portion of the sript to fail with another error. I changed this back to the originals 1024, and slowly decreased this wait time to find a point it didn't occur that much, but it still occurs, so this is obviously NOT the answer/solution.

In the original script this error can occur immediately when starting up, crashing the script. Start again its fine till the error. Obviously as seen in my code one idea was just to fill the error condition with 00 which obviously won't trigger a thing.

Any ideas?

Bug #2 - Chipmunk/fast recording

The original script attempted to open the sound card again and then record the audio via this new handle. Linux threw a fit and crashed on that plan.

Expression 'ret' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 1670
Expression 'AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 1830
Expression 'PaAlsaStreamComponent_Initialize( &self->capture, alsaApi, inParams, StreamDirection_In, NULL != callback )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2092
Expression 'PaAlsaStream_Initialize( stream, alsaHostApi, inputParameters, outputParameters, sampleRate, framesPerBuffer, callback, streamFlags, userData )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2764
Unhandled exception in thread started by <function alert at 0xa6b6684>
Traceback (most recent call last):
  File "T_mybeta.py", line 395, in alert
    output_device_index = output_device_indices[output_device.get()])
  File "/usr/lib/pymodules/python2.7/pyaudio.py", line 714, in open
    stream = Stream(self, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/pyaudio.py", line 396, in __init__
    self._stream = pa.open(**arguments)
IOError: [Errno Device unavailable] -9985

So I commented out the new open statement, which solves the issue, and it records now.... but I now have this issue with the chipmunk recording. Which is probably related to the original handle being processed through the FFT.

So is there a way to open the card again for input to record it?

I've tested recording using the same settings, 1024 chunk, 11025 sample, thats fine, in a sample/test program.

Bug #1 also occurs when I apply my fix (comment out the 2nd attempt to open the card), so I applied the same concept try, wait_sec option... no buffer errors, but the chipmunks are there.

To record the audio coming in AND monitor for the trigger event, ie there could be multiple trigger events that happening at the same time. ie: trigger 1, trigger2, trigger 3, trigger 4, audio (Yes I am being vague on the trigger event, for a reason. The trigger logic seems to work if I can get past the buffer issue and then resolve the recording issue.)

Ideas? ?

Thank in advance.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.