Forums > Dev

python pyext audio crash

December 24, 2007 | 8:39 am

hey all:

I have my first pyext object working in a patch. hooray. it’s working fine. It’s very simple. It makes a list of ints and sends them out one at a time. The idea is to send the ints to mtof and then into one of my msp synths. I have abstractions that can do this, but I thought it would be more elegant (and a great learning tool for both max and python) to write my abstractions using py/pyext.

The problem is when I turn on the audio. max crashes immediately every time. The script is just sending out integers… why would that crash the audio? simply pulling in an ezdac~ and turing it on crashes max, without even connecting it to anything.

My other audio patches work fine. I’m using 4.5, with an iMac g5.

Thanks!!

Here is the pyext code (class Scale is in a separate doc):
######################################
try:
import pyext
except:
print "ERROR: This script must be loaded by the PD/Max pyext external"
from scrale import Scale
from random import randrange as randy
class riff(pyext._class):
count = 0
length = 4
sclea = []
pattern = []
_inlets=3
_outlets=2
def makeriff_2(self, root, mode, length):
print "we are now in func ‘makescale’"
t=Scale(root)
mode = str(mode)

self.length = length

if mode == "major":
self.sclea = t.major()
print "major is %s" % t.major()

elif mode == "minor":
self.sclea = t.minor()
print "%s is: %s" % (mode, self.sclea)

elif mode == "dorian":
self.sclea = t.dorian()
print "%s is: %s" % (mode, self.sclea)

elif mode == "mixolydian":
self.sclea = t.mixolydian()
print "%s is: %s" % (mode, self.sclea)

elif mode == "phrygian":
self.sclea = t.phrygian()
print "%s is: %s" % (mode, self.sclea)

else:
self.sclea = t.crom
print "%s is: %s" % (mode, self.sclea)

for i in range(self.length):
self.pattern.append( randy(len(self.sclea)))

def bang_1(self):

self._outlet(1, self.sclea[self.pattern[self.count]])

if self.count < self.length - 1:
self.count +=1
else:
self.count = 0


December 24, 2007 | 8:52 am

python and indents… here


December 24, 2007 | 10:44 am

Hi John,
my guess is that you have overdrive turned on. There are known problems
with the py object and overdrive, but it’s on my todo list to resolve them.

A few more things:
- You are setting a few variables (like pattern) in the class scope.
This is probably not what you want, because the variables will be shared
among multiple instances of your class (e.g. multiple py/pyext objects
using the same script. You should initialize instance specific variables
in __init__.

- In your Python script you are defining the number of inlets and
outlets in the class. This is deprecated… it should be defined with
the object, like [pyext 3 2 myscript.riff myargs(

- You could instead of converting the mode argument to str compare it to
symbols, as in "if mode == pyext.Symbol('major')", and even cache these
symbols at script initialization.

gr~~~

John Cobbett schrieb:
> hey all:
>
> I have my first pyext object working in a patch. hooray. it's working fine. It's very simple. It makes a list of ints and sends them out one at a time. The idea is to send the ints to mtof and then into one of my msp synths. I have abstractions that can do this, but I thought it would be more elegant (and a great learning tool for both max and python) to write my abstractions using py/pyext.
>
> The problem is when I turn on the audio. max crashes immediately every time. The script is just sending out integers... why would that crash the audio? simply pulling in an ezdac~ and turing it on crashes max, without even connecting it to anything.
>
> My other audio patches work fine. I'm using 4.5, with an iMac g5.
>
> Thanks!!
>
> Here is the pyext code (class Scale is in a separate doc):
> ######################################
> try:
> import pyext
> except:
> print "ERROR: This script must be loaded by the PD/Max pyext external"
> from scrale import Scale
> from random import randrange as randy
> class riff(pyext._class):
> count = 0
> length = 4
> sclea = []
> pattern = []
> _inlets=3
> _outlets=2
> def makeriff_2(self, root, mode, length):
> print "we are now in func ‘makescale’"
> t=Scale(root)
> mode = str(mode)
>
> self.length = length
>
> if mode == "major":
> self.sclea = t.major()
> print "major is %s" % t.major()
>
> elif mode == "minor":
> self.sclea = t.minor()
> print "%s is: %s" % (mode, self.sclea)
>
> elif mode == "dorian":
> self.sclea = t.dorian()
> print "%s is: %s" % (mode, self.sclea)
>
> elif mode == "mixolydian":
> self.sclea = t.mixolydian()
> print "%s is: %s" % (mode, self.sclea)
>
> elif mode == "phrygian":
> self.sclea = t.phrygian()
> print "%s is: %s" % (mode, self.sclea)
>
> else:
> self.sclea = t.crom
> print "%s is: %s" % (mode, self.sclea)
>
> for i in range(self.length):
> self.pattern.append( randy(len(self.sclea)))
>
> def bang_1(self):
>
>
> self._outlet(1, self.sclea[self.pattern[self.count]])
>
> if self.count < self.length - 1:
> self.count +=1
> else:
> self.count = 0
>
>
>
>
>
>
>
>
>
>
>
>
>
>


December 24, 2007 | 10:57 pm

Hey gr you are the one behind py/pyext right? Thanks! Also thanks for the advice! It’s difficult to find info/examples on py/ext – especially at the beginner level so it’s been trial and error all the way…

-John C.


December 24, 2007 | 11:19 pm

John Cobbett schrieb:
> Hey gr you are the one behind py/pyext right? Thanks! Also thanks for the advice! It’s difficult to find info/examples on py/ext – especially at the beginner level so it’s been trial and error all the way…
>
Yes and yes…. py/pyext has originally been made for Pure Data… its
existence for Max/MSP is only a by-product, therefore it’s badly documented.
In case you are interested in better documentation, you are very much
invited to install Pure Data, learn from the help patches and transfer
them to Max.
I’m happy to help in case of other questions… did switching off
overdrive help?

gr~~~


December 25, 2007 | 7:05 am

Ok problem solved. turning overdrive off didn’t fix the problem. what solved it was "deglobalizing" all the variables in my script and putting them in __init__ like you advised – then it worked fine. Interesting… Thanks again!

-JC


February 5, 2013 | 10:21 am

I know raping corpses etc. but I’m having the same problem in PureData and was hoping maybe someone might know how to tell me what "deglobalizing" means. Here my code of a class that needs to be reinstanciated quite a lot with different values:

class NoteObject(pyext._class):
"""The NoteObject class handles everything needed to model a note"""

# number of inlets and outlets
_inlets=1
_outlets=6

#variables – at some point I should decide for either system…
pitch = 60
vel = 127 #velocity
channel = 1
duration = 1.0 / 4 #in beats
timestamp = 0 #in measures

#and by all these powers combined we have:
quintuple = array(‘f’, [pitch, vel, channel, duration, timestamp])
quinnames = ["pitch", "vel", "channel", "duration", "timestamp"]

# methods for first inlet

#set a quint value based on the index or parameter name f1 and the set value f2
def quint(self, f1, f2):
import types
i = -1
if isNumber(f1):
i = int(f1)
else:
i = self.quinnames.index(str(f1))
if (not i == -1) and isNumber(f2):
self.quintuple[i] = f2
if i == 0:
self.pitch = f2
elif i == 1:
self.vel = f2
elif i == 2:
self.channel = f2
elif i == 3 and (f2 > 0):
self.duration = 1.0 / f2
self.quintuple[i] = self.duration
elif i == 4:
self.timestamp = f2
#print "quintuple[",i,"] and ",self.quinnames[i]," set to ", self.quintuple[i]

#put a list of up to 5 parameters into the quintuple
def setquintuple_1(self,*s):
for i in range(len(s)):
self.quint(i, s[i])
if i > 5:
print "Too many arguments to put in a quintuple"
break

#output the quintuple individually to the outlets 2-6 and the whole to the 1th as well as to the log
def getquintuple_1(self):
self._outlet(1, self.quintuple)

#sets the element f1 in the quintuple to f2 with a "set f f"-message to i1
def set_1(self, f1, f2):
self.quint(f1,f2)

#hinders potentially pending note-offs
def nonoteoff_1(self):
self._outlet(1, "nonoteoff")

#compares handed list to self.quintuple and takes appropriate action
def compare_1(self, *f):
#print "comparing ", f, "to quintuple ", self.quintuple
if len(f)==5:
#I know this is no good style. I was planning for feedback per step
if f[2] == self.quintuple[2]:
if f[0] == self.quintuple[0]:
if self.quintuple[3] > 0:
if f[4] > self.quintuple[4]:
self._outlet(1, "nonoteoff")
print "killed note-off of ", self.quintuple
else:
print "this is not even comparable"

#helper function – determine whether argument is a numeric type
def isNumber(value):
import types
if type(value) in (types.FloatType, types.IntType, types.LongType):
return 1
else:
return 0

#Constructor – sets the values put in as args to the quintuple etc
def __init__(self,*args):
for i in range(len(args)):
self.quint(i, args[i])

As you see I put the argument values to the variables in the constructor, so each and every instance should have its own values. But whenever I call any method but setquintuple() the called method works on the variables of the last set instance.


February 7, 2013 | 10:11 pm

FYI, you can wrap your code in html "pre" tags if you want to maintain formatting and indenting.

Cheers


Viewing 8 posts - 1 through 8 (of 8 total)