saving data from component , send OSC, audiobuffer

10 views
Skip to first unread message

Hairi Vogel (airi)

unread,
Nov 7, 2022, 6:05:54 AM11/7/22
to PraxisLIVE discussion group
Hello. 
How do I save data from a component to a file ?
I am looking for something like saveTable() / loadTable() in Processing or
any functioning example to hack.

How can I send OSC from PraxisLive ? 
Is it worth the while trying to use oscP5 the Processing library ?
That would be a workaround for the lack of serial comm. 

I had just a short look at the audio part, but it is complete and there is no need for
libraries like Minim at all. Just one thing: 
On my system it is not possible to do anything with audio with blocksize smaller than 
512. Not with the incorporated Realtek audiodevice , not with the Tascam iXR USB interface I use normally.
I have a AMD Ryzen 9 with 64GB of fast RAM (gaming style) and a Radeon 6050.
It is amazing how your software performs compared to Processing and Isadora !!!
Graphics and Shaders , super. Never a flaw. Impressive. It pays to have architecture made by artists. 

Thanks for the wonderful work
cheers
Hairi




Neil C Smith

unread,
Nov 7, 2022, 9:57:16 AM11/7/22
to praxi...@googlegroups.com
Hi,

On Mon, 7 Nov 2022 at 11:05, Hairi Vogel (airi) <hairi...@gmail.com> wrote:
> How do I save data from a component to a file ?
> I am looking for something like saveTable() / loadTable() in Processing or
> any functioning example to hack.

What format do you want to save data as, and what is the input data?

In general you want to move file IO into a separate root graph (eg.
generic data patch).

The following component will save a PArray of PArray as CSV using
Processing's Table. Just copy and paste the text between the ~~~~
lines onto the data graph. You'll need to change the .file property to
a URI on your system.

~~~~~~~~~~~~~~~

#%praxis.version 5.4.0
@ ./table-save core:custom {
#%graph.x 0
#%graph.y 0
.code "import java.io.File;
import java.io.IOException;


@P(1) Optional<PResource> file;

@In(1) void in(PArray data) throws IOException \{
if (file.isEmpty()) \{
return;
\}
var destFile = new File(file.get().value());
if (data.isEmpty()) \{
throw new IllegalArgumentException(\"No data\");
\}
var table = new processing.data.Table();
var columns = PArray.from(data.get(0)).orElseThrow();
for (Value column : columns) \{
table.addColumn(column.toString());
\}
for (int r = 1; r < data.size(); r++) \{
var row = PArray.from(data.get(r)).orElseThrow();
var count = min(columns.size(), row.size());
var tableRow = table.addRow();
for (int i = 0; i < count; i++) \{
tableRow.setString(table.getColumnTitle(i),
row.get(i).toString());
\}
\}
table.save(destFile, \"csv\");
\}

"
.file file:/home/nsigma/test.csv
}

~~~~~~~~~~~~~~~

This can then be used from another component by doing something along
the lines of -

@T(1)
void trigger() {
var table = PArray.of(
array("Column1 Column2 {Column number three}"),
array("Data1 Data2 {}"),
array("1 2 3")
);
tell(ControlAddress.of("/data/table-save.in"), table);
}



> How can I send OSC from PraxisLive ?
> Is it worth the while trying to use oscP5 the Processing library ?
> That would be a workaround for the lack of serial comm.

I would look at using a Java OSC library. PraxisLIVE actually has
NetUtil in it, but it's hidden. I need to have a think about this
one.

Again, if you do this, use a generic data patch and send data to a
component in that.


> I had just a short look at the audio part, but it is complete and there is no need for
> libraries like Minim at all. Just one thing:
> On my system it is not possible to do anything with audio with blocksize smaller than
> 512. Not with the incorporated Realtek audiodevice , not with the Tascam iXR USB interface I use normally.
> I have a AMD Ryzen 9 with 64GB of fast RAM (gaming style) and a Radeon 6050.
> It is amazing how your software performs compared to Processing and Isadora !!!
> Graphics and Shaders , super. Never a flaw. Impressive. It pays to have architecture made by artists.
>
> Thanks for the wonderful work

Thanks for the feedback!

Part of why performance might be better is that PraxisLIVE has a very
rigid concurrency model, sending messages between different graphs
(audio, video, data, etc.). By doing this we can ensure they don't
interfere with each other, and even run different graphs in different
processes. By default, the IDE, video and audio are running in
separate processes. You can configure this in each project's
properties - https://docs.praxislive.org/projects/#hub-configuration

What OS are you on? For best audio performance, use the JACK backend
if you can.

The internal buffer size for audio in PraxisLIVE is 64 samples (by
default). This can be altered if necessary, as long as the external
buffer size is a direct multiplier of this value. Things should at
least sound the same, even if you have to increase external buffer
sizes.

Best wishes,

Neil

Hans Heinrich Vogel

unread,
Nov 7, 2022, 10:54:17 AM11/7/22
to praxi...@googlegroups.com
sorry not to mention it:
Win 11 it is.
thanks for the hints and stuff

a general question is how to make a dictionary type thing where objects are keys and values,
survive a code change.

preferably allowing nested stuff like HashMap<String,HashMap<Property(or Ref Property ??),Value>>

my current workaround is generating a single string out of the map, store it in a Property
and regenerate the map, 
which means keeping a map that relates names to Property(s) and excludes many types of Properties.



h

Neil C Smith

unread,
Nov 7, 2022, 11:14:41 AM11/7/22
to praxi...@googlegroups.com
On Mon, 7 Nov 2022 at 15:54, Hans Heinrich Vogel <hairi...@gmail.com> wrote:
> a general question is how to make a dictionary type thing where objects are keys and values,
> survive a code change.

Survive code changes or save as part of project?

For carrying across code changes you can now just use a field

@Inject Map<String, Whatever> map;

The map will be created for you.

Or use

@Persist Map<String, Whatever> map;

But then you'll have to create it yourself if it's null.

More on those additions in 5.3 at
https://github.com/praxis-live/praxis-live/releases/tag/v5.3.0

If you need a dictionary that will be saved as part of the project,
then you'll need to use PMap

@P(1) PMap map;

This is an immutable map that only has other Value types as values.

Hope this helps.

Best wishes,

Neil

PS. I think there's still a JACK that runs on Win 11. I should look
at WASAPI or ASIO directly! :-)

Hairi Vogel

unread,
Nov 7, 2022, 2:17:35 PM11/7/22
to praxi...@googlegroups.com
Il giorno lun 7 nov 2022 alle ore 17:14 Neil C Smith <ne...@neilcsmith.net> ha scritto:


For carrying across code changes you can now just use a field

@Inject Map<String, Whatever> map;

The map will be created for you.

Or use

@Persist Map<String, Whatever> map;

But then you'll have to create it yourself if it's null.

More on those additions in 5.3 at
https://github.com/praxis-live/praxis-live/releases/tag/v5.3.0

ok





 
If you need a dictionary that will be saved as part of the project,
then you'll need to use PMap

@P(1) PMap map;

This is an immutable map that only has other Value types as values.

how do I fill this map ? or create it from a HashMap<Obj,Obj> ?
the property @P(0) PMap mymap; does not accept .put

thnx
h

 

Neil C Smith

unread,
Nov 8, 2022, 4:40:04 AM11/8/22
to praxi...@googlegroups.com
On Mon, 7 Nov 2022 at 19:17, Hairi Vogel <hairi...@gmail.com> wrote:
>> If you need a dictionary that will be saved as part of the project,
>> then you'll need to use PMap
>>
>> @P(1) PMap map;
>>
>> This is an immutable map that only has other Value types as values.
>>
> how do I fill this map ? or create it from a HashMap<Obj,Obj> ?
> the property @P(0) PMap mymap; does not accept .put

There's a builder that has put() on it. To create one from code you use -

map = PMap.builder()
.put(key, value)
.put(key, value)
// etc
.build();

If you have one in a property you can also set the values from the
editor (click the ... on the property), or externally.

There are some improvements coming in the API for PMap in 5.5 soon too.

It's not really intended for large or frequently changing data sets,
though. In some ways, more like a struct or Java record. eg. the hub
configuration mentioned earlier is nested PMaps.

What's the data, are you just reading it or generating it at run time,
what types of value, and how much data is it?

Best wishes,

Neil

Hans Heinrich Vogel

unread,
Nov 9, 2022, 6:37:18 AM11/9/22
to praxi...@googlegroups.com

On 8 Nov 2022, at 10:39, Neil C Smith <ne...@neilcsmith.net> wrote:

There's a builder that has put() on it.  To create one from code you use -

map = PMap.builder()
    .put(key, value)
    .put(key, value)
    // etc
    .build();

Hi Neil.
It occurs to me that my mostly Processing based Java-knowledge is to poor
to understand all of your code and that I am asking you questions I should ask
in a Java beginners class. Sorry for that and thanks for your generosity.

So I rather explain to you what is the only feature missing in PraxisLive that I would really need
to completely stop using stuff like Processing and Isadora for my art. I am sure it is possible with your
magic architecture. 

I would like to be able to save states of whole projects (all ControlAdresses in the project and the corresponding values) 
and recall them in a particular way, by morphing the values.
Different morphing schemes should be implemented for values other than floats.

The complete data should be saved as .csv along the project and processable by other code.

I envision a master-preset component that accepts String names, a morphTime and a Easing for floats as input,
and sends the values found to each ControlAddress stored under the preset name .

The same Component needs a way to ask all others in the Project to send the current values of all their properties
for storing under a name. This may happen whenever a String arrives with a name not found in the stored preset data.

If such a component is limited to a single patch, it is no problem, one can sync multiple instances.

My work consists often in LiveProgramming and I keep only track of a fraction of the interesting settings a ´machine´
i work on produces along the way. Isadora works with scenes and snapshots, but in a uncontrollable, messy way.
That costs sometimes 80% of the time.

Have a nice Day
Hairi

Neil C Smith

unread,
Nov 9, 2022, 7:31:40 AM11/9/22
to praxi...@googlegroups.com
On Wed, 9 Nov 2022 at 11:37, Hans Heinrich Vogel <hairi...@gmail.com> wrote:
> It occurs to me that my mostly Processing based Java-knowledge is to poor
> to understand all of your code and that I am asking you questions I should ask
> in a Java beginners class. Sorry for that and thanks for your generosity.

No problem! Some of this is specifics to the PraxisLIVE libraries,
rather than Java, although builder() is something of a convention in
Java for creating immutable objects.

Note that you can right-click on any type in the editor (eg. PMap) and
use Show Javadoc.

> So I rather explain to you what is the only feature missing in PraxisLive that I would really need
> to completely stop using stuff like Processing and Isadora for my art. I am sure it is possible with your
> magic architecture.

:-)

Not sure about magic! Is this achievable? Yes. It's what the IDE
does. But it's not that easy to achieve inside a project at the
moment. I'm actually working on some things at the moment that would
make it easier.

However ...

> I envision a master-preset component that accepts String names, a morphTime and a Easing for floats as input,
> and sends the values found to each ControlAddress stored under the preset name .

I would take a slightly different approach if you can, and create a
controller component with animatable properties for state, then link
the output ports of that to all the input ports you want to control.
That way you don't need to query every component property.

If you use Property for floats you've got animation with easing built
in too, and everything will sync.

Best wishes,

Neil
Reply all
Reply to author
Forward
0 new messages