There is a problem with audio routing.

66 views
Skip to first unread message

sergei.k...@gmail.com

unread,
Oct 9, 2021, 7:48:04 AM10/9/21
to pyo-discuss
Again and again I return to the study of Pyo, but I always stumble over incorrect behavior.

I create a mixer and add sounds to its output.

```py
from pyo import Mixer, Server, SndTable, TableRead

s = Server(duplex = 0).boot()
s.start()

# Create a mixer.
mixer = Mixer(chnls = 2)
mixer.out()

# Output the note to the mixer outputs.
for index in range(0, 12):

table = SndTable("note/{}.wav".format(index))

mixer.addInput(index, TableRead(table = table, freq = table.getRate()))
mixer.setAmp(index, 0, 1)

s.gui(locals())
```
However, this leads to clogging of the audio channel. This problem does not exist if 1 sound. This is compounded by their addition.

Video, if it's not clear what I'm talking about.

https://drive.google.com/file/d/1nhkA4fBGAQRTe7ewXQttYjbwTVr0PSAu/view?usp=sharing

barmin

unread,
Oct 9, 2021, 12:21:07 PM10/9/21
to pyo-d...@googlegroups.com
My guess would be that simply adding the two samples leads to clipping because it's getting too loud. Maybe try with `mixer.setAmp(index, 0, .5)`?

Cheers,

Matthieu

Le 09.10.21 à 13:48, sergei.k...@gmail.com a écrit :

sergei.k...@gmail.com

unread,
Oct 9, 2021, 12:57:38 PM10/9/21
to pyo-discuss
I've thought about it, but the mixer has to do the job under the hood. Otherwise it's not a mixer.

I created a test that shows a negative result. It's just that the overall signal level has decreased, but the problem remains.


from pyo import Mixer, Server, SndTable, TableRead

s = Server(duplex = 0).boot()
s.start()

# Create a mixer.
mixer = Mixer(chnls = 2) 
mixer.out()

p = 0.08333333333333333

# Output the note to the mixer outputs.
for index in range(0, 12):

    table = SndTable("note/{}.wav".format(index))

    mixer.addInput(index, TableRead(table = table, freq = table.getRate()))
    mixer.setAmp(index, 0, p)

    print(p)
    p += 0.08333333333333333

s.gui(locals())

sergei.k...@gmail.com

unread,
Oct 9, 2021, 1:03:07 PM10/9/21
to pyo-discuss
I forgot to delete the test calculations.


from pyo import Mixer, Server, SndTable, TableRead

s = Server(duplex = 0).boot()
s.start()

# Create a mixer.
mixer = Mixer(chnls = 2) 
mixer.out()

p = 0.08333333333333333

# Output the note to the mixer outputs.
for index in range(0, 12):

    table = SndTable("note/{}.wav".format(index))

    mixer.addInput(index, TableRead(table = table, freq = table.getRate()))
    mixer.setAmp(index, 0, p)

s.gui(locals())

Even if I divide the levels by the number of outputs, it does not solve the problem.

barmin

unread,
Oct 11, 2021, 11:25:59 AM10/11/21
to pyo-d...@googlegroups.com
> I've thought about it, but the mixer has to do the job under the hood. Otherwise it's not a mixer.

Not sure about this. I don't think pyo's Mixer object is meant to be an equivalent to a physical mixing console.

Anyway, not sure about what's wrong in your code, sorry.

Cheers,

Matthieu

sergei.k...@gmail.com

unread,
Oct 11, 2021, 11:41:22 AM10/11/21
to pyo-discuss
It looks like the problem is in TableRead, class SfPlayer is working.

from pyo import Mixer, Server, SfPlayer

s = Server(duplex = 0).boot()
s.start()

# Create a mixer.
mixer = Mixer(chnls = 2) 
mixer.out()

# Output the note to the mixer outputs.
for index in range(0, 12):

    mixer.addInput(index, SfPlayer("note/{}.wav".format(index)))
    mixer.setAmp(index, 0, 1)

s.gui(locals())

However, it is slow, so it works with a hard drive.

In parallel, there is another problem. Pyo plays sounds anyway, even during initialization. 
I would like to do this using the play() method at the right moment.

sergei.k...@gmail.com

unread,
Oct 11, 2021, 1:03:03 PM10/11/21
to pyo-discuss
I solved the problem.

from pyo import Mixer, Server, SndTable, TableRead

s = Server(duplex = 0).boot()
s.start()

# Create a mixer.
mixer = Mixer(chnls = 2) 
mixer.out()

# Output the note to the mixer outputs.
for index in range(0, 12):

    table = SndTable("note/{}.wav".format(index))

    tr = TableRead(table = table, freq = table.getRate())
    tr.stop()

    mixer.addInput(index, tr)
    mixer.setAmp(index, 0, 1)

tr.play()

s.gui(locals())

You need to call the stop() method for TableRead object. 
Pyo contains, in my opinion, an error related to logic. When out() is specified, it works like play(). Which is not quite correct.

Olivier Bélanger

unread,
Oct 17, 2021, 9:29:52 PM10/17/21
to pyo-d...@googlegroups.com
Hi,

IMO, an audio processor in a programming environment should never make assumption about what the programmer is trying to do, it should do only what it is asked for. It could be intentional, for example, that all volumes in a Mixer are managed in a way that the sum of the signal is higher than 1, but the overall balance is correct. All is needed is to lower the overall gain after the mixing, and before sending the signal to the output. Internally, the samples are floating-point values (either float or double), so it's legal to produce values greater than the -1.0/1,0 range in the processing chain, it only has to be in range at the output.

Olivier

p.s.: There is nothing wrong in that code!

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyo-discuss/b7520af5-9496-18b8-3ee4-7fcfa6271a49%40bluewin.ch.

sergei.k...@gmail.com

unread,
Oct 18, 2021, 10:50:23 AM10/18/21
to pyo-discuss
Bonjour,  Olivier

I know, but the problem is that Pyo creates active objects by default.

Therefore, after creating an object, you should always call the stop method.

It would be more logical to initially create inactive objects. I am used to classes where there is a __init__ method, during initialization, the sound does not have to shoot like a cannonball.

I like the fact that Pro has become available through pip, I think I will recommend it for game development. The only thing missing to replace OpenAL is spatial sound.

Olivier Bélanger

unread,
Oct 18, 2021, 11:38:54 AM10/18/21
to pyo-d...@googlegroups.com
Hi,

In my experience, it's much more the usual case that an object should be active upon creation, creating an audio object that should not be active is the exception. Either ways, under some circumstances, there will be an extra call, I prefer it to be stop rather than play!

You know you can append the call to stop:

a = Sine().stop()

Olivier


Reply all
Reply to author
Forward
0 new messages