belangeo / pyo

Python DSP module
GNU Lesser General Public License v3.0
1.28k stars 130 forks source link

Setting a parameter for an individual stream of a PyoObject #189

Closed jacksongoode closed 3 years ago

jacksongoode commented 3 years ago

Hi again,

I have a question that may actually be a general confusion about how PyoObjects work.

In this specific case, I have a STRev object that is assigned to an array of Pan PyoObjects. The inpos attribute is assigned to a list of the same length that was used to determine the unique panning for each pan object. The result is an array of players that are positioned spatially with proper reverb.

However, If I want to automate the panning of just one of these voices, it is impossible to target the attribute 'inpos' for a specific stream (just one of these panning PyoObjects that was assigned to STRev). I can only use the set() method to change the 'inpos' of every stream simultaneously.

Here is the initialization code to help explain. I may not be thinking about this correctly.

player_num = 16 # 16 players

for i in range(player_num):
    pan_vals.append(i / player_num + (1 / (2 * player_num))) # create equidistant pan values

for i in range(player_num):
    adsrs[i] = Adsr()
    players[i] = SfPlayer(src + 'empty.flac', mul=adsrs[i])
    panners[i] = Pan(players[i], pan=pan_vals[i])

verbs = STRev(panners, inpos=pan_vals)

# This changes all panning values
# verbs.set(attr='inpos', 0)

# It seems that the panning of the Pan objects is overwritten by STRev's 'inpos' - this appears to do nothing
# panners[i].set(attr='pan', 0)

# Initializing verbs this way is not possible - creates many reverbs, improper - but would allow individual panning
# verbs[i] = STRev(panners[i], inpos=pan_vals[i])
jacksongoode commented 3 years ago

Any thoughts on this?

jacksongoode commented 3 years ago

Should I close this as a feature that will not be worked on?

belangeo commented 3 years ago

Hi,

Regarding the main issue, which is targeting a specific stream in a list of stream, the problem here is that your list of values is not a list of PyoObject, but simple floating-point values. What you can do is to make pan_vals a list of Sig() objects, and change the value attribute of the specific target stream. Something like:

pan_vals = [Sig(1)] * player_num
pan_vals[4].value = Sine(0.5).range(0,1)

Another point... I don't think using the output of Pan as the input of STRev does what you think it does. The Pan object creates 2 stream for each mono input (to be able to pan the signal on a stereo field), so its output count is 32 in your case. But then, STRev does exactly the same thing as it has an internal panner, so your 32 streams becomes 64!

And about your last comment:

Initializing verbs this way is not possible - creates many reverbs, improper - but would allow individual panning

It's not as elegant as creating one reverb object with multiple streams in input, but in the end, it's the same thing. There is no magic, if you give 8 mono streams to a STRev objects, the audio engine will create 8 stereo reverbs under the hood. The code just look better!

belangeo commented 3 years ago

Closing as not an issue.