Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old August 5th, 2012, 07:48 AM
dlsauers dlsauers is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2012
Posts: 1 dlsauers User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 6 m 41 sec
Reputation Power: 0
Question Pyaudio - buffer overflow errors

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

Code:
 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:

Code:
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.

Code:
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.

Reply With Quote
  #2  
Old August 6th, 2012, 02:18 PM
b49P23TIvg's Avatar
b49P23TIvg b49P23TIvg is offline
Contributing User
Dev Shed Loyal (3000 - 3499 posts)
 
Join Date: Aug 2011
Posts: 3,458 b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level) 
Time spent in forums: 1 Month 2 Weeks 4 Days 6 h 26 m 43 sec
Reputation Power: 403
Terribly sorry, I don't begin to know how to run your code fragment. Python is supposed to have batteries included; you'd expect platform independence. If this were my project, I'd learn about the alsa driver/mixer whatever it is using the bash command line:
Code:
$ apropos alsa
aconnect (1)         - ALSA sequencer connection manager
alsactl (1)          - advanced controls for ALSA soundcard driver
alsactl_init (7)     - alsa control management - initialization
alsaloop (1)         - command-line PCM loopback
alsamixer (1)        - soundcard mixer for ALSA soundcard driver, with ncurse...
amidi (1)            - read from and write to ALSA RawMIDI ports
amixer (1)           - command-line mixer for ALSA soundcard driver
aplay (1)            - command-line sound recorder and player for ALSA soundc...
arecord (1)          - command-line sound recorder and player for ALSA soundc...
aseqdump (1)         - show the events received at an ALSA sequencer port
aseqnet (1)          - ALSA sequencer connectors over network
speaker-test (1)     - command-line speaker test tone generator for ALSA


Browsing Gnu solfege, an ear training program written in python might be useful to you.

Or, put on your lisp programming hat, try nyquist or audacity. (audacity might depend on nyquist.)
__________________
[code]Code tags[/code] are essential for python code!

Reply With Quote
  #3  
Old November 9th, 2012, 02:23 PM
b49P23TIvg's Avatar
b49P23TIvg b49P23TIvg is offline
Contributing User
Dev Shed Loyal (3000 - 3499 posts)
 
Join Date: Aug 2011
Posts: 3,458 b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level) 
Time spent in forums: 1 Month 2 Weeks 4 Days 6 h 26 m 43 sec
Reputation Power: 403
Hey! Did you resolve this problem? I'm writing software to visually display data recorded on the microphone. I'd like to connect with alsa directly. The only thing I've managed so far is to open a pipe to arecord and read data from that. Thanks, Dave.
Code:
#python3import math
import array
import tkinter
import subprocess

TAU=2*math.pi # http://www.youtube.com/watch?v=jG7vhMMXagQ

def interpolate(x,p0,p1):
    '''
        # provide 2D linear interplation
        >>> interpolate(0.5,(0,0),(1,1))
        0.5
        >>> interpolate(0.5,(1,0),(0,1))
        0.5
        >>> interpolate(3,(1,0),(5,2))
        1.0
    '''
    (x0,y0) = p0
    (x1,y1) = p1
    slope = (y1-y0)/(x1-x0)
    intercept = y0-slope*x0
    return slope*x+intercept

def coordinates(radii,trig,scale,center):
    '''
        convert amplitude,time data to radius, angle
    '''
    (sin,cos) = trig
    coords = array.array('I',(0,)*(2*len(sin)))
    for (i,(s,c,r)) in enumerate(zip(sin,cos,radii)):
        coords[2*i] = int(center+scale*r*c)
        coords[2*i+1] = int(center+scale*r*s)
    return coords

def average(a,c,L):
    '''
        return list of averages length L centered at intervals spaced c apart.
    '''
    result = []
    h = L//2
    H = h+1
    for i in range(0,len(a),c):
        d = a[max(i-h,0):i+H]
        result.append(sum(d)/len(d))
    return result

class CircleGraph:

    def __init__(self,R = 256):
        '''
            R: maximum radius
        '''
        self.tk = tkinter.Tk()
        self.tk.wm_geometry(newGeometry='%dx%d+20+20'%(2*R,2*R))
        self.canvas = tkinter.Canvas(self.tk)
        self.canvas.pack(expand=tkinter.YES,fill=tkinter.BOTH)
        self.radius = R
        R = float(self.radius)
        rreciprocal = 1.0/R
        sin = array.array('f',range(len(self)))   # precompute re-used trig
        cos = sin[:]
        self.hftrig = sin,cos
        for a in range(len(self)):
            angle = a*rreciprocal
            sin[a] = math.sin(angle)
            cos[a] = math.cos(angle)
        self.lftrig = sin[::5], cos[::5]
        #self.hf = self.canvas.create_polygon(
        #    *coordinates((0.5 for i in sin),self.hftrig,R,R),
        #    outline='red')
        self.hf = [self.canvas.create_line(
            *coordinates((0.5 for i in sin),self.hftrig,R,R),fill='red')
            for i in range(3)
            ]
        self.lf = self.canvas.create_line(
            *coordinates((0.5 for i in self.lftrig[0]),self.lftrig,R,R),
            fill='darkblue',width=3)
        self.controls()

    def terminate(self):
        self.PROCEED = False

    def controls(self):
        L = len(self)
        master = tkinter.Toplevel(self.tk)
        master.wm_geometry(newGeometry='+%d+20'%(40+2*self.radius))
        tkinter.Button(master,text='exit',command=self.terminate).pack(side=tkinter.BOTTOM)
        rate = tkinter.Scale(master,from_=0,to=100,
                             label='sample rate',orient=tkinter.HORIZONTAL)
        rate.pack(side=tkinter.BOTTOM)
        rate.set(50)
        avgspan = tkinter.Scale(master,from_=1,to=L//30,
                                label='filter width',orient=tkinter.HORIZONTAL)
        avgspan.pack(side=tkinter.BOTTOM)
        avgspan.set(min(30,L//30))
        self.controlbox = master
        self.PROCEED = True
        self.rate = rate
        self.avgspan = avgspan
        self.controlBox = master

    def __len__(self):
        return int(self.radius*TAU)

    def __call__(self):
        global coordinates # might run faster with this unnecessary statement
        L = len(self)
        rate = self.rate.get
        RATE = rate()
        a = int(0.5+math.exp(interpolate(RATE,
                                            (0,math.log(2000)),
                                            (100,math.log(192000)))))
        with subprocess.Popen(
                'arecord --format=U8 --rate=%d'%(a), # --format=U8 byte, --rate=8000 Hz,  --mmap could be faster
                bufsize=L,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                shell=True) as arecord:
            tk = self.tk
            hf = self.hf
            HFTally = len(hf)
            hfn = 0
            hftrig = self.hftrig
            lf = self.lf
            lftrig = self.lftrig
            R = self.radius
            read = arecord.stdout.read
            coords = self.canvas.coords
            itemconfig = self.canvas.itemconfig
            avgspan = self.avgspan.get
            scale = 1.0/256.0
            arr = array.array
            while self.PROCEED and (RATE == rate()):
                data = arr('f',(scale*r for r in read(L)))
                coords(lf,*coordinates(average(data,5,avgspan()),lftrig,R/2,R))
                itemconfig(hf[(hfn+2)%HFTally],fill='#f55')
                itemconfig(hf[(hfn+1)%HFTally],fill='#faa')
                coords(hf[hfn],*coordinates(data,hftrig,R,R))
                itemconfig(hf[hfn],fill='#f00')
                hfn = (hfn + 1) % HFTally
                #                itemconfig(hf[hfn],fill='darkred')
                tk.update()
            return self.PROCEED

def main():
    cg = CircleGraph()
    while cg():
        pass

if '__main__' == __name__:
    main()

Reply With Quote
  #4  
Old November 13th, 2012, 05:19 AM
O7ls3o5n O7ls3o5n is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2012
Posts: 6 O7ls3o5n User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 15 m 19 sec
Reputation Power: 0
Python and Tk is all the versions from the Kubuntu repos. Nothing compiled from sources, just apt-get install or synaptic.







Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPython Programming > Pyaudio - buffer overflow errors

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap