Skip to content

Instantly share code, notes, and snippets.

@rbnpi
Last active December 23, 2018 05:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbnpi/4912ea498759ac800ccda7af9b083c73 to your computer and use it in GitHub Desktop.
Save rbnpi/4912ea498759ac800ccda7af9b083c73 to your computer and use it in GitHub Desktop.
Recorder Player for Sonic Pi Read the accompanying article at https://rbnrpi.wordpress.com/project-list/sonic-pi-3-player-recorder-using-touchosc/ for details of setup. Also there is a video at https://youtu.be/2yoJ2ygs0xM

Sonic Pi Record / Player

The three other files enable a TouchOSC interface to be used with Sonic Pi 3 and above to allow notes to be played on Sonic Pi, and also recorded in real time for subsequent replay. Recordings can also be stored in files on your computer. NB spRecordPlayer.rb changed to release 1.0.1 line 144 updated "piano,"pluck" changed to :piano,:pluck

The two Sonic Pi programs should be loaded into separate buffers, where they are both run. At any time you can re-run either file. If you ever press the stop button you must re-run both.

The TouchOSC template is the file index.xml This should be downloaded and then compressed or zipped with the resulting file renamed as spRecordPlayer.touchosc This file should then be loaded into your TouchOSC editor and from there synced to your iPad/iPhone/Android device which is running TouchOSC

You should adjust the IP addresse in the two Sonic Pi programs to point to our TouchOSC device, and also adjust the OSC settings of that device to point back to your computer running Sonic Pi. The Host address should be set equal to the IP address of your Sonic Pi computer, and the outgoing port set to 4559 with the incoming port set to 9000. The Sonic Pi programs should point to the host address of your TouchOSC device.

Full details about the program and how to use it are in an article at https://rbnrpi.wordpress.com/project-list/sonic-pi-3-player-recorder-using-touchosc/

<?xml version="1.0" encoding="UTF-8"?><layout version="16" mode="0" orientation="horizontal"><tabpage name="c3BycA==" scalef="0.0" scalet="1.0" li_t="" li_c="gray" li_s="14" li_o="false" li_b="false" la_t="" la_c="gray" la_s="14" la_o="false" la_b="false" ><control name="bGFiZWw1NA==" x="107" y="26" w="78" h="20" color="yellow" type="labelh" text="YnkgUm9iaW4gTmV3bWFu" size="8" background="true" outline="false" ></control><control name="bGFiZWwzMQ==" x="288" y="92" w="25" h="25" color="red" type="labelh" text="TQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWwyNg==" x="288" y="209" w="25" h="25" color="pink" type="labelh" text="Rg==" size="14" background="true" outline="false" ></control><control name="bGFiZWwyNQ==" x="283" y="295" w="35" h="25" color="yellow" type="labelh" text="bWV0" size="14" background="true" outline="false" ></control><control name="bGFiZWwyNA==" x="288" y="254" w="25" h="25" color="pink" type="labelh" text="Uw==" size="14" background="true" outline="false" ></control><control name="bXQy" x="288" y="230" w="25" h="25" color="pink" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="bXQx" x="288" y="276" w="25" h="25" color="pink" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="bGFiZWwzMA==" x="229" y="409" w="49" h="20" color="yellow" type="labelh" text="b24=" size="14" background="true" outline="false" ></control><control name="bGFiZWwx" x="47" y="5" w="20" h="25" color="yellow" type="labelh" text="Uw==" size="14" background="true" outline="false" ></control><control name="bXVsdGlwdXNoMQ==" x="7" y="45" w="280" h="280" color="red" scalef="0.0" scalet="1.0" type="multipush" number_x="8" number_y="8" local_off="false" ></control><control name="bGFiZWwy" x="68" y="400" w="44" h="24" color="green" type="labelh" text="cGlhbm8=" size="14" background="true" outline="false" ></control><control name="cmVjb3Jk" x="270" y="7" w="35" h="35" color="red" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="cGxheWJhY2s=" x="8" y="6" w="35" h="35" color="blue" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="bGFiZWwz" x="229" y="396" w="49" h="20" color="yellow" type="labelh" text="bGVkIHBi" size="14" background="true" outline="false" ></control><control name="a2V5" x="63" y="332" w="248" h="50" color="red" scalef="0.0" scalet="1.0" type="multitoggle" number_x="7" number_y="1" ex_mode="true" local_off="false" ></control><control name="bWFqbWlu" x="7" y="332" w="50" h="50" color="purple" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="bWFqbWluTGFiZWw=" x="12" y="346" w="39" h="20" color="red" type="labelh" text="bWFqb3I=" size="14" background="true" outline="false" ></control><control name="bGFiZWw1" x="72" y="347" w="20" h="20" color="yellow" type="labelh" text="Qw==" size="14" background="true" outline="false" ></control><control name="bGFiZWw2" x="107" y="347" w="20" h="20" color="yellow" type="labelh" text="RA==" size="14" background="true" outline="false" ></control><control name="bGFiZWw3" x="142" y="347" w="20" h="20" color="yellow" type="labelh" text="RQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWw4" x="177" y="347" w="20" h="20" color="yellow" type="labelh" text="Rg==" size="14" background="true" outline="false" ></control><control name="bGFiZWw5" x="212" y="347" w="20" h="20" color="yellow" type="labelh" text="Rw==" size="14" background="true" outline="false" ></control><control name="bGFiZWwxMA==" x="247" y="347" w="20" h="20" color="yellow" type="labelh" text="QQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWwxMQ==" x="282" y="347" w="20" h="20" color="yellow" type="labelh" text="Qg==" size="14" background="true" outline="false" ></control><control name="bGFiZWwxMw==" x="15" y="13" w="20" h="20" color="yellow" type="labelh" text="UA==" size="14" background="true" outline="false" ></control><control name="bGFiZWwxNA==" x="277" y="14" w="20" h="20" color="yellow" type="labelh" text="Ug==" size="14" background="true" outline="false" ></control><control name="bTE=" x="17" y="297" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTk=" x="17" y="56" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTg=" x="121" y="90" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTc=" x="224" y="124" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTY=" x="86" y="159" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTU=" x="189" y="193" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTQ=" x="52" y="228" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTM=" x="155" y="262" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTI=" x="259" y="297" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bTEw" x="258" y="55" w="18" h="18" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="bGFiZWwxNQ==" x="62" y="5" w="35" h="25" color="green" type="labelh" text="b25pYw==" size="14" background="true" outline="false" ></control><control name="bGFiZWwxNw==" x="115" y="5" w="20" h="25" color="green" type="labelh" text="aQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWwxNg==" x="103" y="5" w="20" h="25" color="yellow" type="labelh" text="UA==" size="14" background="true" outline="false" ></control><control name="bGFiZWwyMA==" x="145" y="5" w="115" h="25" color="yellow" type="labelh" text="UmVjb3JkIC8gUGxheWVy" size="14" background="true" outline="false" ></control><control name="bGFiZWwyMQ==" x="0" y="406" w="35" h="24" color="pink" type="labelh" text="b24=" size="14" background="true" outline="false" ></control><control name="bGFiZWwyMg==" x="182" y="400" w="44" h="24" color="green" type="labelh" text="cGx1Y2s=" size="14" background="true" outline="false" ></control><control name="c3ludGg=" x="109" y="387" w="75" h="50" color="green" scalef="0.0" scalet="1.0" type="multitoggle" number_x="2" number_y="1" ex_mode="true" local_off="false" ></control><control name="bGFiZWwyMw==" x="288" y="173" w="25" h="25" color="yellow" type="labelh" text="cGI=" size="14" background="true" outline="false" ></control><control name="bGFiZWwyNw==" x="288" y="133" w="25" h="25" color="red" type="labelh" text="Uw==" size="14" background="true" outline="false" ></control><control name="bGFiZWwyOA==" x="288" y="49" w="25" h="25" color="red" type="labelh" text="Rg==" size="14" background="true" outline="false" ></control><control name="bGFiZWwyOQ==" x="0" y="391" w="35" h="24" color="pink" type="labelh" text="bWV0" size="14" background="true" outline="false" ></control><control name="bGVkcGxheWJhY2s=" x="276" y="394" w="35" h="35" color="yellow" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="bWV0cm9ub21l" x="33" y="394" w="35" h="35" color="pink" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="cGIz" x="288" y="70" w="25" h="25" color="red" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="cGIy" x="288" y="113" w="25" h="25" color="red" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control><control name="cGIx" x="288" y="153" w="25" h="25" color="red" scalef="0.0" scalet="1.0" type="toggle" local_off="false" ></control></tabpage><tabpage name="YXJjaGl2ZQ==" scalef="0.0" scalet="1.0" li_t="" li_c="gray" li_s="14" li_o="false" li_b="false" la_t="" la_c="gray" la_s="14" la_o="false" la_b="false" ><control name="bGFiZWw1Mg==" x="111" y="164" w="61" h="25" color="green" type="labelh" text="Q29udGVudA==" size="12" background="true" outline="false" ></control><control name="c2xvdA==" x="73" y="187" w="50" h="250" color="yellow" scalef="0.0" scalet="1.0" type="multitoggle" number_x="1" number_y="10" ex_mode="true" local_off="false" ></control><control name="c2xvdGJhbms=" x="216" y="131" w="87" h="50" color="yellow" scalef="0.0" scalet="1.0" type="multitoggle" number_x="2" number_y="1" ex_mode="true" local_off="false" ></control><control name="cmVhZA==" x="179" y="190" w="45" h="45" color="green" scalef="0.0" scalet="1.0" type="push" local_off="false" sp="true" sr="true" ></control><control name="d3JpdGU=" x="183" y="289" w="45" h="45" color="red" scalef="0.0" scalet="1.0" type="push" local_off="false" sp="true" sr="true" ></control><control name="ZW5hYmxlc2F2ZQ==" x="255" y="238" w="45" h="45" color="red" scalef="0.0" scalet="1.0" type="push" local_off="false" sp="true" sr="true" ></control><control name="bGFiZWwzMw==" x="8" y="30" w="80" h="25" color="green" type="labelh" text="U2F2ZSBGb2xkZXI=" size="14" background="true" outline="false" ></control><control name="cGF0aA==" x="-1" y="54" w="321" h="25" color="green" type="labelh" text="U2V0IHRoaXMgaW4gc2F2ZS5yYiBwcm9ncmFt" size="12" background="true" outline="false" ></control><control name="YmFuaw==" x="217" y="99" w="80" h="25" color="yellow" type="labelh" text="U2xvdCBCYW5r" size="14" background="true" outline="false" ></control><control name="bGFiZWwzNg==" x="49" y="143" w="80" h="20" color="yellow" type="labelh" text="U2xvdCBTZWxlY3Q=" size="14" background="true" outline="false" ></control><control name="bGFiZWwzNw==" x="234" y="199" w="73" h="25" color="green" type="labelh" text="TG9hZCBGaWxl" size="14" background="true" outline="false" ></control><control name="bGFiZWwzOA==" x="164" y="248" w="87" h="25" color="red" type="labelh" text="RW5hYmxlIFNhdmU=" size="14" background="true" outline="false" ></control><control name="bGFiZWwzOQ==" x="232" y="299" w="80" h="25" color="red" type="labelh" text="U2F2ZSBGaWxl" size="14" background="true" outline="false" ></control><control name="bGFiZWw0MA==" x="39" y="191" w="25" h="25" color="yellow" type="labelh" text="MQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0MQ==" x="39" y="409" w="25" h="25" color="yellow" type="labelh" text="MTA=" size="14" background="true" outline="false" ></control><control name="bGFiZWw0Mg==" x="39" y="384" w="25" h="25" color="yellow" type="labelh" text="OQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0Mw==" x="39" y="360" w="25" h="25" color="yellow" type="labelh" text="OA==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0NA==" x="39" y="336" w="25" h="25" color="yellow" type="labelh" text="Nw==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0NQ==" x="39" y="312" w="25" h="25" color="yellow" type="labelh" text="Ng==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0Ng==" x="39" y="287" w="25" h="25" color="yellow" type="labelh" text="NQ==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0Nw==" x="39" y="263" w="25" h="25" color="yellow" type="labelh" text="NA==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0OA==" x="39" y="239" w="25" h="25" color="yellow" type="labelh" text="Mw==" size="14" background="true" outline="false" ></control><control name="bGFiZWw0OQ==" x="39" y="215" w="25" h="25" color="yellow" type="labelh" text="Mg==" size="14" background="true" outline="false" ></control><control name="bGFiZWw1MA==" x="40" y="3" w="190" h="25" color="blue" type="labelh" text="UmVjb3JkIC8gUGxheWVyIHNhdmUgc2NyZWVu" size="14" background="true" outline="false" ></control><control name="bGVkU2F2ZQ==" x="302" y="249" w="15" h="15" color="red" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDI=" x="127" y="218" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE=" x="127" y="194" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDEw" x="127" y="412" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDk=" x="127" y="387" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDg=" x="127" y="363" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDc=" x="127" y="339" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDY=" x="127" y="315" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDU=" x="127" y="290" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDQ=" x="127" y="266" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDM=" x="127" y="242" w="15" h="15" color="blue" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDEy" x="142" y="218" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDEx" x="142" y="194" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDIw" x="142" y="412" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE5" x="142" y="388" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE4" x="142" y="364" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE3" x="142" y="339" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE2" x="142" y="315" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE1" x="142" y="291" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDE0" x="142" y="267" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="ZDEz" x="142" y="243" w="15" h="15" color="purple" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTI=" x="5" y="220" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE=" x="5" y="196" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTEw" x="5" y="414" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTk=" x="5" y="390" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTg=" x="5" y="366" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTc=" x="5" y="341" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTY=" x="5" y="317" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTU=" x="5" y="293" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTQ=" x="5" y="269" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTM=" x="5" y="245" w="15" h="15" color="orange" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTEy" x="22" y="220" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTEx" x="22" y="196" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTIw" x="22" y="414" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE5" x="22" y="390" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE4" x="22" y="366" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE3" x="22" y="341" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE2" x="22" y="317" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE1" x="22" y="293" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTE0" x="22" y="269" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="YTEz" x="22" y="245" w="15" h="15" color="brown" scalef="0.0" scalet="1.0" type="led" ></control><control name="bGFiZWw1MQ==" x="2" y="165" w="68" h="25" color="green" type="labelh" text="TGFzdCBBY2Nlc3M=" size="12" background="true" outline="false" ></control><control name="bWlzc2luZw==" x="161" y="345" w="147" h="25" color="yellow" type="labelh" text="IA==" size="14" background="true" outline="false" ></control></tabpage></layout>
#spRecordPlayer.rb
#Sonic Pi Record / Player control using TouchOSC written by Robin Newman, March 2018
#handles recording and playback, real time or double speed, key changes, metronome, two synths
#uses Ableton push2 style layout
#release version 1.0.1
#few comments because of space limitations
use_osc "192.168.1.240",9000 #adjust for the address of your TouchOSC device
use_real_time
use_osc_logging false
use_bpm 60
st=Time.now
#intialise various flags
set :playing,false
set :recflag,false
set :leds,true
set :key,1
set :majmin,0
set :metroflag,false
set :ms,90
set :pb,60
set :synptr,1
delta=0.1
define :clearData do #clear all stored data
recn=[].clear;timn=[].clear
recp=[].clear;timp=[].clear
recm=[].clear;timm=[].clear
recs=[].clear;tims=[].clear
set :recn,recn;set :timn,timn
set :recp,recp;set :timp,timp
set :recm,recm;set :timm,timm
set :recs,recs;set :tims,tims
sleep 0.2
end
define :blueledsOn do
10.times do |x|
osc "/sprp/m"+(x+1).to_s,1
sleep 0.01
end
end
define :flashPush do |c,r| #flash matrix button pushed
osc "/sprp/multipush1/"+c.to_s+"/"+r.to_s,1
sleep 0.2
osc "/sprp/multipush1/"+c.to_s+"/"+r.to_s,0
end
define :parse_sync_address do |address| #get address wildcards
v= get_event(address).to_s.split(",")[6]
if v != nil
return v[3..-2].split("/")
else
return ["error"]
end
end
define :init do #init page 1 of the display
osc "/sprp/record",0
osc "/sprp/playback",0
osc "/sprp/key/1/1",1
osc "/sprp/majmin",0
osc "/sprp/majminLabel","major"
osc "/sprp/mt1",1
osc "/sprp/mt2",0
osc "/sprp/pb1",1
osc "/sprp/pb2",0
osc "/sprp/pb3",0
osc "/sprp/synth/1/1",1
osc "/sprp/metronome",0
osc "/sprp/ledplayback",1
blueledsOn
end
##next section handles metronome
live_loop :setmetronome do
b = sync "/osc/sprp/metronome "
if b[0]==1
set :metroflag,true
else
set :metroflag,false
end
end
live_loop :adjustMetro do
b = sync "/osc/sprp/mt*"
res = parse_sync_address "/osc/sprp/mt*"
if b[0]==1
if res[2][-1]=="1"
osc "/sprp/mt2",0
set :ms,90
elsif res[2][-1]=="2"
osc "/sprp/mt1",0
set :ms,120
end
end
end
live_loop :metro do
use_bpm get(:ms)
play :c5,release:0.05 if get(:metroflag)
sleep 1
end
#handle playback tempo
live_loop :adjustPBtempo do
b = sync "/osc/sprp/pb*"
res = parse_sync_address "/osc/sprp/pb*"
if b[0]==1
if res[2][-1]=="1"
osc "/sprp/pb2",0
osc "/sprp/pb3",0
set :pb,60
elsif res[2][-1]=="2"
osc "/sprp/pb1",0
osc "/sprp/pb3",0
set :pb,90
elsif res[2][-1]=="3"
osc "/sprp/pb1",0
osc "/sprp/pb2",0
set :pb,120
end
end
end
#handle led pb on button
live_loop :getledplayback do
b = sync "/osc/sprp/ledplayback"
if b[0]==1
set :leds,true
else
set :leds,false
end
end
init # run the screen init
define :doExtraToggles do |c,r,state| #control extra notes display
osc "/sprp/multipush1/"+(c.to_i-3).to_s+"/"+(r.to_i-1).to_s,state if c.to_i-3>0 and r.to_i-1 > 0
osc "/sprp/multipush1/"+(c.to_i-6).to_s+"/"+(r.to_i-2).to_s,state if c.to_i-6>0 and r.to_i-2 > 0
osc "/sprp/multipush1/"+(c.to_i+3).to_s+"/"+(r.to_i+1).to_s,state if c.to_i+3<9 and r.to_i+1 < 9
osc "/sprp/multipush1/"+(c.to_i+6).to_s+"/"+(r.to_i+2).to_s,state if c.to_i+6<9 and r.to_i+2 < 9
end
##next section handles note input recording and playback
define :playNote do |c,r|
use_synth [:piano,:pluck][(get(:synptr)).to_i-1]
sc=["c","d","e","f","g","a","b"][get(:key).to_i-1]
type = [:major,:minor][get(:majmin).to_i]
play scale(sc+"2",type,num_octaves: 7)[(c.to_i-1)+3*(8-r.to_i)]
if get(:leds)
in_thread do
flashPush c,r
end
end
sleep 0.1
end
live_loop :testNoteKeyPushed do
b= sync "/osc/sprp/multipush1/*/*"
if b[0]==1
res = parse_sync_address "/osc/sprp/multipush1/*/*"
in_thread do
doExtraToggles(res[3],res[4],1)
end
if get(:recflag)
in_thread do
recn=get(:recn);timn=get(:timn)
rn=recn + [[res[3],res[4]]]
tn=timn + [Time.now-st]
set :recn,rn
set :timn,tn
end
end
playNote res[3],res[4]
end
end
live_loop :testNoteKeyReleased do
b= sync "/osc/sprp/multipush1/*/*"
if b[0]==0
res = parse_sync_address "/osc/sprp/multipush1/*/*"
in_thread do
doExtraToggles(res[3],res[4],0)
end
end
end
define :playRecordedNotes do
use_bpm get(:pb)
set :notesfinish,false
recn= get(:recn)
timn = get(:timn)
sleep 0.2
if recn != nil
recn.length.times do |x|
if x==0
sleep timn[0]-delta
else
sleep timn[x]-timn[x-1]-delta
end
playNote(recn[x][0],recn[x][1])
break if get(:kill)
end
end
puts "finished notes playback"
set :notesfinish,true
end
## next section handles major/minor changes
live_loop :getMajminChanges do
b = sync "/osc/sprp/majmin"
set :majmin,b[0]
if b[0]==1
osc "/sprp/majminLabel","minor"
else
osc "/sprp/majminLabel","major"
end
if get(:recflag)
recm=get(:recm);timm=get(:timm)
rnm=recm + [b[0]]
tnm=timm + [Time.now-st]
set :recm,rnm
set :timm,tnm
end
end
define :playbackMajmin do
set :mmfinish,false
use_bpm get(:pb)
recm= get(:recm)
timm = get(:timm)
sleep 0.2
if recm != nil
recm.length.times do |x|
if x==0
sleep 0
else
sleep timm[x]-timm[x-1]-delta
end
set :majmin,recm[x]
osc "/sprp/majmin",recm[x].to_i
osc "/sprp/majminLabel",["major","minor"][recm[x].to_i]
break if get(:kill)
end
end
set :mmfinish,true
puts "finished majmin playback"
end
###### next section handles Key changes
live_loop :keySwitchChanged do
b= sync "/osc/sprp/key/*/*"
res = parse_sync_address "/osc/sprp/key/*/1"
if b[0]==1
set :key,res[3]
if get(:recflag)
recp=get(:recp);timp=get(:timp)
rnp=recp + [res[3].to_i]
tnp=timp + [Time.now-st]
set :recp,rnp
set :timp,tnp
end
end
end
define :playbackRecordedKey do
set :pushfinish,false
use_bpm get(:pb)
recp= get(:recp)
timp = get(:timp)
sleep 0.2
if recp !=nil
recp.length.times do |x|
if x==0
sleep 0
else
sleep timp[x]-timp[x-1]-delta
end
set :key,recp[x]
osc "/sprp/key/"+ recp[x].to_s+"/1",1
break if get(:kill)
end
end
set :pushfinish,true
puts "finished key playback"
end
#next section handles Synth selection
live_loop :chooseSynth do
b = sync "/osc/sprp/synth/*/1"
if b[0]==1
v = parse_sync_address "/osc/sprp/synth/*/1"
set :synptr,v[3]
if get(:recflag)
recs=get(:recs);tims=get(:tims)
rns=recs + [v[3]]
tns=tims + [Time.now-st]
set :recs,rns
set :tims,tns
end
end
end
define :playbackSynth do
set :synfinish,false
use_bpm get(:pb)
recs= get(:recs)
tims = get(:tims)
sleep 0.2
if recs != nil
recs.length.times do |x|
if x==0
sleep 0
else
sleep tims[x]-tims[x-1]-delta
end
s=recs[x].to_i
set :synptr,s
osc "/sprp/synth/"+s.to_s+"/1",1
break if get(:kill)
end
end
set :synfinish,true
puts "finished synth playback"
end
#next section recording/playback logic
live_loop :recording do
b = sync "/osc/sprp/record"
if b[0]==1
if get(:playing)==false
clearData #initialise for recording
set :recp,[get(:key)];set :timp,[0]
set :recm,[get(:majmin)];set:timm,[0]
set :recs,[get(:synptr)];set:tims,[0]
st=Time.now
set :recflag,true
puts "recording"
else
osc "/sprp/record",0
end
else
set :recflag,false
#data is extracted for saving in the other program
puts "stopped recording"
end
end
define :playbackControl do
set :playing,true
in_thread do
playbackSynth
end
in_thread do
playRecordedNotes
end
in_thread do
playbackRecordedKey
end
in_thread do
playbackMajmin
end
end
live_loop :checkNotPlaying do
#puts "playing is",get(:playing)
if get(:notesfinish)==true and get(:pushfinish)==true and get(:mmfinish)==true and get(:synfinish)==true
set :playing,false
osc "/sprp/playback",0
end
if get(:rec)==true
osc "/sprp/playback",0
end
sleep 0.5
end
live_loop :handlePlayButton do
b = sync "/osc/sprp/playback"
if b[0]==1
if get(:recflag)==false and get(:playing)==false
set :playing, true
puts "starting playback"
set :kill,false
playbackControl
end
else
set :kill,true
set :playing,false
puts "Playback finished"
end
end
#spRecordPlayerSaver.rb
#Record save and playback load for Sonic Pi player/recorder
#written by Robin Newman March 2018
#release version 1.0
use_osc "192.168.1.240",9000 #adjust for the address of your TouchOSC device
use_osc_logging false
#setup some flags
set :slot,01;set :bank,0;set :saveFlag,0;set :minFileSize,190
#intialise display page 2
osc "/archive/slot/1/1",1
osc "/archive/slotbank/1/1",1
osc "/archive/ledSave",0
osc "/archive/missing"," "
#set path for json files location
JSONfilePath="/Users/rbn/Documents/SPfromXML/recordplayer/"
osc "/archive/path",JSONfilePath
define :restoreHash do #restore values to arrays for other program
restore=get(:restore)
puts restore
set :timn, restore["Vtimn"]
set :recn, restore["Vrecn"]
set :timp, restore["Vtimp"]
set :recp, restore["Vrecp"]
set :timm, restore["Vtimm"]
set :recm, restore["Vrecm"]
set :tims, restore["Vtims"]
set :recs, restore["Vrecs"]
end
define :writeJson do |n| #write Json file using current data
vals=Hash.new #initialise vals hash
#now load values from the other program arrays
vals[:Vtimn]=get(:timn)
vals[:Vrecn]=get(:recn)
vals[:Vtimp]=get(:timp)
vals[:Vrecp]=get(:recp)
vals[:Vtimm]=get(:timm)
vals[:Vrecm]=get(:recm)
vals[:Vtims]=get(:tims)
vals[:Vrecs]=get(:recs)
#now write hash to json file
File.open(JSONfilePath+(n).to_s+".json", 'w') do |f|
f.write(MultiJson.dump(vals, pretty: true))
f.close
sleep 0.2
setFileIndicator n #(indicate whether file contains data)
end
end
define :readJson do |n| #read Json file
if File.exist?(JSONfilePath+n.to_s+".json")==false
sample :misc_crow
osc "/archive/missing",n.to_s+".json file missing"
else
osc "/archive/missing",n.to_s+".json file found"
content =File.read(JSONfilePath+n.to_s+".json")
#store retrieved content in time state
set :restore,MultiJson.load(content)
sleep 0.2
#extract the data for use in the other program
restoreHash
end
end
#This is actually defined in both programs
define :parse_sync_address do |address|
v= get_event(address).to_s.split(",")[6]
if v != nil
return v[3..-2].split("/")
else
return ["error"]
end
end
define :setFileIndicator do |n| #show whether file contains data
if File.exists?(JSONfilePath+(n).to_s+".json")
if File.size(JSONfilePath+(n).to_s+".json") > get(:minFileSize)
osc "/archive/d"+n.to_s,1
else
osc "/archive/d"+n.to_s,0
end
end
end
20.times do |n| #initialise file content indicators
setFileIndicator n+1
end
define :clearLastAccess do #clear all last access indicators
20.times do |n|
osc "/archive/a"+(n+1).to_s,0
end
end
define :setLastAccess do |n| #set last file accessed indicator
clearLastAccess
osc "/archive/a"+n.to_s,1
end
clearLastAccess #initial clear of all last access states
live_loop :setReadSlot do #deal with slot (pattern select) changes
use_real_time
b = sync "/osc/archive/slot/1/*"
if b[0]==1
res=parse_sync_address "/osc/archive/slot/1/*"
slot=res[4].to_i
set :slot,slot
puts "slot is #{slot}"
end
end
live_loop :writeData do #deal with Save Pattern button, using write enable
use_real_time
b = sync "/osc/archive/write"
if get(:saveFlag)==0
puts "Save not enabled"
osc "/archive/missing","Enable Save First!"
sample :misc_crow #warning noise
else
if b[0]==1
slot=get(:slot)+10*get(:bank)
writeJson(slot)
setLastAccess slot
puts "data written to slot #{slot}"
osc "/archive/missing","File #{slot}.json saved"
end
end
end
live_loop :readData do #deal with Load slot button
use_real_time
b = sync "/osc/archive/read"
if b[0]==1
slot=get(:slot)+10*get(:bank)
readJson(slot)
setLastAccess(slot)
puts "data read from slot #{slot}"
end
end
live_loop :slotbank do #deal with Slot Bank select
b = sync "/osc/archive/slotbank/*/1"
if b[0]==1
res = parse_sync_address "/osc/archive/slotbank/*/1"
bank= res[3].to_i - 1 #value will be 0 or 1
set :bank,bank
puts "bank selected is #{bank}"
end
end
live_loop :enablesave do #deal with enable save button
use_real_time
b = sync "/osc/archive/enablesave"
if b[0]==1
osc "/archive/ledSave",1
set :saveFlag,1 #enable save
sleep rt(1.5) #1.5 seconds regardless of any tempo
osc "/archive/ledSave",0
set :saveFlag,0 #disable save
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment