GithubHelp home page GithubHelp logo

python-sonic's Introduction

python-sonic - Programming Music with Python, Sonic Pi or Supercollider

Python-Sonic is a simple Python interface for Sonic Pi, which is a real great music software created by Sam Aaron (http://sonic-pi.net).

At the moment Python-Sonic works with Sonic Pi. It is planned, that it will work with Supercollider, too.

If you like it, use it. If you have some suggestions, tell me ([email protected]).

Installation

Or try

$ pip install python-sonic

That should work.

Limitations

  • You have to start Sonic Pi first before you can use it with python-sonic
  • Only the notes from C2 to C6

Changelog

V ersion
0.2.0 Some changes for Sonic Pi 2.11. Simpler multi-threading with decorator @in_thread. Messaging with cue and sync.
0.3.0 OSC Communication
0.3.1. Update, sort and duration of samples
0.3.2. Restructured
0.4.0 Changes communication ports and recording

Communication

The API python-sonic communications with Sonic Pi over UDP and two ports. One port is an internal Sonic Pi port and could be changed.
For older Sonic Pi Version you have to set the ports explicitly
from psonic import *
set_server_parameter('127.0.0.1',4557,4559)

Examples

Many of the examples are inspired from the help menu in Sonic Pi.

from psonic import *

The first sound

play(70) #play MIDI note 70

Some more notes

play(72)
sleep(1)
play(75)
sleep(1)
play(79) 

In more tratitional music notation

play(C5)
sleep(0.5)
play(D5)
sleep(0.5)
play(G5) 

Play sharp notes like F# or dimished ones like Eb

play(Fs5)
sleep(0.5)
play(Eb5)

Play louder (parameter amp) or from a different direction (parameter pan)

play(72,amp=2)
sleep(0.5)
play(74,pan=-1) #left

Different synthesizer sounds

use_synth(SAW)
play(38)
sleep(0.25)
play(50)
sleep(0.5)
use_synth(PROPHET)
play(57)
sleep(0.25)

ADSR (Attack, Decay, Sustain and Release) Envelope

play (60, attack=0.5, decay=1, sustain_level=0.4, sustain=2, release=0.5) 
sleep(4)

Play some samples

sample(AMBI_LUNAR_LAND, amp=0.5)
sample(LOOP_AMEN,pan=-1)
sleep(0.877)
sample(LOOP_AMEN,pan=1)
sample(LOOP_AMEN,rate=0.5)
sample(LOOP_AMEN,rate=1.5)
sample(LOOP_AMEN,rate=-1)#back
sample(DRUM_CYMBAL_OPEN,attack=0.01,sustain=0.3,release=0.1)
sample(LOOP_AMEN,start=0.5,finish=0.8,rate=-0.2,attack=0.3,release=1)

Play some random notes

import random

for i in range(5):
    play(random.randrange(50, 100))
    sleep(0.5)
for i in range(3):
    play(random.choice([C5,E5,G5]))
    sleep(1)

Sample slicing

from psonic import *

number_of_pieces = 8

for i in range(16):
    s = random.randrange(0,number_of_pieces)/number_of_pieces #sample starts at 0.0 and finishes at 1.0
    f = s + (1.0/number_of_pieces)
    sample(LOOP_AMEN,beat_stretch=2,start=s,finish=f)
    sleep(2.0/number_of_pieces)

An infinite loop and if

while True:
  if one_in(2):
    sample(DRUM_HEAVY_KICK)
    sleep(0.5)
  else:
    sample(DRUM_CYMBAL_CLOSED)
    sleep(0.25)

:

---------------------------------------------------------------------------

KeyboardInterrupt                         Traceback (most recent call last)

<ipython-input-18-d8759ac2d27e> in <module>()
      5   else:
      6     sample(DRUM_CYMBAL_CLOSED)
----> 7     sleep(0.25)


/mnt/jupyter/python-sonic/psonic.py in sleep(duration)
    587     :return:
    588     """
--> 589     time.sleep(duration)
    590     _debug('sleep', duration)
    591 


KeyboardInterrupt: 

If you want to hear more than one sound at a time, use Threads.

import random
from psonic import *
from threading import Thread

def bass_sound():
    c = chord(E3, MAJOR7)
    while True:
        use_synth(PROPHET)
        play(random.choice(c), release=0.6)
        sleep(0.5)

def snare_sound():
    while True:
        sample(ELEC_SNARE)
        sleep(1)

bass_thread = Thread(target=bass_sound)
snare_thread = Thread(target=snare_sound)

bass_thread.start()
snare_thread.start()

while True:
    pass

:

---------------------------------------------------------------------------

KeyboardInterrupt                         Traceback (most recent call last)

<ipython-input-19-5b8671a783d6> in <module>
     22 
     23 while True:
---> 24     pass


KeyboardInterrupt: 

Every function bass_sound and snare_sound have its own thread. Your can hear them running.

from psonic import *
from threading import Thread, Condition
from random import choice

def random_riff(condition):
    use_synth(PROPHET)
    sc = scale(E3, MINOR)
    while True:
        s = random.choice([0.125,0.25,0.5])
        with condition:
            condition.wait() #Wait for message
        for i in range(8):
            r = random.choice([0.125, 0.25, 1, 2])
            n = random.choice(sc)
            co = random.randint(30,100)
            play(n, release = r, cutoff = co)
            sleep(s)

def drums(condition):
    while True:
        with condition:
            condition.notifyAll() #Message to threads
        for i in range(16):
            r = random.randrange(1,10)
            sample(DRUM_BASS_HARD, rate=r)
            sleep(0.125)

condition = Condition()
random_riff_thread = Thread(name='consumer1', target=random_riff, args=(condition,))
drums_thread = Thread(name='producer', target=drums, args=(condition,))

random_riff_thread.start()
drums_thread.start()

input("Press Enter to continue...")

Press Enter to continue...

''

To synchronize the thread, so that they play a note at the same time, you can use Condition. One function sends a message with condition.notifyAll the other waits until the message comes condition.wait.

More simple with decorator __@in_thread_

from psonic import *
from random import choice

tick = Message()

@in_thread
def random_riff():
    use_synth(PROPHET)
    sc = scale(E3, MINOR)
    while True:
        s = random.choice([0.125,0.25,0.5])
        tick.sync()
        for i in range(8):
            r = random.choice([0.125, 0.25, 1, 2])
            n = random.choice(sc)
            co = random.randint(30,100)
            play(n, release = r, cutoff = co)
            sleep(s)

@in_thread
def drums():
    while True:
        tick.cue()
        for i in range(16):
            r = random.randrange(1,10)
            sample(DRUM_BASS_HARD, rate=r)
            sleep(0.125)

random_riff()
drums()

input("Press Enter to continue...")

Press Enter to continue...

from psonic import *

tick = Message()

@in_thread
def metronom():
    while True:
        tick.cue()
        sleep(1)

@in_thread
def instrument():
    while True:
        tick.sync()
        sample(DRUM_HEAVY_KICK)

metronom()
instrument()

while True:
    pass

Play a list of notes

from psonic import *

play ([64, 67, 71], amp = 0.3) 
sleep(1)
play ([E4, G4, B4])
sleep(1)

Play chords

play(chord(E4, MINOR)) 
sleep(1)
play(chord(E4, MAJOR))
sleep(1)
play(chord(E4, MINOR7))
sleep(1)
play(chord(E4, DOM7))
sleep(1)

Play arpeggios

play_pattern( chord(E4, 'm7')) 
play_pattern_timed( chord(E4, 'm7'), 0.25) 
play_pattern_timed(chord(E4, 'dim'), [0.25, 0.5]) 

Play scales

play_pattern_timed(scale(C3, MAJOR), 0.125, release = 0.1) 
play_pattern_timed(scale(C3, MAJOR, num_octaves = 2), 0.125, release = 0.1) 
play_pattern_timed(scale(C3, MAJOR_PENTATONIC, num_octaves = 2), 0.125, release = 0.1)

The function scale returns a list with all notes of a scale. So you can use list methodes or functions. For example to play arpeggios descending or shuffeld.

import random
from psonic import *

s = scale(C3, MAJOR)
s

[48, 50, 52, 53, 55, 57, 59, 60]

s.reverse()
play_pattern_timed(s, 0.125, release = 0.1)
random.shuffle(s)
play_pattern_timed(s, 0.125, release = 0.1)

Live Loop

One of the best in SONIC PI is the Live Loop. While a loop is playing music you can change it and hear the change. Let’s try it in Python, too.

from psonic import *
from threading import Thread

def my_loop():
  play(60)
  sleep(1)

def looper():
  while True:
    my_loop()

looper_thread = Thread(name='looper', target=looper)

looper_thread.start()

input("Press Enter to continue...")

Press Enter to continue...Y

'Y'

Now change the function my_loop und you can hear it.

def my_loop():
  use_synth(TB303)
  play (60, release= 0.3)
  sleep (0.25)
def my_loop():
  use_synth(TB303)
  play (chord(E3, MINOR), release= 0.3)
  sleep(0.5)
def my_loop():
    use_synth(TB303)
    sample(DRUM_BASS_HARD, rate = random.uniform(0.5, 2))
    play(random.choice(chord(E3, MINOR)), release= 0.2, cutoff=random.randrange(60, 130))
    sleep(0.25)

To stop the sound you have to end the kernel. In IPython with Kernel –> Restart

Now with two live loops which are synch.

from psonic import *
from threading import Thread, Condition
from random import choice

def loop_foo():
  play (E4, release = 0.5)
  sleep (0.5)


def loop_bar():
  sample (DRUM_SNARE_SOFT)
  sleep (1)


def live_loop_1(condition):
    while True:
        with condition:
            condition.notifyAll() #Message to threads
        loop_foo()

def live_loop_2(condition):
    while True:
        with condition:
            condition.wait() #Wait for message
        loop_bar()

condition = Condition()
live_thread_1 = Thread(name='producer', target=live_loop_1, args=(condition,))
live_thread_2 = Thread(name='consumer1', target=live_loop_2, args=(condition,))

live_thread_1.start()
live_thread_2.start()

input("Press Enter to continue...")

Press Enter to continue...y

'y'

def loop_foo():
  play (A4, release = 0.5)
  sleep (0.5)
def loop_bar():
  sample (DRUM_HEAVY_KICK)
  sleep (0.125)

If would be nice if we can stop the loop with a simple command. With stop event it works.

from psonic import *
from threading import Thread, Condition, Event

def loop_foo():
  play (E4, release = 0.5)
  sleep (0.5)


def loop_bar():
  sample (DRUM_SNARE_SOFT)
  sleep (1)


def live_loop_1(condition,stop_event):
    while not stop_event.is_set():
        with condition:
            condition.notifyAll() #Message to threads
        loop_foo()

def live_loop_2(condition,stop_event):
    while not stop_event.is_set():
        with condition:
            condition.wait() #Wait for message
        loop_bar()



condition = Condition()
stop_event = Event()
live_thread_1 = Thread(name='producer', target=live_loop_1, args=(condition,stop_event))
live_thread_2 = Thread(name='consumer1', target=live_loop_2, args=(condition,stop_event))


live_thread_1.start()
live_thread_2.start()

input("Press Enter to continue...")

Press Enter to continue...y

'y'

stop_event.set()

More complex live loops

sc = Ring(scale(E3, MINOR_PENTATONIC))

def loop_foo():
  play (next(sc), release= 0.1)
  sleep (0.125)

sc2 = Ring(scale(E3,MINOR_PENTATONIC,num_octaves=2))

def loop_bar():
  use_synth(DSAW)
  play (next(sc2), release= 0.25)
  sleep (0.25)

Now a simple structure with four live loops

import random
from psonic import *
from threading import Thread, Condition, Event

def live_1():
    pass

def live_2():
    pass

def live_3():
    pass

def live_4():
    pass

def live_loop_1(condition,stop_event):
    while not stop_event.is_set():
        with condition:
            condition.notifyAll() #Message to threads
        live_1()

def live_loop_2(condition,stop_event):
    while not stop_event.is_set():
        with condition:
            condition.wait() #Wait for message
        live_2()

def live_loop_3(condition,stop_event):
    while not stop_event.is_set():
        with condition:
            condition.wait() #Wait for message
        live_3()

def live_loop_4(condition,stop_event):
    while not stop_event.is_set():
        with condition:
            condition.wait() #Wait for message
        live_4()

condition = Condition()
stop_event = Event()
live_thread_1 = Thread(name='producer', target=live_loop_1, args=(condition,stop_event))
live_thread_2 = Thread(name='consumer1', target=live_loop_2, args=(condition,stop_event))
live_thread_3 = Thread(name='consumer2', target=live_loop_3, args=(condition,stop_event))
live_thread_4 = Thread(name='consumer3', target=live_loop_3, args=(condition,stop_event))

live_thread_1.start()
live_thread_2.start()
live_thread_3.start()
live_thread_4.start()

input("Press Enter to continue...")

Press Enter to continue...y

'y'

After starting the loops you can change them

def live_1():
    sample(BD_HAUS,amp=2)
    sleep(0.5)
    pass
def live_2():
    #sample(AMBI_CHOIR, rate=0.4)
    #sleep(1)
    pass
def live_3():
    use_synth(TB303)
    play(E2, release=4,cutoff=120,cutoff_attack=1)
    sleep(4)
def live_4():
    notes = scale(E3, MINOR_PENTATONIC, num_octaves=2)
    for i in range(8):
        play(random.choice(notes),release=0.1,amp=1.5)
        sleep(0.125)

And stop.

stop_event.set()

Creating Sound

from psonic import *

synth(SINE, note=D4)
synth(SQUARE, note=D4)
synth(TRI, note=D4, amp=0.4)
detune = 0.7
synth(SQUARE, note = E4)
synth(SQUARE, note = E4+detune)
detune=0.1 # Amplitude shaping
synth(SQUARE, note = E2, release = 2)
synth(SQUARE, note = E2+detune, amp =  2, release = 2)
synth(GNOISE, release = 2, amp = 1, cutoff = 60)
synth(GNOISE, release = 0.5, amp = 1, cutoff = 100)
synth(NOISE, release = 0.2, amp = 1, cutoff = 90)

Next Step

Using FX Not implemented yet

from psonic import *

with Fx(SLICER):
    synth(PROPHET,note=E2,release=8,cutoff=80)
    synth(PROPHET,note=E2+4,release=8,cutoff=80)
with Fx(SLICER, phase=0.125, probability=0.6,prob_pos=1):
    synth(TB303, note=E2, cutoff_attack=8, release=8)
    synth(TB303, note=E3, cutoff_attack=4, release=8)
    synth(TB303, note=E4, cutoff_attack=2, release=8)

OSC Communication (Sonic Pi Ver. 3.x or better)

In Sonic Pi version 3 or better you can work with messages.

from psonic import *

First you need a programm in the Sonic Pi server that receives messages. You can write it in th GUI or send one with Python.

run("""live_loop :foo do
  use_real_time
  a, b, c = sync "/osc*/trigger/prophet"
  synth :prophet, note: a, cutoff: b, sustain: c
end """)

Now send a message to Sonic Pi.

send_message('/trigger/prophet', 70, 100, 8)
stop()

Recording

With python-sonic you can record wave files.

from psonic import *
# start recording
start_recording()

play(chord(E4, MINOR)) 
sleep(1)
play(chord(E4, MAJOR))
sleep(1)
play(chord(E4, MINOR7))
sleep(1)
play(chord(E4, DOM7))
sleep(1)
# stop recording
stop_recording

<function psonic.psonic.stop_recording()>

# save file
save_recording('/Volumes/jupyter/python-sonic/test.wav')

More Examples

from psonic import *
#Inspired by Steve Reich Clapping Music

clapping = [1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0]

for i in range(13):
    for j in range(4):
        for k in range(12): 
          if clapping[k] ==1 : sample(DRUM_SNARE_SOFT,pan=-0.5)
          if clapping[(i+k)%12] == 1: sample(DRUM_HEAVY_KICK,pan=0.5)
          sleep (0.25)

Projects that use Python-Sonic

Raspberry Pi sonic-track.py a Sonic-pi Motion Track Demo https://github.com/pageauc/sonic-track

Sources

Joe Armstrong: Connecting Erlang to the Sonic Pi http://joearms.github.io/2015/01/05/Connecting-Erlang-to-Sonic-Pi.html

Joe Armstrong: Controlling Sound with OSC Messages http://joearms.github.io/2016/01/29/Controlling-Sound-with-OSC-Messages.html

python-sonic's People

Contributors

csik avatar fdm1 avatar gkvoelkl avatar kant avatar m-roberts avatar osteele avatar p6rguvyrst avatar wallysalami avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-sonic's Issues

sonic-track.py demo opencv motion tracking to sound

FYI. I have written a motion tracking program using your library. This project is still a work in progress. Still trying to figure best way to do things. I am retired and just do this as a hobby.
Just want to say thanks. I had the idea and your work made my job faster and easier. Still more work to do GitHub Repo is here https://github.com/pageauc/sonic-track. I will do a shorter demo of changing synths via motion activated camera view area (top left corner)
Thanks again
Claude ...

adding .reverse and .shuffle commands

Would it be possible to add these?
The first one at least would be very useful in being able to play descending scales.
using scale(:c4,:major).reverse for the list of notes to use.

(Just taken a look at psonic and it works nicely. Trying it with a skywriter hat at present.)

Implementation of sample_duration

Hi, everyone!

I'm planning a Microcontroller 101 course in my university that will use Raspberry Pi. Sonic Pi sounds like a great way to engage students, and this library will help a lot because we have to use Python.

I've been playing with python-sonic for a few days, and I miss one feature from the original API in Ruby: sample_duration. That is very handy for drumming loops. Sure, I could give the students a reference table with all the durations, but it would be great if they could just call a function to speed up experimentations.

I'm not familiar with OscMessageBuilder, but it seems complicated (or impossible) to get a value back from Sonic Pi. So I was wondering if we can manually add the duration of all samples in the class initializer, and the create a our sample_duration function.

#...
LOOP_COMPUS = Sample('loop_compus', 6.486485260770975)
LOOP_AMEN = Sample('loop_amen', 1.753310657596372)
#...

class Sample:
    """
    Sample
    """

    def __init__(self, name, duration):
        self.name = name
        self.duration = duration

def sample_duration(sample):
    return sample.duration

How about that? I can write the changes and make a pull request, if you want.

Rename package so that it complies with packaging standards

When trying to package this for Debian, the source-package-encodes-python-version package quality check tag is triggered.

This source package encodes a Python version in its name such as python2-foo or python3-bar.

This could result in a misleading future situation where this source package supports multiple versions as well unnecessary given that the binary package names will typically encode the supported versions.

If the package were called, for example, sonic-py, then the Debian package would be called python3-sonic-py, and everything would play nice.

Intervals in chords seem funny

Am I somehow fundamentally wrong about MIDI notes and chords or are the intervals somewhat off? Minor / major triands look ok, but the the fifths and sevenths worry me... (Sounds off, too.)

 for ctype in [MAJOR, MAJOR7, MINOR, MINOR7]:
    print(ctype)
    ns = chord(C4, ctype)
    for n in ns:
    	print(n, n - ns[0])
	play(n)
	sleep(0.25)
 sleep(1)

major
60 0
64 4
71 11
major7
60 0
64 4
71 11
82 22
minor
60 0
63 3
70 10
minor7
60 0
63 3
70 10
80 20

Awesome project by the way. I always thought I'd love to have Python for SonicPi, ever since I discovered it.

Pip install not working

Hi

I tried "sudo pip install python-sonic" on my Pi 3 and it fails, states there is no such file. Any other methods to install your python-sonic? Thanks

Feature - load_sample

Hey guys,

Awesome library and really easy to use, also great documentation so thanks!

I was wondering if there was any way of implementing the load_sample function from sonic pi into your library.

eg
bass = "~/Desktop/dnb/Bass Track.wav" load_sample bass sample(bass)

I tried to add it to the library but it seems like the UPD interface doesn't remember loading a sample in when you run it as separate commands, which means you'll have to reload the sample every time you want to use it - which is a bit clunky, especially on a Rpi.

so this will work

command = 'bass = "~/Desktop/dnb/Bass Track.wav"\nload_sample bass\nbass = sample(bass)'
self.run(command)

However this won't

command = 'bass = "~/Desktop/dnb/Bass Track.wav"\nload_sample bass'
self.run(command)
command = 'sample(bass)'
self.run(command)

Happy to contribute in any way - just need some guidance :)

Thanks!

Packaging

This is a really great library. Were you planning on packaging it? Would be great to have this available in pip, and later the Raspbian repo (apt-get) Let me know if I can help.

This library works brilliantly with GPIO Zero, essentially allowing direct Sonic Pi control from GPIO inputs.

Do you have any plans for further development?

Thanks

How to install python-sonic on Python 3?

Hi Gerhard, congratulations for the great work!

How can I install python-sonic on my Python 3 installation?
When I try pip install python-sonic
it says:
Could not find a version that satisfies the requirement python-sonic (from versions: ) No matching distribution found for python-sonic
as it's not linking to Python 3...

Thank you!

Alexandre Rangel

Can't send 0 or 1

Test case:

Python:

from pythonosc import udp_client
sender = udp_client.SimpleUDPClient('127.0.0.1', 4559)
sender.send_message('/trigger/prophet', [0, 1, 2])

Sonic Pi:

live_loop :foo do
  use_real_time
  a, b, c = sync "/osc/trigger/prophet"
  print(a,b,c)
end

Sonic Pi log:

{run: 9, time: 108.8493}
 └─ 2 nil nil

Please tell how to run this project

I am having problem in running the project even after downloading this project and downloading the SonicPi .
untitledscreen
Please tell and guide me how to run the project.

with_fx function

Good stuff! Might I suggest adding in a with_fx() function? Seems to be the only major omission, and seems easy enough to do.

use_bpm

Can't find a way to change bpm similar to "use_bpm 100" of Sonic Pi
It would be nice to have.

synthServer.stop() raises pythonosc.osc_message.ParseError exception

To reproduce:

from psonic import *
synthServer.stop()

produces this result

Traceback (most recent call last):
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/pythonosc/osc_message.py", line 43, in _parse_datagram
    val, index = osc_types.get_string(self._dgram, index)
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/pythonosc/parsing/osc_types.py", line 68, in get_string
    'OSC string cannot begin with a null byte: %s' % dgram[start_index:])
pythonosc.parsing.osc_types.ParseError: OSC string cannot begin with a null byte: b'\x00\x00\x00\x00'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/psonic.py", line 769, in stop
    self.send_command(SonicPi.STOP_COMMAND)
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/psonic.py", line 780, in send_command
    msg = msg.build()
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/pythonosc/osc_message_builder.py", line 119, in build
    return osc_message.OscMessage(dgram)
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/pythonosc/osc_message.py", line 22, in __init__
    self._parse_datagram()
  File "/Users/osteele/anaconda3/envs/assignment-dashboard/lib/python3.6/site-packages/pythonosc/osc_message.py", line 58, in _parse_datagram
    raise ParseError('Found incorrect datagram, ignoring it', pe)
pythonosc.osc_message.ParseError: ('Found incorrect datagram, ignoring it', ParseError("OSC string cannot begin with a null byte: b'\\x00\\x00\\x00\\x00'",))

Import issue

I am using this script inside Blender, and try loading the Python-Sonic using:

from psonic import *

however, that causes issue with binding.

So, I need to use it like this:
import psonic as ps

ps.play(value) actually works

but using it like above causing
ps.use_synth(BLAH)

failed to work :(

Is there a better way to load this python module?

Two plucks in psonic.py

In psonic.py I Just noticed that there are two plucks in the synthesizers. One at line 173 and the other at line 192. Did a quick check for other dups but could not see any.
BTW I am still working at sonic-track. version 0.82 just released. That is how I found duplicate.
Going to work on saving and reading note data information to/from file(s). This morning I pointed sonic-track at the TV with sports, news and other channels with motion. It was quite interesting. I found that there is a lot of panning in sports so most of the action is near the middle of the screen. Baseball was good and a weather person was pretty interesting. I would like to create a video and use some of sonic-track sounds as part of the audio since it tends to sync with the motion. Just for Fun
Regards Claude.

Sonic-Pi 4.4

Hi, I am not sure of the status of this repository, but is the current main branch compatible with v4 of Sonic-Pi?

I had a look, and it looks like that methods have updating, requiring parsing of the token and server from the spider logs, and as far as I can see, this is not implemented in synth_server.py. It also looks like the format of the logs is now changed as well.

See This comment

Therefore an example OSC message is something like the following now:

"localhost", 32373, "/run-code", 1605599894, "play 72"

Access from remote pc's

I had a look at the code, and the address appears to be hard coded for localhost, i.e.127.0.0.1
I have a pi running sonic-pi, and a separate Linux LMDE PC running JupyterLab.

I know I can change the code to address my Pi, and pretty certain that would work, but it would be nice to have an option.

p.p. I tried editing the server code, it doesn't work as I thought. I believe that sonic running as a server using command
/opt/sonic-pi/app/server/ruby/bin/sonic-pi-server.rb
has an issue itself. I haven't got the sonic-pi-tool running yet...
I haven't managed to figure out if it is the wrong port, or that it isn't actually listening outside of localhost. Will continue investigating. For the moment, I have jupyter running locally, and your interface is very nice. Looking forward to the supercollider version.... I bet that is a lot more difficult. I am currently accessing supercollider via node-red and node-red-contrib-music which may be of some interest.

[Feature] Some sort of use_bpm integration

One of the mains thing I want to use this library for is to control the tempo of a song using a potentiometer, with a visual display.

I know one can set the specific BPM of loops in Sonic Pi by doing something like this:

set :bpm , 150

live_loop :kicky do
  use_bpm get(:bpm)
  sample :drum_bass_hard, rate: 1
  sleep 1
end

live_loop :snare_guy do
  use_bpm get(:bpm) #gets 100
  sync :kicky
  sleep 1
  sample :drum_snare_hard, rate: 1
end

Would it be hard to integrate that into this library? It would really help!

Note: I tried making this using subprocess and user inputs. It works but it updates pretty slowly. https://hastebin.com/rexavuzepa.py

Keep reference to note and pause?

Is it possible to keep a reference to a note to be able to pause it at a later time?
i.e something equivalent to this :
mynote = play :C4, sustain: 100
and then later do:
mynote.pause

Using use_bpm function from python

What would be the equivalent code for python ?

live_loop :foo do
  b = sync "/osc*/live_loop/foo"
  sample :drum_heavy_kick
  sleep 1
  sample :drum_snare_hard
  sleep 1
  use_bpm b[0]
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.