NumPy array to Table or Matrix

288 views
Skip to first unread message

Lennart Hilbert

unread,
Dec 11, 2011, 12:07:05 PM12/11/11
to pyo-d...@googlegroups.com
Hi,

I am looking for a way to write the values of a NumPy float array into a pyo Table or Matrix object in a single, whole array operation.

I assume I could use a loop over each element of the NumPy array. In each loop iteration I can use the put(value,x,y) method to the Matrix object to store the values one by one.

But, that seems very inefficient to me. Is there a straight-forward way to assign a whole NumPy array to a pyo Matrix or Table in a single, whole array operation?

Any comments appreciated. I did not find anything on this topic in the documentation and in this discussion group.

Many thanks,

Lennart

Olivier Bélanger

unread,
Dec 11, 2011, 1:50:38 PM12/11/11
to pyo-d...@googlegroups.com
Hi Lennart,

There is no direct support for numpy array in pyo (it's in my plan to implement it). The most straight-forward way to do this by now is to convert your array to a list and give it to the "init" argument of a DataTable or a NewMatrix object:

##################################################################################
from pyo import *
import numpy as np
import math

s = Server().boot()

size = 512
arr = np.array([math.sin(2 * math.pi * i / size) for i in range(size)])
t = DataTable(size, init=arr.tolist())
t.view()

size = 256
arr2 = np.array([[math.sin(2 * math.pi * j / size + math.sin(i/16.0)) for j in range(size)] for i in range(size)])
m = NewMatrix(size, size, arr2.tolist())
m.view()

s.gui(locals())
##################################################################################

Olivier

2011/12/11 Lennart Hilbert <lennart...@googlemail.com>

Lennart Hilbert

unread,
Dec 11, 2011, 6:34:36 PM12/11/11
to pyo-d...@googlegroups.com
Hi Olivier,

thank you for the quick response, that were exactly the directions I needed. Very helpful!

In your code I found two minor issues:
1) I needed to add s.start() to make the server work
2) The second part of creating a matrix causes no audio output. It does not produce an error, however. I could narrow it down to the three lines:

rr2 = np.array([[math.sin(2 * math.pi * j / size + math.sin(i/16.0)) for j in range(size)] for i in range(size)])
m = NewMatrix(size, size, arr2.tolist())
m.view()
I simply threw the whole Matrix part out then.

With what you gave me I could implement the playback of a random array, here is the code:


##########################

from pyo import *

import numpy as np

import math

s = Server().boot()

s.start()

# ----

# Create and play a table with random waveform

snippet_length = 3; # in seconds, no more audio output above appr. 5.25

samples = secToSamps(snippet_length) # corresponding number of samples

cycle_freq = 1.0/snippet_length # Frequency at which random snippet is played

# Create NumPy array with uniform random numbers between 0 and 1

size = samples

monte_carlo_array = np.random.random_sample(size)

# Convert into pyo table object

monte_carlo_table = DataTable(size,

init=monte_carlo_array.tolist())

monte_carlo_table.normalize() # Should normalize to range -1 to 1

monte_carlo_table.view() # But here seems not to do so, see graph

# Loop the snippet using Osc object

output = Osc(table=monte_carlo_table,

freq=1.0/snippet_length,mul=0.5).out()

s.gui(locals())

##########################

This is basically working, and I am super happy that it does. It seems to produce something like white noise - as expected.

There are two issues which so far do not cause much trouble, but you might want to know about:
1) For snippet lengths >~5.25 seconds, the script executes without error, but there is simply no audio output and the server GUI also shows now amplitude.
2) The .normalize() method does not seem to affect the monte_carlo_table Table. I expected to see random numbers between -1 and 1 after normalization, but they are between 0 and 1 in my graph.

Thank you, and greetings to UdM from the other side of the mountain,

Lennart

Olivier Bélanger

unread,
Dec 11, 2011, 9:30:38 PM12/11/11
to pyo-d...@googlegroups.com
Hi Lennart,

2011/12/11 Lennart Hilbert <lennart...@googlemail.com>

Hi Olivier,

thank you for the quick response, that were exactly the directions I needed. Very helpful!

Nice!
 

In your code I found two minor issues:
1) I needed to add s.start() to make the server work

Not really an issue. I never use s.start(). I prefer to start the audio with the button in the server window. This way, I can control the gain before the playback. I receive thousands of student's script per year...!
 
2) The second part of creating a matrix causes no audio output. It does not produce an error, however. I could narrow it down to the three lines:

rr2 = np.array([[math.sin(2 * math.pi * j / size + math.sin(i/16.0)) for j in range(size)] for i in range(size)])
m = NewMatrix(size, size, arr2.tolist())
m.view()
I simply threw the whole Matrix part out then.

Yep, that's is just the creation of the matrix. I took it from a waveterrain example that I already had. Here, with playback:

###########################################################################
from pyo import *
import random, math

s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot()

def terrain(size=256, freq=1, phase=16):
    l = []
    xfreq = 2 * math.pi * freq
    for i in range(size):
        ph = math.sin(i/float(phase))
        tmp = [math.sin(xfreq * (j/float(size)) + ph) for j in range(size)]
        l.append(tmp)
    return l

SIZE = 512
m = NewMatrix(SIZE, SIZE, terrain(SIZE, 2, 16)).normalize()
m.view()
rnd = Randi(0.05, 0.45, .1)
x = Sine([99.5,99.76], 0, .49, .5)
y = Sine([25, 51.5, 75.2, 100.1], 0, rnd, .5)
a = MatrixPointer(m, x, y, mul=.1).out()

s.gui(locals())
###########################################################################


I have sound here with 30 seconds length... Which version of pyo do you use?
 
2) The .normalize() method does not seem to affect the monte_carlo_table Table. I expected to see random numbers between -1 and 1 after normalization, but they are between 0 and 1 in my graph.

What you expect here is more a DC block filter than a normalize. The normalization process looks for the absolute maximum value, compute the multiplication factor and then applies to all samples. The table sould be already bipolar. Something like:

monte_carlo_array = np.random.random_sample(size) * 2 - 1

However, it's not a bad idea to add a method removeDC() to the PyoTableObject, added it in my TODO!



Thank you, and greetings to UdM from the other side of the mountain,

Oh, we'll probably see us soon... I'll give a workshop on pyo this winter at McGill!

Olivier
 

Lennart

Olivier Bélanger

unread,
Dec 11, 2011, 10:12:02 PM12/11/11
to pyo-d...@googlegroups.com
In SVN now, PyoTableObject.removeDC(). Can be called on any table object (particularly useful with SndTable). The method returns self, so it's safe to call it at the object's creation. In the Lennart's script, the lines (from a random generator between 0 and 1):

monte_carlo_table = DataTable(size, init=monte_carlo_array.tolist())
monte_carlo_table.removeDC()

Give a bipolar white noise signal.
 
Olivier

Lennart Hilbert

unread,
Dec 11, 2011, 11:40:10 PM12/11/11
to pyo-d...@googlegroups.com
Limited length of sound:
I installed using the following advice from your google code page
svn checkout http://pyo.googlecode.com/svn/trunk/ pyo-read-only
to get the source, then installed it using
sudo python setup.py install --install-layout=deb --use-double
I am on Ubuntu 10.04, if that is of any help...

I see, I misunderstood the meaning of the normalize() method a little. I am not from sound engineering or acoustics...
A DC blocker, as you say, seems more like what I was looking for. Great you implemented that!

I got more questions about interfacing with pygame, but that's another post by itself...

Thanks,

Lennart

Olivier Bélanger

unread,
Dec 12, 2011, 12:48:08 AM12/12/11
to pyo-d...@googlegroups.com
Strange... Do you update regularly?

I have a computer running Lubuntu 11.04, I will check tomorrow if I get the same behavior.

Olivier

2011/12/11 Lennart Hilbert <lennart...@googlemail.com>
Limited length of sound:

Olivier Bélanger

unread,
Dec 12, 2011, 9:25:30 AM12/12/11
to pyo-d...@googlegroups.com
Hi Lennart,

Here on Lubuntu 11.04 I can set the duration to 30 seconds without problem. Maybe the problem come from the fact that you compile pyo in double but you use single precision in your script. Is the single precision up-to-date?

If you compile with --use-double, you should import pyo64. "import pyo" will load the 32-bit library, which is compiled without the flag --use-double.

There is a script in the scripts folder that compile both single and double:

sudo sh scripts/compile_linux_withJack.sh

This way, both version are always sync...

Olivier
Reply all
Reply to author
Forward
0 new messages