pyo :snap: how to get the float value of a frequency ?

60 views
Skip to first unread message

Pascal KREZEL

unread,
Dec 20, 2017, 3:59:19 PM12/20/17
to pyo-discuss
Hi,

I have used the snap function with the parameter scale=1 to get a frequency that I apply to a SineLoop function. It works but if I want to obtain the float value of this frequency it is not possible !
How is it possible to get this value ?

Pascal

Aaron Krister Johnson

unread,
Dec 20, 2017, 9:31:36 PM12/20/17
to pyo-d...@googlegroups.com
I don't understand. Snap returns a float in Hz when scale=1.

And, you can make the 'choice' a list of floats to begin with, if that's what you mean.

Aaron Krister Johnson
http://www.untwelve.org

--
You received this message because you are subscribed to the Google Groups "pyo-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyo-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pascal KREZEL

unread,
Dec 21, 2017, 2:31:57 AM12/21/17
to pyo-discuss
HI,

Thank you for your answer.

If you make a print of what is returned by the SNAP function (with scale=1)  you will get "< Instance of Snap class > " and not a float in Hz. This is the problem.
What is surprising is that it can be directly used as frequency in functions like SINELOOP.

Pascal

Le jeudi 21 décembre 2017 03:31:36 UTC+1, Aaron Krister Johnson a écrit :
I don't understand. Snap returns a float in Hz when scale=1.

And, you can make the 'choice' a list of floats to begin with, if that's what you mean.

Aaron Krister Johnson
http://www.untwelve.org

On Wed, Dec 20, 2017 at 2:59 PM, Pascal KREZEL <pascal...@gmail.com> wrote:
Hi,

I have used the snap function with the parameter scale=1 to get a frequency that I apply to a SineLoop function. It works but if I want to obtain the float value of this frequency it is not possible !
How is it possible to get this value ?

Pascal

--
You received this message because you are subscribed to the Google Groups "pyo-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyo-discuss...@googlegroups.com.

Aaron Krister Johnson

unread,
Dec 21, 2017, 10:14:53 AM12/21/17
to pyo-d...@googlegroups.com
It must be that underneath, the code object (e.g. SineLoop) is accessing a "getter" method on the Snap object to fetch its output value and use it as input. Otherwise, it would make no sense, as there would be a TypeError.

I'm thinking it's actually using 'get()' off the base class PyoObject, I'm not looking at the code now, but examining the source can tell you more, or Oliviér can chime in. In any event, I still don't really understand what you're trying to do. You need to provide us with some code example that's not working for anyone to really help. Most audio objects in Pyo return an audio stream of floats, so conversion in this case is a non-issue.

-AKJ

To unsubscribe from this group and stop receiving emails from it, send an email to pyo-discuss+unsubscribe@googlegroups.com.

Pascal KREZEL

unread,
Dec 21, 2017, 11:29:37 AM12/21/17
to pyo-discuss
What I want to do  is as follows:

I have :
a1 = SineLoop(freq=n0, feedback=0.0, mul=env1).out()

And after, I want to do :

fnb = Sig(value=fn)
f1= Snap(fnb, choice=Gamme[iG], scale=1)
a1.setFreq([f1,f1*Dh[H]])

I found that the multiplication doesn't work. So I realized that f1 is not a float as waited for.
I tried the "get()" function but it returns 0!

Aaron Krister Johnson

unread,
Dec 21, 2017, 8:55:36 PM12/21/17
to pyo-d...@googlegroups.com
Pascal,

I'd need more code-in-context, but the use of a1.setFreq() is not only awkward, but probably cannot happen at an audio rate. It's for initializing a value once, or, say, interactively. It's not meant to be used for continuous variance of the frequency signal.

If you want a continuously varying frequency for the SineLoop, why not calculate the input values *beforehand*, and feed them into the SineLoop object as signals, as it was meant to be? E.G.:

fnb = Sig(value=fn)
f1= Snap(fnb, choice=Gamme[iG], scale=1)

# also, you have to make sure Dh[H] is a Pyo stream, not sure this works if 'Dh' is a normal list...but you can try!
a1 = SineLoop(freq=[f1, f1 * Dh[H]], feedback=0.0, mul=env1).out()  

You'd have to come up with a means of swapping out 'n0' from your example above, which is what, an initial value? You'd probably have to find some score control or trigger way to do that.

Cheers,
AKJ

Aaron Krister Johnson
http://www.untwelve.org

To unsubscribe from this group and stop receiving emails from it, send an email to pyo-discuss+unsubscribe@googlegroups.com.

Olivier Bélanger

unread,
Dec 21, 2017, 9:01:04 PM12/21/17
to pyo-discuss
Hi Pascal,

First thing to consider, almost all component of pyo are objects, not functions. So, if you print the return of SineLoop, for sure, you will get an instance of the SineLoop class. Now, pyo objects know how to handle signal from other pyo object. At the low level, receiver use the float or double buffer of sample directly. At a higher level (Python), if you want to convert an audio signal to a float value, as Aaron said, there is a getter for this. But the .get() method return the current sample, as a float, at the moment of the call. If you use this method a the init of the script, you'll get the first sample of the buffer initialized to 0s. You should use it in a callback. For Ex.:

a1 = SineLoop(100)

def callback():
    a1_as_float = a1.get()
    print("Do something with your float...")

# call the function callback every 50 ms
pat = Pattern(callback, 0.05).play()  

Anyway, as Aaron said, I'm not sure the conversion is really needed here... "fnb = Sig(value=fn)" convert a float to an audio signal but the output of SineLoop is already an audio signal, so better to use it directly. And pyo object can be use in arithmetic with float, that will return a new audio object handling the computation.

Olivier


To unsubscribe from this group and stop receiving emails from it, send an email to pyo-discuss+unsubscribe@googlegroups.com.

Olivier Bélanger

unread,
Dec 21, 2017, 9:03:27 PM12/21/17
to pyo-discuss
Multiplying an audio object with a list of floats returns a multi-stream audio object, the signal times each values in the list!

Olivier

Pascal KREZEL

unread,
Dec 22, 2017, 3:48:24 AM12/22/17
to pyo-discuss
Hi Olivier,

Thank you for your explanations.
Excuse-me to be not clear about what I want to do.  Here is a longer part of my script:
My goal is to make  a sonification of data. 
Dh is a dictionnary dedicated to apply a chord of two notes depending on the property of the data.
I use two functions  to make these modifications, it  is not a continuous variations.

def pat1():
global i,f1
i+=1

LeR=dssp[LesR[i]]
R=LeR[1]
H=LeR[2]
ASA=LeR[3]

if R in Res.iterkeys():
fn=n0+(n1-n0)*Res[R]

fnb = Sig(value=fn)
f1= Snap(fnb, choice=Gamme[iG], scale=1)
a1.setFreq([f1,f1*Dh[H]])
a1.setFeedback(0.3*ASA)
pat1.time=kt/Dd[H]
env1.play()


def pat2():
global i

if i+di==nL:
if typdur==1:
serv.recstop()
serv.shutdown()
sys.exit()
print("-----Debut------")
i=0
LeR=dssp[LesR[i+di]]
R=LeR[1]
H=LeR[2]
ASA=LeR[3]

if R in Res.iterkeys():
if rev==0:
fn=n0+(n1-n0)*Res[R]
else:
fn=n1-(n1-n0)*Res[R]

fnb = Sig(value=fn)
f= Snap(fnb, choice=Gamme[iG], scale=1)
a2.setFreq([f,f*Dh[H]])
a2.setFeedback(0.3*ASA)
pat2.time=kt/Dd[H]
env2.play()



#-------------------------------
#Lancement de pyo
serv = Server(audio='offline').boot()
serv.recordOptions(dur=dur,filename=nomR, fileformat=1)
globalamp1 = Fader(fadein=2, fadeout=2, dur=0).play()
env1 = Adsr(attack=0.01, decay=0.1, sustain=0.15, release=0.2, dur=0.8, mul=0.5)
a1 = SineLoop(freq=n0, feedback=0.0, mul=env1).out()
pat1 = Pattern(pat1,0.125)
pat1.play()


env2 = Adsr(attack=0.02, decay=0.15, sustain=0.15, release=0.2, dur=0.8, mul=0.5)
a2 = SineLoop(freq=n0, feedback=0.0, mul=env2).out()
pat2 = Pattern(pat2,0.125)
pat2.play()
res=a1+a2

res=a1

x=res.mix(2).out()
serv.start()
time.sleep(0.25)
serv.shutdown()


Is there a solution to this problem of multiplication "a2.setFreq([f,f*Dh[H]])" ?

Olivier Bélanger

unread,
Jan 11, 2018, 4:11:41 PM1/11/18
to pyo-discuss
Hi Pascal,

The problem here is that you create audio objects inside a function call without keeping references to them, so the are garbage collected right after their creation.

Two solutions:

1) These objects:

fnb = Sig(value=fn)
f= Snap(fnb, choice=Gamme[iG], scale=1)

should be created globally and your function only set/use their values (you can retrieve the current floating-point value from an audio stream with the get() method).

2) You just don't use audio objects for the snapping and implement the Snap algorithm in pure python... This involves more work!

Olivier
  

To unsubscribe from this group and stop receiving emails from it, send an email to pyo-discuss+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages