belangeo / pyo

Python DSP module

Home Page:http://ajaxsoundstudio.com/software/pyo/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Inconsistency in NoteinRead and NoteinRec file format

JRice15 opened this issue · comments

Thank you so much for the library!

I found one problem. Using NoteinRec generates a file like the following:

3.738413 523.252869 0.850394
3.773243 523.252869 0.000000
6.977596 1318.515625 0.850394
7.070476 1318.515625 0.000000

Looks like we've got a time frequency velocity format. However, when I try to use NoteinRead on this file it segfaults. But if I replace it with this line from the documentation example, it works: notes = NoteinRead(SNDS_PATH+"/NoteinRead_example_test", loop=True). If we look at the NoteinRead example files provided in the SNDS_PATH, the difference is fairly obvious, NoteinRead seems to be expecting pitch as the midi number instead of the hz:

0.000000 48 0.15
0.500000 55 0.25
1.000000 58 0.35
1.500000 60 0.5

My full pyo version/build is: pyo-1.0.5-py3.8-macosx-10.9-x86_64

Hi, there are potentially two problems here...

  1. The documentation for NoteinRec is wrong, it records the stream values of a Notein object, according to the Notein's scale attribute (can be MIDI, Hz, or transpo). I'll fix the doc.

  2. Where are you using notes["pitch"] to make the program segfault? NoteinRead just reads floating-point values, so the segfault does not happen from that object, it's something afterwards. Still, the pitch should be wrong, and very high, but it shouldn't segfault. The faulty object must be fixed!

You're right, the problem was caused by my use of MToF in this block of code, I should have noticed that:

notes = NoteinRead(noteoutpath, loop=True)
amps = Port(notes['velocity'], 0.001, 0.45, mul=.3)
sines = SineLoop(freq=MToF(notes['pitch']), feedback=.05, mul=amps).out()

Removing the MToF call makes it work

To isolate the problem, this block of code works, but if the 400 is increased to 500, a segfault occurs:

from pyo import *

s = Server().boot()

bad_midi_value = 400
sig = Sig(bad_midi_value)
hz = MToF(sig)
syn = SineLoop(freq=hz, feedback=.07, mul=.2).out()

s.start()
s.gui(locals())

NoteinRec documentation is now correct. About the segfault, the "true" fix would have been to clip the freq argument of Sine and SineLoop objects, but for performance concerns, I don't want to add a conditional branch in the computation of these oscillators. At this point, it is the responsibility of the user to pass values that make sense (which can be well beyond nyquist frequency anyway). Still, I fixed the segfault in this particular case by clipping the input value of MToF (and midiToHz function), which lie in a well defined range. I clipped between -256 and 256 to give some headroom!