added streaming liq and updated readme, installation fixed for streaming version

master
Rob Canning 2023-11-15 13:43:06 +01:00
parent fef370c2c1
commit a43176bc0d
6 changed files with 224 additions and 168 deletions

View File

@ -1,10 +1,31 @@
curl --insecure --data "username=data-api-user&password=jBD0CD1wGOKoTVtC&grant_type=password&client_id=phenode" https://phenode-link.com:8443/realms/grafana/protocol/openid-connect/token
# Whistling in the Wind
And get a tolken in return:
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJPbjJGUXVKOFktOTA5dUpHV1FFRGtiekctR1JObU1jNDNIc2xFZ1Z2X1ZRIn0.eyJleHAiOjE2OTYzNDk0NzUsImlhdCI6MTY5NjMzMTQ3NSwianRpIjoiODg0ZTg5ZTctOGE2Zi00YWIzLWIwNjMtYjlmZDg5MTEyMDkxIiwiaXNzIjoiaHR0cHM6Ly9waGVub2RlLWxpbmsuY29tOjg0NDMvcmVhbG1zL2dyYWZhbmEiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiZGYzMzBhNjItOGNmYS00ZWY0LWEzYzgtZTE5OTY4NzE2YTViIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicGhlbm9kZSIsInNlc3Npb25fc3RhdGUiOiI2YWE1OTg3ZC1hMjc5LTQ4NzItYmRlNS02YzdmZDc1ODkzNDgiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL3BoZW5vZGUtbGluay5jb206MzAwMiIsImh0dHA6Ly93d3cucGhlbm9kZS1saW5rLmNvbTozMDAyIiwiaHR0cHM6Ly93d3cucGhlbm9kZS1saW5rLmNvbTozMDAyIiwiaHR0cHM6Ly9sb2NhaG9zdDozMDAyIiwiaHR0cHM6Ly93d3cucGhlbm9kZS1saW5rLmNvbSIsImh0dHBzOi8vMy4xMzkuMTkxLjgwLjMwMDIiLCJodHRwOi8vbG9jYWhvc3Q6MzAwMiIsImh0dHA6Ly93d3cucGhlbm9kZS1saW5rLmNvbSIsImh0dHA6Ly8zLjEzOS4xOTEuODAuMzAwMiIsImh0dHBzOi8vbG9jYWxob3N0OjMwMDIiLCJodHRwczovL3BoZW5vZGUtbGluay5jb206MzAwMiIsImh0dHBzOi8vMy4xMzkuMTkxLjgwIiwiaHR0cDovL3BoZW5vZGUtbGluay5jb20iLCJodHRwczovL3BoZW5vZGUtbGluay5jb20iLCJodHRwOi8vMy4xMzkuMTkxLjgwIl0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiI2YWE1OTg3ZC1hMjc5LTQ4NzItYmRlNS02YzdmZDc1ODkzNDgiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInJvbGVzIjpbInZpZXdlciIsIm9mZmxpbmVfYWNjZXNzIiwiZGVmYXVsdC1yb2xlcy1ncmFmYW5hIiwidW1hX2F1dGhvcml6YXRpb24iXSwicHJlZmVycmVkX3VzZXJuYW1lIjoiZGF0YS1hcGktdXNlciIsImdpdmVuX25hbWUiOiIiLCJmYW1pbHlfbmFtZSI6IiJ9.PrEaqR0f5v4KtJlrDegHPGsw8-RLJUB0y3D22BYDZgAVeVBu823vRBuyoOsmG1paE-Q46M_RtBUMEOLd62mjOZEOaVJ9-gQC7f2Guc26ji02U1Glf6AVMtR9K-Se_M8Pq8nhHjDouuSpvLvcyP3YolkT3iGkXEsoRhd7cjFuiK3hiJU2y7iSKhEinKbw6K_engCEtBN-V_r21gDeCt_xIgI_bGkMXKWHQWasj4h5AixwIJtqpHPKmI6OUYah0xR2KhZiqKV0aWFQZAOy8ZP80ksYG5AKDVbJ491UjVAPG8acmFsPV5FumJIPG8hdENEA4vBxgFPk_b_6TzBlLaSWdg","expires_in":18000,"refresh_expires_in":31536000,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJiYjY3ODY2NS1lNjk0LTQzNWEtYjViYi04YzExZTQ3MjdjMWMifQ.eyJleHAiOjE3Mjc4Njc0NzUsImlhdCI6MTY5NjMzMTQ3NSwianRpIjoiMDNjNWI1NTUtNzlhMi00NWQ0LWJiY2ItZmIxODcyMmZiZThlIiwiaXNzIjoiaHR0cHM6Ly9waGVub2RlLWxpbmsuY29tOjg0NDMvcmVhbG1zL2dyYWZhbmEiLCJhdWQiOiJodHRwczovL3BoZW5vZGUtbGluay5jb206ODQ0My9yZWFsbXMvZ3JhZmFuYSIsInN1YiI6ImRmMzMwYTYyLThjZmEtNGVmNC1hM2M4LWUxOTk2ODcxNmE1YiIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJwaGVub2RlIiwic2Vzc2lvbl9zdGF0ZSI6IjZhYTU5ODdkLWEyNzktNDg3Mi1iZGU1LTZjN2ZkNzU4OTM0OCIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjZhYTU5ODdkLWEyNzktNDg3Mi1iZGU1LTZjN2ZkNzU4OTM0OCJ9.17Hxv-n8jiUTbHGjXiEu-E0zBUV6UCz2cDGku-8e05M","token_type":"Bearer","not-before-policy":1662482026,"session_state":"6aa5987d-a279-4872-bde5-6c7fd7589348","scope":"profile email"}
curl --insecure -X POST https://phenode-link.com:2537/devices/D7:80:BE:2C:63:BD/all-data/2023-04-10T16:52:21Z -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJPbjJGUXVKOFktOTA5dUpHV1FFRGtiekctR1JObU1jNDNIc2xFZ1Z2X1ZRIn0.eyJleHAiOjE2OTYzNDk0NzUsImlhdCI6MTY5NjMzMTQ3NSwianRpIjoiODg0ZTg5ZTctOGE2Zi00YWIzLWIwNjMtYjlmZDg5MTEyMDkxIiwiaXNzIjoiaHR0cHM6Ly9waGVub2RlLWxpbmsuY29tOjg0NDMvcmVhbG1zL2dyYWZhbmEiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiZGYzMzBhNjItOGNmYS00ZWY0LWEzYzgtZTE5OTY4NzE2YTViIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicGhlbm9kZSIsInNlc3Npb25fc3RhdGUiOiI2YWE1OTg3ZC1hMjc5LTQ4NzItYmRlNS02YzdmZDc1ODkzNDgiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL3BoZW5vZGUtbGluay5jb206MzAwMiIsImh0dHA6Ly93d3cucGhlbm9kZS1saW5rLmNvbTozMDAyIiwiaHR0cHM6Ly93d3cucGhlbm9kZS1saW5rLmNvbTozMDAyIiwiaHR0cHM6Ly9sb2NhaG9zdDozMDAyIiwiaHR0cHM6Ly93d3cucGhlbm9kZS1saW5rLmNvbSIsImh0dHBzOi8vMy4xMzkuMTkxLjgwLjMwMDIiLCJodHRwOi8vbG9jYWhvc3Q6MzAwMiIsImh0dHA6Ly93d3cucGhlbm9kZS1saW5rLmNvbSIsImh0dHA6Ly8zLjEzOS4xOTEuODAuMzAwMiIsImh0dHBzOi8vbG9jYWxob3N0OjMwMDIiLCJodHRwczovL3BoZW5vZGUtbGluay5jb206MzAwMiIsImh0dHBzOi8vMy4xMzkuMTkxLjgwIiwiaHR0cDovL3BoZW5vZGUtbGluay5jb20iLCJodHRwczovL3BoZW5vZGUtbGluay5jb20iLCJodHRwOi8vMy4xMzkuMTkxLjgwIl0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiI2YWE1OTg3ZC1hMjc5LTQ4NzItYmRlNS02YzdmZDc1ODkzNDgiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInJvbGVzIjpbInZpZXdlciIsIm9mZmxpbmVfYWNjZXNzIiwiZGVmYXVsdC1yb2xlcy1ncmFmYW5hIiwidW1hX2F1dGhvcml6YXRpb24iXSwicHJlZmVycmVkX3VzZXJuYW1lIjoiZGF0YS1hcGktdXNlciIsImdpdmVuX25hbWUiOiIiLCJmYW1pbHlfbmFtZSI6IiJ9.PrEaqR0f5v4KtJlrDegHPGsw8-RLJUB0y3D22BYDZgAVeVBu823vRBuyoOsmG1paE-Q46M_RtBUMEOLd62mjOZEOaVJ9-gQC7f2Guc26ji02U1Glf6AVMtR9K-Se_M8Pq8nhHjDouuSpvLvcyP3YolkT3iGkXEsoRhd7cjFuiK3hiJU2y7iSKhEinKbw6K_engCEtBN-V_r21gDeCt_xIgI_bGkMXKWHQWasj4h5AixwIJtqpHPKmI6OUYah0xR2KhZiqKV0aWFQZAOy8ZP80ksYG5AKDVbJ491UjVAPG8acmFsPV5FumJIPG8hdENEA4vBxgFPk_b_6TzBlLaSWdg" --output D7-80-BE-2C-63-BD.zip
Whistling in the Wind is a hybrid data-sonification / electronic music composition. The piece can be thought of as a 'data-guided' generative music composition. It uses live and histoic data from environmental monitoring stations located around the city of Maribor in Slovenia as its data inputs. This data influence musical change, in real-ttime, within the composition's own generative logic.
The installation can be thought of as similar to wind chimes in that one system (the collection of tuned pipes) is exposed to another (the wind speed and direction), but a little more complex. The first system is the musical composition, described in software, where some parameters are variable and open to external influence while other element are fixed and more deliberatly composed.
The composition can be installed in a physical location such as a gallery or public space as well as existing as a live streaming Internet radio station.
## Live Stream
[http://rizom.si:8000/whistling_in_the_wind.mp3]()
## Credits
*Whistling in the Wind* was commissioned through the EU funded KonS Platform for Contemporary Investigative Arts as a creative response within the city{making}sense project directed by urban planner and architect Andrej Žižek.
[https://kons-platforma.org/dogodki/andrej-zizek-citymakingsense/()]()
## Technologies
The composition uses Supercollider in conjuntion with a set of Python and Bash scripts which gather data from the environmental monitoring stations via an API. The composition is then streamed as an online radio using Liquidsoap and Icecast. Everything runs headless on a Debian 12 server requiring minimal long term maintenance.
### Code
The code lives in a git reposity publicly hosted by kompot.si, a collective of Slovenia's finest autonomous infrastructure and free software advocates.
- https://git.kompot.si/rob/witw
### System Requirments
Debian 12 OS, Jack2, Supercollider 3.13.0, Python3, Bash, Liquidsoap, Icecast2 Streaming Server
----
A ZIP file is created in the folder, named D7-80-BE-2C-63-BD.zip
(3) For the second sensor set the command is adopted using the F1:CC:C3:0B:7F:5C adress and F1-CC-C3-0B-7F-5C.zip name.

View File

@ -1,6 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<instant>
<LastUsedSnapshot name="witw"/>
<Main x="0" y="0" w="1916" h="1036" current-tab="mixer"/>
<Editor id="49" edit-horizontal-pane-pos="0.82035928964614868" notebook-shrunk="0" edit-vertical-pane-pos="0.89999997615814209" mixer-width="Wide" zoom-focus="ZoomFocusPlayhead" zoom="729" grid-type="GridTypeBeat" snap-mode="SnapOff" internal-grid-type="GridTypeBeat" internal-snap-mode="SnapOff" pre-internal-grid-type="GridTypeBeat" pre-internal-snap-mode="SnapOff" edit-point="EditAtMouse" visible-track-count="-1" draw-length="GridTypeNone" draw-velocity="-1" draw-channel="-1" playhead="0" left-frame="0" y-origin="0" maximised="0" follow-playhead="1" stationary-playhead="0" mouse-mode="MouseRange" join-object-range="0" show-editor-mixer="1" show-editor-list="0" editor-list-page="0" show-marker-lines="0" show-touched-automation="0" nudge-clock-value="a1411200000@a0">
<Window name="Editor" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1" tabbed="1"/>
<Buttons>
<Press/>
<Release/>
</Buttons>
<Selection>
<StripableView id="71"/>
</Selection>
<EditorLocations clock-mode="Samples"/>
</Editor>
<Mixer mixer-rhs-pane1-pos="0.69696968793869019" mixer-rhs_pane2-pos="0.69999998807907104" mixer-list-hpane-pos="0.1111111119389534" mixer-inner-pane-pos="0.31874999403953552" narrow-strips="0" show-mixer="0" maximised="0" show-mixer-list="0" monitor-section-visible="1" foldback-strip-visible="0" show-vca-pane="0">
<Window name="Mixer" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1" tabbed="1"/>
</Mixer>
@ -24,25 +36,10 @@
<Clock name="EditorTimeInfo-selection-start" mode="Timecode" on="0"/>
<Clock name="EditorTimeInfo-selection-end" mode="Timecode" on="0"/>
<Clock name="EditorTimeInfo-selection-length" mode="Timecode" on="0"/>
<Clock name="EditorTimeInfo-punch-start" mode="Timecode" on="0"/>
<Clock name="EditorTimeInfo-punch-end" mode="Timecode" on="0"/>
<Clock name="EditorTimeInfo-punch-start" mode="Timecode" on="1"/>
<Clock name="EditorTimeInfo-punch-end" mode="Timecode" on="1"/>
<Clock name="ToolbarTimeInfo-selection-start" mode="Timecode" on="0"/>
<Clock name="ToolbarTimeInfo-selection-end" mode="Timecode" on="0"/>
<Clock name="ToolbarTimeInfo-selection-length" mode="Timecode" on="0"/>
</ClockModes>
<LastUsedSnapshot name="witw"/>
<Editor id="49" edit-horizontal-pane-pos="0.82035928964614868" notebook-shrunk="0" edit-vertical-pane-pos="0.89999997615814209" mixer-width="Wide" zoom-focus="ZoomFocusPlayhead" zoom="729" grid-type="GridTypeBeat" snap-mode="SnapOff" internal-grid-type="GridTypeBeat" internal-snap-mode="SnapOff" pre-internal-grid-type="GridTypeBeat" pre-internal-snap-mode="SnapOff" edit-point="EditAtMouse" visible-track-count="-1" draw-length="GridTypeNone" draw-velocity="-1" draw-channel="-1" playhead="0" left-frame="0" y-origin="0" maximised="0" follow-playhead="1" stationary-playhead="0" mouse-mode="MouseRange" join-object-range="0" show-editor-mixer="1" show-editor-list="0" editor-list-page="0" show-marker-lines="0" show-touched-automation="0" nudge-clock-value="a1411200000@a0">
<Window name="Editor" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1" tabbed="1"/>
<Buttons>
<Press/>
<Release/>
</Buttons>
<Selection>
<StripableView id="240"/>
<StripableView id="308"/>
<StripableView id="376"/>
<StripableView id="172"/>
</Selection>
<EditorLocations clock-mode="Samples"/>
</Editor>
</instant>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Session version="7002" name="witw" sample-rate="48000" session-range-is-free="1" id-counter="629" name-counter="1" event-counter="0" vca-counter="1">
<Session version="7002" name="witw" sample-rate="48000" session-range-is-free="1" id-counter="1319" name-counter="1" event-counter="0" vca-counter="1">
<ProgramVersion created-with="Ardour 7.3.0~ds0-1" modified-with="Ardour 7.3.0~ds0-1"/>
<MIDIPorts>
<Port name="Cue Control in" direction="input"/>
@ -73,10 +73,7 @@
<TriggerBindings/>
<Regions/>
<Selection>
<StripableAutomationControl stripable="172" control="0" order="3"/>
<StripableAutomationControl stripable="240" control="0" order="0"/>
<StripableAutomationControl stripable="308" control="0" order="1"/>
<StripableAutomationControl stripable="376" control="0" order="2"/>
<StripableAutomationControl stripable="71" control="0" order="4"/>
</Selection>
<Locations>
<Location id="626" name="Punch" start="a0" end="a0" flags="IsAutoPunch" locked="0" timestamp="1697622442" cue="0"/>
@ -105,10 +102,12 @@
</IO>
<IO name="Master" id="100" direction="Output" default-type="audio">
<Port type="audio" name="Master/audio_out 1">
<Connection other="input.jack_0:in_0"/>
<Connection other="system:playback_1"/>
<Connection other="system:playback_7"/>
</Port>
<Port type="audio" name="Master/audio_out 2">
<Connection other="input.jack_0:in_1"/>
<Connection other="system:playback_2"/>
<Connection other="system:playback_8"/>
</Port>
@ -149,7 +148,7 @@
<Automation>
<AutomationList automation-id="gain" id="74" interpolation-style="Exponential" time-domain="AudioTime" state="Off"/>
</Automation>
<Controllable name="gaincontrol" id="75" flags="GainLike" value="0"/>
<Controllable name="gaincontrol" id="75" flags="GainLike" value="0.99854636192321777"/>
</Processor>
<Processor id="468" name="LSP Impulse Reverb Stereo" active="1" user-latency="0" use-user-latency="0" type="lv2" unique-id="http://lsp-plug.in/plugins/lv2/impulse_reverb_stereo" count="1" custom="0">
<Automation>
@ -248,8 +247,8 @@
<Channelmap type="audio" from="1" to="1"/>
</OutputMap-0>
<ThruMap/>
<lv2 last-preset-uri="" last-preset-label="" parameter-changed-since-last-preset="1" state-dir="state2">
<Port symbol="enabled" value="0"/>
<lv2 last-preset-uri="" last-preset-label="" parameter-changed-since-last-preset="1" state-dir="state3">
<Port symbol="enabled" value="1"/>
<Port symbol="fsel" value="0"/>
<Port symbol="fft" value="6"/>
<Port symbol="pd" value="0.19999998807907104"/>
@ -325,7 +324,7 @@
<Port symbol="hcm" value="0"/>
<Port symbol="hcf" value="10000"/>
</lv2>
<Controllable name="Enabled" id="470" flags="Toggle" value="0" parameter="4" symbol="enabled"/>
<Controllable name="Enabled" id="470" flags="Toggle" value="1" parameter="4" symbol="enabled"/>
<Controllable name="File selector" id="472" flags="" value="0" parameter="5" symbol="fsel"/>
<Controllable name="FFT size" id="474" flags="" value="6" parameter="6" symbol="fft"/>
<Controllable name="Pre-delay" id="476" flags="" value="0.19999998807907104" parameter="7" symbol="pd"/>
@ -400,10 +399,10 @@
<Controllable name="Band 10 kHz gain" id="614" flags="" value="1" parameter="88" symbol="eq_7"/>
<Controllable name="High-cut mode" id="616" flags="" value="0" parameter="89" symbol="hcm"/>
<Controllable name="High-cut frequency" id="618" flags="" value="10000" parameter="90" symbol="hcf"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn2" id="619" flags="NotAutomatable" property="222"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn1" id="620" flags="NotAutomatable" property="223"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn3" id="621" flags="NotAutomatable" property="224"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn0" id="622" flags="NotAutomatable" property="225"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn0" id="832" flags="NotAutomatable" property="222"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn1" id="833" flags="NotAutomatable" property="223"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn2" id="834" flags="NotAutomatable" property="224"/>
<Controllable name="property-http://lsp-plug.in//ports#ifn3" id="835" flags="NotAutomatable" property="225"/>
</Processor>
<Processor id="105" name="Master" active="1" user-latency="0" use-user-latency="0" own-input="1" own-output="0" output="Master" type="main-outs" role="Main">
<PannerShell bypassed="0" user-panner="" linked-to-route="1"/>
@ -417,9 +416,7 @@
<Controllable name="solo-iso" id="203" flags="Toggle,RealTime" value="0" solo-isolated="0"/>
<Controllable name="solo-safe" id="205" flags="Toggle" value="0" solo-safe="0"/>
<IO name="SC 1" id="217" direction="Input" default-type="audio">
<Port type="audio" name="SC 1/audio_in 1">
<Connection other="SuperCollider:out_1"/>
</Port>
<Port type="audio" name="SC 1/audio_in 1"/>
</IO>
<IO name="SC 1" id="218" direction="Output" default-type="audio">
<Port type="audio" name="SC 1/audio_out 1">
@ -508,9 +505,7 @@
<Controllable name="solo-iso" id="271" flags="Toggle,RealTime" value="0" solo-isolated="0"/>
<Controllable name="solo-safe" id="273" flags="Toggle" value="0" solo-safe="0"/>
<IO name="SC 2" id="285" direction="Input" default-type="audio">
<Port type="audio" name="SC 2/audio_in 1">
<Connection other="SuperCollider:out_2"/>
</Port>
<Port type="audio" name="SC 2/audio_in 1"/>
</IO>
<IO name="SC 2" id="286" direction="Output" default-type="audio">
<Port type="audio" name="SC 2/audio_out 1">
@ -599,9 +594,7 @@
<Controllable name="solo-iso" id="339" flags="Toggle,RealTime" value="0" solo-isolated="0"/>
<Controllable name="solo-safe" id="341" flags="Toggle" value="0" solo-safe="0"/>
<IO name="SC 3" id="353" direction="Input" default-type="audio">
<Port type="audio" name="SC 3/audio_in 1">
<Connection other="SuperCollider:out_3"/>
</Port>
<Port type="audio" name="SC 3/audio_in 1"/>
</IO>
<IO name="SC 3" id="354" direction="Output" default-type="audio">
<Port type="audio" name="SC 3/audio_out 1">
@ -690,9 +683,7 @@
<Controllable name="solo-iso" id="407" flags="Toggle,RealTime" value="0" solo-isolated="0"/>
<Controllable name="solo-safe" id="409" flags="Toggle" value="0" solo-safe="0"/>
<IO name="SC 4" id="421" direction="Input" default-type="audio">
<Port type="audio" name="SC 4/audio_in 1">
<Connection other="SuperCollider:out_4"/>
</Port>
<Port type="audio" name="SC 4/audio_in 1"/>
</IO>
<IO name="SC 4" id="422" direction="Output" default-type="audio">
<Port type="audio" name="SC 4/audio_out 1">

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Session version="7002" name="witw" sample-rate="48000" session-range-is-free="1" id-counter="628" name-counter="1" event-counter="0" vca-counter="1">
<Session version="7002" name="witw" sample-rate="48000" session-range-is-free="1" id-counter="629" name-counter="1" event-counter="0" vca-counter="1">
<ProgramVersion created-with="Ardour 7.3.0~ds0-1" modified-with="Ardour 7.3.0~ds0-1"/>
<MIDIPorts>
<Port name="Cue Control in" direction="input"/>
@ -784,7 +784,7 @@
</Playlists>
<UnusedPlaylists/>
<RouteGroups>
<RouteGroup id="169" rgba="2716103167" used-to-share-gain="0" name="SC" hidden="0" active="1" relative="1" gain="1" mute="1" solo="1" recenable="1" select="1" route-active="1" color="1" monitoring="1" group-master-number="-1" routes="172 240 308 376 "/>
<RouteGroup id="169" rgba="2699260159" used-to-share-gain="0" name="SC" hidden="0" active="1" relative="1" gain="1" mute="0" solo="0" recenable="1" select="1" route-active="1" color="1" monitoring="1" group-master-number="-1" routes="172 240 308 376 "/>
</RouteGroups>
<Click>
<IO name="Click" id="66" direction="Output" default-type="audio">
@ -868,7 +868,7 @@
<Window name="P-240-243" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1" custom-ui="1"/>
<Window name="P-308-311" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1" custom-ui="1"/>
<Window name="P-376-379" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1" custom-ui="1"/>
<Window name="P-71-468" visible="0" x-off="383" y-off="0" x-size="832" y-size="634" custom-ui="1"/>
<Window name="P-71-468" visible="0" x-off="23" y-off="169" x-size="832" y-size="634" custom-ui="1"/>
<Window name="PM-71-468" visible="0" x-off="-1" y-off="-1" x-size="-1" y-size="-1"/>
<GUIObjectState>
<Object id="rtav 71" height="66"/>

View File

@ -2,18 +2,27 @@
// initial settings .....................................
s.options.numInputBusChannels = 4;
s.options.numOutputBusChannels = 4;
s.options.numInputBusChannels = 2; // 4 for installation 2 for webstream
s.options.numOutputBusChannels = 2;
~dataPath = "/home/rizoma/witw/data/"; // CHANGE THIS TO RELATIVE PATH
// create 8 control busses to pass data between synths
~ctrlBus = 8.collect({arg i; Bus.control(s,1); });
//~dataPath = "/home/rob/witw/data/"; // laptop
~dataPath = "/home/rizoma/witw/data/"; // installation computer
~devices = ["D7:80:BE:2C:63:BD", "F1:CC:C3:0B:7F:5C"];
// load and process the data source /////////////////////////////////
~csvFile=CSVFileReader.read(~dataPath ++ ~devices[0] ++ "/" ++ "sensor_data.csv",true,true);
// flatten ~data from 2D Array to regular array (per column);
~data = ( ~csvFile[0].size ).collect({ arg itt;
Array.fill( ~csvFile.size-1,{ arg i;
~csvFile.at(i+1).asArray.at(itt)}); // +1 to skip the column name
});
s.waitForBoot{
// create 8 control busses to pass data between synths
~ctrlBus = 8.collect({arg i; Bus.control(s,1); });
// initial settings .....................................
// define synths
SynthDef(\sgrain, { | out=0, atk=0.01, dcy=0.01, freq=100, pan=0, amp=1|
var sig, env;
@ -36,48 +45,20 @@ s.waitForBoot{
}).add;
SynthDef.new(\sine, {
arg freq=440, modfreq=6, pmindex=3, modphase=0, panfreq=1.3, panphase=0.5, rel=0.5, gate=0, amp=0.0001;
arg freq=440, modfreq=6, pmindex=3, modphase=0,
panfreq=1.3, panphase=0.5, rel=0.5, gate=0, amp=0.0001;
var sig, env;
sig = PMOsc.ar(freq, modfreq, pmindex, modphase);
//env = Env.perc(0.04,rel);
env = Env.new([ 0, 1, 0.3, 0], [ 0.01, rel ,1], [1,-1]);
sig = sig * EnvGen.kr(env, doneAction:2);
//sig = Pan2.ar(sig, FSinOsc.kr(panfreq, panphase));
sig = PanAz.ar(4, sig, LFSaw.kr(panfreq, modphase), width: 1, orientation: 0);
sig = Pan2.ar(sig, FSinOsc.kr(panfreq, modphase));
//sig = PanAz.ar(4, sig, LFSaw.kr(panfreq, modphase), width: 1, orientation: 0);
sig = sig * amp;
Out.ar(0, sig);
}).add;
// initial settings .....................................
// load and process the data source /////////////////////////////////
~csvFile=CSVFileReader.read(~dataPath ++ ~devices[0] ++ "/" ++ "sensor_data.csv",true,true);
// flatten ~data from 2D Array to regular array (per column);
~data = ( ~csvFile[0].size ).collect({ arg itt;
Array.fill( ~csvFile.size-1,{ arg i;
~csvFile.at(i+1).asArray.at(itt)}); // +1 to skip the column name
});
~data[2]; // Temperature C
~data[3]; // F
~data[10]; // wind speed MPH
~data[11]; // wind direction
~data[13]; // wind gusts MPH
~data[5]; // rain bucket capacity
~data[6]; // rain bucket tips per minute?
~data[20]; // LON
~data[21]; // LAT
// normalize data ranges //////
~date=~data[0];
~freq=~data[2].asFloat.normalize(0, 400);
~atk=~data[4].asFloat.normalize(0.02, 0.04);
~dcy=~data[2].asFloat.normalize(0.05, 0.1);
~dur=~data[2].asFloat.normalize(0.1, 0.1);
~level=~data[2].asFloat.normalize(0, 0);
//start the slewing synth /////////////////////////////
@ -117,7 +98,7 @@ s.waitForBoot{
~sca = PatternProxy.new; // scale
~rel = PatternProxy.new; // release
~dur.source = Pseq(Array.geom(30, rrand(1,1.5), rrand(0.98,0.99)).mirror,inf);
~dur.source = Pseq(Array.geom(30, rrand(2,2.5), rrand(0.98,0.99)).mirror,inf);
~deg.source = Prand([0,5,7],inf); // carrier frequency
~mfr.source = Pexprand(0.1,3, inf); // modulation frequency
~pmi.source = Pexprand(0.5,3, inf); // phase modulation index
@ -126,13 +107,13 @@ s.waitForBoot{
~oct.source = Prand([2,3,4],inf);
~voc.source = 4;
~amp.source = Pwhite(0.001, 0.1,inf);
~amp.source = Pwhite(0.001, 0.02,inf);
~sca.source = Scale.harmonicMinor;
~rel.source = Pexprand(1.5,3.35, inf);
// initial settings .....................................
Pdef(\c, Pspawner({ | sp | 4.do { | i | sp.par(
Pdef(\c, Pspawner({ | sp | 3.do { | i | sp.par( // 4 do for installation version
Pbind( *[
\instrument, \sine,
\dur, ~dur,
@ -151,106 +132,128 @@ s.waitForBoot{
]);
); sp.wait(10); }}); ).play;
}; // closes s.waitForBoot .....................................
( /////////////////////////////////////////////////////////
// temporal structure of wind controled layer ///////////
// .....................................
s.sync;
~temperature=~data[2];//.asFloat; //.normalize(0, 11);
~dateTime=~data[0];
( // normalize data ranges or not ///////////////////////////
~windDirection=~data[13];
~windGust=~data[14]; // m/s
~temperature=~data[2];//.asFloat; //.normalize(0, 11);
~dateTime=~data[0];
~windDirection=~data[13];
~windGust=~data[14]; // m/s
~windNorth=~data[16]; // m/s
~windEast=~data[18]; // m/s
~windNorth=~data[16]; // m/s
~windEast=~data[18]; // m/s
// data player ////////////////////////////////////////////
~global_t = 0; // temperature C
~global_wD = 0; // wind direction 360degrees
~time = Routine {
arg inval; var t = 0;
// itterate through data at a fixed rate // data point every 15mins
// 4sec = 1 hr 24 * 96seconds = 1 day // 9.6 seconds = 1 day @ 0.1.wait
loop {
t = (t + 1) % (~csvFile.size - 1);
postln( t +
" " + ~dateTime[t] +
"C:" ++ ~temperature[t] +
"Wind Dir: " + ~windDirection[t] +
"Gust:" ++ ~windGust[t] +
"North: " + ~windNorth[t] +
"East: " + ~windEast[t]);
0.1.wait;
}}.play();
~time.stop;
// temporal structure of wind controled layer ///////////
// ......................................................
// conditional logic goes here //////////////////////////
~time = Routine {
arg inval; var t = 0;
// itterate through data at a fixed rate // data point every 15mins
// 4sec = 1 hr 24 * 96seconds = 1 day // 9.6 seconds = 1 day @ 0.1.wait
loop {
t = (t + 1) % (~csvFile.size - 1) ;
~global_t = ~temperature[t];
~global_wD = ~windDirection[t];
postln( t + " " + ~dateTime[t] + " C:" ++ ~temperature[t] + " Wind Dir: " + ~windDirection[t] + " Gust: " ++ ~windGust[t] + "North: " + ~windNorth[t] + "East: " + ~windEast[t]);
0.1.wait;
}}.play();
r = Routine { arg inval; var i = 0;
r = Routine { arg inval; var i = 0;
loop {
i = i + 1; // this loop itterator is not used?
postln(t); // only t the ~time counter
loop {
postf("beats: % seconds: % time: % \n",
thisThread.beats, thisThread.seconds, Main.elapsedTime );
postln(t);
~sca.source = Scale.harmonicMinor;
~deg.source = Prand([0,1,2,3,5,7],inf);
~oct.source = Prand([4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(2,4), rrand(0.96,0.97)).mirror,inf);
~rel.source = Pexprand(2.1,5.5, inf);
~amp.source = Pwhite(0.05, 0.2,inf);
i = i + 1;
50.wait;
postln("line 2");
~deg.source = Prand([0,3,5,7],inf);
~oct.source = Prand([3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(1,2.5), rrand(0.96,0.97)).mirror,inf);
postln(~temperature[i]); postf("beats: % seconds: % time: % \n",
thisThread.beats, thisThread.seconds, Main.elapsedTime );
50.wait;
~sca.source = Scale.harmonicMinor;
~deg.source = Prand([0,1,2,3,5,7],inf);
~oct.source = Prand([4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(2,4), rrand(0.96,0.97)).mirror,inf);
~rel.source = Pexprand(2.1,5.5, inf);
~amp.source = Pwhite(0.001, 0.05,inf);
postln("line 3");
~deg.source = Prand([0,3,5],inf);
~oct.source = Prand([3,4,5],inf);
~rel.source = Pexprand(1,3, inf);
~dur.source = Pseq(Array.geom(30, rrand(1,1.5), rrand(0.96,0.97)).mirror,inf);
30.wait;
postln("line 2");
~deg.source = Prand([0,3,5,7],inf);
~oct.source = Prand([3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(1,2.5), rrand(0.96,0.97)).mirror,inf);
50.wait;
30.wait;
postln("line 4");
~sca.source = Scale.chromatic;
~deg.source = Prand([0,2,4,6,8,10],inf);
~oct.source = Prand([3,4,5],inf);
postln("line 3");
~deg.source = Prand([0,3,5],inf);
~oct.source = Prand([3,4,5],inf);
~rel.source = Pexprand(1,3, inf);
~dur.source = Pseq(Array.geom(30, rrand(1,1.5), rrand(0.96,0.97)).mirror,inf);
50.wait;
30.wait;
postln("line 5");
~deg.source = Prand([0,2,4,6,8,10],inf);
~oct.source = Prand([3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(0.5,0.6), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(0.5,3, inf);
postln("line 4");
~sca.source = Scale.chromatic;
~deg.source = Prand([0,2,4,6,8,10],inf);
~oct.source = Prand([3,4,5],inf);
50.wait;
20.wait;
postln("line 6");
~deg.source = Prand([0,7,5],inf);
~oct.source = Prand([2,3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(1.5,3.6), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(2,4, inf);
postln("line 5");
~deg.source = Prand([0,2,4,6,8,10],inf);
~oct.source = Prand([3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(0.5,0.6), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(0.5,3, inf);
50.wait;
30.wait;
~sca.source = Scale.harmonicMinor;
postln("line 6");
~deg.source = Prand([0,7,5],inf);
~oct.source = Prand([2,3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(1.5,3.6), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(2,4, inf);
postln("line 7");
~deg.source = Prand([0,7,5],inf);
~oct.source = Prand([2,3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(1,1.5), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(2,6, inf);
30.wait;
50.wait;
postln("line 7");
~deg.source = Prand([0,7,5],inf);
~oct.source = Prand([2,3,4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(1,1.5), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(2,6, inf);
30.wait;
};
}.play;
postln("line 8");
~deg.source = Prand([0,5,7,9],inf);
~oct.source = Prand([4,5,6],inf);
~dur.source = Pseq(Array.geom(30, rrand(2,3.5), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(6,12, inf);
50.wait;
postln("line 9");
~deg.source = Prand([1,6,8,10],inf);
~oct.source = Prand([3, 4,5],inf);
~dur.source = Pseq(Array.geom(30, rrand(3,4.5), rrand(0.98,0.99)).mirror,inf);
~rel.source = Pexprand(4,12, inf);
50.wait;
};
}.play;
);
r.stop;
}; // closes s.waitForBoot .....................................
~time.pause;
r.stop;
~time.stop;

44
witw.liq 100644
View File

@ -0,0 +1,44 @@
#!/usr/bin/liquidsoap
# Log dir
log.file.path.set("/tmp/basic-radio.log")
# Music
#myplaylist = playlist("~/radio/music.m3u")
# Some jingles
#jingles = playlist("~/radio/jingles.m3u")
# If something goes wrong, we'll play this
#security = single("~/radio/sounds/default.ogg")
# Start building the feed with music
#radio = myplaylist
# Now add some jingles
#radio = random(weights = [1, 4],[jingles, radio])
# And finally the security
#radio = fallback(track_sensitive = false, [radio, security])
radio = input.jack();
# Stream it out
output.icecast(%vorbis,
host = "rizom.si", port = 8000,
password = "hackmeheklab", mount = "whistling_in_the_wind.ogg",
genre= "Ambient",
url= "https://kons-platforma.org/" ,
description = "Sound Installation / Data Sonification",
id="WITW",
name="Whistling in the Wind",
radio)
output.icecast(%mp3(bitrate=256),
host = "rizom.si", port = 8000,
password = "hackmeheklab", mount = "whistling_in_the_wind.mp3",
genre= "Ambient",
url= "https://kons-platforma.org/" ,
description = "Sound Installation / Data Sonification",
id="WITW",
name="Whistling in the Wind",
radio)