Coder Social home page Coder Social logo

bubobubobubobubo / sardine Goto Github PK

View Code? Open in Web Editor NEW
183.0 7.0 32.0 50.54 MB

Python's missing "algorave" module

Home Page: https://sardine.raphaelforment.fr

License: GNU General Public License v3.0

Python 82.35% HTML 15.23% Makefile 0.15% CSS 0.03% TeX 2.14% Emacs Lisp 0.10%
algorave algorithmic-music audio improvisation live-coding midi music musicology open-source osc

sardine's Introduction

Sardine: ✨ Live Coding Library for Python ✨

Python's missing algorave module. Hackable live coding tool for modern Python (3.10+)

Discord | Website | Examples | Installation | Author | About Live Coding

Buy Me a Coffee at ko-fi.com


Sardine algorave picture

Sardine is a versatile and hacker-friendly Python library designed for musical improvisation, algorithmic composition, and beyond. It transforms your standard Python interpreter into a powerful music instrument, enabling you to create and map melodic and rhythmic patterns to any electronic instrument (MIDI, OSC, and SuperCollider). With Sardine, you can:

  • Unleash your musical creativity on stage, in the studio, or for personal enjoyment

    • Seamlessly communicate with any MIDI/OSC device and the SuperCollider audio engine using Sardine.
    • Utilize bindings for SuperDirt, a widely recognized synthesis engine embraced by live coders globally.
  • Empower your Python code with time-aware capabilities

    • Employ temporal recursion to make any Python code time and tempo aware.
    • Accurately launch synchronous or asynchronous functions with time-specific results.
    • Customize your own Senders or Receivers to pattern any desired elements!
  • Develop intricate audio/visual installations with MIDI and OSC I/O

    • Assign callbacks to any OSC event, transforming Sardine into a sophisticated reactive toolbox.
    • Monitor changing values and incorporate them into your musical patterns or code.
  • Synchronize with other computers and musical instruments

    • Synchronise your hardware with MIDI Clocks.
    • Synchronize effortlessly with other tools or players using the Link Protocol.

Installation

Refer to the installation section.

Contributions

Sardine is in its early stages of development, and we're actively seeking contributors to help enhance the project. If you're passionate about music and technology, we welcome your expertise, whether it's code, documentation, or ideas. We are looking for contributors!

To collaborate with the Sardine community, connect with us on Discord, Github or send a private message if you have specific inquiries. Together, we can create an even more powerful tool for musical expression and creativity!

Generating documentation

Sardine documentation is using mdbook.

You first need to have Rust properly installed.

cargo install mdbook
mdbook serve --open

You should have the documentation automatically opened in your browser at http://localhost:3000/.

sardine's People

Contributors

amiika avatar bubobubobubobubo avatar giohappy avatar hatchjaw avatar highharmonics2 avatar jarmitage avatar jmpothelune avatar jure2018 avatar lutangar avatar martindelille avatar mugulmd avatar pipazoul avatar rhoumi avatar ssidorenko avatar thegamecracks avatar twal 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

sardine's Issues

Can python3 -m sardine fall to an asyncio REPL automatically?

Currently, starting Sardine is a two steps process:

  • python3 -m asyncio (to start the asyncio REPL)
  • from sardine import * (to import the library)

From the look of the file given as a link, it should be possible to reduce all this to python3 -m sardine. It's just a matter of pushing things so that Sardine falls back into the asyncio REPL before/after importing the library. I might be completely wrong but this is worth investigating. It would be a huge quality of life improvement and would maybe allow more sophisticated things in the future.

enable hush() in Quickstep to be Player specific

The hush() function used with Quickstep will shut down all players. A more refined implementation would allow the hush() function to take an argument of the specific player and shut down that player only.

desired behavior:

  • hush(Pa) #shuts down only Pa, leaves other players running
  • hush(Pa, Pb, PZ)
  • hush() #shuts down all players

Also, hush() works, but I see this error:
init.py", line 407, in hush
c.remove(runner)
File "~/sardine/sardine/clock/Clock.py", line 643, in remove
runner = self.runners.get(func.name)
AttributeError: 'str' object has no attribute 'name'

Midi Out port on Windows doesn't respect the configuration file

The first available port is used even if another port has been configured with sardine-config on Windows.

The following patch fixes it:

diff --git a/sardine/handlers/midi.py b/sardine/handlers/midi.py
index 821d67e..087aee9 100644
--- a/sardine/handlers/midi.py
+++ b/sardine/handlers/midi.py
@@ -17,13 +17,18 @@ class MidiHandler(Sender):
     MidiHandler: a class capable of reacting to most MIDI Messages.
     """
 
-    def __init__(self, port_name: str = "Sardine", nudge: float = 0.0):
+    def __init__(self, port_name: Optional[str] = None, nudge: float = 0.0):
         super().__init__()
         self.active_notes: dict[tuple[int, int], asyncio.Task] = {}
 
         # Setting up the MIDI Connexion
         self._available_ports = mido.get_output_names()
         self._port_name = port_name
+        if self._port_name is None:
+            if sys.platform not in "win32":
+                self._port_name = "Sardine"
+            else:
+                self._port_name = self._available_ports[0]
         self._midi = None
 
         # For MacOS/Linux
@@ -42,8 +47,7 @@ class MidiHandler(Sender):
         # For W10/W11
         else:
             try:
-                self._midi = mido.open_output(self._available_ports[0])
-                self._port_name = str(self._available_ports[0])
+                self._midi = mido.open_output(self._port_name)
             except Exception as err:
                 print(f"[red]Failed to open a MIDI Connexion: {err}")

pip3 install fails on python-rtmidi

After launching pip3 install -e . pip fails to install python-rtmidi

Building wheels for collected packages: python-rtmidi
  Building wheel for python-rtmidi (setup.py) ... error
  error: subprocess-exited-with-error
  
  × python setup.py bdist_wheel did not run successfully.
  │ exit code: 1
  ╰─> [41 lines of output]
      Package jack was not found in the pkg-config search path.
      Perhaps you should add the directory containing `jack.pc'
      to the PKG_CONFIG_PATH environment variable
      No package 'jack' found
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.linux-x86_64-3.10
      creating build/lib.linux-x86_64-3.10/rtmidi
      copying rtmidi/version.py -> build/lib.linux-x86_64-3.10/rtmidi
      copying rtmidi/__init__.py -> build/lib.linux-x86_64-3.10/rtmidi
      copying rtmidi/midiutil.py -> build/lib.linux-x86_64-3.10/rtmidi
      copying rtmidi/midiconstants.py -> build/lib.linux-x86_64-3.10/rtmidi
      running egg_info
      writing python_rtmidi.egg-info/PKG-INFO
      writing dependency_links to python_rtmidi.egg-info/dependency_links.txt
      writing top-level names to python_rtmidi.egg-info/top_level.txt
      reading manifest file 'python_rtmidi.egg-info/SOURCES.txt'
      reading manifest template 'MANIFEST.in'
      warning: no previously-included files found matching '.appveyor.yml'
      warning: no previously-included files found matching '.travis.yml'
      warning: no previously-included files found matching '*.rst.in'
      no previously-included directories found matching 'ci'
      warning: no previously-included files matching '__pycache__' found under directory '*'
      warning: no previously-included files matching '*.py[co]' found under directory '*'
      adding license file 'LICENSE.txt'
      adding license file 'AUTHORS.rst'
      writing manifest file 'python_rtmidi.egg-info/SOURCES.txt'
      running build_ext
      building 'rtmidi._rtmidi' extension
      creating build/temp.linux-x86_64-3.10
      creating build/temp.linux-x86_64-3.10/src
      creating build/temp.linux-x86_64-3.10/src/rtmidi
      x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -D__RTMIDI_SILENCE_WARNINGS__ -D__LINUX_ALSA__ -D__UNIX_JACK__ -Isrc/rtmidi -I/usr/include/python3.10 -c src/_rtmidi.cpp -o build/temp.linux-x86_64-3.10/src/_rtmidi.o
      x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -D__RTMIDI_SILENCE_WARNINGS__ -D__LINUX_ALSA__ -D__UNIX_JACK__ -Isrc/rtmidi -I/usr/include/python3.10 -c src/rtmidi/RtMidi.cpp -o build/temp.linux-x86_64-3.10/src/rtmidi/RtMidi.o
      src/rtmidi/RtMidi.cpp:3010:10: fatal error: jack/jack.h: No such file or directory
       3010 | #include <jack/jack.h>
            |          ^~~~~~~~~~~~~
      compilation terminated.
      error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
      [end of output]

Adding one liners

The Sardine architecture makes it possible to have one-line runners but it's just not coded yet. Add it.

Better packaging and distribution

Witnessed a disastrous Sardine install today on Linux Mint. I don't know specifically where it went wrong but dealing with pip can prove to be particularly tricky and stuff can break anytime if multiple Python versions are entering the game. Some ideas to get going:

  • switch to a more robust packaging process (poetry)?
  • don't assume that sclang will be found even if installed properly! (bugfix coming in parser branch).
  • add a minimal Python version requirement in setup.py: python_requires='>=3.9'.
  • find a way to properly handle the rtmidi and python-rtmidi dependency.
  • make sure that users have all the setuptools they need (https://docs.python.org/3/distutils/setupscript.html).
  • fix fishery assuming that config.json is a thing before even having started Sardine.
  • add a diagnostic tool to check if sclang and supercollider are cooperative.

It's usually easier to get Sardine installed on Win/Linux/MacOS but this experience is a good indicator of the absolute worst to expect! Python projects are notoriously hard to distribute.

Packaging

Installing Sardine on MacOS/Linux is straightforward because most users already have a decent compilation toolchain installed one way or the other (CMake, GCC, etc..). However, installing on Windows is currently super painful for no good reason:

  • rtmidi: no wheels for Windows 10 / 11.
  • link: source distribution, no wheels.

Users are required to download CMake and MSVC just to compile some of the dependencies used by Sardine. Ideally, Sardine should be shipped and packaged as a wheel and released on Pypi. This means that all packages used by Sardine should propose both a source and binary distribution. This problem is not only affecting Sardine but more likely everyone using the same libraries.

A sender for common MIDI Messages

The MM() sender for MIDI Messages such as control and program changes, etc.. is very much needed. This is already trivial to achieve via the generic P() object but I guess that it doesn't hurt to have it ready when you need it. Having an argument taking the message type could also open up the way to very intense and random MIDI patterning.

Support feeding lists of patterns

It would be lovely if you could feed a list of patterns like so:

D(['bd, cp', 'sd, sd'])

The patterns would be concatenated to yield bd, cp, sd, sd. This is not only useful for readability but it could make it easier to arrange interesting patterns of the same size. However, this change is not really trivial to make as it concerns pretty much every I/O Handlers.

Stabilise grammars for first release

Having a patterning grammar is fun but it is currently very experimental and error-prone for the end user. There should be a last check of the grammar to ensure that everything is alright and that errors will not invade user space everytime they miss a token. Furthermore, arithmetics should be checked for each parser to ensure that they match properly with their respective tokens:

  • Check name grammar (automated tests?)
  • Document and rewrite ListParser.py with docstrings.
  • Add a better debug REPL for parsers.

SuperDirt protocol support

Sardine messages to SuperDirt look like this:

OSC Message Received:
    time: 53.718025123933
    address: a NetAddr(127.0.0.1, 62275)
    recvPort: 57120
    msg: [ /play2, sound, bd, orbit, 0, legato, 1, gain, 1, trig, 1 ]

The /play2 path is for backwards compatibility only:
https://github.com/musikinformatik/SuperDirt/blob/develop/classes/SuperDirt.sc#L333-L338

Tidal messages to SuperDirt look like this:

OSC Message Received:
    time: 10.919082131004
    address: a NetAddr(127.0.0.1, 6010)
    recvPort: 57120
    msg: [ /dirt/play, _id_, 1, cps, 0.5625, cycle, 2430.0, delta, 1.777777671814, orbit, 1, s, bd ]

cps, cycle and delta are the parameters that allow SuperDirt to schedule messages on time. I am not exactly sure how Tidal calculates them (maybe @yaxu can advise) but:

Sardine has SuperDirtSender.py, but for some reason the /play2 message is being sent in: https://github.com/Bubobubobubobubo/sardine/blob/main/sardine/io/Osc.py#L185. Probably some refactoring is needed here as well to fully address this.

Sardine roadmap

@Bubobubobubobubo could you outline some issues for the roadmap?
I’d like to contribute, but it’s still obscured to me where to help, or test, etc…

cheers

Rewrite boot methods

The current boot process is very opaque and does not tell anything useful to the user.

  • SuperCollider and SuperDirt should be way more verbose than they are to assert if boot succeeded.
  • The boolean -boot in CLI is not always taken into account like it should.
  • The configuration file should be pretty printed each time Sardine boots so that user can troublecheck any missing information.
  • A message should be printed when selecting MIDI Port to tell users that they don't have to do this all the time!

And the list goes on. It's not supposed to be the mess it is right now!

Fix chord inversion algorithm

The chord inversion algorithm does not work very well. The inversion generated by negative values is just plain wrong. The inversion generated by positive values works well for every value but 1...

Bring missing SuperDirt messages bits

TidalCycles is way more verbose when sending information to SuperDirt. It includes information about timing among other things, which is surely used to compute the delay times and other things needed by SuperDirt. A proper study of SuperDirt messages should be done to bring missing features to Sardine.

Sardine GUI

Small GUI using Eel + CodeMirror? Could be fun for having a small GUI editor available to newcomers.

Adding functions to the FuncLibrary

With the new parser soon arriving in the main branch, it will now be possible to write custom functions for altering patterns. Functions are now supported directly in the pattern notation: disco(sopr(C@maj7)). It means that all the functions have a direct definition, with some functions being promoted to syntactic sugar if they are very useful or frequent. Here is a list of functions (at time of writing) :

"dmitri": voice-leading algorithm (works for 4 notes only)
"voice": : voice-leading algorithm (works for 4 notes but can be abused)
"sopr": the last note of the pattern will be up +12.
"quant": quantize to a given collection (everything in major, minor, etc..)
"disco": every pair element of pattern down an octave.
"adisco": every pair element of pattern up an octave.
"bass",: every first note down an octave.
"euclid": euclidian patterns on lists!
"mask": boolean mask a pattern.
"vanish": make x% of values disappear from a pattern.
"expand": add a chance operation that will transpose every element +/- 1 or 2 octaves.
"pal": palindrome operation with repetition of last element.
"apal": palindrome operation without repetition of the last element.
"rev": reverse a pattern.
"leave": interleave x lists together. Works for any number of lists.
"inp": insert pair, insert an element (variable size) as pair value of the new pattern.
"in": insert odd, //
"inprot": insert pair rotation, insert one value from pattern 2 with rotation.
"inrot": insert odd rotation, //
"shuf": shuffle a list.
"clamp": clamp pattern values between min and max.
"sin": sin function over a pattern.
"cos": cos function over a pattern.
"tan": tan function over a pattern.
"abs": abs function over a pattern.
"max": max function over a pattern.
"min": min function over a pattern.
"mean": mean function over a pattern.
"scale": scaling a pattern from x, y to x', y'
"filt": functional filter function.

This is a topic for pondering / discussing about new functions that could be added to Sardine :)

Better syntax for ramps

Ramps are written {1,2} or {1,2,0.1} for custom step specification. It works pretty well but a better and simpler syntax could be added that requires less typing. @mugulmd was proposing [1..2] and [1..2,0.1]. It currently breaks the parser but I guess it should/could work.

Embedded Sardinopedia

The Sardinopedia is included whenever you download Sardine but it is not served. It is written in pure Markdown. That means that we could probably include a function to help users search/browse the Sardinopedia directly from the command line. Rich can be used to render Markdown chunks. It is not easy to do but it could be incredibly useful.

Parser improvement branch: broken bits

Some things are still a bit broken in the parser improved branch:

  • P('C@fifths',0): chord association (79bb878 is trying to fix it..)
  • P('{1,10,0.1}',0): ramps with step. Tried to fix it with e26a282.
  • P('name:4',0): name association (good enough temporary fix by eb2fdfc)
  • P('la:{1,10}',0): name association with ramps (good enough temporary fix by eb2fdfc)
  • Unknown functions: sin, cos, etc...: it was just that the cos, sin and tan function declarations were shadowing Python math module function imports. Fixed with e26a282.
  • v.a=5 is broken (amphibian variables). Fixed with 9ec5d55.
  • P('[name, baba]:1',1) or P('[name, baba]:[1,2,3]',1) breaks with a cryptic error message. This last one is out of my reach. Can't understand how to fix it. It looks like the parser actually breaks before even reaching the function.
  • Many things fail when they encounter the Silence (. in parser, [None] in code). Fixed by @TWal.

This is alright. It is usually the side effect of turning everything into a list, which can break some functions not expecting that type. The answer to some of these problems can prove to be tricky sometimes...

Updating to Python 3.11

While packaging is still an issue, it is probably a good idea to try to get it neatly packaged for Python 3.11. Problematic packages will of course remain problematic but if we manage to pull it off, we would surely get (?) performance increases as well from the new Python optimisations.

Is Ableton Link a possibility?

I made Sardine based on a MIDI Clock because I needed it to sequence all my machines. However, it is not always the best option to play with other musicians. Support for the Ableton Link protocol would be great, and could possibly be quite easy to support.

Packaging it is difficult.. It would have to rely on the C++ Ableton Link library or possibly on Carabiner which would be a difficult thing to package right for cross-platform distribution.

Documenting Sardine: videos

It would be great to introduce Sardine through a series of videos that demonstrate all the existing features. They would need to be general enough so that they don't specifically target unstable syntax. It could either be one monolithic video or one per written documentation section. Here is a list of topics that need to be covered:

  • Installation: prerequisites, download, installation, pitfalls.
    • Python and pip: crossplatform setup.
    • Compilers and building: CMake, GCC, etc..
    • Cloning/forking/updating using Git or simple download.
    • Getting a proper text editor.
  • Configuration(1/2): CLI, options, configuration files.
    • Tour of sardine-config
    • Tour of the other commands
    • The configuration folder, the configuration files
  • Configuration(2/2): text editors, shortcuts.
    • Setting up a working REPL + text buffer workflow (non VIM)
  • General advice: how to feel comfortable using Sardine
    • Learning a tiny bit of Python
    • Learning about the terminal and text-editing
  • Clock: operation, modes (MIDI/Link), options, nudging.
    • Active and passive clock
    • Link synchronisation
    • Clock attributes
    • Nudging the clock: multi-layered nudging system
    • Acceleration
  • SuperCollider: the internal SC instance, debug and configuration.
    • What is SuperCollider? What is SuperDirt? Why?
    • How is SuperCollider booted? How to troubleshot?
    • Opening the VUmeter, the scope, sending code to SC.
    • The boot config option, the verbose_superdirt flag.
  • Senders: MIDI Sender, OSC Sender, SuperCollider Sender
    • dealing with the .out() method.
    • SuperCollider (S): composition of a message, possible arguments, etc..
    • MIDI (M): sending MIDI notes, parameter for MIDI notes, etc..
    • MIDI: functions for sending control messages, pitchwheel, etc..
    • MIDI: dealing with MIDI-In and controls
    • OSC: Sardine is transmitting clock information already
    • OSC: declaring an OSC out
  • Swimming functions: syntax, usage, details, pitfalls.
    • What is a swimming function? The @swim and @die decorators.
    • hush() and similar functions.
    • Swimming functions are immune to crashes.
    • Swimming functions can overlap themselves.
    • Duration and calling other functions from a swimming function.
  • Iterators and data flow: passing arguments, using iterators.
    • Argument passing
    • Iterating, why?
  • Pattern syntax 101: basic tokens, basic operations.
    • the debug() mode
    • data types: numbers & goodies, notes, names
    • basic arithmetic
    • list arithmetic
    • custom operators
    • weird tokens: time, phase, measure, second, etc..
    • math functions: cos, sin, tan
    • notes, qualifiers, modifiers
    • addresses and names
  • Advanced pattern syntax: composition and improvisation with the syntax.
  • Improvisation workflow: a final video showing up the workflow for improvising.

Some examples of Sardine in the wild would also be needed. I have yet to record footage of upcoming gigs.

filepath not found on first sardine import

After a succesfull install (pip3 install -e .)
when using for the first time from sardine import * i've got the following error

File "/sardine/io/UserConfig.py", line 84, in read_user_configuration
create_template_configuration_file(config_file)
TypeError: create_template_configuration_file() missing 1 required positional argument: 'file_path'

The error disapeared on the second import attempt

Reworking amphibian variables and iterators

A few months ago, I implemented amphibian variables and amphibian iterators but never went as far as making it cohesive with the whole language. Now is probably a good time to deal with that. Some features are broken or just feel weird given the current state of the language.

A pattern system and the problem of state

If you need to write a melody or a sequence with Sardine, you currently have two basic options:

  • using iterators or structures stored at the top-level.
  • using recursion to iterate over a local-scope sequence or structure.
from itertools import cycle

melody = cycle([60,64,67,69,71])

@swim
def test(): 
    S('pluck', midinote=next(melody)).out()
    cs(test)

It is not possible to store iterators inside a swimming function, because you still need to rely on some sort of global state to keep track of the next element to use.

@swim
def test(delay=1, iter=0): 
    melo = [60, 64, 67, 69, 71]
    if iter > len(melo) - 1: iter = 0
    S('pluck', midinote=melo[iter]).out()
    cs(test, iter=iter+1)

If you ever re-evalute the function, you will loose state and the melody will restart from the first note. This is not optimal for long running functions that you would like to update on-the-fly.

A good patterning system for Sardine would allow the user to deal easily with scopes and the duality between global and local states in swimming functions. Obviously, it would also need some sort of parser to write more easily complex sequences. I'm not sure of the best path to follow to implement such a feature.

Bring back polyphonic messages

In an early version of Sardine, it was possible to build polyphonic messages using lists. Since the new patterning system has been introduced, it is no longer the case. The polyphonic algorithm was a bit convoluted (the old .out() method) but the introduction of iterators should streamline this old mechanism quite a lot.

I think that it is now a matter of properly handling lists in the parser syntax.

Making use of clock attributes

Clock attributes are nice random number generators but they aren't really useful for now. It would be nice to make use of them somehow:

  • usage for longer non-loop based compositions (trigger events at x)
  • usage in swimming functions (as conditionals).
  • conditional swimming function triggering? (some sort of time target)

Stronger scheduler

The current scheduler is pretty cool and it can handle a lot of things going on at the same time but I keep dreaming about a very strong future-proof scheduler with a nice representation of time. I don't know if it can happen soon but this is something to keep in mind somewhere.

Rewrite configuration tool

The configuration tool is currently being rewritten using InquirerPy. It seems to be a good lightweight alternative to static CLIs that can be a bit frightening for many.

Unifying time notation

Sardine is using multiple non-homogeneous representations of time. Sometimes the time is denoted in ticks (MIDI duration), sometimes it is denoted using delays, etc.. It can be hard to make sense of it, and harder even to reason about time with conflicting representations. One can imagine some simple functions (even hidden ones) that would unify this. It is not needed for playing per se, but more for thinking / reasoning about Sardine and its way of doing things in time.

Sardine should open its own MIDI port

To prevent users from having to specify an existing MIDI port on first boot, it might be better to make Sardine create its own MIDI Port. rtmidi might be able to help with this.

Patterning overhaul

The parser hasn't seen any improvement in the past few weeks. Following Sardine design, the basic parser shouldn't be the only parser you can use and it would be nice to have different flavours.

Default Sardine Parser :

  • allow a pattern to have an incidence on other keys in a sender or to return multiple key:pattern elements.
  • better support for *args and functions in the FuncLibrary.
  • support for high-order functions at the pattern level (that's where the fun begins)

Ziffers parser

  • add a default Ziffers parser.
  • add a few default zplay players, following Ziffers current design.

Vortex-like mode

  • add support for Tidal patterns by including logic from the Vortex experiment.

Better usage of Lark

Including Lark as a POC of a mechanism for dealing with musical patterns has proven to be a really nice addition to Sardine. However, the grammar is really extremely poor and not well built. Tokenization is not fully handled by lark (using .split instead) and a more readable syntax could be included by learning more about Lark.

  • the call to .split should be removed and tokenization should be handled directly by Lark.
  • support for polyphonic expression AND lists using their own symbols ([], {} ?)
  • no regression and progressively adding more features!

The dependency of 'LinkPython' is breaking while 'Poetry install'

Hi Folks,
First of all, thanks for sharing the passion and the results of yours codes with Sardine.
I'm getting some errors while poetry installing Sardine:
the full output is here.
I have tried to pip install it, and it also returns the same error.
Do you have an old fork of this library?

Cheers!

Parser improvement: notes and chords

Description

It would be nice to be able to write chords and notes using the new parser. The simplest thing to do would be to have multiple parsers, each one specialised for one thing: notes for notes, name for names (sample names or OSC addresses), numbers for numbers. It might actually be possible to keep only one object, Parser.py and to specialise it by feeding it a specific grammar for each purpose, given as argument: ListParser(pattern=pattern, grammar='numbers'). It shouldn't be too hard to do but would require updating the sender objects as well: SuperDirtParser, MIDIParser and OSCParser. New specialised grammars should be written and tested for this. Hopefully, they will be really simple to grasp and extend without ending up writing lexer shenanigans.

Notes

Notes will be written using the anglo-saxon system: a-g or A-G and/or the french system (do re mi fa sol la si) and can receive an octave (0-9) and a sharp (#) or a flat (b). The result will always yield a midi note number. This parser will only be used for the note or midinote parameter. A mechanism is needed to check for this. It would be easy to extend the system afterwards to support chords and stacking multiple notes even though there is no polyphonic mode as of now (could generate arpeggios?).

Sample names

Same old parser?

Numbers

Same old parser?

This should be relatively easy to do but it will take some time!

Better integration of the Sardinopedia

The Sardinopedia can be summoned locally by using the help() function but it is not practical at all. Make the help() function behave like a search engine and serve snippets of the Sardinopedia in the form of single headers.

Sound Sender doesn't work with samples starting with numbers

Issue

  • dirt~ sample names starting with numbers generate errors when specific samples are referenced using the colon.
  • dirt~ sample names starting with numbers that contain numbers and letters generate errors whether there is a specific colon ref or not.

examples - number names:
S('808').out(i, div=1) #this works
S('808:0').out(i, div=1) # this errors: "Non valid token: 808:0: Unexpected token Token('COLON', ':')"

number + letter names:
S('808hc') # fails: "AttributeError: 'PatternStr' object has no attribute 'raw'"
S('808hc:0') # fails: "AttributeError: 'PatternStr' object has no attribute 'raw'"

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.