Csound in Pure Data on Raspberry-Pi

Today I got Csound running inside Pure Data (using the [csoundapi~] object) on Raspberry-Pi.

These instructions assume you have already installed pd-extended on R-Pi. See this post to learn how. https://reactivemusic.net/?p=4930

Install Csound

# sudo apt-get install cloud

Install csoundapi~

# sudo apt-get install pd-csound

Copy csoundapi~ library into the pd-extended extras folder

# cd /usr/lib/pd/csound/extras
# sudo cp csoundapi~.pd_linux ../../pd-extended/extra

Here’s a test patch:

Here’s the Csound source file (should be in the same folder as the test patch)

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz

sr = 44100
nchnls = 2
0dbfs = 1
ksmps = 8

giSine    ftgen     0, 0, 2^10, 10, 1

instr 1
kFreq     invalue   "freq"
kAmp      invalue   "amp"
aSin      oscili    kAmp, kFreq, giSine
          outs      aSin, aSin
endin

</CsInstruments>
<CsScore>
i 1 0 10000
</CsScore>
</CsoundSynthesizer>

Here are the source files:

http://zerokidz.com/rpi/csound/cstest2.pd

http://zerokidz.com/rpi/csound/control.csd

Here’s the command line to run the test:

# pd-extended -nogui -noadc cstest2.pd

Here are general instructions on running csound in Pure Data from Victor Lazzarini:

http://booki.flossmanuals.net/csound/_draft/_v/1.0/csound-in-pd/

 

csoundapi~ in Pd

notes

A preliminary test before trying this in Raspberry-Pi, I used the general instructions for csound in pd from Victor Lazzarini found here:

http://booki.flossmanuals.net/csound/_draft/_v/1.0/csound-in-pd/

to get csound running in pd-extended in Mac OS.

Looks pretty straightforward – biggest question will be compiling the external if it doesn’t install via package manager.

local test files are in tkzic/rpi/pd/csound

Here’s something from Victor Lazzarini which shows csound running on R-Pi

http://csound.1045644.n5.nabble.com/csound-on-raspberry-pi-td5718623.html

Here is installation instructions from Richard Dobson

http://csound.1045644.n5.nabble.com/Raspberry-Pi-w-Csound-td5717410.html

 

 

Running http: requests from Max

notes
  1. How to separate the status return code  from the actual response data?

For jit.uldl-  status reports get sent out the right outlet and errors are reported in the Max window. However their doesn’t appear to be a way to get the http: status codes or other header data.

For curl, you can write the response (JSON for example) to a file. Then you can read the file using the [js] object and parse the JSON. If you are using [aka.shell] to run the curl command, the stdout and stderr can be routed from the object – for instance, into the Max window. The -v flag (verbose mode) causes curl to output a bunch of header data.

 

 

 

 

Car engine enhancement with Max and OBD-II

Much of our driving experience is wrapped up in sounds that happen when you press the pedal to the metal. Like Superman emerging from a phone booth, this 2006 Jetta seems different.  The project connects RPM data from an OBD2 diagnostic sensor with the input of the car radio. Via synthesizers.

[update 11/2013 – source code is available at https://github.com/tkzic/automax  – this version features

  • V8 engine
  • Jet engine
  • Spaceship
  • Star Trek TOS transporter button
  • Korg nano-control Midi controller interface]

This project uses the RPM data from an automobile OBD-II port to control the engine speed of an engine simulation from Andy Farnell’s book “Designing Sound”

Here’s the patch that polls and translates OBD-II data

patch is tkzic/automax/rpm4.maxpat

Here’s a Max version of the Farnell car engine simulation:

patch is tkzic/automax/waveguide_engine2e-1.maxpat

 

 

 

Using a Wiimote with Osculator in Max

Update 6/2014: The Max patch is available from the max-projects archive: https://reactivemusic.net/?p=11130

original post

I had a difficult day with wiimotes…

Here’s a general purpose Max patch to read Wiimote Osc data from Osculator:

Located in tkzic/max teaching examples/wiimote/wiimote_read.maxpat

<code>
----------begin_max5_patcher----------
1412.3oc2ZsrjahCEcs8WgJVSr06GYWlY0rJUMyxolJEFqzMorAW.ticmJ+6
iPxNF2sMPm1Hn7hz.JXw4dz8w4J3GSmDrHamtH.7Qv+BlL4GSmLwNT0.SNb8
jf0Q6hWEUXusfT82yV7sfP2+UodWoc3O+O+4Gxy1VpAygf4Hvb7waYSTY7iI
oO7kbcbo6Iww7YbNiSUg.DGMCZN.kUGvvYPv+c3WltcsYFWoKsOY5gQ+ZVZY
Qxy5pwPXyOxMr6NK2uQ6dFAAg092ulyjkV3ZLgOfYA0lxzn01eYvmxShVEbB
BIoGQ.pZreNcZ0eBeezUgNcIHIeeCjDBBYyXHjjhL7ByROLRKjDrYRpt0SGb
qeWCVuBo9kKROX7DOX7wYqWqSKek0GEGqWoyiJSxR+HXW39vm6XrBVQswJtC
XQ6LQ9CKrWO6hbi7hbCdfcLhZhNjF+h9Kn.w8fs+0UYl4nq1ncQBHbYGIW0F
wWxFoyDJnRH90iJ2XQk57unSiVrRWmadU5SCJiJqxctHJ8gS4OW7Pb1prb2M
AmoXbAkYbIqfGz3nJ4Jt8xKkwEIFZWqlR3Jv39z0RNz19ttlk41a6pwPX0Yq
u2SgUX3XfdOyE5thdQCcjabbC7NC+5JhpaWnKaL3aclMNt8snLlz1Wiy2RPT
7FJHRGPcnwOZrCMn7QMv7LVnyAkYf0Uje8wRRAetHd6pnxr7YfDcH36IIm5t
aURpNNaapcJIWeEj.g1rCxP.EZEwxrGnuaQrW1s0GB7WrsrLKsoV3bgiHwwv
wFCJQWyw6b+s5VIxK4eZRzDk7JQST9MK6yPqYJuAKmP3G8nOZ3zalgOzMmuo
ACGaBfYmLZwsqVy.lLzEKWzz5MyZntdukhdrC7QgZ4y29oQdMWifNrppbqTn
Hlmjq56UJ5NJ5w+r825dhcEilcVaSHHODrODD0gjYG1RMorGiqYiAMIXrs4f
Ca6dOHJA26Ky45nkUpPWmUpAlxUEY4fkQkQfsEFaEjcTtJ3hhTwMzlAiMCcH
nzoREiQ2FUpmbHdYunRJAQO0u.kAURaWo3KwtiCcsDmyCCaOvmQjDEDW6zam
DWBxi1kfNioXBHwSFGV4OiSpfyvr9LxWI68P++5uqdgIcstpKot.0i4zQvAb
2gdSuz05Lyv8RWQPezZyZcQQzC5WQXysJDluIeektFI2HbxbBCxkJd0IbjRw
LmfgD5oE1ttGGtFeEts2fXSePYsFe0Yp8xz4aUTAtOTyd1t.bGs+bJ7XnWg5
6zvcD4JGE84drAf6IhULlJIAlSZh9culwiEjvnVJHwdOEjtVQIAdLnp1z6IR
IYbOI9jy8mocXuy7gjZnzit3eBL+OZU30Ai2kfAgICgGNGOJRI3bT.0jgc3z
c6eFLOI2brXNpoNzTVWHkKMMeP3RDTMbj41kaLrgN4IMPAgv1oJ2KeRo5X2d
uc0nmUmhHEDrcqBogVI1HDUb8chENJ7Jqdglcvoy8V0akIw+N9bWhcXuG2L6
DZ6b4EecuV6qZ7yorhrs4wGgzw0FvIabotnLI0typ0toJHV6ldLY4RcZc4NK
SJpT.YMJ3EW75Jddwi5x3w1ND.Ml.j+XnpumY.tM.I7KdPsfGLzu3osErpO1
GOgGmuQaKXu.08If3cgendCNht.Gh+Vt5BdPb+4N2kDzUe0o9BOntfGkmCuH
slfl5YD0ZFQOim1Vx33QFAI7GfrOpVcg7nGDsKwXdrhQmxA4uRpJbGvi+RIJ
6R7k+7djcpBleCtZS9ixyA6sk7Qp7KdZ0Y1e544cge3b+hmV62gf7KfZsZAV
4W.0dKpROVfuKEvTiM.I7LdZMH62DOtMEJZylmz4EGlRKTBVG8M2l3wCsWlj
5tzNiA45mRNd+xoUy1Om9+nVZpDJ
-----------end_max5_patcher-----------
</code>

Some tips…

  • Use a real Wii remote, not the Nyko. If you do get the Nyko, get the one with motion-plus.
  • update Osculator to the latest version
  • Under parameters (in osculator) press + to add the little pacman symbol labeled “same address”, and set the the OSC URL to whatever you’ll be using like 9000 for Max
  • remember to add the Event type (OSC routing) and value (pacman thing) for every wiimote event you’ll be using
  • remember to enter checkbox on the wiimote window for every type of data you want to send

 

 

Real time Irish train map in Max

Using node.js

Time compressed video of Irish railway data from November 30th 2012.

update notes 2/11/2021

After many years…. I was able to get this running

  • in the project folder (ie., /trains)
    • npm init
    • then do: npm install <package> for these packages:
      • request
      • xml2js
      • util
      • http
      • ws
  • then just ran: node max-train1.js and started polling in train-drawing4.maxpat and the data started rolling in
  • webSockets code was replace using ws library

Also using sample webSockets code from here to handle the map points: https://masteringjs.io/tutorials/node/websockets

Next steps:

I would like to update all of this in node for max – but its also nice to have an example of doing OSC communication with Max the old way.

Original documentation follows


This map is centered on Dublin. Each train is a different color and the train number gets printed next to the current position. So for example you can see P607 coming into Dublin from the South.

It gets updates every 10 seconds or so – but sometimes the trains seem to ‘jump’ so I don’t think the actual  data itself gets updated that fast.

download

https://github.com/tkzic/internet-sensors

folder: trains

files:

main Max patches
  • max-train3.maxpat
  • train-drawing4.maxpat
abstractions and other files
  • data_recorder_list-tz.maxpat
node.js
  • max-train1.js: (main server)
  • bigInt.js: (Osc support)
  • byteConverter.js: (Osc support)
  • libOsc.js: (Osc library)
  • max.html: (the web client file – runs in browser)

node.js installation

Install node.js on your computer (or a separate server). Instructions here: http://nodejs.org

In a terminal window go to the project folder ie., /internetsensors/trains

type: npm init

(just accept all the default values)

The following node packages are required. Install using npm. For example:

type: npm install request

Do the same with all these packages

  • request
  • xml2js
  • util
  • http
  • ws

instructions

These instructions are a bit confusing. A simpler UI is in the works. (that’s funny – I said it 8 years ago)

  • Open both Max patches: max-train3 and train-drawing4
  • To run the server, open a terminal window, go to trains folder, and type:
node ./max-train1.js
  • Back in Max, in train-drawing4, you can start and stop polling with the toggle button in the upper left corner. If you want to toggle playback from the data recorder, you’ll need to have some data recorded – or load a file (this is done from max-train3)
  •  In max-train3, select a preset in the preset object. Try the top left one, The presets go from low res to high res on Dublin (left to right).
  •  You can load train-data1.txt by clicking read message on the data recorder. Then press play, or use metro (set to low number) for high speed.
  • In train-drawing4 you’ll need to manually clear the lcd and lcdsprites in the drawing section.
  • In max-train3 you can clear the color database using labeled button (if the train names don’t print on the map)

Running the chat thing

When you connect to the node server in a web browser, for example using the following url:

http://localhost:8124

You will get a message welcoming you and asking you to enter your name. After you enter your name, Max will send you a response. Then you can enter map points using the following format:

Dublin 53.15 -6.90

The map point will be drawn on the map in the Max patch.

how does it work?

Data communication is done with OSC messages. Here’s how

  • Max sends a /getTrains message to a node.js server
  • The server runs an http: request to the Irish rail API
  • The server parses the response data and sends back a bunch of /train name x y messages. to Max
  • You can also connect to the node server from web browsers in kind of a ‘chat’ thing (using Web sockets) and enter geographical place names with lat/lon – which get pinned to the map – and Max sends back personalized thank-you notes.

Here’s what the raw data looks like:

Note: if there’s no data at this link, check the time of day. Trains stop running around midnight UTC.

Programming:

Essentially what this program does is collect current train position data from Ireland and display it as points on an XY grid.

components:

  • Max/MSP
  • node.js
  • Web browser
  • Irish train API

Server

The server is written in node.js. This was my first real project using node. So I tried to make it do a bunch of things, just to test them out.The necessary features are

  • web server to make http: requests to get the train data
  • UDP server to pass data and messages back and forth from Max to node.js using Osc
  • convert XML train data to JSON,
  • convert point data from lat/lon to XY format
Additional features of the server include:
  • chat server using socket.io which allows several web browser sessions to connect to the server, talk with each other, send point data to Max, and receive acknowledgement from Max
Localhost vs. separate server

This is probably the most confusing part about this program. You can run it on the Mac in localhost mode, or you can run the node.js program on a separate server, as long as there is a direct ip path back to the computer where Max is running.  Running a separate server makes more sense if you are using the chat or a remote web control aspect of this. I have run the node program on a Ubuntu server on my local network without making any changes other than to the IP addresses as explained next.

You need to make 2 changes to go from localhost mode, to separate server mode:

In the client program, max.html – near the top, change the ip address from localhost to the specific ip like this:

// note: if you want to run this program on something other than localhost, then put in the ip
// address of the server here, instead of local host...

//     var socket = io.connect('http://localhost:8124');
//
       var socket = io.connect(192.168.1.10:8124');

 

In the server program, max-train1.js – change the destination address for UDP to the address of the computer where max is running:


var dSendAddress = '127.0.0.1';	// send response messages to max at this address
// do this if max is running somewhere other than the same computer as the node server
// var dSendAddress = '192.168.1.104';	// send response messages to max at this address

 

Also in the Max patch max-train3.maxpat you will need to change the [udpsend] object to give it the host address of the node server.

screenshots:

max-train3.maxpat

train-drawing4.maxpat

Data recorder:

To be able to save and replay data I included a data recorder in the patch. Its a revision of the data recorder from CNMAT by Michael Z. This version

  • works with lists that start with a symbol (not just ones that start with numbers)
  • handles the time delta correctly on the first record
  • adds additional transport controls, for example playback using a [metro] at any speed – and ability to goto a particular position in the data file

The actual code for the patch is horrendous. Its filled with debugging objects and is a maze of patch cords lacking explanation. But it works…

what’s next

  • Make sure that the Max Patch loads a preset map setting by default
  • put a timestamp message in the node console and Max console so we know at the end of a train list what the current time is.
  • clean up  instructions 
  • make a screencast do demonstrate how to use this needlessly complicated patch.

sending Tweets with curl in Max,

Using xively.com and zapier.com

Note: To get this project to work you’ll need a Twitter account. And you’ll need to set up a device (feed) at xively.com and a ‘zap’ at zapier.com as directed in this post. It explains how to send tweets using triggers.

 https://reactivemusic.net/?p=6903

Also, you may notice delays due to the number of steps involved.

Looking for an easier way? Send Tweets using ruby: https://reactivemusic.net/?p=7013

download

https://github.com/tkzic/internet-sensors

folder: twitter-curl

files

Max
  • tweetCurl5a.maxpat
externals

[aka.shell] download from here: http://www.iamas.ac.jp/~aka/max/ – and add the path to the folder to Options | File Preferences in Max

authorization

  • xively.com feed id and api-key is embedded in max patch
  • you need a Twitter account
  • you need to set up a xively.com feed with twitter trigger, (as described here  https://reactivemusic.net/?p=6903) to get your own feed id, API-key, and authorize access to your Twitter account

instructions

  • Open the Max patch: tweetcurl5a.maxpat
  • enter your xively feed number and API-key into the fields (then press enter)
  • Type your Tweet text.
  • Press the big green button.

notes on curl

You can use curl for http: requests in Max by formatting the command line with [sprintf] and running it in [aka.shell]. There are a few idiosyncrasies – for example with escape sequences.

In tweetCurl5a.maxpat, the curl command is built in two sections:

  1. The request data is written to a data file /tmp/abc.json
  2.  the actual curl command is formatted and run from the command line. 
Here is the part of the patch which formats request data:

Using ‘quotes’ with [sprintf]

You’ll notice a lot of backslashes used in [sprintf]. This is done to preserve quotes. Normally a quote in [sprintf] indicates a string. Use 3 backslashes to escape a quote:

\\\"

Passing arguments into [sprintf]

The [sprintf] code is obtuse because we are formatting JSON data. The resulting data looks like this:

{ "id":95586, "datastreams":[{ "current_value":"this is a tweet", "id": "tweet"}]}

 

Note that you can pass arguments into [sprintf] using %s – but if you are using a [textedit] to collect data from the user, you’ll need to use [tosymbol] to consolidate the text into a single symbol before passing into [sprintf]

Here’s the code which writes the formatted JSON data to a file:

The next step is to format the curl command, which will read the JSON data file and send an http: request to cosm.com. Here you can see the [sprintf] for this command.

Redirecting aka.shell output to the Max window

At the very end of the [sprintf] you will see

>2&1

This is the linux method to redirect error messages and standard output from [aka.shell] to the same place, which in this case will be the Max window.

command line curl

By the way, here is what the curl command will look like on the command line

curl -v --request PUT --data-binary @/tmp/abc.json --header "X-ApiKey: abcdefg1234567" http://api.cosm.com/v2/feeds/95586.json 2>&1

 

Note: The actual ApiKey above has been replaced with: abcdefg1234567 – so that you don’t accidentally send embarrassing Tweets from my account.