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...
-
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.
-
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!