././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.6235404 renardo_lib-0.9.12/0000755000175100001770000000000014611211157013467 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/LICENSE0000644000175100001770000003524014611211152014473 0ustar00runnerdockerCreative Commons Attribution-ShareAlike 4.0 International Public License http://creativecommons.org/licenses/by-sa/4.0/legalcode By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 – Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. c. BY-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License. d. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. e. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. f. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. g. License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike. h. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. i. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. j. Licensor means the individual(s) or entity(ies) granting rights under this Public License. k. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. l. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or s ucceeded, as well as other essentially equivalent rights anywhere in the world. m. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 – Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: A. reproduce and Share the Licensed Material, in whole or in part; and B. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 5. Downstream recipients. A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. B. Additional offer from the Licensor – Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. C. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 – License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material (including in modified form), You must: A. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. b. ShareAlike. In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. 1. The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License. 2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. 3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. Section 4 – Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 – Disclaimer of Warranties and Limitation of Liability. a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 – Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 – Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 – Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.6235404 renardo_lib-0.9.12/PKG-INFO0000644000175100001770000003057014611211157014571 0ustar00runnerdockerMetadata-Version: 2.1 Name: renardo_lib Version: 0.9.12 Summary: Python livecoding environment - New fork of FoxDot Home-page: http://renardo.org/ Author: Elie Gavoty Author-email: eliegavoty@free.fr License: cc-by-sa-4.0 Description-Content-Type: text/markdown License-File: LICENSE Requires-Dist: renardo_gatherer==0.1.3 Requires-Dist: midiutil Renardo v0.9 - FoxDot fork =========================== Renardo/FoxDot is a Python programming environment that provides a fast and user-friendly abstraction to SuperCollider. It also comes with its own IDE, which means it can be used straight out of the box; all you need is Python and SuperCollider and you're ready to go! ## Important If you are having trouble installing using `pip install FoxDot`, try updating Python's `setuptools` and `wheel` libraries using the following code and trying again. ``` pip install -U setuptools pip install -U wheel ``` ### v0.8 Updates - Added `stretch` synth for timestretching samples, similar to `loop` but better and only plays the whole file. Stretches the audio's duration to the `sus` attribute without affecting pitch and does not require the tempo to be known. ```python # Stretches the audio to 4 beats without affecting pitch p1 >> stretch("Basic_Rock_135", dur=4) ``` --- ## Installation and startup #### Prerequisites - [Python 2 or 3](https://www.python.org/) - add Python to your path and install "pip" when prompted during the install. - [SuperCollider 3.8 and above](http://supercollider.github.io/download) - [Tkinter](https://tkdocs.com/tutorial/install.html) - Usually packaged with Python but Linux and MacOS users may need to install using: ```bash $ sudo apt-get install python3-tk (Linux) $ sudo port install py-tkinter (MacOS) ``` #### Recommended - [sc3 plugins](http://sc3-plugins.sourceforge.net/) #### Installing FoxDot - Open up a command prompt and type `pip install --user FoxDot`. This will download and install the latest stable version of FoxDot from the Python Package Index if you have properly configured Python. - You can update FoxDot to the latest version if it's already installed by adding `-U` or `--upgrade` flag to this command. - Alternatively, you can build from source from directly from this repository: ``` bash $ git clone https://github.com/Qirky/FoxDot.git $ cd FoxDot $ python setup.py install ``` - Open SuperCollder and install the FoxDot Quark and its dependencies (this allows FoxDot to communicate with SuperCollider) by entering the following and pressing `Ctrl+Return` (Note: this requires [Git to be installed](http://git-scm.com/) on your machine if it is not already): ```supercollider Quarks.install("FoxDot") ``` - Recompile the SuperCollider class library by going to `Language -> Recompile Class Library` or pressing `Ctrl+Shift+L` #### Startup 1. Open SuperCollider and type in `FoxDot.start` and evaluate this line. SuperCollider is now listening for messages from FoxDot. 2. Start FoxDot by entering `FoxDot` at the command line. If that doesn't work, try `python -m FoxDot`. 3. If you have installed the SC3 Plugins, use the "Code" drop-down menu to select "Use SC3 Plugins". Restart FoxDot and you'll have access to classes found in the SC3 Plugins. 4. Keep up to date with the latest verion of FoxDot by running `pip install FoxDot --upgrade` every few weeks. 5. Check out the [YouTube tutorials](https://www.youtube.com/channel/UCRyrNX07lFcfRSymZEWwl6w) for some in-depth tutorial videos on getting to grips with FoxDot #### Installing with SuperCollider 3.7 or earlier If you are having trouble installing the FoxDot Quark in SuperCollider, it is usually because the version of SuperCollider you are installing doesn’t have the functionality for installing Quarks or it doesn’t work properly. If this is the case, you can download the contents of the following SuperCollider script: [foxdot.scd](http://foxdot.org/wp-content/uploads/foxdot.scd). Once downloaded, open the file in SuperCollider and press Ctrl+Return to run it. This will make SuperCollider start listening for messages from FoxDot. #### Frequently Asked Questions You can find answers to many frequently asked questions on the [FAQ post on the FoxDot discussion forum](http://foxdot.org/forum/?view=thread&id=1). ## Basics ### Executing Code A 'block' of code in FoxDot is made up of consecutive lines of code with no empty lines. Pressing `Ctrl+Return` (or `Cmd+Return` on a Mac) will execute the block of code that the cursor is currently in. Try `print(1 + 1)` to see what happens! ### Player Objects Python supports many different programming paradigms, including procedural and functional, but FoxDot implements a traditional object orientated approach with a little bit of cheating to make it easier to live code. A player object is what FoxDot uses to make music by assigning it a synth (the 'instrument' it will play) and some instructions, such as note pitches. All one and two character variable names are reserved for player objects at startup so, by default, the variables `a`, `bd`, and `p1` are 'empty' player objects. If you use one of these variables to store something else but want to use it as a player object again, or you want to use a variable with more than two characters, you just have to reserve it by creating a `Player` and assigning it like so: ``` python p1 = Player("p1") # The string name is optional ``` To stop a Player, use the `stop` method e.g. `p1.stop()`. If you want to stop all players, you can use the command `Clock.clear()` or the keyboard short-cut `Ctrl+.`, which executes this command. Assigning synths and instructions to a player object is done using the double-arrow operator `>>`. So if you wanted to assign a synth to `p1` called 'pads' (execute `print(SynthDefs)` to see all available synths) you would use the following code: ``` python p1 >> pads([0,1,2,3]) ``` The empty player object, `p1` is now assigned a the 'pads' synth and some playback instructions. `p1` will play the first four notes of the default scale using a SuperCollider `SynthDef` with the name `\pads`. By default, each note lasts for 1 beat at 120 bpm. These defaults can be changed by specifying keyword arguments: ```python p1 >> pads([0,1,2,3], dur=[1/4,3/4], sus=1, vib=4, scale=Scale.minor) ``` The keyword arguments `dur`, `oct`, and `scale` apply to all player objects - any others, such as `vib` in the above example, refer to keyword arguments in the corresponding `SynthDef`. The first argument, `degree`, does not have to be stated explicitly. Notes can be grouped together so that they are played simultaneously using round brackets, `()`. The sequence `[(0,2,4),1,2,3]` will play the the the first harmonic triad of the default scale followed by the next three notes. ### 'Sample Player' Objects In FoxDot, sound files can be played through using a specific SynthDef called `play`. A player object that uses this SynthDef is referred to as a Sample Player object. Instead of specifying a list of numbers to generate notes, the Sample Player takes a string of characters (known as a "PlayString") as its first argument. To see a list of what samples are associated to what characters, use `print(Samples)`. To create a basic drum beat, you can execute the following line of code: ``` python d1 >> play("x-o-") ``` To have samples play simultaneously, you can create a new 'Sample Player' object for some more complex patterns. ``` python bd >> play("x( x) ") hh >> play("---[--]") sn >> play(" o ") ``` Alternatively, you can do this in one line using `<>` arrows to separate patterns you want to play together like so: ```python d1 >> play("<---[--]>< o >") ``` Or you can use `PZip`, the `zip` method, or the `&` sign to create one pattern that does this. This can be useful if you want to perform some function on individual layers later on: ``` python d1 >> play(P["x( x) "].palindrome().zip("---[--]").zip(P[" o "].amen())) # The first item must be a P[] pattern, not a string. d1 >> play(P["x( x) "].palindrome() & "---[--]" & P[" o "].amen()) ``` Grouping characters in round brackets laces the pattern so that on each play through of the sequence of samples, the next character in the group's sample is played. The sequence `(xo)---` would be played back as if it were entered `x---o---`. Using square brackets will force the enclosed samples to played in the same time span as a single character e.g. `--[--]` will play two hi-hat hits at a half beat then two at a quarter beat. You can play a random sample from a selection by using curly braces in your Play String like so: ``` python d1 >> play("x-o{-[--]o[-o]}") ``` There is now the functionality to specify the sample number for an individual sample when using the `play` SynthDef. This can be done from the play string itself by using the bar character in the form `||`. These can also be patterns created using brackets: ```python # Plays the kick drum with sample 2 but the rest with sample 0 p1 >> play("|x2|-o-") # You can use square brackets to play multiple samples p1 >> play("|x[12]| o ") # Round brackets alternate which sample is used on each loop through the sequence p1 >> play("|x(12)| o ") # Curly braces will pick a sample at random p1 >> play("|x{0123}| o ") ``` ## Scheduling Player methods You can perform actions like shuffle, mirror, and rotate on Player Objects just by calling the appropriate method. ```python bd >> play("x o xo ") # Shuffle the contents of bd bd.shuffle() ``` You can schedule these methods by calling the `every` method, which takes a list of durations (in beats), the name of the method as a string, and any other arguments. The following syntax mirrors the string of sample characters after 6 beats, then again 2 beats later and also shuffles it every 8 beats. ```python bd >> play("x-o-[xx]-o(-[oo])").every([6,2], 'mirror').every(8, 'shuffle') ``` ## Documentation [Link to documentation website](https://foxdot.org/docs/) (still in progress) ## Using alternative editors FoxDot comes pre-packaged with its own basic editor so that you don't have to tinker with config files or download any other tools but if you want to use an existing editor you can. [Koltes](https://github.com/KoltesDigital) has written a plugin for the popular Atom editor. You can install it by going to Settings -> Install -> Searching "foxdot" and pressing install on the plug in. Press Ctrl+Alt+f or go to menu -> Packages -> FoxDot -> Toggle to start FoxDot running. ## Running Python files with FoxDot code You can import `FoxDot` into your own Python programs as you would any other module. If you are not writing an interactive program, i.e. only containing FoxDot code, then you need to call a function `Go()` at the end of your program to get playback otherwise the program will terminate immediately. For example your program, `my_file.py`, should look something like this: ```python from FoxDot import * p1 >> pads([0, 1, 2, 3]) d1 >> play("x-o-") Go() ``` Then just run like any other Python program: `python my_file.py` ## Thanks - The SuperCollider development community and, of course, James McCartney, its original developer - PyOSC, Artem Baguinski et al - Members of the Live Coding community who have contributed to the project in one way or another including, but not limited to, Alex McLean, Sean Cotterill, and Dan Hett. - Big thanks to those who have used, tested, and submitted bugs, which have all helped improve FoxDot - Thank you to those who have found solutions for SuperCollider related issues, such as DavidS48 ### Samples FoxDot's audio files have been obtained from a number of sources but I've lost record of which files are attributed to which original author. Here's a list of thanks for the unknowing creators of FoxDot's sample archive. - [Legowelt Sample Kits](https://awolfe.home.xs4all.nl/samples.html) - [Game Boy Drum Kit](http://bedroomproducersblog.com/2015/04/08/game-boy-drum-kit/) - A number of sounds courtesy of Mike Hodnick's live coded album, [Expedition](https://github.com/kindohm/expedition) - Many samples have been obtained from http://freesound.org and have been placed in the public domain via the Creative Commons 0 License: http://creativecommons.org/publicdomain/zero/1.0/ - thank you to the original creators - Other samples have come from the [Dirt Sample Engine](https://github.com/tidalcycles/Dirt-Samples/tree/c2db9a0dc4ffb911febc613cdb9726cae5175223) which is part of the TidalCycles live coding language created by Yaxu - another huge amount of thanks. If you feel I've used a sample where I shouldn't have, please get in touch! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/README.md0000644000175100001770000003003414611211152014741 0ustar00runnerdockerRenardo v0.9 - FoxDot fork =========================== Renardo/FoxDot is a Python programming environment that provides a fast and user-friendly abstraction to SuperCollider. It also comes with its own IDE, which means it can be used straight out of the box; all you need is Python and SuperCollider and you're ready to go! ## Important If you are having trouble installing using `pip install FoxDot`, try updating Python's `setuptools` and `wheel` libraries using the following code and trying again. ``` pip install -U setuptools pip install -U wheel ``` ### v0.8 Updates - Added `stretch` synth for timestretching samples, similar to `loop` but better and only plays the whole file. Stretches the audio's duration to the `sus` attribute without affecting pitch and does not require the tempo to be known. ```python # Stretches the audio to 4 beats without affecting pitch p1 >> stretch("Basic_Rock_135", dur=4) ``` --- ## Installation and startup #### Prerequisites - [Python 2 or 3](https://www.python.org/) - add Python to your path and install "pip" when prompted during the install. - [SuperCollider 3.8 and above](http://supercollider.github.io/download) - [Tkinter](https://tkdocs.com/tutorial/install.html) - Usually packaged with Python but Linux and MacOS users may need to install using: ```bash $ sudo apt-get install python3-tk (Linux) $ sudo port install py-tkinter (MacOS) ``` #### Recommended - [sc3 plugins](http://sc3-plugins.sourceforge.net/) #### Installing FoxDot - Open up a command prompt and type `pip install --user FoxDot`. This will download and install the latest stable version of FoxDot from the Python Package Index if you have properly configured Python. - You can update FoxDot to the latest version if it's already installed by adding `-U` or `--upgrade` flag to this command. - Alternatively, you can build from source from directly from this repository: ``` bash $ git clone https://github.com/Qirky/FoxDot.git $ cd FoxDot $ python setup.py install ``` - Open SuperCollder and install the FoxDot Quark and its dependencies (this allows FoxDot to communicate with SuperCollider) by entering the following and pressing `Ctrl+Return` (Note: this requires [Git to be installed](http://git-scm.com/) on your machine if it is not already): ```supercollider Quarks.install("FoxDot") ``` - Recompile the SuperCollider class library by going to `Language -> Recompile Class Library` or pressing `Ctrl+Shift+L` #### Startup 1. Open SuperCollider and type in `FoxDot.start` and evaluate this line. SuperCollider is now listening for messages from FoxDot. 2. Start FoxDot by entering `FoxDot` at the command line. If that doesn't work, try `python -m FoxDot`. 3. If you have installed the SC3 Plugins, use the "Code" drop-down menu to select "Use SC3 Plugins". Restart FoxDot and you'll have access to classes found in the SC3 Plugins. 4. Keep up to date with the latest verion of FoxDot by running `pip install FoxDot --upgrade` every few weeks. 5. Check out the [YouTube tutorials](https://www.youtube.com/channel/UCRyrNX07lFcfRSymZEWwl6w) for some in-depth tutorial videos on getting to grips with FoxDot #### Installing with SuperCollider 3.7 or earlier If you are having trouble installing the FoxDot Quark in SuperCollider, it is usually because the version of SuperCollider you are installing doesn’t have the functionality for installing Quarks or it doesn’t work properly. If this is the case, you can download the contents of the following SuperCollider script: [foxdot.scd](http://foxdot.org/wp-content/uploads/foxdot.scd). Once downloaded, open the file in SuperCollider and press Ctrl+Return to run it. This will make SuperCollider start listening for messages from FoxDot. #### Frequently Asked Questions You can find answers to many frequently asked questions on the [FAQ post on the FoxDot discussion forum](http://foxdot.org/forum/?view=thread&id=1). ## Basics ### Executing Code A 'block' of code in FoxDot is made up of consecutive lines of code with no empty lines. Pressing `Ctrl+Return` (or `Cmd+Return` on a Mac) will execute the block of code that the cursor is currently in. Try `print(1 + 1)` to see what happens! ### Player Objects Python supports many different programming paradigms, including procedural and functional, but FoxDot implements a traditional object orientated approach with a little bit of cheating to make it easier to live code. A player object is what FoxDot uses to make music by assigning it a synth (the 'instrument' it will play) and some instructions, such as note pitches. All one and two character variable names are reserved for player objects at startup so, by default, the variables `a`, `bd`, and `p1` are 'empty' player objects. If you use one of these variables to store something else but want to use it as a player object again, or you want to use a variable with more than two characters, you just have to reserve it by creating a `Player` and assigning it like so: ``` python p1 = Player("p1") # The string name is optional ``` To stop a Player, use the `stop` method e.g. `p1.stop()`. If you want to stop all players, you can use the command `Clock.clear()` or the keyboard short-cut `Ctrl+.`, which executes this command. Assigning synths and instructions to a player object is done using the double-arrow operator `>>`. So if you wanted to assign a synth to `p1` called 'pads' (execute `print(SynthDefs)` to see all available synths) you would use the following code: ``` python p1 >> pads([0,1,2,3]) ``` The empty player object, `p1` is now assigned a the 'pads' synth and some playback instructions. `p1` will play the first four notes of the default scale using a SuperCollider `SynthDef` with the name `\pads`. By default, each note lasts for 1 beat at 120 bpm. These defaults can be changed by specifying keyword arguments: ```python p1 >> pads([0,1,2,3], dur=[1/4,3/4], sus=1, vib=4, scale=Scale.minor) ``` The keyword arguments `dur`, `oct`, and `scale` apply to all player objects - any others, such as `vib` in the above example, refer to keyword arguments in the corresponding `SynthDef`. The first argument, `degree`, does not have to be stated explicitly. Notes can be grouped together so that they are played simultaneously using round brackets, `()`. The sequence `[(0,2,4),1,2,3]` will play the the the first harmonic triad of the default scale followed by the next three notes. ### 'Sample Player' Objects In FoxDot, sound files can be played through using a specific SynthDef called `play`. A player object that uses this SynthDef is referred to as a Sample Player object. Instead of specifying a list of numbers to generate notes, the Sample Player takes a string of characters (known as a "PlayString") as its first argument. To see a list of what samples are associated to what characters, use `print(Samples)`. To create a basic drum beat, you can execute the following line of code: ``` python d1 >> play("x-o-") ``` To have samples play simultaneously, you can create a new 'Sample Player' object for some more complex patterns. ``` python bd >> play("x( x) ") hh >> play("---[--]") sn >> play(" o ") ``` Alternatively, you can do this in one line using `<>` arrows to separate patterns you want to play together like so: ```python d1 >> play("<---[--]>< o >") ``` Or you can use `PZip`, the `zip` method, or the `&` sign to create one pattern that does this. This can be useful if you want to perform some function on individual layers later on: ``` python d1 >> play(P["x( x) "].palindrome().zip("---[--]").zip(P[" o "].amen())) # The first item must be a P[] pattern, not a string. d1 >> play(P["x( x) "].palindrome() & "---[--]" & P[" o "].amen()) ``` Grouping characters in round brackets laces the pattern so that on each play through of the sequence of samples, the next character in the group's sample is played. The sequence `(xo)---` would be played back as if it were entered `x---o---`. Using square brackets will force the enclosed samples to played in the same time span as a single character e.g. `--[--]` will play two hi-hat hits at a half beat then two at a quarter beat. You can play a random sample from a selection by using curly braces in your Play String like so: ``` python d1 >> play("x-o{-[--]o[-o]}") ``` There is now the functionality to specify the sample number for an individual sample when using the `play` SynthDef. This can be done from the play string itself by using the bar character in the form `||`. These can also be patterns created using brackets: ```python # Plays the kick drum with sample 2 but the rest with sample 0 p1 >> play("|x2|-o-") # You can use square brackets to play multiple samples p1 >> play("|x[12]| o ") # Round brackets alternate which sample is used on each loop through the sequence p1 >> play("|x(12)| o ") # Curly braces will pick a sample at random p1 >> play("|x{0123}| o ") ``` ## Scheduling Player methods You can perform actions like shuffle, mirror, and rotate on Player Objects just by calling the appropriate method. ```python bd >> play("x o xo ") # Shuffle the contents of bd bd.shuffle() ``` You can schedule these methods by calling the `every` method, which takes a list of durations (in beats), the name of the method as a string, and any other arguments. The following syntax mirrors the string of sample characters after 6 beats, then again 2 beats later and also shuffles it every 8 beats. ```python bd >> play("x-o-[xx]-o(-[oo])").every([6,2], 'mirror').every(8, 'shuffle') ``` ## Documentation [Link to documentation website](https://foxdot.org/docs/) (still in progress) ## Using alternative editors FoxDot comes pre-packaged with its own basic editor so that you don't have to tinker with config files or download any other tools but if you want to use an existing editor you can. [Koltes](https://github.com/KoltesDigital) has written a plugin for the popular Atom editor. You can install it by going to Settings -> Install -> Searching "foxdot" and pressing install on the plug in. Press Ctrl+Alt+f or go to menu -> Packages -> FoxDot -> Toggle to start FoxDot running. ## Running Python files with FoxDot code You can import `FoxDot` into your own Python programs as you would any other module. If you are not writing an interactive program, i.e. only containing FoxDot code, then you need to call a function `Go()` at the end of your program to get playback otherwise the program will terminate immediately. For example your program, `my_file.py`, should look something like this: ```python from FoxDot import * p1 >> pads([0, 1, 2, 3]) d1 >> play("x-o-") Go() ``` Then just run like any other Python program: `python my_file.py` ## Thanks - The SuperCollider development community and, of course, James McCartney, its original developer - PyOSC, Artem Baguinski et al - Members of the Live Coding community who have contributed to the project in one way or another including, but not limited to, Alex McLean, Sean Cotterill, and Dan Hett. - Big thanks to those who have used, tested, and submitted bugs, which have all helped improve FoxDot - Thank you to those who have found solutions for SuperCollider related issues, such as DavidS48 ### Samples FoxDot's audio files have been obtained from a number of sources but I've lost record of which files are attributed to which original author. Here's a list of thanks for the unknowing creators of FoxDot's sample archive. - [Legowelt Sample Kits](https://awolfe.home.xs4all.nl/samples.html) - [Game Boy Drum Kit](http://bedroomproducersblog.com/2015/04/08/game-boy-drum-kit/) - A number of sounds courtesy of Mike Hodnick's live coded album, [Expedition](https://github.com/kindohm/expedition) - Many samples have been obtained from http://freesound.org and have been placed in the public domain via the Creative Commons 0 License: http://creativecommons.org/publicdomain/zero/1.0/ - thank you to the original creators - Other samples have come from the [Dirt Sample Engine](https://github.com/tidalcycles/Dirt-Samples/tree/c2db9a0dc4ffb911febc613cdb9726cae5175223) which is part of the TidalCycles live coding language created by Yaxu - another huge amount of thanks. If you feel I've used a sample where I shouldn't have, please get in touch! ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5715406 renardo_lib-0.9.12/renardo_lib/0000755000175100001770000000000014611211157015747 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Bang.py0000644000175100001770000000472014611211152017166 0ustar00runnerdocker""" This is an experimental module that contains the `Bang` class; events that are triggered in time with `Player` rhythms to give visual aid to which players are creating which sounds. """ from time import time, sleep from threading import Thread from renardo_lib.Code import execute class Bang: duration = 0.1 def __init__(self, player, kwargs): self.widget = execute.namespace['FoxDot'] self.func = kwargs.get("func", None) # Argument is by default, the player self.args = kwargs.get("args", (player,)) # User can supply a function to call on bang if self.func: try: self.func.__call__(*self.args) except Exception as e: print(e) else: # Get visible portion of the text window try: a = self.widget.text.index("@0,0") b = self.widget.text.index("@0,%d" % self.widget.text.winfo_height()) a, b = (int(s.split(".")[0]) for s in (a, b)) except: a, b = 9999, 0 # Only update visuals if the line is visible if player.line_number is None: return if a <= player.line_number <= b: row = player.line_number col = player.whitespace env = player.envelope clock = player.metro duration = clock.beat_dur( player.dur / 2 ) # message_time = player.queue_block.time message_time = player.get_timestamp(player.queue_block.beat) # clock.latency self.id = "{}_bang".format(player.id) start = "%d.%d" % (row, col) end = "%d.end" % row def bang(): # wait until the time osc messages are sent while time() < message_time: sleep(0.001) self.widget.addTask(target=self.widget.text.tag_add, args=(self.id, start, end)) self.widget.addTask(target=self.widget.text.tag_config, args=(self.id,), kwargs=kwargs) self.widget.root.after(int(1000 * duration), self.remove) return Thread(target=bang).start() return def remove(self): self.widget.addTask(target=self.widget.text.tag_delete, args=(self.id,)) return ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Buffers.py0000644000175100001770000004321514611211152017715 0ustar00runnerdocker""" This module manages the allocation of buffer numbers and samples. To see a list of descriptions of what sounds are mapped to what characters, simply evaluate print(Samples) Future: Aiming on being able to set individual sample banks for different players that can be proggrammed into performance. """ import fnmatch import os import wave from contextlib import closing from itertools import chain from os.path import abspath, join, isabs, isfile, isdir, splitext from renardo_lib import spack_manager from renardo_lib.Code import WarningMsg from renardo_lib.Logging import Timing from renardo_lib.SCLang import SampleSynthDef from renardo_lib.ServerManager import Server from renardo_lib.Settings import SAMPLES_PACK_NUMBER alpha = "abcdefghijklmnopqrstuvwxyz" DESCRIPTIONS = { 'a' : "Gameboy hihat", 'A' : "Gameboy kick drum", 'b' : "Noisy beep", 'B' : "Short saw", 'c' : "Voice/string", 'C' : "Choral", 'd' : "Woodblock", 'D' : "Dirty snare", 'e' : "Electronic Cowbell", 'E' : "Ringing percussion", 'f' : "Pops", 'F' : "Trumpet stabs", 'g' : "Ominous", 'G' : "Ambient stabs", 'h' : "Finger snaps", 'H' : "Clap", 'i' : "Jungle snare", 'I' : "Rock snare", 'j' : "Whines", 'J' : "Ambient stabs", 'k' : "Wood shaker", 'K' : "Percussive hits", 'l' : "Robot noise", 'L' : "Noisy percussive hits", 'm' : "808 toms", 'M' : "Acoustic toms", 'n' : "Noise", 'N' : "Gameboy SFX", 'o' : "Snare drum", 'O' : "Heavy snare", 'p' : "Tabla", 'P' : "Tabla long", 'q' : "Ambient stabs", 'Q' : "Electronic stabs", 'r' : "Metal", 'R' : "Metallic", 's' : "Shaker", 'S' : "Tamborine", 't' : "Rimshot", 'T' : "Cowbell", 'u' : "Soft snare", 'U' : "Misc. Fx", 'v' : "Soft kick", 'V' : "Hard kick", 'w' : "Dub hits", 'W' : "Distorted", 'x' : "Bass drum", 'X' : "Heavy kick", 'y' : "Percussive hits", 'Y' : "High buzz", 'z' : "Scratch", "Z" : "Loud stabs", '-' : "Hi hat closed", "|" : "Hangdrum", '=' : "Hi hat open", "/" : "Reverse sounds", '*' : "Clap", "\\" : "Lazer", '~' : "Ride cymbal", "%" : "Noise bursts", '^' : "'Donk'", "$" : "Beatbox", '#' : "Crash", "!" : "Yeah!", '+' : "Clicks", "&" : "Chime", '@' : "Gameboy noise", ":" : "Hi-hats", '1' : "Vocals (One)", '2' : 'Vocals (Two)', '3' : 'Vocals (Three)', '4' : 'Vocals (Four)'} # class _get_sample_path_from_symbol: # '''Function-like (singleton pattern) class to search the directory for a sample # file based on input symbol''' # def __init__(self, samples_directory, _): # if os.path.isdir(samples_directory): # self.samples_directory = os.path.realpath(samples_directory) # else: # raise OSError("{!r} is not a valid directory".format(samples_directory)) # def __call__(self, symbol, samples_pack): # """ Return the sample search directory for a symbol """ # samples_pack = ( # spack_manager.get_spack_from_num(samples_pack) if isinstance(samples_pack, int) # else samples_pack # ) # sample_path = None # if symbol.isalpha(): # low_up_dirname = 'upper' if symbol.isupper() else 'lower' # samples_path = samples_pack.path / symbol.lower() / low_up_dirname # elif symbol in nonalpha: # longname = nonalpha[symbol] # samples_path = samples_pack.path / '_' / longname # return sample_path # # get_sample_path_from_symbol = _get_sample_path_from_symbol(FOXDOT_SND, SAMPLES_PACK_NUMBER) # singleton class Buffer(object): def __init__(self, fn, number, channels=1): self.fn = fn self.bufnum = int(number) self.channels = channels def __repr__(self): return "".format(self.bufnum) def __int__(self): return self.bufnum @classmethod def fromFile(cls, filename, number): try: with closing(wave.open(filename)) as snd: numChannels = snd.getnchannels() except wave.Error: numChannels = 1 return cls(filename, number, numChannels) nil = Buffer('', 0) class BufferManager(object): def __init__(self, server=Server, paths=[]): self._server = server self._max_buffers = server.max_buffers # Keep buffer 0 unallocated because we use it as the "nil" buffer self._nextbuf = 1 self._buffers = [None for _ in range(self._max_buffers)] self._fn_to_buf = {} self._paths = [spack_manager.default_spack().loop_path] + list(paths) self._ext = ['wav', 'wave', 'aif', 'aiff', 'flac'] self.loops = [ sample_path.with_suffix('').name #file name without extension for sample_path in spack_manager.default_spack().loop_path.iterdir() ] def __str__(self): return "\n".join(["%r: %s" % (k, v) for k, v in sorted(DESCRIPTIONS.items())]) def __repr__(self): return '' def __getitem__(self, key): """ Short-hand access for getBufferFromSymbol() i.e. Samples['x'] """ if isinstance(key, tuple): return self.getBufferFromSymbol(*key) return self.getBufferFromSymbol(key) def _reset_buffers(self): """ Clears the cache of loaded buffers """ files = list(self._fn_to_buf.keys()) self._fn_to_buf = {} for fn in files: self.loadBuffer(fn) return def reset(self): return self._reset_buffers() def _incr_nextbuf(self): self._nextbuf += 1 if self._nextbuf >= self._max_buffers: self._nextbuf = 1 def _getNextBufnum(self): """ Get the next free buffer number """ start = self._nextbuf while self._buffers[self._nextbuf] is not None: self._incr_nextbuf() if self._nextbuf == start: raise RuntimeError("Buffers full! Cannot allocate additional buffers.") freebuf = self._nextbuf self._incr_nextbuf() return freebuf def addAPath(self, path): """ Add a path to the search paths for samples """ self._paths.append(abspath(path)) def free(self, filenameOrBuf): """ Free a buffer. Accepts a filename or buffer number """ if isinstance(filenameOrBuf, int): buf = self._buffers[filenameOrBuf] else: buf = self._fn_to_buf[filenameOrBuf] del self._fn_to_buf[buf.fn] self._buffers[buf.bufnum] = None self._server.bufferFree(buf.bufnum) def freeAll(self): """ Free all buffers """ buffers = list(self._fn_to_buf.values()) for buf in buffers: self.free(buf.bufnum) def setMaxBuffers(self, max_buffers): """ Set the max buffers on the SC server """ if max_buffers < self._max_buffers: if any(self._buffers[max_buffers:]): raise RuntimeError( "Cannot shrink buffer size. Buffers already allocated." ) self._buffers = self._buffers[:max_buffers] elif max_buffers > self._max_buffers: while len(self._buffers) < max_buffers: self._buffers.append(None) self._max_buffers = max_buffers self._nextbuf = self._nextbuf % max_buffers def getBufferFromSymbol(self, symbol, spack, index=0): """ Get buffer information from a symbol """ if symbol.isspace(): return nil sample_path = spack_manager.get_spack(spack).sample_path_from_symbol(symbol) if sample_path is None: return nil sample_path = self._findSample(sample_path, index) if sample_path is None: return nil return self._allocateAndLoad(sample_path) def getBuffer(self, bufnum): """ Get buffer information from the buffer number """ return self._buffers[bufnum] def _allocateAndLoad(self, filename, force=False): """ Allocates and loads a buffer from a filename, with caching """ if filename not in self._fn_to_buf: bufnum = self._getNextBufnum() buf = Buffer.fromFile(filename, bufnum) self._server.bufferRead(filename, bufnum) self._fn_to_buf[filename] = buf self._buffers[bufnum] = buf elif force: buf = self._fn_to_buf[filename] self._server.bufferRead(filename, buf.bufnum) # self._fn_to_buf[filename] = bufnum # self._buffers[bufnum] = buf return self._fn_to_buf[filename] def reload(self, filename): # symbol = self.getBufferFrom return self.loadBuffer(filename, force=True) def _getSoundFile(self, filename): """ Look for a file with all possible extensions """ base, cur_ext = splitext(filename) if cur_ext: # If the filename already has an extensions, keep it if isfile(filename): return filename else: # Otherwise, look for all possible extensions for ext in self._ext: # Look for .wav and .WAV for tryext in [ext, ext.upper()]: extpath = filename + '.' + tryext if isfile(extpath): return extpath return None def _getSoundFileOrDir(self, filename): """ Get a matching sound file or directory """ if isdir(filename): return abspath(filename) foundfile = self._getSoundFile(filename) if foundfile: return abspath(foundfile) return None def _searchPaths(self, filename): """ Search our search paths for an audio file or directory """ if isabs(filename): return self._getSoundFileOrDir(filename) else: for root in self._paths: fullpath = join(root, filename) foundfile = self._getSoundFileOrDir(fullpath) if foundfile: return foundfile return None def _getFileInDir(self, dirname, index): """ Return nth sample in a directory """ candidates = [] for filename in sorted(os.listdir(dirname)): name, ext = splitext(filename) if 'Placeholder' in name: continue if ext.lower()[1:] in self._ext: fullpath = join(dirname, filename) if len(candidates) == index: return fullpath candidates.append(fullpath) if candidates: return candidates[int(index) % len(candidates)] return None def _patternSearch(self, filename, index): """ Return nth sample that matches a path pattern Path pattern is a relative path that can contain wildcards such as * and ? (see fnmatch for more details). Some example paths: samp* **/voices/* perc*/bass* """ def _findNextSubpaths(path, pattern): """ For a path pattern, find all subpaths that match """ # ** is a special case meaning "all recursive directories" if pattern == '**': for dirpath, _, _ in os.walk(path): yield dirpath else: children = os.listdir(path) for c in fnmatch.filter(children, pattern): yield join(path, c) candidates = [] queue = self._paths[:] subpaths = filename.split(os.sep) filepat = subpaths.pop() while subpaths: subpath = subpaths.pop(0) queue = list(chain.from_iterable( (_findNextSubpaths(p, subpath) for p in queue) )) # If the filepat (ex. 'foo*.wav') has an extension, we want to match # the full filename. If not, we just match against the basename. match_base = not hasext(filepat) for path in queue: for subpath, _, filenames in os.walk(path): for filename in sorted(filenames): basename, ext = splitext(filename) if ext[1:].lower() not in self._ext: continue if match_base: ismatch = fnmatch.fnmatch(basename, filepat) else: ismatch = fnmatch.fnmatch(filename, filepat) if ismatch: fullpath = join(subpath, filename) if len(candidates) == index: return fullpath candidates.append(fullpath) if candidates: return candidates[index % len(candidates)] return None @Timing('bufferSearch', logargs=True) def _findSample(self, filename, index=0): """ Find a sample from a filename or pattern Will first attempt to find an exact match (by abspath or relative to the search paths). Then will attempt to pattern match in search paths. """ path = self._searchPaths(filename) if path: # If it's a file, use that sample if isfile(path): return path # If it's a dir, use one of the samples in that dir elif isdir(path): foundfile = self._getFileInDir(path, index) if foundfile: return foundfile else: WarningMsg("No sound files in %r" % path) return None else: WarningMsg("File %r is neither a file nor a directory" % path) return None else: # If we couldn't find a dir or file with this name, then we use it # as a pattern and recursively walk our paths foundfile = self._patternSearch(filename, index) if foundfile: return foundfile WarningMsg("Could not find any sample matching %r" % filename) return None def loadBuffer(self, filename, index=0, force=False): """ Load a sample and return the number of a buffer """ samplepath = self._findSample(filename, index) if samplepath is None: return 0 else: buf = self._allocateAndLoad(samplepath, force=force) return buf.bufnum def hasext(filename): return bool(splitext(filename)[1]) Samples = BufferManager() class LoopSynthDef(SampleSynthDef): def __init__(self): SampleSynthDef.__init__(self, "loop") self.pos = self.new_attr_instance("pos") self.sample = self.new_attr_instance("sample") self.spack = self.new_attr_instance("spack") self.beat_stretch = self.new_attr_instance("beat_stretch") self.defaults['pos'] = 0 self.defaults['sample'] = 0 self.defaults['spack'] = SAMPLES_PACK_NUMBER self.defaults['beat_stretch'] = 0 self.base.append("rate = (rate * (1-(beat_stretch>0))) + ((BufDur.kr(buf) / sus) * (beat_stretch>0));") self.base.append("osc = PlayBuf.ar(2, buf, BufRateScale.kr(buf) * rate, startPos: BufSampleRate.kr(buf) * pos, loop: 1.0);") self.base.append("osc = osc * EnvGen.ar(Env([0,1,1,0],[0.05, sus-0.05, 0.05]));") self.osc = self.osc * self.amp self.add() def __call__(self, filename, pos=0, sample=0, **kwargs): kwargs["buf"] = Samples.loadBuffer(filename, sample) proxy = SampleSynthDef.__call__(self, pos, **kwargs) proxy.kwargs["filename"] = filename return proxy class StretchSynthDef(SampleSynthDef): def __init__(self): SampleSynthDef.__init__(self, "stretch") self.base.append("osc = Warp1.ar(2, buf, Line.kr(0,1,sus), rate, windowSize: 0.2, overlaps: 4, interp:2);") self.base.append("osc = osc * EnvGen.ar(Env([0,1,1,0],[0.05, sus-0.05, 0.05]));") self.osc = self.osc * self.amp self.add() def __call__(self, filename, pos=0, sample=0, **kwargs): kwargs["buf"] = Samples.loadBuffer(filename, sample) proxy = SampleSynthDef.__call__(self, pos, **kwargs) proxy.kwargs["filename"] = filename return proxy class GranularSynthDef(SampleSynthDef): def __init__(self): SampleSynthDef.__init__(self, "gsynth") self.pos = self.new_attr_instance("pos") self.sample = self.new_attr_instance("sample") self.defaults['pos'] = 0 self.defaults['sample'] = 0 self.defaults['spack'] = SAMPLES_PACK_NUMBER self.base.append("osc = PlayBuf.ar(2, buf, BufRateScale.kr(buf) * rate, startPos: BufSampleRate.kr(buf) * pos);") self.base.append("osc = osc * EnvGen.ar(Env([0,1,1,0],[0.05, sus-0.05, 0.05]));") self.osc = self.osc * self.amp self.add() def __call__(self, filename, pos=0, sample=0, **kwargs): kwargs["buf"] = Samples.loadBuffer(filename, sample) return SampleSynthDef.__call__(self, pos, **kwargs) loop = LoopSynthDef() stretch = StretchSynthDef() # gsynth = GranularSynthDef()././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Chords.py0000644000175100001770000000061314611211152017536 0ustar00runnerdockerfrom renardo_lib.Patterns import PGroup I = PGroup(0, 2, 4) II = PGroup(1, 3, 5) III = PGroup(2, 4,-1) IV = PGroup(3, 5, 0) V = PGroup(4,-1, 1) VI = PGroup(5, 0, 2) VII = PGroup(-1,1, 3) I7 = PGroup(I).concat(6) II7 = PGroup(II).concat(7) III7 = PGroup(III).concat(8) IV7 = PGroup(IV).concat(9) V7 = PGroup(V).concat(10) VI7 = PGroup(VI).concat(11) VII7 = PGroup(VII).concat(12) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5715406 renardo_lib-0.9.12/renardo_lib/Code/0000755000175100001770000000000014611211157016621 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Code/__init__.py0000644000175100001770000000024014611211152020721 0ustar00runnerdockerfrom renardo_lib.Code.main_lib import * from renardo_lib.Code.foxdot_live_function import livefunction from renardo_lib.Code.foxdot_when_statement import when ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Code/foxdot_func_cmp.py0000644000175100001770000000126414611211152022346 0ustar00runnerdocker""" compare_functions.py(funcA, funcB): returns True if the functions are identical """ def func_cmp(funcA, funcB): codeA = funcA.__code__ A_bytecode = codeA.co_code A_constants = codeA.co_consts A_variables = codeA.co_names codeB = funcB.__code__ B_bytecode = codeB.co_code B_constants = codeB.co_consts B_variables = codeB.co_names return all([A_bytecode == B_bytecode, A_constants == B_constants, A_variables == B_variables]) def func_str(func): """ Returns a function as a string """ code = func.__code__ return ",".join([func.__name__, str(code.co_names), str(code.co_consts)]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Code/foxdot_live_function.py0000644000175100001770000000273414611211152023423 0ustar00runnerdocker""" Allows you continually update a function """ # TODO: dependencies _live_functions_dict = {} class _live_function: def __init__(self, func, dependency=None): self.func = func self.name = func.__name__ self.live = False self.dependency = dependency def __call__(self, *args, **kwargs): self.live = True if isinstance(self.dependency, self.__class__): self.dependency.live = False return self.func.__call__(*args, **kwargs) def update(self, func, dependency=None): self.func = func if dependency: self.dependency = dependency return def livefunction(f, dependency=None): """ Wraps a function 'f' in a flexible/interactive way """ # Live functions can "depend" on others for switching from live or not if dependency in _live_functions_dict: dependenct = _live_functions_dict[dependency.__name__] # Add / update a dictionary of all live functions if f.__name__ not in _live_functions_dict: _live_functions_dict[f.__name__] = _live_function(f, dependency) else: _live_functions_dict[f.__name__].update(f, dependency) f = _live_functions_dict[f.__name__] # If the function is "live" call it if f.live: f.__call__() return f if __name__ == "__main__": # debug @livefunction def part1(): return 10 @livefunction def part2(): return 20 part1() print(part1.__class__) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Code/foxdot_tokenize.py0000644000175100001770000001254614611211152022411 0ustar00runnerdocker##''' ## Code to allow Python files written in FoxDot to account for the "when" ## statements. These files are given a header of `# coding: FoxDot` and ## should then be automatically tokenized. ## ## Source: http://stackoverflow.com/questions/214881/can-you-add-new-statements-to-pythons-syntax ## ##''' ## ##try: ## import new ##except ImportError: ## from types import ModuleType ## new = ModuleType ## ##import tokenize ##import codecs, cStringIO, encodings ##from encodings import utf_8 ## ##def read(file): ## ''' Converts a file-like object into FoxDot code ''' ## return tokenize.untokenize(translate(file.readline)) ## ##def translate(readline): ## ''' Searches for any FoxDot syntax (currently only when statements) ''' ## tokens = [] ## startline = 0 ## thisline = 0 ## compiling = False ## justcompiled = False ## ## expr = False # If we have defined the expression ## do = False # If we have defined the do method ## elsedo = False # If we have defined the elsedo method ## ## dedent = False ## indent = False ## ## # Iterate through all of the tokens in a file ## for type, name, start, end, line in tokenize.generate_tokens(readline): ## ## if compiling: ## ## if start[0] == startline and not expr: ## ## # Get the rest of the statement ## ## tokens.insert(-1, (tokenize.STRING, ## line.strip().replace('when', '').replace(':',''))) ## ## tokens.append((tokenize.OP, '.')) ## tokens.append((tokenize.NAME, 'do')) ## tokens.append((tokenize.OP, '(')) ## tokens.append((tokenize.OP, ')')) ## ## # We have define the expression ## ## expr = True ## ## # New line in the statement ## ## elif start[0] > thisline: ## ## thisline = start[0] ## ## if type == tokenize.INDENT: ## ## indent = True ## dedent = False ## ## elif type == tokenize.DEDENT: ## ## dedent = True ## indent = False ## ## # Add line that have been indented ## ## if indent == True: ## ## # We have the right bracket already, so insert before ## ## if line.strip() != "": ## ## tokens.insert(-1, (tokenize.STRING, repr(line.strip()))) ## tokens.insert(-1, (tokenize.OP, ',')) ## ## # We've gone back an indendatoin level ## ## elif dedent == True: ## ## if type == tokenize.NAME and name == 'else': ## ## tokens.append((tokenize.OP, '.')) ## tokens.append((tokenize.NAME, 'elsedo')) ## tokens.append((tokenize.OP, '(')) ## tokens.append((tokenize.OP, ')')) ## ## elsedo = True ## dedent = False ## ## else: ## ## dedent = False ## compiling = False ## ## # We've now exited the when statement. ## ## tokens.append((tokenize.NEWLINE, '\n')) ## tokens.append((tokenize.NL, '\n')) ## tokens.append((type, name)) ## ## for token, name in tokens: ## ## yield token, name ## ## tokens = [] ## ## else: ## ## # If we have a when statement, start to compile ## if type ==tokenize.NAME and name =='when': ## ## tokens.append((tokenize.NAME, '__when__')) ## tokens.append((tokenize.OP, '(')) ## tokens.append((tokenize.NAME, 'lambda')) ## tokens.append((tokenize.OP, ':')) ## tokens.append((tokenize.OP, ')')) ## ## compiling = True ## ## thisline = startline = start[0] ## ## else: ## ## yield type, name ## ##def _test(filename): ## ''' Prints out the converted contents of a file ''' ## f = open(filename) ## data = tokenize.untokenize(translate(f.readline)) ## f.close() ## print(data) ## ##def _import(filename): ## ''' Returns a 'translated' version of a Python file into FoxDot as a module ''' ## mod = new.module(filename) ## f = open(filename) ## data = tokenize.untokenize(translate(f.readline)) ## exec(data, mod.__dict__) ## return mod ## ##class StreamReader(utf_8.StreamReader): ## def __init__(self, *args, **kwargs): ## codecs.StreamReader.__init__(self, *args, **kwargs) ## data = tokenize.untokenize(translate(self.stream.readline)) ## self.stream = cStringIO.StringIO(data) ## ##def search_function(s): ## ''' Allows "FoxDot" files to be imported properly ''' ## if s!='foxdot': return None ## utf8=encodings.search_function('utf8') # Assume utf8 encoding ## return codecs.CodecInfo( ## name='foxdot', ## encode = utf8.encode, ## decode = utf8.decode, ## incrementalencoder=utf8.incrementalencoder, ## incrementaldecoder=utf8.incrementaldecoder, ## streamreader=StreamReader, ## streamwriter=utf8.streamwriter) ## ##codecs.register(search_function) ## ##if __name__ == "__main__": ## ## _test("test.py") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Code/foxdot_when_statement.py0000644000175100001770000001310314611211152023574 0ustar00runnerdocker""" How to use `when` statements ---------------------------- A `when` statement is similar to your traditional `if` statement but instead of evaluating the expression at the time the code is run, it is constantly testing it to see if it is true.abs Example 1 --------- :: when 5 < 10: print True else: print False Currently there is no `elif` statement implemented yet and lines of code cannot be spread over multiple lines. To "stop" an individual `when` statement from monitoring its test. You need to call the `__when__` object with a `lambda` expression equalling that of the test and call the `remove` method. Example 2 --------- :: a, b = 5, 10 when a > b: print "a is bigger" else: print "b is bigger" # This is how to 'stop' the statement above __when__(lambda: a > b).remove() # This removes *all* currently running when statements __when__.reset() """ from renardo_lib.Code.foxdot_func_cmp import * from threading import Thread from time import sleep class _whenStatement: namespace = {} def __init__(self, func=lambda: True): self.expr = func self.reset() self.remove_me = False def __repr__(self): return func_str(self.expr) def __enter__(self): when.editing = self return self def __exit__(self, *args): when.editing = None return self @classmethod def set_namespace(cls, ns): ''' Define the namespace to execute the actions. Should be a `dict` ''' cls.namespace = ns def reset(self): ''' Sets the `when` and `else` actions to nothing ''' self.action = lambda: None self.notaction = lambda: None self.do_switch = False self.elsedo_switch = False def evaluate(self): ''' Calls the test expression, and if it has changed then run the appropriate response code ''' if self.expr(): if not self.do_switch: self.action() self.toggle_live_functions(True) self.do_switch = True self.elsedo_switch = False else: if not self.elsedo_switch: self.notaction() self.toggle_live_functions(False) self.do_switch = False self.elsedo_switch = True def toggle_live_functions(self, switch): """ If the action functions are @livefunctions, turn them on/off """ try: self.action.live = switch except: pass try: self.notaction.live = (not switch) except: pass return def when(self, func): self.expr = func return self def then(self, func): ''' Set the instructions for when the test expression is True. Should be a list of strings. ''' self.action = func return self def elsedo(self, func): ''' Set the instructions for when the test expression is False. Should be a list of strings. ''' self.notaction = func return self def stop(self): self.reset() return self def remove(self): self.reset() self.remove_me = True return self class _whenLibrary: """ Used to store 'when statements'. Is accessed through the `__when__` object. """ def __init__(self): self.library = {} self.editing = None def start_thread(self): self.thread = Thread(target=self.run) self.thread.daemon = True self.thread.start() @staticmethod def set_namespace(env): _whenStatement.set_namespace(env.namespace) def __len__(self): return len(self.library) def __repr__(self): return repr(self.library) def run(self): """ Continual loop evaluating when_statements """ while len(self.library) > 0: for name, expression in self.library.items(): if expression.remove_me == True: del self.library[name] else: expression.evaluate() sleep(0.01) return def __call__(self, name, **kwargs): """ Calling when() with no arguments will evaluate all expressions stored in self.library. Calling with func as a valid function will see if the function is in self.library and add it if not, or update do / elsedo """ if name in self.library: return self.library[name] else: # Make a new statement self.library[name] = _whenStatement() # If that is the first statement, start the thread if len(self.library) == 1: self.start_thread() # Return the last added expression return self.library[name] # what do these do? def a(self, expr): if self.editing is not None: self.editing.when(expr) return None def b(self, expr): if self.editing is not None: self.editing.do(expr) return None def c(self, expr): if self.editing is not None: self.editing.elsedo(expr) return None def reset(self): """ Clears the library and stop scheduling """ self.library = {} return self when = _whenLibrary() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Code/main_lib.py0000644000175100001770000001567414611211152020755 0ustar00runnerdockerimport sys import re import os.path import time from traceback import format_exc as error_stack from types import CodeType, FunctionType try: from types import TypeType except ImportError: TypeType = type from renardo_lib.Utils import modi from renardo_lib.Settings import * """ Live Object =========== Base for any self-scheduling objects """ # Player RegEx re_player = re.compile(r"(\s*?)(\w+)\s*?>>\s*?\w+") class LiveObject(object): foxdot_object = True isAlive = True metro = None step = None n = 0 def kill(self): self.isAlive = False return self def __call__(self): self.metro.schedule(self, self.metro.now() + float(modi(self.step, self.n))) self.n += 1 return self """ FoxCode ======= Handles the execution of FoxDot code """ class CodeString: def __init__(self, raw): self.raw = raw self.iter = -1 self.lines = [s + "\n" for s in self.raw.split("\n")] + [''] def readline(self): self.iter += 1 return self.lines[self.iter] def __str__(self): return self.raw if sys.version_info[0] > 2: def clean(string): string = string.replace("\u03BB", "lambda") return string else: def clean(string): """ Removes non-ascii characters from a string """ string = string.replace(u"\u03BB", "lambda") return string.encode("ascii", "replace") class _StartupFile: def __init__(self, path): self.set_path(path) def set_path(self, path): self.path = path if path is None else os.path.realpath(path) def load(self): if self.path is not None: try: file = open(self.path) code = file.read() file.close() return code except (IOError, OSError): WarningMsg("'{}' startup file not found.".format(self.path)) return "" FOXDOT_STARTUP = _StartupFile(FOXDOT_STARTUP_PATH) class FoxDotCode: namespace={} player_line_numbers={} @staticmethod def _compile(string): ''' Returns the bytecode for ''' return compile(str(CodeString(string)), "FoxDot", "exec") @classmethod def use_sample_directory(cls, directory): ''' Forces FoxDot to look in `directory` instead of the default directory when using audio samples. ''' return cls.namespace['symbolToDir'].set_root( directory ) @classmethod def use_startup_file(cls, path): return cls.namespace['FOXDOT_STARTUP'].set_path(path) @classmethod def no_startup(cls): return cls.namespace["FOXDOT_STARTUP"].set_path(None) def load_startup_file(self): """ Must be initialised first """ code = self.namespace["FOXDOT_STARTUP"].load() return self.__call__(code, verbose=False) def __call__(self, code, verbose=True, verbose_error=None): """ Takes a string of FoxDot code and executes as Python """ if self.namespace['_Clock'].waiting_for_sync: time.sleep(0.25) return self.__call__(code, verbose, verbose_error) if verbose_error is None: verbose_error = verbose if not code: return try: if type(code) != CodeType: code = clean(code) response = stdout(code) if verbose is True: print(response) exec(self._compile(code), self.namespace) except Exception as e: response = error_stack() if verbose_error is True: print(response) return response def update_line_numbers(self, text_widget, start="1.0", end="end", remove=0): lines = text_widget.get(start, end).split("\n")[remove:] update = [] offset = int(start.split(".")[0]) for i, line in enumerate(lines): # Check line for a player and assign it a line number match = re_player.match(line) line_changed = False if match is not None: whitespace = len(match.group(1)) player = match.group(2) line = i + offset if player in self.player_line_numbers: if (line, whitespace) != self.player_line_numbers[player]: line_changed = True if line_changed or player not in self.player_line_numbers: self.player_line_numbers[player] = (line, whitespace) update.append("{}.id = '{}'".format(player, player)) update.append("{}.line_number = {}".format(player, line)) update.append("{}.whitespace = {}".format(player, whitespace)) # Execute updates if necessary if len(update) > 0: self.__call__("\n".join(update), verbose = False) return execute = FoxDotCode() # this is not well named def get_now(obj): """ Returns the value of objects if they are time-varying """ return getattr(obj, 'now', lambda: obj).__call__() def get_input(): """ Similar to `input` but can handle multi-line input. Terminates on a final "\n" """ line = " "; text = [] while len(line) > 0: line = input("") text.append(line) return "\n".join(text) def handle_stdin(): """ When FoxDot is run with the --pipe added, this function is called and continuosly """ load_startup_file() while True: try: text = get_input() execute(text, verbose=False, verbose_error=True) except(EOFError, KeyboardInterrupt): sys.exit("Quitting") def stdout(code): """ Shell-based output """ console_text = code.strip().split("\n") return ">>> {}".format("\n... ".join(console_text)) def debug_stdout(*args): """ Forces prints to server-side """ sys.__stdout__.write(" ".join([str(s) for s in args]) + "\n") def load_startup_file(): return execute.load_startup_file() def WarningMsg(*text): print("Warning: {}".format( " ".join(str(s) for s in text) )) def write_to_file(fn, text): try: with open(fn, "w") as f: f.write(clean(text)) except IOError: print("Unable to write to {}".format(fn)) return # These functions return information about an imported module # Should use insepct module def classes(module): """ Returns a list of class names defined in module """ return [name for name, data in vars(module).items() if type(data) == TypeType] def instances(module, cls): """ Returns a list of instances of cls from module """ return [name for name, data in vars(module).items() if isinstance(data, cls)] def functions(module): """ Returns a list of function names defined in module """ return [name for name, data in vars(module).items() if type(data) == FunctionType] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Constants.py0000644000175100001770000000536314611211152020277 0ustar00runnerdockerfrom renardo_lib.Patterns import Pattern, PGroup # Constants and constant values class const: """ A number value that cannot be changed """ def __init__(self, value): if isinstance(value, (list, Pattern)): self.__class__ = Pattern self.__init__([const(x) for x in value]) elif isinstance(value, tuple): self.__class__ = PGroup self.__init__([const(x) for x in value]) elif isinstance(value, PGroup): self.__class__ = value.__class__ self.__init__([const(x) for x in value]) else: self.value = value def __int__(self): return int(self.value) def __float__(self): return float(self.value) def __repr__(self): return str(self.value) def __add__(self, other): return self.value def __radd__(self, other): return self.value def __sub__(self, other): return self.value def __rsub__(self, other): return self.value def __mul__(self, other): return self.value def __rmul__(self, other): return self.value def __div__(self, other): return self.value def __rdiv__(self, other): return self.value def __gt__(self, other): return self.value > other def __ge__(self, other): return self.value >= other def __lt__(self, other): return self.value < other def __le__(self, other): return self.value <= other def __eq__(self, other): return self.value == other def __ne__(self, other): return self.value != other class _inf(const): def __repr__(self): return "inf" def __add__(self, other): return _inf(self.value + other) def __radd__(self, other): return _inf(other + self.value) def __sub__(self, other): return _inf(self.value - other) def __rsub__(self, other): return _inf(other - self.value) def __mul__(self, other): return _inf(self.value * other) def __rmul__(self, other): return _inf(other * self.value) def __div__(self, other): return _inf(self.value / other) def __rdiv__(self, other): return _inf(other / self.value) def __truediv__(self, other): return _inf(self.value / other) def __rtruediv__(self, other): return _inf(other / self.value) def __eq__(self, other): return isinstance(other, _inf) def __gt__(self, other): return not isinstance(other, _inf) def __ge__(self, other): return True def __lt__(self, other): return False def __le__(self, other): return isinstance(other, _inf) inf = _inf(0) class NoneConst(const): def __init__(self): self.value = None././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5715406 renardo_lib-0.9.12/renardo_lib/Custom/0000755000175100001770000000000014611211157017221 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Custom/__init__.py0000644000175100001770000000000014611211152021313 0ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Custom/startup.py0000644000175100001770000000031514611211152021267 0ustar00runnerdocker### LOAD CUSTOM FX & SYNTHDEFS ##### # try: # from .Killa.synth_killa import * # from .Killa.fx_killa import * # except: # print("Error importing custom SynthDefs or FX : ", sys.exc_info()[0]) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5715406 renardo_lib-0.9.12/renardo_lib/Effects/0000755000175100001770000000000014611211157017326 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Effects/NewEffects.py0000644000175100001770000001071414611211152021727 0ustar00runnerdockerimport inspect from renardo_lib.SCLang.SCLang import cls, instance, Vibrato, RHPF # To be moved to SCLang later EnvGen = cls("EnvGen") Env = cls("Env") class _Effect: _in = "osc" def __init__(self): self.lines = [] def __call__(self, order=0): def decorator(effect): effect_data = inspect.getargspec(effect) # Original args and defaults # Get filename from function name filename = "{}.scd".format(effect.__name__) # filename # Supplies arg names effect(*map(instance, effect_data.args)) # Default values for arguments, to store defaults = dict(zip(effect_data.args, effect_data.defaults)) return decorator def In(self): """ Returns 'osc', which is where In.ar() is stored """ return self._in def Out(self, output): """ Writes to file and loads synthdef """ print(";\n".join(self.lines)) self.lines = [] return output def add(self, *args, **kwargs): lines = ["{} = {}".format(key, value) for key, value in kwargs.items()] self.lines.extend(lines) return Effect = _Effect() # singleton @Effect(order=0) def vibrato(vib=0, vibdepth=0.02): osc = Vibrato.ar(Effect.In(), vib, depth=vibdepth) return Effect.Out(osc) @Effect(order=0) def slideTo(slide=0, sus=1, slide_delay=0): osc = Effect.In() * \ EnvGen.ar( Env([1, 1, slide + 1], [sus * slide_delay, sus * (1 - slide_delay)])) return Effect.Out(osc) @Effect(order=0) def slideFrom(slide_from=0, sus=1, slide_delay=0): osc = Effect.In() * EnvGen.ar(Env([slide_from + 1, slide_from + 1, 1], [ sus * slide_delay, sus * (1 - slide_delay)])) return Effect.Out(osc) # fx = FxList.new("glide", "glissando", {"glide": 0, "glide_delay": 0.5, "sus": 1}, order=0) # fx.add("osc = osc * EnvGen.ar(Env([1, 1, (1.059463**glide)], [sus*glide_delay, sus*(1-glide_delay)]))") # fx.save() # fx = FxList.new("bend", "pitchBend", {"bend": 0, "sus": 1, "benddelay": 0}, order=0) # fx.add("osc = osc * EnvGen.ar(Env([1, 1, 1 + bend, 1], [sus * benddelay, (sus*(1-benddelay)/2), (sus*(1-benddelay)/2)]))") # fx.save() # fx = FxList.new("coarse", "coarse", {"coarse": 0, "sus": 1}, order=0) # fx.add("osc = osc * LFPulse.ar(coarse / sus)") # fx.save() # fx = FxList.new("striate", "striate", {"striate": 0, "sus": 1, "buf": 0, "rate": 1}, order=0) # fx.add("osc = osc * LFPulse.ar(striate / sus, width: (BufDur.kr(buf) / rate) / sus)") # fx.save() # fx = FxList.new("pshift", "pitchShift", {"pshift":0}, order=0) # fx.add("osc = osc * (1.059463**pshift)") # fx.save() # @Effect(order=2) # def formantFilter(formant=0): # Effect.add(formant=(formant % 8) + 1) # Effect.add(osc=Formlet.ar(Effect.In(), formant * 200, (formant % # 5 + 1) / 1000, (formant * 1.5) / 600).tanh) # return Effect.Out(osc) # # # @Effect(order=2) # def filterSwell(swell=0, sus=1, hpr=1): # env = EnvGen.kr( # Env([0, 1, 0], times=[(sus * 0.25), (sus * 0.25)], curve="\\sin")) # osc = RHPF.ar(Effect.In(), env * swell * 2000, hpr) # return Effect.Out(osc) # # # @Effect(order=2) # def squiz(squiz=0): # osc = Squiz.ar(Effect.In(), pitchratio=squiz) # return Effect.Out(osc) # # # @Effect(order=2) # def sample_atk(sample_atk=0, sample_sus=1): # osc = Effect.In()*EnvGen.ar(Env.new([0, 1, 0], [sample_atk, sample_sus])) # return Effect.Out(osc) # # # @Effect(order=2) # def comp(comp=0, comp_above=1, comp_below=0.8): # osc = Compander.ar(osc, osc, comp, slopeBelow=comp_below, # slopeAbove=comp_above, clampTime=0.01) # return Effect.Out(osc) # # # @Effect(order=2) # def position(position=0, sus=1): # osc = osc * EnvGen.ar(Env([0, 0, 1], curve='step', # times=[sus * position, 0])) # return Effect.Out(osc) # # # @Effect(order=2) # def triode(triode=0): # osc = LeakDC.ar(osc * (osc > 0)) + (tanh(osc * (triode * 10 + 1e-3)) # / (triode * 10 + 1e-3) * (osc < 0))*1.2 # return Effect.Out(osc) # # # @Effect(order=2) # def krush(krush=0, kutoff=15000): # freq = Select.kr(kutoff > 0, [DC.kr(4000), kutoff]) # signal = (osc.squared + (krush * osc)) / \ # (osc.squared + (osc.abs * (krush-1.0)) + 1.0) # signal = RLPF.ar(signal, clip(freq, 20, 10000), 1) # osc = SelectX.ar(krush * 2.0, [osc, signal]) # return Effect.Out(osc) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Effects/Util.py0000644000175100001770000006641514611211152020624 0ustar00runnerdocker""" Filter Effects -------------- Effects are added to Player objects as keywords instructions like `dur` or `amp` but are a little more tricky. Each effect has a "title" keyword, which requires a nonzero value to add the effect to a Player. Effects also have other attribute keywords which can be any value and may have a default value which is set when a Player is created. :: # Example. Reverb effect "title" is `room` and attribute is `mix`, which # defaults to 0.25. The following adds a reverb effect p1 >> pads(room=0.5) # This still adds the effect, but a mix of 0 doesn't actually do anything p1 >> pads(room=0.5, mix=0) # This effect is not added as the "title" keyword, room, is 0 p1 >> pads(room=0, mix=0.5) Other effects are outlined below: *High Pass Filter* - Title keyword: `hpf`, Attribute keyword(s): `hpr` Only frequences **above** the value of `hpf` are kept in the final signal. Use `hpr` to set the resonance (usually a value between 0 and 1) *Low Pass Filter* - Title keyword: `lpf`, Attribute keyword(s): `lpr` Only frequences **below** the value of `lpf` are kept in final signal. Use `lpr` to set the resonance (usually a value between 0 and 1) *Bitcrush* - Title keyword: `bits`, Attribute keyword(s): `crush` The bit depth, in number of `bits`, that the signal is reduced to; this is a value between 1 and 24 where other values are ignored. Use `crush` to set the amount of reduction to the bitrate (defaults to 8) *Reverb* - Title keyword: `room`, Attribute keyword(s): `mix` The `room` argument specifies the size of the room and `mix` is the dry/wet mix of reverb; this should be a value between 0 and 1 (defalts to 0.25) *Chop* - Title keyword: `chop`, Attribute keyword(s): `sus` 'Chops' the signal into chunks using a low frequency pulse wave over the sustain of a note. *Slide To* - Title keyword: `slide`, Attribute keyword(s): Slides' the frequency value of a signal to `freq * (slide+1)` over the duration of a note (defaults to 0) *Slide From* - Title keyword: `slidefrom`, Attribute keyword(s): Slides' the frequency value of a signal from `freq * (slidefrom)` over the duration of a note (defaults to 1) *Comb delay (echo)* - Title keyword: `echo`, Attribute keyword(s): `decay` Sets the decay time for any echo effect in beats, works best on Sample Player (defaults to 0) *Panning* - Title keyword: `pan`, Attribute keyword(s): Panning, where -1 is far left, 1 is far right (defaults to 0) *Vibrato* - Title keyword: `vib`, Attribute keyword(s): Vibrato (defaults to 0) Undocumented: Spin, Shape, Formant, BandPassFilter, Echo """ import os.path from renardo_lib.Settings import EFFECTS_DIR, SC3_PLUGINS from renardo_lib.ServerManager import Server class Effect: server = Server def __init__(self, foxdot_name, synthdef, args={}, control=False): self.name = foxdot_name self.synthdef = synthdef self.filename = EFFECTS_DIR + "/{}.scd".format(self.synthdef) self.args = args.keys() self.vars = ["osc"] self.defaults = args self.effects = [] self.control = control self.suffix = "kr" if self.control else "ar" self.channels = 1 if self.control else 2 self.input = "osc = In.{}(bus, {});\n".format( self.suffix, self.channels) self.output = "ReplaceOut.{}".format(self.suffix) @classmethod def set_server(cls, server): cls.server = server def __repr__(self): # return "".format(self.synthdef, ", ".join(self.args)) other_args = ['{}'.format(arg) for arg in self.args if arg != self.name] other_args = ", other args={}".format(other_args) if other_args else "" return "<'{}': keyword='{}'{}>".format(self.synthdef, self.name, other_args) def __str__(self): s = "SynthDef.new(\{},\n".format(self.synthdef) s += "{" + "|bus, {}|\n".format(", ".join(self.args)) s += "var {};\n".format(",".join(self.vars)) s += self.input s += self.list_effects() s += self.output s += "(bus, osc)}).add;" return s def add(self, string): self.effects.append(string) return def doc(self, string): """ Set a docstring for the effects""" return def list_effects(self): s = "" for p in self.effects: s += p + ";\n" return s def add_var(self, name): if name not in self.vars: self.vars.append(name) return def save(self): ''' writes to file and sends to server ''' # 1. See if the file exists if os.path.isfile(self.filename): with open(self.filename) as f: contents = f.read() else: contents = "" # 2. If it does, check contents this_string = self.__str__() if contents != this_string: try: with open(self.filename, 'w') as f: f.write(this_string) except IOError: print("IOError: Unable to update '{}' effect.".format(self.synthdef)) # 3. Send to server self.load() def load(self): """ Load the Effect """ if self.server is not None: self.server.loadSynthDef(self.filename) return class In(Effect): def __init__(self): Effect.__init__(self, 'startSound', 'startSound') self.save() def __str__(self): s = "SynthDef.new(\startSound,\n" s += "{ arg bus, rate=1, sus; var osc;\n" s += " ReplaceOut.kr(bus, rate)}).add;\n" return s class Out(Effect): def __init__(self): self.max_duration = 8 Effect.__init__(self, 'makeSound', 'makeSound') self.save() def __str__(self): s = "SynthDef.new(\makeSound,\n" s += "{ arg bus, sus; var osc;\n" s += " osc = In.ar(bus, 2);\n" s += " osc = EnvGen.ar(Env([1,1,0],[sus * {}, 0.1]), doneAction: 14) * osc;\n".format( self.max_duration) s += " DetectSilence.ar(osc, amp:0.0001, time: 0.1, doneAction: 14);\n" #s += " Out.ar(0, osc);\n" s += "OffsetOut.ar(0, osc[0]);\n" s += "OffsetOut.ar(1, osc[1]);\n" s += " }).add;\n" return s class EffectManager(dict): def __init__(self): dict.__init__(self) self.kw = [] self.all_kw = [] self.defaults = {} self.order = {N: [] for N in range(3)} def __repr__(self): return "\n".join([repr(value) for value in self.values()]) def values(self): return [self[key] for key in self.sort_by("synthdef")] def sort_by(self, attr): """ Returns the keys sorted by attribute name""" return sorted(self.keys(), key=lambda effect: getattr(self[effect], attr)) def new(self, foxdot_arg_name, synthdef, args, order=2): self[foxdot_arg_name] = Effect( foxdot_arg_name, synthdef, args, order == 0) if order in self.order: self.order[order].append(foxdot_arg_name) else: self.order[order] = [foxdot_arg_name] # Store the main keywords together self.kw.append(foxdot_arg_name) # Store other sub-keys for arg in args: if arg not in self.all_kw: self.all_kw.append(arg) # Store the default value self.defaults[arg] = args[arg] return self[foxdot_arg_name] def kwargs(self): """ Returns the title keywords for each effect """ return tuple(self.kw) def all_kwargs(self): """ Returns *all* keywords for all effects """ return tuple(self.all_kw) def __iter__(self): for key in self.kw: yield key, self[key] def reload(self): """ Re-sends each effect to SC """ for kw, effect in self: effect.load() In() Out() return # -- TODO # Have ordered effects e.g. # 0. Process frequency / playback rate # 1. Before envelope # 2. Adding the envelope # 3. After envelope FxList = EffectManager() Effects = FxList # Alias - to become default # Frequency Effects fx = FxList.new("vib", "vibrato", {"vib": 0, "vibdepth": 0.02}, order=0) fx.add("osc = Vibrato.ar(osc, vib, depth: vibdepth)") fx.save() fx = FxList.new("slide", "slideTo", { "slide": 0, "sus": 1, "slidedelay": 0}, order=0) fx.add( "osc = osc * EnvGen.ar(Env([1, 1, slide + 1], [sus*slidedelay, sus*(1-slidedelay)]))") fx.save() fx = FxList.new("slidefrom", "slideFrom", { "slidefrom": 0, "sus": 1, "slidedelay": 0}, order=0) fx.add( "osc = osc * EnvGen.ar(Env([slidefrom + 1, slidefrom + 1, 1], [sus*slidedelay, sus*(1-slidedelay)]))") fx.save() fx = FxList.new("glide", "glissando", { "glide": 0, "glidedelay": 0.5, "sus": 1}, order=0) fx.add( "osc = osc * EnvGen.ar(Env([1, 1, (1.059463**glide)], [sus*glidedelay, sus*(1-glidedelay)]))") fx.save() fx = FxList.new("bend", "pitchBend", { "bend": 0, "sus": 1, "benddelay": 0}, order=0) fx.add( "osc = osc * EnvGen.ar(Env([1, 1, 1 + bend, 1], [sus * benddelay, (sus*(1-benddelay)/2), (sus*(1-benddelay)/2)]))") fx.save() fx = FxList.new("coarse", "coarse", {"coarse": 0, "sus": 1}, order=0) fx.add("osc = osc * LFPulse.ar(coarse / sus)") fx.save() fx = FxList.new("striate", "striate", { "striate": 0, "sus": 1, "buf": 0, "rate": 1}, order=0) fx.add("rate = (BufDur.kr(buf) / sus)") fx.add("rate = Select.kr(rate > 1, [1, rate])") fx.add("osc = osc * LFPulse.ar(striate / sus, width: (BufDur.kr(buf) / rate) / sus) * rate") fx.save() fx = FxList.new("pshift", "pitchShift", {"pshift": 0}, order=0) fx.add("osc = osc * (1.059463**pshift)") fx.save() # fx = FxList.new("fm_sin", "FrequencyModulationSine", {"fm_sin":0, "fm_sin_i":1}, order=0) # fx.add("osc = osc + (fm_sin_i * SinOsc.kr(osc * fm_sin))") # fx.save() # fx = FxList.new("fm_saw", "FrequencyModulationSaw", {"fm_saw":0, "fm_saw_i":1}, order=0) # fx.add("osc = osc + (fm_saw_i * Saw.kr(osc * fm_saw))") # fx.save() # fx = FxList.new("fm_pulse", "FrequencyModulationPulse", {"fm_pulse":0, "fm_pulse_i":1}, order=0) # fx.add("osc = osc + (fm_pulse_i * Pulse.kr(osc * fm_pulse))") # fx.save() # Signal effects fx = FxList.new('hpf', 'highPassFilter', {'hpf': 0, 'hpr': 1}, order=2) fx.doc("Highpass filter") fx.add('osc = RHPF.ar(osc, hpf, hpr)') fx.save() fx = FxList.new('lpf', 'lowPassFilter', {'lpf': 0, 'lpr': 1}, order=2) fx.add('osc = RLPF.ar(osc, lpf, lpr)') fx.save() # Lpf slide fx = FxList.new('spf', 'SLPF', {'spf': 0, 'spr': 1, 'spfslide': 1, 'spfend': 15000}, order=2) fx.add_var("spfenv") fx.add('spfenv = EnvGen.ar(Env.new([spf, spfend], [spfslide]))') fx.add('osc = RLPF.ar(osc, spfenv, spr)') fx.save() fx = FxList.new('swell', 'filterSwell', { 'swell': 0, 'sus': 1, 'hpr': 1}, order=2) fx.add_var("env") fx.add( "env = EnvGen.kr(Env([0,1,0], times:[(sus*0.25), (sus*0.25)], curve:\\sin))") fx.add('osc = RHPF.ar(osc, env * swell * 2000, hpr)') fx.save() fx = FxList.new("bpf", "bandPassFilter", { "bpf": 0, "bpr": 1, "bpnoise": 0, "sus": 1}, order=2) fx.add("bpnoise = bpnoise / sus") fx.add("bpf = LFNoise1.kr(bpnoise).exprange(bpf * 0.5, bpf * 2)") fx.add("bpr = LFNoise1.kr(bpnoise).exprange(bpr * 0.5, bpr * 2)") fx.add("osc = BPF.ar(osc, bpf, bpr)") fx.save() # MoogLPF fx = FxList.new('mpf', 'MoogFF', {'mpf': 0, 'mpr': 0}, order=2) fx.doc("MoogFF filter") fx.add('osc = MoogFF.ar(osc, mpf, mpr,0,1)') fx.save() # DFM1 LPF fx = FxList.new('dfm', 'DFM1', {'dfm': 0, 'dfmr': 0.1, 'dfmd': 1}, order=2) fx.doc("DFM1 filter") fx.add('osc = DFM1.ar(osc, dfm, dfmr, dfmd,0.0)') fx.save() if SC3_PLUGINS: fx = FxList.new('crush', 'bitcrush', { 'bits': 8, 'sus': 1, 'amp': 1, 'crush': 0}, order=1) fx.add("osc = Decimator.ar(osc, rate: 44100/crush, bits: bits)") fx.add("osc = osc * Line.ar(amp * 0.85, 0.0001, sus * 2)") fx.save() fx = FxList.new('dist', 'distortion', {'dist': 0, 'tmp': 0}, order=1) fx.add("tmp = osc") fx.add("osc = CrossoverDistortion.ar(osc, amp:0.2, smooth:0.01)") fx.add( "osc = osc + (0.1 * dist * DynKlank.ar(`[[60,61,240,3000 + SinOsc.ar(62,mul:100)],nil,[0.1, 0.1, 0.05, 0.01]], osc))") fx.add("osc = (osc.cubed * 8).softclip * 0.5") fx.add("osc = SelectX.ar(dist, [tmp, osc])") fx.save() # Envelope -- just include in the SynthDef and use asdr? # Post envelope effects #New Chop, with wave select : #chopwave = (0: Pulse, 1: Tri, 2: Saw, 3: Sin, 4: Parabolic ) # and chopi = oscillator phase fx = FxList.new('chop', 'chop', { 'chop': 0, 'sus': 1, 'chopmix': 1, 'chopwave': 0, 'chopi': 0}, order=2) fx.add("osc = LinXFade2.ar(osc * SelectX.kr(chopwave, [LFPulse.kr(chop / sus, iphase:chopi, add: 0.01), LFTri.kr(chop / sus, iphase:chopi, add: 0.01), LFSaw.kr(chop / sus, iphase:chopi, add: 0.01), FSinOsc.kr(chop / sus, iphase:chopi, add: 0.01), LFPar.kr(chop / sus, iphase:chopi, add: 0.01)]), osc, 1-chopmix)") fx.save() fx = FxList.new('tremolo', 'tremolo', {'tremolo': 0, 'beat_dur': 1}, order=2) fx.add("osc = osc * SinOsc.ar( tremolo / beat_dur, mul:0.5, add:0.5)") fx.save() fx = FxList.new('echo', 'combDelay', { 'echo': 0, 'beat_dur': 1, 'echotime': 1}, order=2) fx.add('osc = osc + CombL.ar(osc, delaytime: echo * beat_dur, maxdelaytime: 2 * beat_dur, decaytime: echotime * beat_dur)') fx.save() fx = FxList.new('spin', 'spinPan', {'spin': 0, 'sus': 1}, order=2) fx.add('osc = osc * [FSinOsc.ar(spin / 2, iphase: 1, mul: 0.5, add: 0.5), FSinOsc.ar(spin / 2, iphase: 3, mul: 0.5, add: 0.5)]') fx.save() fx = FxList.new("cut", "trimLength", {"cut": 0, "sus": 1}, order=2) fx.add( "osc = osc * EnvGen.ar(Env(levels: [1,1,0.01], curve: 'step', times: [sus * cut, 0.01]))") fx.save() fx = FxList.new('room', 'reverb', {'room': 0, 'mix': 0.1}, order=2) fx.add("osc = FreeVerb.ar(osc, mix, room)") fx.save() fx = FxList.new("formant", "formantFilter", {"formant": 0}, order=2) fx.add("formant = (formant % 8) + 1") fx.add("osc = Formlet.ar(osc, formant * 200, ((formant % 5 + 1)) / 1000, (formant * 1.5) / 600).tanh") fx.save() fx = FxList.new("shape", "wavesShapeDistortion", {"shape": 0}, order=2) fx.add("osc = (osc * (shape * 50)).fold2(1).distort / 5") fx.save() fx = FxList.new("drive", "overdriveDistortion", {"drive": 0}, order=2) fx.add("osc = (osc * (drive * 50)).clip(0,0.2).fold2(2)") fx.save() ################# fx = FxList.new("squiz", "squiz", {"squiz": 0}, order=2) fx.add("osc = Squiz.ar(osc, squiz)") fx.save() fx = FxList.new("comp", "comp", {"comp": 0, "comp_down": 1, "comp_up": 0.8}, order=2) fx.add("osc = Compander.ar(osc, osc, thresh: comp, slopeAbove: comp_down, slopeBelow: comp_up, clampTime: 0.01, relaxTime: 0.01, mul: 1)") fx.save() fx = FxList.new("triode", "triode", {"triode": 0}, order=2) fx.add_var("sc") fx.add("sc = triode * 10 + 1e-3") fx.add("osc = (osc * (osc > 0)) + (tanh(osc * sc) / sc * (osc < 0))") fx.add("osc = LeakDC.ar(osc)*1.2") fx.save() fx = FxList.new("krush", "krush", { "krush": 0, "kutoff": 15000}, order=2) fx.add_var("signal") fx.add_var("freq") fx.add("freq = Select.kr(kutoff > 0, [DC.kr(4000), kutoff])") fx.add("signal = (osc.squared + (krush * osc)) / (osc.squared + (osc.abs * (krush-1.0)) + 1.0)") fx.add("signal = RLPF.ar(signal, clip(freq, 20, 10000), 1)") fx.add("osc = SelectX.ar(krush * 2.0, [osc, signal])") fx.save() fx = FxList.new("leg", "leg", {"leg": 0, "sus": 1}, order=0) fx.add("osc = osc * XLine.ar(Rand(0.5,1.5)*leg,1,0.05*sus)") fx.save() fx = FxList.new("tanh", "tanhDisto", {"tanh": 0}, order=2) fx.add("osc = osc + (osc*tanh).tanh.sqrt()") fx.save() fx = FxList.new("fdist", "fdist", {"fdist": 0, "fdistfreq": 1600}, order=2) fx.add("osc = LPF.ar(osc, fdistfreq)") fx.add("osc = (osc * 1.1 * fdist).tanh") fx.add("osc = LPF.ar(osc, fdistfreq)") fx.add("osc = (osc * 1.1 * fdist).tanh") fx.add("osc = LPF.ar(osc, fdistfreq)") fx.add("osc = (osc * 1.4 * fdist).tanh") fx.add("osc = LPF.ar(osc, fdistfreq)") fx.add("osc = (osc * 2 * fdist).tanh") fx.add("osc = osc*0.2") fx.save() fx = FxList.new("fdistc", "fdistc", {"fdistc": 0, "fdistcfreq1": 1600, "fdistcfreq2": 1600, "fdistcfreq3": 1600, "fdistcfreq4": 1600, "fdistcm1": 1.1, "fdistcm2": 1.1, "fdistcm3": 1.4, "fdistcm4": 2, "fdistcq1": 1, "fdistcq2": 1, "fdistcq3": 1, "fdistcq4": 1}, order=2) fx.add("osc = RLPF.ar(osc, fdistcfreq1, fdistcq1)") fx.add("osc = (osc * fdistcm1 * fdistc).tanh") fx.add("osc = RLPF.ar(osc, fdistcfreq2, fdistcq2)") fx.add("osc = (osc * fdistcm2 * fdistc).tanh") fx.add("osc = RLPF.ar(osc, fdistcfreq3, fdistcq3)") fx.add("osc = (osc * fdistcm3 * fdistc).tanh") fx.add("osc = RLPF.ar(osc, fdistcfreq4, fdistcq4)") fx.add("osc = (osc * fdistcm4 * fdistc).tanh") fx.save() #based on Derek Kwan chorus fx = FxList.new("chorus", "chorus", {"chorus": 0, "chorusrate": 0.5}, order=2) fx.add_var("lfos") fx.add_var("numDelays = 4") fx.add_var("chrate") fx.add_var("maxDelayTime") fx.add_var("minDelayTime") fx.add( "chrate = Select.kr(chorusrate > 0.5, [LinExp.kr(chorusrate, 0.0, 0.5, 0.025, 0.125),LinExp.kr(chorusrate, 0.5, 1.0, 0.125, 2)])") fx.add("maxDelayTime = LinLin.kr(chorus, 0.0, 1.0, 0.016, 0.052)") fx.add("minDelayTime = LinLin.kr(chorus, 0.0, 1.0, 0.012, 0.022)") fx.add("osc = osc * numDelays.reciprocal") fx.add( "lfos = Array.fill(numDelays, {|i| LFPar.kr(chrate * {rrand(0.95, 1.05)},0.9 * i,(maxDelayTime - minDelayTime) * 0.5,(maxDelayTime + minDelayTime) * 0.5,)})") fx.add("osc = DelayC.ar(osc, (maxDelayTime * 2), lfos).sum") fx.add("osc = Mix(osc)") fx.save() fx = FxList.new("squiz", "squiz", {"squiz": 0}, order=2) fx.add("osc = Squiz.ar(osc, squiz)") fx.save() fx = FxList.new("sample_atk", "sample_atk", { "sample_atk": 0, "sample_sus": 1}, order=2) fx.add_var("env") fx.add( "env = EnvGen.ar(Env.new(levels: [0,1,0], times:[sample_atk, sample_sus], curve: 'lin'))") fx.add("osc = osc*env") fx.save() fx = FxList.new("position", "trimPos", {"position": 0, "sus": 1}, order=2) fx.add( "osc = osc * EnvGen.ar(Env(levels: [0,0,1], curve: 'step', times: [sus * position, 0]))") fx.save() fx = FxList.new("ring", "ring_modulation", { "ring": 0, "ringl": 500, "ringh": 1500}, order=0) fx.add_var("mod") fx.add("mod = ring * SinOsc.ar(Clip.kr(XLine.kr(ringl, ringl + ringh), 20, 20000))") fx.add("osc = ring1(osc, mod)") fx.save() fx = FxList.new("lofi", "lofi", {"lofi": 0, "lofiwow": 0.5, "lofiamp": 0.5}, order=2) fx.add_var("minWowRate") fx.add_var("wowRate") fx.add_var("maxDepth") fx.add_var("maxLfoDepth") fx.add_var("depth") fx.add_var("depthLfoAmount") fx.add_var("wowMul") fx.add_var("maxDelay") fx.add_var("ratio") fx.add_var("threshold") fx.add_var("gain") fx.add("osc = HPF.ar(osc, 25)") fx.add("ratio = LinExp.kr(lofiamp, 0, 1, 0.15, 0.01)") fx.add("threshold = LinLin.kr(lofiamp, 0, 1, 0.8, 0.33)") fx.add("gain = 1/(((1.0-threshold) * ratio) + threshold)") fx.add("osc = Limiter.ar(Compander.ar(osc, osc, threshold, 1.0, ratio, 0.1, 1, gain), dur: 0.0008)") fx.add("minWowRate = 0.5") fx.add("wowRate = LinExp.kr(lofiwow, 0, 1, minWowRate, 4)") fx.add("maxDepth = 35") fx.add("maxLfoDepth = 5") fx.add("depth = LinExp.kr(lofiwow, 0, 1, 1, maxDepth - maxLfoDepth)") fx.add("depthLfoAmount = LinLin.kr(lofiwow, 0, 1, 1, maxLfoDepth).floor") fx.add("depth = LFPar.kr(depthLfoAmount * 0.1, mul: depthLfoAmount, add: depth)") fx.add("wowMul = ((2 ** (depth * 1200.reciprocal)) - 1)/(4 * wowRate)") fx.add("maxDelay = (((2 ** (maxDepth * 1200.reciprocal)) - 1)/(4 * minWowRate)) * 2.5") fx.add("osc = DelayC.ar(osc, maxDelay, SinOsc.ar(wowRate, 2, wowMul, wowMul + ControlRate.ir.reciprocal))") fx.add("osc = ((osc * LinExp.kr(lofiamp, 0, 1, 1, 2.5))).tanh") fx.add("osc = LPF.ar(osc, LinExp.kr(lofi, 0, 1, 2500, 10000))") fx.add("osc = HPF.ar(osc, LinExp.kr(lofi, 0, 1, 40, 1690))") fx.add("osc = MoogFF.ar(osc, LinExp.kr(lofi, 0, 1, 1000, 10000), 0)") fx.save() fx = FxList.new('phaser', 'phaser', {'phaser': 0, 'phaserdepth': 0.5}, order=2) fx.add_var("delayedSignal") fx.add("delayedSignal = osc") fx.add("for(1, 4, {|i| delayedSignal = AllpassL.ar(delayedSignal, 0.01 * 4.reciprocal, LFPar.kr(LinExp.kr(phaser, 0, 1, 0.275, 16), i + 0.5.rand, LinExp.kr(phaserdepth*4.reciprocal, 0, 1, 0.0005, 0.01 * 0.5), LinExp.kr(phaserdepth*4.reciprocal, 0, 1, 0.0005, 0.01 * 0.5)), 0)})") fx.add("osc = osc + delayedSignal") fx.save() fx = FxList.new( foxdot_arg_name='vol', synthdef='volume', args={'vol': 1}, order=2 ) fx.add("osc = osc * vol") fx.save() fx = FxList.new('room2', 'reverb_stereo', { 'room2': 0, 'mix2': 0.2, 'damp2': 0.8, 'revatk': 0, 'revsus': 1}, order=2) fx.add_var("dry") fx.add("dry = osc") fx.add("osc = HPF.ar(osc, 100)") fx.add("osc = LPF.ar(osc, 10000)") fx.add("osc = FreeVerb2.ar(osc[0], osc[1], 1, room2, damp2)") fx.add("osc = osc * EnvGen.ar(Env([0,1,0], [revatk,revsus], curve: 'welch'))") fx.add("osc = SelectX.ar(mix2, [dry, osc])") fx.save() In() Out() Effect.server.setFx(FxList) ####FXs that need work before implementing########### ##Does not work############### # fx = FxList.new("sidechain", "sidechain", { # "sidechain": 0, "sidechain_atk": 0.05, "sidechain_rel": 0.1, "thresh": 0.006}, order=2) # fx.add_var("schain") # fx.add("schain = In.ar(sidechain,1)") # fx.add("osc = Compander.ar(osc, schain, thresh: thresh, slopeAbove: 0.1, slopeBelow: 1, clampTime: sidechain_atk, relaxTime: sidechain_rel, mul: 1)") # fx.save() # #### Need Tweak ############## # fx = FxList.new("octer", "octer", {"octer":0, "octersub": 0, "octersubsub": 0}, order=1) # fx.add_var("oct1") # fx.add_var("oct2") # fx.add_var("oct3") # fx.add_var("sub") # fx.add("oct1 = 2.0 * LeakDC.ar(abs(osc))") # fx.add("sub = LPF.ar(osc, 440)") # fx.add("oct2 = ToggleFF.ar(sub)") # fx.add("oct3 = ToggleFF.ar(oct2)") # fx.add("osc = SelectX.ar(octer, [osc, octer*oct1, DC.ar(0)])") # fx.add("osc = osc + (octersub * oct2 * sub) + (octersubsub * oct3 * sub)") # fx.save() # # fx = FxList.new("feed", "feeddelay", {"feed":0.7, "feedfreq": 50}, order=2) # fx.add_var("out") # fx.add("out = osc + Fb({\ # arg feedback;\ # osc = CombN.ar(HPF.ar(feedback*feed, feedfreq) + osc, 0.5, 0.25).tanh;\ # },0.5,0.125)") # fx.save() ##Does not work at the mo # # dub delay based on «Dub Echo» by Bjorn Westergard [sccode https://sccode.org/1-h] # fx = FxList.new('dubd', 'dubdelay', { # 'dubd': 0, 'dublen': 0.1, 'dubwidth': 0.12, 'dubfeed': 0.8}, order=2) # fx.add_var("dry") # fx.add("dry = osc") # fx.add( # "osc = osc + Fb({ |feedback| var left, right; var magic = LeakDC.ar(feedback*dubfeed + osc); magic = HPF.ar(magic, 400); magic = LPF.ar(magic, 5000); magic = magic.tanh; #left, right = magic; magic = [DelayC.ar(left, 1, LFNoise2.ar(12).range(0,dubwidth)), DelayC.ar(right, 1, LFNoise2.ar(12).range(dubwidth,0))].reverse; },dublen)") # fx.add("osc = SelectX.ar(dubd, [dry, osc])") # fx.save() ##Needs tweaking # fx = FxList.new('octafuz', 'octafuz', {'octafuz': 0, 'octamix': 1}, order=2) # fx.add_var("dis") # fx.add_var("osc_base") # fx.add("osc_base = osc") # fx.add("dis = [1,1.01,2,2.02,4.5,6.01,7.501]") # fx.add("dis = dis ++ (dis*6)") # fx.add("osc = ((osc * dis*octafuz).sum.distort)") # fx.add("osc = (osc * 1/16)!2") # fx.add("osc = LinXFade2.ar(osc_base, osc, octamix)") # fx.save() ##Needs tweaking # fx = FxList.new('tek', 'tek', {'tek': 0, 'tekr': 500, 'tekd': 8}, order=2) # fx.add_var("osc_low") # fx.add_var("osc_med") # fx.add_var("osc_high") # fx.add_var("osc_base") # fx.add_var("lfo") # fx.add("lfo = SinOsc.ar(0.5, phase: 0, mul: 5, add: 1)") # fx.add("osc = In.ar(bus, 2)") # fx.add("osc_base = osc") # fx.add("osc_low = LPF.ar(osc, lfo) * 1") # fx.add("osc_med = BPF.ar(osc, lfo * 2)") # fx.add("osc_med = osc_med + Ringz.ar(CrossoverDistortion.ar(osc_med, 1, 0.1, 0.4),100, decaytime: 0.15, mul:0.1)") # fx.add("osc_med = LeakDC.ar(osc_med)") # fx.add("osc_high = HPF.ar(osc, 4000 + SinOsc.ar(4, mul: 24))") # fx.add("osc = osc_low + osc_med + osc_high") # fx.add("osc = DFM1.ar(osc, [400, 600], 0.99, tekd, 0) + osc") # fx.add("osc = RHPF.ar(Gammatone.ar(osc, tekr), tekr, mul:2) + osc") # fx.add("osc = LinXFade2.ar(osc_base, osc, tek)") # fx.save() # fx = FxList.new("drop", "waveloss", {"drop": 0, "dropof": 100}, order=2) # fx.add("osc = WaveLoss.ar(osc, drop, outof: dropof, mode: 2)") # fx.save() # fx = FxList.new('resonz', 'resonz', {'rfreq': 50, 'resonz': 0.1}, order=2) # fx.doc("Resonz") # fx.add('osc = Resonz.ar(osc, freq: rfreq, bwr: resonz)') # fx.save() # fx = FxList.new('stut', 'stutterfx', { # 't_reset': 0, 'stut': 1, 'stutrate': 1, 'stutlen': 0.02}, order=2) # fx.add_var("dry") # fx.add_var("reset") # fx.add_var("wet") # fx.add("~stutter = { |snd, reset, stutlen, maxdelay = 1| var phase, fragment, del; phase = Sweep.ar(reset); fragment = { |ph| (ph - Delay1.ar(ph)) < 0 + Impulse.ar(0) }.value(phase / stutlen % 1); del = Latch.ar(phase, fragment) + ((stutlen - Sweep.ar(fragment)) * (stutrate - 1)); DelayC.ar(snd, maxdelay, del); }") # fx.add("dry = osc") # fx.add("reset = Onsets.kr(FFT(LocalBuf(1024), osc), t_reset)") # fx.add("wet = ~stutter.(osc, reset, stutlen)") # fx.add("osc = SelectX.ar(stut, [dry, wet], wrap:1)") # fx.save() # fx = FxList.new('ringz', 'Ringmod', {'ringzfreq': 50, 'ringz': 0.1}, order=2) # fx.doc("Ringmodulation") # fx.add('osc = Ringz.ar(osc, freq: ringzfreq, decaytime: ringz, mul: 0.05)') # fx.save() # fx = FxList.new('low', 'L_Equalizer', {'low': 1, 'lowfreq': 80}, order=2) # fx.doc("Low shelf Equalizer") # fx.add('osc = BLowShelf.ar(osc, freq: lowfreq, db: abs(low).ampdb)') # fx.save() # # fx = FxList.new('mid', 'M_Equalizer', { # 'mid': 1, 'midfreq': 1000, 'midq': 1}, order=2) # fx.doc("Middle boost Equalizer") # fx.add('osc = BPeakEQ.ar(osc, freq: midfreq, rq: midq.reciprocal, db: abs(mid).ampdb)') # fx.save() # # fx = FxList.new('high', 'H_Equalizer', {'high': 1, 'highfreq': 8000}, order=2) # fx.doc("High shelf Equalizer") # fx.add('osc = BHiShelf.ar(osc, freq: highfreq, db: abs(high).ampdb)') # fx.save() ##Not implemented yet######### # # Fx LOOP # fx = FxList.new('fx1','fxout', {'fx1': 0, 'lpfx1':22000, 'hpfx1':0}, order=2) # fx.doc("FX1 Bus") # fx.add_var("fxsig") # fx.add("fxsig = LPF.ar(osc, lpfx1)") # fx.add("fxsig = HPF.ar(fxsig, hpfx1)") # fx.add("Out.ar(2, Mix.ar(fxsig*fx1))") # fx.save() # # fx = FxList.new('fx2','fx2out', {'fx2': 0, 'lpfx2':22000, 'hpfx2':0}, order=2) # fx.doc("FX2 Bus") # fx.add_var("fxsig") # fx.add("fxsig = LPF.ar(osc, lpfx2)") # fx.add("fxsig = HPF.ar(fxsig, hpfx2)") # fx.add("Out.ar(3, Mix.ar(fxsig*fx2))") # fx.save() # # fx = FxList.new('output','output', {'output': 0}, order=2) # fx.doc("Output select Bus") # fx.add("Out.ar(output, osc)") # fx.save() # ### need the miSCellaneous Quark, install in SC # fx = FxList.new("fold", "wavefold", { # "fold": 0, "symetry": 1, "smooth": 0.5}, order=2) # fx.add_var("gain") # fx.add_var("compensationGain") # fx.add_var("envFollower") # fx.add_var("ampgain") # fx.add("compensationGain = max(LinLin.kr(fold, 0, 1, 1, 20) * 0.75, 1).reciprocal") # fx.add("envFollower = EnvFollow.ar((osc * 2).softclip, 0.9999)") # fx.add("ampgain = (compensationGain * (1 - 0.4)) + (envFollower * 0.4)") # fx.add("osc = SmoothFoldS.ar((osc + LinLin.kr(symetry, 0, 1, 1, 0)) * LinLin.kr(fold, 0, 1, 1, 20), smoothAmount: smooth)") # fx.add("osc = LeakDC.ar(osc*ampgain)") # fx.save() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Effects/__init__.py0000644000175100001770000000004614611211152021432 0ustar00runnerdockerfrom renardo_lib.Effects.Util import *././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5715406 renardo_lib-0.9.12/renardo_lib/EspGrid/0000755000175100001770000000000014611211157017304 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/EspGrid/EspGridHelper.py0000644000175100001770000000663314611211152022356 0ustar00runnerdockerfrom renardo_lib.ServerManager import BidirectionalOSCServer, OSCMessage class EspGrid: def __init__(self, address=("localhost", 5510), clock=None): self.server_address = address self.metro = clock self.server = BidirectionalOSCServer(("0.0.0.0", 0)) self.server.connect(self.server_address) self.server.addMsgHandler('/reset', self._reset_clock) def __repr__(self): return self.__class__.__name__ def _reset_clock(self, *args): self.metro.reset() return def set_clock_mode(self, value): message = OSCMessage("/esp/clockMode/s") message.append(int(value)) return self.server.send(message) def get_clock_mode(self): self.server.send(OSCMessage("/esp/clockMode/q")) return self.server.receive("/esp/clockMode/r") # Retrieve tempo information def query(self): self.server.send(OSCMessage("/esp/clock/q")) return self.server.receive("/esp/clock/r") def get_tempo(self): """ Queries the EspGrid Server for tempo and return a list: [on, bpm, seconds, nanoseconds, beat] """ self.server.send(OSCMessage("/esp/tempo/q")) return self.server.receive("/esp/tempo/r") def get_tempo_cpu(self): self.server.send(OSCMessage("/esp/tempoCPU/q")) return self.server.receive("/esp/tempoCPU/r") # Setting tempo data def toggle_tempo(self, flag): message = OSCMessage("/esp/beat/on") message.append(flag) return self.server.send(message) def start_tempo(self): return self.toggle_tempo(1) def stop_tempo(self): return self.toggle_tempo(0) def set_tempo(self, value): message = OSCMessage("/esp/beat/tempo") message.append(float(value)) return self.server.send(message) def get_start_time(self): data = self.get_tempo() sec, nano = data[2], data[3] return float("{}.{}".format(sec, nano)) # Subcription to immediate messages def subscribe(self): message = OSCMessage("/esp/subscribe") return self.server.send(message) def unsubscribe(self): message = OSCMessage("/esp/unsubscribe") return self.server.send(message) # Identification def set_name(self, name): message = OSCMessage("/esp/person/s") message.append(str(name)) return self.server.send(message) def get_name(self): self.server.send(OSCMessage("/esp/person/q")) return self.server.receive("/esp/person/r") def set_machine_name(self, name): message = OSCMessage("/esp/machine/s") message.append(str(name)) return self.server.send(message) def get_machine_name(self): self.server.send(OSCMessage("/esp/machine/q")) return self.server.receive("/esp/machine/r") # Sending messages def now(self, args): message = OSCMessage("/esp/msg/now") message.append(args) return self.server.send(message) def soon(self, args): message = OSCMessage("/esp/msg/soon") message.append(args) return self.server.send(message) def future(self, seconds, nanoseconds, args): message = OSCMessage("/esp/msg/future") message.append([seconds, nanosecons, args]) return self.server.send(message) # Receiving def recv(self, pattern): return self.server.receive(pattern) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/EspGrid/__init__.py0000644000175100001770000000005714611211152021412 0ustar00runnerdockerfrom renardo_lib.EspGrid.EspGridHelper import *././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/Extensions/0000755000175100001770000000000014611211157020106 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/PArp.py0000644000175100001770000000755714611211152021333 0ustar00runnerdockerfrom renardo_lib.Patterns import P, Pattern from renardo_lib import Scale def PArp(seq, index=0): ### Return an arpeggio Pattern ### from a dictionnary inspired by the BlueARP VST ### e.g. PArp([k1, k2, k3, k4], index) ### PArp([0,1,2], 9) -> P[-7,7,0,1, -7,7,0,2] arp = [] oc = len(Scale.default) ### get Default Scale octave length k1 = k2 = k3 = k4 = P[seq[0]] ### for different sequence lenght if len(seq) > 1: k2 = P[seq[1]] if len(seq) > 2: k3 = P[seq[2]] if len(seq) > 3: k4 = P[seq[3]] ### Dict with {index: [[note_index], [nbr of octave]]} arpdict = { # Standard Arp 3K 0 : [[k1,k2,k3,k1, k2,k3,k1,k2, k3,k1,k2,k3, k1,k2,k3,k2], [0]], 1 : [[k3,k2,k1,k3, k2,k1,k3,k2, k1,k3,k2,k1, k3,k2,k1,k2], [0]], 2 : [[k1,k2,k3,k2, k1,k2,k3,k2, k1,k2,k3,k2, k1,k3,k1,k2], [0]], 3 : [[k3,k2,k1,k2, k3,k2,k1,k2, k3,k2,k1,k2, k3,k2,k3,k1], [0]], 4 : [[k2,k3,k1,k3, k2,k3,k1,k3], [0,-1,0,-1, 0,-1,0,-1]], 5 : [[k1,k3,k2,k1, k1,k1,k2,k3], [-1,0,0,-1, 0,-1,0,0]], 6 : [[k1,k1,k3,k1, k1,k2,k1,k3], [-1,-5,0,-1, 0,0,-1,0]], 7 : [[k3,k1,k2,k1, k3,k1,k2,k1], [0]], 8 : [[k3,k2,k1,k3, k2,k1,k3,k2], [0]], 9 : [[k1,k1,k1,k2, k1,k1,k1,k3], [-1,1,0,0, -1,1,0,0]], # More complex Arp 3K 10 : [[k3,k2,k1,k3, k2,k1,k3,k2, k1,k3,k1,k3, k2,k1,k3,k2], [-1,0,0,-1, 0,0,-1,0, 0,-1,0,-1, 0,0,-1,0]], 11 : [[k2,k1,k1,k3, k1,k1,k3,k1, k2,k1,k1,k3, k1,k1,k3,k1], [0,-1,0,0, -1,0,0,0]], 12 : [[k2,k1,k1,k3, k1,k1,k3,k1, k2,k1,k1,k3, k1,k1,k3,k1], [0,-2,-1,0, -2,-1,0,-1, 0,-2,-1,0, -1,-2,0,-1]], 13 : [[k1,k1,k1,k1, k1,k1,k1,k1, k2,k2,k1,k1, k1,k1,k1,k1], [0,0,-1,-5, -1,-5,0,0, 0,0,-1,-5, 0,0,-1,0]], 14 : [[k1,k1,k2,k1, k1,k2,k1,k1, k2,k1,k1,k2, k1,k1,k2,k1], [-2,-1,0,-2, -1,0,-2,-1, 0,-2,-1,0, -2,-1,0,-1]], 15 : [[k1,k1,k2,k3, k1,k1,k2,k3], [-1,0,0,0]], 16 : [[k3,k1,k2,k1, k2,k1,k1,k3, k1,k1,k2,k1, k2,k1,k1,k1], [0,-2,0,-2, 0,-2,-1,0, -2,-1,0,-2, 0,-2,-1,-2]], 17 : [[k3,k1,k2,k1, k1,k2,k1,k3, k1,k2,k1,k1, k2,k2,k1,k2], [0,-1,0,-2, -1,0,-2,0, -1,0,-2,-1, 0,0,-2,0]], # 2K Arp Scale 20 : [[k1,k2+2,k2+3,k1, k2+5,k2+4,k1,k2, k2+2,k1,k2,k2+2, k1,k2+1,k1,k2], [-1,0,0,-1, 0,0,-1,0, 0,-1,0,0, -1,0,-1,0]], 21 : [[k1,k1,k2+5,k1, k2+5,k1,k1,k2+4, k1,k1,k2+5,k1, k2+7,k1,k1,k2+4], [0,-1,0,-1, 0,0,-1,0, -1,0,0,-1, 0,-1,0,0]], 22 : [[k1,k1,k2+5,k1, k2+5,k1,k1,k2+4, k1,k1,k2+5,k1, k2+7,k1,k1,k2+4], [-1,-1,0,-1, 0,-1,-1,0 ,-1,-1,0,-1, 0,-1,-1,0]], 23 : [[k1,k1,k2+2,k1, k2+6,k1,k2+5,k1, k1,k2,k1,k1, k2+5,k1,k1,k2], [-1,0,0,-1, 0,-1,0,0, -1,0,-1,0, 0,-1,0,0]], # 3k Compldex Arp 32 steps 30 : [[k1,k1,k2,k1, k3,k1,k1,k1, k2,k1,k3,k1, k1,k1,k2,k1, k3,k1,k1,k1, k2,k1,k3,k1, k1,k1,k2,k1, k3,k1,k3,k2], [0,-1,0,-1, 0,-1,0,-1, 0,-1,0,-1, 0,-1,0,-1, 0,-1,0,-1, 0,-1,0,-1, 0,-1,0,-1, 0,-1,0,0]], # 4K Arp 40 : [[k1,k2,k3,k4, k2,k3,k4,k1, k3,k4,k1,k2, k4,k1,k2,k3], [0,0,0,0, 0,0,0,1, 0,0,1,1, 0,1,1,1]], 41 : [[k4,k3,k2,k1, k3,k2,k1,k4, k2,k1,k4,k3, k1,k4,k3,k2], [1,1,1,1, 1,1,1,0, 1,1,0,0, 1,0,0,0]], 42 : [[k1,k2,k3,k1, k3,k2,k3,k4, k1,k4,k3,k1, k1,k2,k1,k3], [-1,0,0,-1, 0,0,0,0, -1,0,0,-1, 0,0,-1,0]], 43 : [[k1,k2,k3,k4, k2,k3,k4,k1, k3,k4,k1,k2, k4,k1,k2,k3, k3,k2,k1,k4, k2,k1,k4,k3, k1,k4,k3,k2, k4,k3,k2,k1], [0,0,0,0, 0,0,0,1, 0,0,1,1, 0,1,1,1, 1,1,1,0, 1,1,0,0, 1,0,0,0, 0,0,0,0]], 44 : [[k1,k2,k1,k4, k2,(k2,k1),k3,k1, (k1,k1),k2,k1,(k1,k1), k2,k1,k3,k1], [-1,0,-1,-1, 0,(-1,-5),-1,-1, (-1,-5),0,-1,(-1,-5), 0,-1,0,-1]], # Simple Arp 50 : [[k1,k2,k1,k1, k2,k1,k1,k1], [0,0,1,0, 0,1,0,1]], 51 : [[k1,k2,k3,k2+4, k1,k2+4, k3,k2], [0,0,0,0, 1,0,0,0]], 52 : [[k1,k2,(k1,k2,k3),k2], [0]], 53 : [[k1,k2,k1,k3, k1,k2,k1,k1], [0,0,0,0, 0,0,0,1]], 54 : [[k1,k2,k3,k1, k2,k1,k3,k1], [0,0,0,1, 0,0,0,1]], } if (index in arpdict): arp = P[arpdict[index][0]] + P[arpdict[index][1]] * oc else: arp = seq return Pattern(arp) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/Extensions/SonicPi/0000755000175100001770000000000014611211157021452 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/SonicPi/__init__.py0000644000175100001770000001041314611211152023555 0ustar00runnerdockerimport os import json from subprocess import check_output from renardo_lib.Scale import freqtomidi from renardo_lib.SCLang import CompiledSynthDef from renardo_lib.Settings import SYNTHDEF_DIR from urllib.request import urlretrieve HERE = os.path.dirname(__file__) SONIC_PI_FILE = os.path.join(HERE, 'sonicpi.json') RUBY_SCRIPT = os.path.join(HERE, "generate.rb") class Container(dict): """ Simple dict that allows access to keys via properties """ def __getattr__(self, attr): return self[attr] pisynth = Container() class SonicPiSynthDef(CompiledSynthDef): bus_name = 'out_bus' def __init__(self, name, filename, synthdata): super(SonicPiSynthDef, self).__init__(name, filename) # These synths are all really loud for some reason self.balance = 0.2 self._arg_defaults = synthdata['arg_defaults'] for key in self._arg_defaults: if not hasattr(self, key): setattr(self, key, self.new_attr_instance(key)) def preprocess_osc(self, osc_msg): super(SonicPiSynthDef, self).preprocess_osc(osc_msg) # sonic-pi uses 'note' instead of 'freq', so we have to translate osc_msg['note'] = freqtomidi(osc_msg['freq']) # Need to set frequency to 0 because this will cause the 'rate' to be # set to 0 for the startSound synth of the init node. This is important # because sonic-pi's synths use Out instead of ReplaceOut, so we don't # want the startSound synth to be adding anything to that bus. osc_msg['freq'] = 0 # sonic-pi has a full ADSR, but if those values are not explicitly # passed, translate the 'sus' into the sustain or release # (depending on what the synthdef uses by default) if 'attack' not in osc_msg and \ 'decay' not in osc_msg and \ 'sustain' not in osc_msg and \ 'release' not in osc_msg: if self._arg_defaults['sustain'] > 0: osc_msg['sustain'] = osc_msg['sus'] else: osc_msg['release'] = osc_msg['sus'] # can't delete 'sus' yet because it's used by ServerManager # del osc_msg['sus'] def _load_synths(data, create_filename): for key, synthdata in data.items(): # Don't handle FX or non-user facing synths (e.g. mixer) yet if not synthdata['is_synth'] or not synthdata['user_facing']: continue fullname = synthdata['prefix'] + synthdata['synth_name'] filename = create_filename(fullname) synth = SonicPiSynthDef(fullname, filename, synthdata) synth.add() pisynth[key] = synth def LoadSonicPiSynthsDev(sonic_pi_dir): """ Load the sonic pi synths from a live sonic-pi repo """ synthinfo = os.path.join(sonic_pi_dir, 'app/server/sonicpi/lib/sonicpi/synths/synthinfo') datastr = check_output(["ruby", RUBY_SCRIPT, synthinfo]) data = json.loads(datastr) _load_synths( data, lambda fn: os.path.join(sonic_pi_dir, 'etc/synthdefs/compiled/', fn + '.scsyndef') ) def LoadSonicPiSynths(metadata_file=SONIC_PI_FILE): """ Load sonic-pi synths from json metadata, downloading compiled synths if needed """ with open(metadata_file, 'r') as ifile: data = json.load(ifile) ref = data.pop('__ref__') def create_filename(fullname): filename = os.path.join(SYNTHDEF_DIR, fullname + '.scsyndef') if not os.path.exists(filename): url = "https://github.com/samaaron/sonic-pi/raw/%s/etc/synthdefs/compiled/%s.scsyndef" % (ref, fullname) print("Downloading", url) urlretrieve(url, filename) return filename _load_synths(data, create_filename) def GenerateSonicPiData(sonic_pi_dir): """ Generate the sonic-pi json metadata from a sonic-pi source repo """ synthinfo = os.path.join(sonic_pi_dir, 'app/server/sonicpi/lib/sonicpi/synths/synthinfo') datastr = check_output(["ruby", RUBY_SCRIPT, synthinfo]) ref = check_output(["git", "rev-parse", "HEAD"], cwd=sonic_pi_dir).strip() data = json.loads(datastr) data['__ref__'] = ref with open(SONIC_PI_FILE, 'w') as ofile: json.dump(data, ofile, separators=(',', ':')) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/SonicPi/generate_sonic_pi.py0000644000175100001770000000021714611211152025474 0ustar00runnerdockerfrom renardo_lib.Extensions.SonicPi import GenerateSonicPiData if __name__ == '__main__': import sys GenerateSonicPiData(sys.argv[1]) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/Extensions/VRender/0000755000175100001770000000000014611211157021453 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/VRender/Composer.py0000644000175100001770000000245214611211152023612 0ustar00runnerdockerfrom renardo_lib.Extensions.VRender.MidiFactory import createMidi import os from math import ceil def extendScale(scale,times): scaleAux = scale[:] for i in range(1,times): for note in scaleAux: scale.append(note+12*i) return scale def matchListsSize(rhythm,melody): n_rhythm =len(rhythm) n_melody = len(melody) if n_rhythm < n_melody: rhythm = (rhythm*int(ceil(n_melody/float(n_rhythm))))[:n_melody] elif n_rhythm != n_melody: melody = (melody*int(ceil(n_rhythm/float(n_melody))))[:n_rhythm] return rhythm,melody def toList(rhythm, melody, scale): scale = extendScale(scale,2) scaleSize = len(scale) volume = 100 baseNote = 60 rhythm, melody = matchListsSize(rhythm,melody) composition = [] time = 0 for i in range(len(rhythm)): dur = rhythm[i] note = scale[melody[i]%scaleSize] + baseNote composition.append((note,dur,volume,time)) time += dur return composition def compose(notes,durations,scale, new_midi_path, new_musicxml_path): print(notes) print(durations) print(scale) composition = toList(durations,notes,scale) print(composition) createMidi(new_midi_path, composition) os.system("musescore "+ new_midi_path +" -o " + new_musicxml_path)././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/VRender/MidiFactory.py0000644000175100001770000000103514611211152024231 0ustar00runnerdockerfrom midiutil import MIDIFile # dependency to add to installer def createMidi(midi_file, composition): print("Composition:") print(composition) MyMIDI = MIDIFile(1) track = 0 channel = 0 for note in composition: pitch = note[0] duration = note[1] # In beats volume = note[2] # 0-127, as per the MIDI standard time = note[3] MyMIDI.addNote(track, channel, pitch, time, duration, volume) with open(midi_file, "wb") as output_file: MyMIDI.writeFile(output_file)././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/VRender/Sinsy.py0000644000175100001770000000051414611211152023125 0ustar00runnerdockerimport urllib from functools import reduce def download(output,wavPath): text = reduce(lambda accum,x: accum + x, output, "") index = text.find('./temp/') + len('./temp/') text = text[index:index+40].split(".")[0] testfile = urllib.URLopener() testfile.retrieve("http://sinsy.sp.nitech.ac.jp/temp/" + text + ".wav", wavPath)././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/VRender/VRender.py0000644000175100001770000000363614611211152023375 0ustar00runnerdockerimport os from renardo_lib.Extensions.VRender.Composer import compose from renardo_lib.Extensions.VRender.VoiceSpecificator import generateVoiceSpecification from renardo_lib.Extensions.VRender.Sinsy import download def renderizeVoice(outputName,lyrics,notes,durations,tempo,scale,sex,foxdot_root): # Constants print(foxdot_root) FILES_ROOT = os.path.realpath(foxdot_root + "/lib/Extensions/VRender/tmp/") LAST_MIDI = FILES_ROOT + "/last_midi_generated_by_vrender.mid" VOICE_XML_ORIGINAL=FILES_ROOT + "/last_voice.musicxml" VOICE_XML_PROCESSED=FILES_ROOT+"/last_voice.xml" # WAVS_ROOT = os.path.realpath(foxdot_root + "/snd/_loop_/") WAVS_ROOT = os.path.realpath(foxdot_root + "/snd/" + SAMPLES_DB + "/_loop_/") LAST_VOICE_WAV = WAVS_ROOT + "/last_voice_generated.wav" print("Running voice renderization") compose(notes,durations,scale,LAST_MIDI,VOICE_XML_ORIGINAL) lyrics = tokenize(lyrics) generateVoiceSpecification(lyrics,tempo,VOICE_XML_ORIGINAL,VOICE_XML_PROCESSED) if sex == "male": urlfileName = os.popen("curl -X POST -F 'SPKR_LANG=english' -F 'SPKR=5' -F 'SYNALPHA=0.55' -F 'VIBPOWER=1' -F 'F0SHIFT=0' -F 'SYNSRC=@" + VOICE_XML_PROCESSED +"' http://sinsy.sp.nitech.ac.jp/index.php | grep 'lf0'").read() else: urlfileName = os.popen("curl -X POST -F 'SPKR_LANG=english' -F 'SPKR=4' -F 'SYNALPHA=0.55' -F 'VIBPOWER=1' -F 'F0SHIFT=0' -F 'SYNSRC=@" + VOICE_XML_PROCESSED +"' http://sinsy.sp.nitech.ac.jp/index.php | grep 'lf0'").read() download(urlfileName,LAST_VOICE_WAV) os.system("cp " + LAST_VOICE_WAV + " " + WAVS_ROOT + "/" + outputName + ".wav") print("Finished voice renderization") def tokenize(text): textSyllables = cleanText(text) return filter(lambda x: len(x) > 0, textSyllables.replace(" ", "-").split("-")) def cleanText(text): text.replace("\n"," ") text = text.lower() symbolsToDelete = ".,'!?" + '"' for symbol in symbolsToDelete: text = text.replace(symbol,"") return text ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Extensions/VRender/VoiceSpecificator.py0000644000175100001770000000153714611211152025427 0ustar00runnerdocker# -*- coding: latin-1 -*- def generateVoiceSpecification(lyrics,tempo,inputMusicXMLPath,outputMusicXMLPath): with open(inputMusicXMLPath, 'r') as c: content = [x.strip() for x in c.readlines()] with open(outputMusicXMLPath,'w') as f: f.write(addVoiceTags(tempo,lyrics,content)) def addVoiceTags(tempo, text, content): print("Text:\n" + str(text)) output = "" tempo_xml = '\n\n'.format(tempo) lyrics_xml = '1\n\n{}\n' i = 0 ignoreThisNote = False for line in content: if "" in line: ignoreThisNote = True if " other) return self.transform(function) @convert_pattern_args def __ge__(self, other): function = lambda value: (value >= other) return self.transform(function) @convert_pattern_args def __lt__(self, other): function = lambda value: (value < other) return self.transform(function) @convert_pattern_args def __le__(self, other): function = lambda value: (value <= other) return self.transform(function) def __abs__(self): return self.transform(abs) def __getitem__(self, key): def function(value): try: return value[key] except TypeError: return value return self.spawn_child(function) def index(self, sequence): """ Returns a Player Key that returns the element from sequence indexed using int(self) """ new = self.child(sequence) def getitem(b, a): try: return b[a] except TypeError: return b new.calculate = getitem return new def semitones(self): """ Converts the current value into the semitone value using the parent's scale """ new = self.child(0) new.calculate = lambda a, b: self.parent.scale.semitones(b) return new def simple_map(self, mapping): """ Creates a new Player key that maps the values in the dictionary (mapping) to new values. Example use case: ``` d1 >> play("x-o-", sample=d1.degree.simple_map( { "-" : -1, "o" : var([0,2]) })) ``` """ assert isinstance(mapping, dict) data = [ ((self == key) * value) for key, value in mapping.items() ] new_key = data[0] for i in data[1:]: new_key = new_key + i return new_key def map(self, mapping, default=0): # input functions functions = [] # Convert default output to function if callable(default): default_func = default else: default_func = partial(lambda x, y: x, default) # Convert input values to functions for key, value in mapping.items(): if callable(key): test_func = force_pattern_args(key) else: test_func = partial(lambda x, y: x == y, key) if callable(value): result_func = force_pattern_args(value) else: result_func = partial(lambda x, y: x, value) functions.append((test_func, result_func)) # Define mapping function to test input functions def mapping_function(value): # For PGroups if isinstance(value, PGroup): return PGroup([mapping_function(item) for item in value]) # For other values for func, result in functions: if bool(func(value)) is True: return result(value) return default_func(value) return self.spawn_child(mapping_function) def get_min(self): new = self.child(0) def f(a, b): try: return min(b) except TypeError: return b new.calculate = f return new def get_max(self): new = self.child(0) def f(a, b): try: return max(b) except TypeError: return b new.calculate = f return new def transform(self, func): """ Returns a child Player Key based on the func. If the value returned is a PGroup, that is also transformed by the function """ # def new_func(item): # if isinstance(item, (PGroup, Pattern)): # return item.transform(func) # else: # return func(item) def new_func(item): try: return func(item) except AttributeError as e: error = e try: return item.transform(func) except AttributeError: # Raise original error for more information raise error return self.spawn_child(new_func) def accompany(self, rel=[0,2,4]): """ Returns a PlayerKey whose function returns an accompanying note """ return self.transform(Accompany(rel=rel)) def versus(self, rule=lambda x, y: x > y): """ p1 >> pads([0, 1, 2, 3]) p2 >> pluck([4, 5, 0]).versus(p1, rule) """ # 1. Sets this source player key amplify to be "off" when the rule is satisfied # 2. Returns a new PlayKey return # Values def __nonzero__(self): return self.__bool__() def __bool__(self): return bool(self.now()) def __int__(self): return int(self.now()) def __float__(self): return float(self.now()) def __str__(self): return str(self.now()) def __repr__(self): return repr(self.now()) def __len__(self): return len(self.now()) def __iter__(self): try: for item in self.now(): yield item except TypeError: yield self.now() # def child(self, other): # return NumberKey(self.value, other) def spawn_child(self, function): return self.__class__(self, function) def now(self, other=None): """ Returns the current value in the Key by calling the parent """ value = self.value.now() if hasattr(self.value, "now") else self.value return self.calculate(value) class PlayerKey(NumberKey): # def __init__(self, value=None, reference=None, parent=None, attr=None): def __init__(self, value, function=None, player=None, attr=None): NumberKey.__init__(self, value, function) if player is None and isinstance(self.value, PlayerKey): self.attr = self.value.attr self.player = self.value.player else: self.attr = attr self.player = player # self.pattern = asStream(self.parent.attr[self.key]) if self.parent is not None else asStream([]) # # self.pattern = NumberKey().transform(lambda x: self.player.attr[self.attr]) self.last_updated = 0 def cmp(self, player, attr): return player == self.player and attr == self.attr def get_player_attribute(self): return self.player.attr[self.attr] def name(self): return "{}.{}".format(self.player.id, self.attr) def set(self, value, time): self.value = value self.last_updated = time return def update(self, value, time): """ Updates the contents of the PlayerKey *if* the time value is different to self.last_updated. If they are the same, the the contents become a PGroup of the two values """ if not equal_values(value, self.value): #if value != self.value: if time == self.last_updated: try: self.value.append(value) except AttributeError: self.value = PGroup(self.value, value) else: self.value = value self.last_updated = time return # Could be removed def update_pattern(self): # try: # self.pattern[:] = asStream(self.parent.attr[self.key]) # except TypeError: # self.pattern = asStream(self.parent.attr[self.key]) return class Accompany: """ Like PlayerKey except it returns """ this_last_value = 0 keys_last_value = None def __init__(self, rel=[0,2,4]): # self.frequency = freq self.scale_size = 7 self.relations = list(rel) def __call__(self, playerkey): """ Acts as a function in Player Key """ # Only change value if the player key has changed - maybe set a frequency? if self.keys_last_value != playerkey: self.this_last_value = self.find_new_value(playerkey) self.keys_last_value = playerkey return self.this_last_value def find_new_value(self, playerkey): # Which value is the closest to this_last_value values = [(playerkey + x) % 7 for x in self.relations] + [(playerkey % 7) + (x - self.scale_size) for x in self.relations] nearby = [abs(self.this_last_value - value) for value in values] indices = [nearby.index(val) for val in sorted(nearby)] r = random.random() if r <= 0.65: i = 0 elif r <= 0.9: i = 1 else: i = 2 index = indices[i % len(indices)] return values[index] class Versus(Accompany): def __init__(self): pass def find_new_value(self, playerkey): return # Give pattern objects a reference to the PlayerKey type Pattern.PlayerKey = PlayerKey././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Logging.py0000644000175100001770000000543414611211152017710 0ustar00runnerdocker""" Utilities related to logging """ import functools import logging import time def enablePerfLogging(): """ This is just a small convenience method """ logging.getLogger('FoxDot.perf').setLevel(logging.DEBUG) class Timing(object): """ Utility for profiling events :param str event: Unique identifier for the perf event :param str logger: Logger path (default 'FoxDot.perf') :param bool logargs: If true when used as a decorator, log the arguments to the decorated function This can be used in multiple ways. As a decorator:: @Timing('fibonacci') def fib(num): ... As a context manager:: with Timing('pi'): # calculate pi... Or directly as an object:: timer = Timing('crank') # do crank timer.finish() Note that it will log the perf data to the specified logger (FoxDot.perf by default) at the DEBUG level. That means that in order for the information to be visible, you will need to configure either that logger or a parent logger to use the DEBUG level. For example:: # Set root logger to DEBUG logging.root.setLevel(logging.DEBUG) # Set just the perf logger to DEBUG logging.getLogger('FoxDot.perf').setLevel(logging.DEBUG) """ def __init__(self, event, logger='FoxDot.perf', logargs=False): self._event = event self._logger = logger self._log = logging.getLogger(logger) self._messages = [] self._start = None self._logargs = logargs def __str__(self): return "Timing(%s)" % self._event def addMessage(self, message): self._messages.append(message) def start(self): if self._start is not None: self._log.warn("Entering %s twice!", self) self._start = time.time() def finish(self): if self._start is None: self._log.warn("Finishing %s before start!", self) return diff = 1000 * (time.time() - self._start) formatted_messages = '' if self._messages: formatted_messages = ', '.join(self._messages) + ': ' self._log.debug("%s: %s%.02fms", self._event, formatted_messages, diff) def __enter__(self): self.start() return self def __exit__(self, type, value, traceback): self.finish() def __call__(self, fxn): @functools.wraps(fxn) def wrapper(*args, **kwargs): with Timing(self._event, self._logger) as timer: if self._logargs: if args: timer.addMessage("args:%s" % list(args)) if kwargs: timer.addMessage("kwargs:%s" % kwargs) return fxn(*args, **kwargs) return wrapper ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Midi.py0000644000175100001770000001372114611211152017202 0ustar00runnerdocker""" Module for converting handling MIDI in/out and functions relating to MIDI pitch calculation. """ from renardo_lib.SCLang import SynthDefProxy try: import rtmidi from rtmidi import midiconstants TIMING_CLOCK = midiconstants.TIMING_CLOCK SONG_POSITION_POINTER = midiconstants.SONG_POSITION_POINTER SONG_START = midiconstants.SONG_START SONG_STOP = midiconstants.SONG_STOP except ImportError as _err: pass import time class MidiInputHandler(object): """Midi Handler CallBack Function""" def __init__(self, midi_ctrl): self.midi_ctrl = midi_ctrl self.bpm_group = [] self.played = False self.bpm = 120.0 self.tt = False self.tt_bpm = self.bpm self.tt_time = time.time() self.tt_ptime = self.tt_time self.msg = [0, 0, 0] self.msg_list = [] self.print_msg = False def __call__(self, event, data=None): message, delta = event self.msg = message if self.print_msg == True: print(self.msg) if(self.msg[0] == 144 or self.msg[0] == 145): if len(self.msg_list) == 0: self.msg_list.append(self.msg) else: if self.msg not in self.msg_list: self.msg_list.append(self.msg) elif self.msg[0] == 128: if len(self.msg_list) > 0: for count, item in enumerate(self.msg_list): if self.msg[1] == item[1]: self.msg_list.remove(self.msg_list[count]) elif self.msg[0] == 129: for count, item in enumerate(self.msg_list): if self.msg[1] == item[1]: self.msg_list[count][2] = 0 else: if len(self.msg_list) == 0: self.msg_list.append(self.msg) else: if self.msg not in self.msg_list: self.msg_list.append(self.msg) else: for count, item in enumerate(self.msg_list): if self.msg[1] == item[1]: self.msg_list.remove(self.msg_list[count]) self.msg_list.append(self.msg) #print(self.msg_list) if self.tt and message[0] == 128 and message[1] == 0: self.tt_time = time.time() if self.tt_ptime < self.tt_time: self.tt_bpm = (1/(self.tt_time - self.tt_ptime)) * 60 self.tt_ptime = self.tt_time self.midi_ctrl.delta += delta #if TIMING_CLOCK in datatype and not self.played: if not self.played: self.midi_ctrl.pulse += 1 if self.midi_ctrl.pulse == self.midi_ctrl.ppqn: t_master = 60.0 self.midi_ctrl.bpm = round(60.0 / self.midi_ctrl.delta,0) self.midi_ctrl.pulse = 0 self.midi_ctrl.delta = 0.0 #print("CONTROLLER BPM : " + repr(self.midi_ctrl.bpm)) class MidiIn: metro = None def __init__(self, port_id=0): """ Class for listening for MIDI clock messages from a midi device """ try: self.device = rtmidi.MidiIn() except NameError: raise ImportError("Rtmidi not imported") self.available_ports = self.device.get_ports() if not self.available_ports: raise MIDIDeviceNotFound else: print("MidiIn: Connecting to " + self.available_ports[port_id]) self.device.open_port(port_id) self.device.ignore_types(timing=False) self.pulse = 0 self.delta = 0.0 self.bpm = 120.0 self.tt_bpm = 120.0 self.ppqn = 24 self.beat = 0 self.ctrl_value = 0 self.note = 0 self.velocity = 0 self.handler = MidiInputHandler(self) self.device.set_callback(self.handler) self.msg = self.handler.msg @classmethod def set_clock(cls, tempo_clock): cls.metro = tempo_clock return def tempo_tapper(self, tt_bool): self.handler.tt = tt_bool return def tempo_tapper_bpm(self): self.bpm = self.handler.tt_bpm return self.bpm def get_ctrl(self, channel): for i in range(len(self.handler.msg_list)): if self.handler.msg_list[i][1] == channel: self.ctrl_value = self.handler.msg_list[i][2] return self.ctrl_value def get_note(self): self.note = () if len(self.handler.msg_list) > 0: for i in range(len(self.handler.msg_list)): self.note = self.note + (self.handler.msg_list[i][1],) else: self.note = self.note + (0, ) return self.note def get_velocity(self): self.velocity = () if len(self.handler.msg_list) > 0: for i in range(len(self.handler.msg_list)): self.velocity = self.velocity + \ (self.handler.msg_list[i][2] / 64, ) else: self.velocity = (0, ) return self.velocity def get_delta(self): self.delta = self.handler.delta return self.delta def print_message(self, boolmsg): self.handler.print_msg = boolmsg return self.handler.print_msg def close(self): """ Closes the active port """ self.device.close_port() return class MidiOut(SynthDefProxy): """ SynthDef proxy for sending midi message via supercollider """ def __init__(self, degree=0, **kwargs): SynthDefProxy.__init__(self, self.__class__.__name__, degree, kwargs) midi = MidiOut # experimental alias # Midi information exceptions class MIDIDeviceNotFound(Exception): def __str__(self): return self.__class__.__name__ + " Error" class rtMidiNotFound(Exception): def __str__(self): return self.__class__.__name__ + ": Module 'rtmidi' not found" if __name__ == "__main__": a = MidiIn() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/OSC3.py0000644000175100001770000032024414611211152017030 0ustar00runnerdocker#!/usr/bin/python """ This module contains an OpenSoundControl implementation (in Pure Python), based (somewhat) on the good old 'SimpleOSC' implementation by Daniel Holth & Clinton McChesney. This implementation is intended to still be 'simple' to the user, but much more complete (with OSCServer & OSCClient classes) and much more powerful (the OSCMultiClient supports subscriptions & message-filtering, OSCMessage & OSCBundle are now proper container-types) =============================================================================== OpenSoundControl =============================================================================== OpenSoundControl is a network-protocol for sending (small) packets of addressed data over network sockets. This OSC-implementation supports the classical UDP/IP protocol for sending and receiving packets but provides as well support for TCP/IP streaming, whereas the message size is prepended as int32 (big endian) before each message/packet. OSC-packets come in two kinds: - OSC-messages consist of an 'address'-string (not to be confused with a (host:port) network-address!), followed by a string of 'typetags' associated with the message's arguments (ie. 'payload'), and finally the arguments themselves, encoded in an OSC-specific way. The OSCMessage class makes it easy to create & manipulate OSC-messages of this kind in a 'pythonesque' way (that is, OSCMessage-objects behave a lot like lists) - OSC-bundles are a special type of OSC-message containing only OSC-messages as 'payload'. Recursively. (meaning; an OSC-bundle could contain other OSC-bundles, containing OSC-bundles etc.) OSC-bundles start with the special keyword '#bundle' and do not have an OSC-address (but the OSC-messages a bundle contains will have OSC-addresses!). Also, an OSC-bundle can have a timetag, essentially telling the receiving server to 'hold' the bundle until the specified time. The OSCBundle class allows easy cration & manipulation of OSC-bundles. For further information see also http://opensoundcontrol.org/spec-1_0 ------------------------------------------------------------------------------- To send OSC-messages, you need an OSCClient, and to receive OSC-messages you need an OSCServer. The OSCClient uses an 'AF_INET / SOCK_DGRAM' type socket (see the 'socket' module) to send binary representations of OSC-messages to a remote host:port address. The OSCServer listens on an 'AF_INET / SOCK_DGRAM' type socket bound to a local port, and handles incoming requests. Either one-after-the-other (OSCServer) or in a multi-threaded / multi-process fashion (ThreadingOSCServer/ ForkingOSCServer). If the Server has a callback-function (a.k.a. handler) registered to 'deal with' (i.e. handle) the received message's OSC-address, that function is called, passing it the (decoded) message. The different OSCServers implemented here all support the (recursive) un- bundling of OSC-bundles, and OSC-bundle timetags. In fact, this implementation supports: - OSC-messages with 'i' (int32), 'f' (float32), 'd' (double), 's' (string) and 'b' (blob / binary data) types - OSC-bundles, including timetag-support - OSC-address patterns including '*', '?', '{,}' and '[]' wildcards. (please *do* read the OSC-spec! http://opensoundcontrol.org/spec-1_0 it explains what these things mean.) In addition, the OSCMultiClient supports: - Sending a specific OSC-message to multiple remote servers - Remote server subscription / unsubscription (through OSC-messages, of course) - Message-address filtering. ------------------------------------------------------------------------------- SimpleOSC: Copyright (c) Daniel Holth & Clinton McChesney. pyOSC: Copyright (c) 2008-2010, Artem Baguinski et al., Stock, V2_Lab, Rotterdam, Netherlands. Streaming support (OSC over TCP): Copyright (c) 2010 Uli Franke , Weiss Engineering, Uster, Switzerland. ------------------------------------------------------------------------------- Changelog: ------------------------------------------------------------------------------- v0.3.0 - 27 Dec. 2007 Started out to extend the 'SimpleOSC' implementation (v0.2.3) by Daniel Holth & Clinton McChesney. Rewrote OSCMessage Added OSCBundle v0.3.1 - 3 Jan. 2008 Added OSClient Added OSCRequestHandler, loosely based on the original CallbackManager Added OSCServer Removed original CallbackManager Adapted testing-script (the 'if __name__ == "__main__":' block at the end) to use new Server & Client v0.3.2 - 5 Jan. 2008 Added 'container-type emulation' methods (getitem(), setitem(), __iter__() & friends) to OSCMessage Added ThreadingOSCServer & ForkingOSCServer - 6 Jan. 2008 Added OSCMultiClient Added command-line options to testing-script (try 'python OSC.py --help') v0.3.3 - 9 Jan. 2008 Added OSC-timetag support to OSCBundle & OSCRequestHandler Added ThreadingOSCRequestHandler v0.3.4 - 13 Jan. 2008 Added message-filtering to OSCMultiClient Added subscription-handler to OSCServer Added support fon numpy/scipy int & float types. (these get converted to 'standard' 32-bit OSC ints / floats!) Cleaned-up and added more Docstrings v0.3.5 - 14 aug. 2008 Added OSCServer.reportErr(...) method v0.3.6 - 19 April 2010 Added Streaming support (OSC over TCP) Updated documentation Moved pattern matching stuff into separate class (OSCAddressSpace) to facilitate implementation of different server and client architectures. Callbacks feature now a context (object oriented) but dynamic function inspection keeps the code backward compatible Moved testing code into separate testbench (testbench.py) ----------------- Original Comments ----------------- > Open SoundControl for Python > Copyright (C) 2002 Daniel Holth, Clinton McChesney > > This library is free software; you can redistribute it and/or modify it under > the terms of the GNU Lesser General Public License as published by the Free > Software Foundation; either version 2.1 of the License, or (at your option) any > later version. > > This library is distributed in the hope that it will be useful, but WITHOUT ANY > WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A > PARTICULAR PURPOSE. See the GNU Lesser General Public License for more > details. > > You should have received a copy of the GNU Lesser General Public License along > with this library; if not, write to the Free Software Foundation, Inc., 59 > Temple Place, Suite 330, Boston, MA 02111-1307 USA > > For questions regarding this module contact Daniel Holth > or visit http://www.stetson.edu/~ProctoLogic/ > > Changelog: > 15 Nov. 2001: > Removed dependency on Python 2.0 features. > - dwh > 13 Feb. 2002: > Added a generic callback handler. > - dwh """ import math, re, socket, select, string, struct, sys, threading, time, types, array, errno from socketserver import UDPServer, DatagramRequestHandler, ThreadingMixIn, StreamRequestHandler, TCPServer try: from socketserver import ForkingMixIn except ImportError: ForkingMixIn = ThreadingMixIn long = int global version version = ("0.3","6", "$Rev: 6382 $"[6:-2]) global FloatTypes FloatTypes = [float] global IntTypes IntTypes = [int] global NTP_epoch from calendar import timegm NTP_epoch = timegm((1900,1,1,0,0,0)) # NTP time started in 1 Jan 1900 del timegm global NTP_units_per_second NTP_units_per_second = 0x100000000 # about 232 picoseconds ## # numpy/scipy support: ## try: from numpy import typeDict for ftype in ['float32', 'float64', 'float128']: try: FloatTypes.append(typeDict[ftype]) except KeyError: pass for itype in ['int8', 'int16', 'int32', 'int64']: try: IntTypes.append(typeDict[itype]) IntTypes.append(typeDict['u' + itype]) except KeyError: pass # thanks for those... del typeDict, ftype, itype except ImportError: pass ###### # # OSCMessage classes # ###### class OSCMessage(object): """ Builds typetagged OSC messages. OSCMessage objects are container objects for building OSC-messages. On the 'front' end, they behave much like list-objects, and on the 'back' end they generate a binary representation of the message, which can be sent over a network socket. OSC-messages consist of an 'address'-string (not to be confused with a (host, port) IP-address!), followed by a string of 'typetags' associated with the message's arguments (ie. 'payload'), and finally the arguments themselves, encoded in an OSC-specific way. On the Python end, OSCMessage are lists of arguments, prepended by the message's address. The message contents can be manipulated much like a list: >>> msg = OSCMessage("/my/osc/address") >>> msg.append('something') >>> msg.insert(0, 'something else') >>> msg[1] = 'entirely' >>> msg.extend([1,2,3.]) >>> msg += [4, 5, 6.] >>> del msg[3:6] >>> msg.pop(-2) 5 >>> print msg /my/osc/address ['something else', 'entirely', 1, 6.0] OSCMessages can be concatenated with the + operator. In this case, the resulting OSCMessage inherits its address from the left-hand operand. The right-hand operand's address is ignored. To construct an 'OSC-bundle' from multiple OSCMessage, see OSCBundle! Additional methods exist for retreiving typetags or manipulating items as (typetag, value) tuples. """ def __init__(self, address="", *args): """Instantiate a new OSCMessage. The OSC-address can be specified with the 'address' argument. The rest of the arguments are appended as data. """ self.clear(address) if len(args)>0: self.append(*args) def setAddress(self, address): """Set or change the OSC-address """ self.address = address def clear(self, address=""): """Clear (or set a new) OSC-address and clear any arguments appended so far """ self.address = address self.clearData() def clearData(self): """Clear any arguments appended so far """ self.typetags = "," self.message = bytes() def append(self, argument, typehint=None): """Appends data to the message, updating the typetags based on the argument's type. If the argument is a blob (counted string) pass in 'b' as typehint. 'argument' may also be a list or tuple, in which case its elements will get appended one-by-one, all using the provided typehint """ if type(argument) == dict: argument = list(argument.items()) elif isinstance(argument, OSCMessage): raise TypeError("Can only append 'OSCMessage' to 'OSCBundle'") if isinstance(argument, (tuple, list)): for arg in argument: self.append(arg, typehint) return if typehint == 'b': binary = OSCBlob(argument) tag = 'b' elif typehint == 't': binary = OSCTimeTag(argument) tag = 't' else: tag, binary = OSCArgument(argument, typehint) self.typetags += tag self.message += binary def getBinary(self): """Returns the binary representation of the message """ binary = OSCString(self.address) binary += OSCString(self.typetags) binary += self.message return binary def __repr__(self): """Returns a string containing the decode Message """ return str(decodeOSC(self.getBinary())) def __str__(self): """Returns the Message's address and contents as a string. """ return "%s %s" % (self.address, str(list(self.values()))) def __len__(self): """Returns the number of arguments appended so far """ return (len(self.typetags) - 1) def __eq__(self, other): """Return True if two OSCMessages have the same address & content """ if not isinstance(other, self.__class__): return False return (self.address == other.address) and (self.typetags == other.typetags) and (self.message == other.message) def __ne__(self, other): """Return (not self.__eq__(other)) """ return not self.__eq__(other) def __add__(self, values): """Returns a copy of self, with the contents of 'values' appended (see the 'extend()' method, below) """ msg = self.copy() msg.extend(values) return msg def __iadd__(self, values): """Appends the contents of 'values' (equivalent to 'extend()', below) Returns self """ self.extend(values) return self def __radd__(self, values): """Appends the contents of this OSCMessage to 'values' Returns the extended 'values' (list or tuple) """ out = list(values) out.extend(list(self.values())) if type(values) == tuple: return tuple(out) return out def _reencode(self, items): """Erase & rebuild the OSCMessage contents from the given list of (typehint, value) tuples""" self.clearData() for item in items: self.append(item[1], item[0]) def values(self): """Returns a list of the arguments appended so far """ # print(self.getBinary().decode()) return decodeOSC(self.getBinary())[2:] def tags(self): """Returns a list of typetags of the appended arguments """ return list(self.typetags.lstrip(',')) def items(self): """Returns a list of (typetag, value) tuples for the arguments appended so far """ out = [] values = list(self.values()) typetags = self.tags() for i in range(len(values)): out.append((typetags[i], values[i])) return out def __contains__(self, val): """Test if the given value appears in the OSCMessage's arguments """ return (val in list(self.values())) def __getitem__(self, i): """Returns the indicated argument (or slice) """ return list(self.values())[i] def __delitem__(self, i): """Removes the indicated argument (or slice) """ items = list(self.items()) del items[i] self._reencode(items) def _buildItemList(self, values, typehint=None): if isinstance(values, OSCMessage): items = list(values.items()) elif type(values) == list: items = [] for val in values: if type(val) == tuple: items.append(val[:2]) else: items.append((typehint, val)) elif type(values) == tuple: items = [values[:2]] else: items = [(typehint, values)] return items def __setitem__(self, i, val): """Set indicatated argument (or slice) to a new value. 'val' can be a single int/float/string, or a (typehint, value) tuple. Or, if 'i' is a slice, a list of these or another OSCMessage. """ items = list(self.items()) new_items = self._buildItemList(val) if type(i) != slice: if len(new_items) != 1: raise TypeError("single-item assignment expects a single value or a (typetag, value) tuple") new_items = new_items[0] # finally... items[i] = new_items self._reencode(items) def setItem(self, i, val, typehint=None): """Set indicated argument to a new value (with typehint) """ items = list(self.items()) items[i] = (typehint, val) self._reencode(items) def copy(self): """Returns a deep copy of this OSCMessage """ msg = self.__class__(self.address) msg.typetags = self.typetags msg.message = self.message return msg def count(self, val): """Returns the number of times the given value occurs in the OSCMessage's arguments """ return list(self.values()).count(val) def index(self, val): """Returns the index of the first occurence of the given value in the OSCMessage's arguments. Raises ValueError if val isn't found """ return list(self.values()).index(val) def extend(self, values): """Append the contents of 'values' to this OSCMessage. 'values' can be another OSCMessage, or a list/tuple of ints/floats/strings """ items = list(self.items()) + self._buildItemList(values) self._reencode(items) def insert(self, i, val, typehint = None): """Insert given value (with optional typehint) into the OSCMessage at the given index. """ items = list(self.items()) for item in reversed(self._buildItemList(val)): items.insert(i, item) self._reencode(items) def popitem(self, i): """Delete the indicated argument from the OSCMessage, and return it as a (typetag, value) tuple. """ items = list(self.items()) item = items.pop(i) self._reencode(items) return item def pop(self, i): """Delete the indicated argument from the OSCMessage, and return it. """ return self.popitem(i)[1] def reverse(self): """Reverses the arguments of the OSCMessage (in place) """ items = list(self.items()) items.reverse() self._reencode(items) def remove(self, val): """Removes the first argument with the given value from the OSCMessage. Raises ValueError if val isn't found. """ items = list(self.items()) # this is not very efficient... i = 0 for (t, v) in items: if (v == val): break i += 1 else: raise ValueError("'%s' not in OSCMessage" % str(v)) # but more efficient than first calling self.values().index(val), # then calling self.items(), which would in turn call self.values() again... del items[i] self._reencode(items) def __iter__(self): """Returns an iterator of the OSCMessage's arguments """ return iter(list(self.values())) def __reversed__(self): """Returns a reverse iterator of the OSCMessage's arguments """ return reversed(list(self.values())) def itervalues(self): """Returns an iterator of the OSCMessage's arguments """ return iter(list(self.values())) def iteritems(self): """Returns an iterator of the OSCMessage's arguments as (typetag, value) tuples """ return iter(list(self.items())) def itertags(self): """Returns an iterator of the OSCMessage's arguments' typetags """ return iter(self.tags()) class OSCBundle(OSCMessage): """Builds a 'bundle' of OSC messages. OSCBundle objects are container objects for building OSC-bundles of OSC-messages. An OSC-bundle is a special kind of OSC-message which contains a list of OSC-messages (And yes, OSC-bundles may contain other OSC-bundles...) OSCBundle objects behave much the same as OSCMessage objects, with these exceptions: - if an item or items to be appended or inserted are not OSCMessage objects, OSCMessage objectss are created to encapsulate the item(s) - an OSC-bundle does not have an address of its own, only the contained OSC-messages do. The OSCBundle's 'address' is inherited by any OSCMessage the OSCBundle object creates. - OSC-bundles have a timetag to tell the receiver when the bundle should be processed. The default timetag value (0) means 'immediately' """ def __init__(self, address="", time=0): """Instantiate a new OSCBundle. The default OSC-address for newly created OSCMessages can be specified with the 'address' argument The bundle's timetag can be set with the 'time' argument """ super(OSCBundle, self).__init__(address) self.timetag = time def __str__(self): """Returns the Bundle's contents (and timetag, if nonzero) as a string. """ if (self.timetag > 0.): out = "#bundle (%s) [" % self.getTimeTagStr() else: out = "#bundle [" if self.__len__(): for val in list(self.values()): out += "%s, " % str(val) out = out[:-2] # strip trailing space and comma return out + "]" def setTimeTag(self, time): """Set or change the OSCBundle's TimeTag In 'Python Time', that's floating seconds since the Epoch """ if time >= 0: self.timetag = time def getTimeTagStr(self): """Return the TimeTag as a human-readable string """ fract, secs = math.modf(self.timetag) out = time.ctime(secs)[11:19] out += ("%.3f" % fract)[1:] return out def append(self, argument, typehint = None): """Appends data to the bundle, creating an OSCMessage to encapsulate the provided argument unless this is already an OSCMessage. Any newly created OSCMessage inherits the OSCBundle's address at the time of creation. If 'argument' is an iterable, its elements will be encapsuated by a single OSCMessage. Finally, 'argument' can be (or contain) a dict, which will be 'converted' to an OSCMessage; - if 'addr' appears in the dict, its value overrides the OSCBundle's address - if 'args' appears in the dict, its value(s) become the OSCMessage's arguments """ if isinstance(argument, OSCMessage): binary = OSCBlob(argument.getBinary()) else: msg = OSCMessage(self.address) if type(argument) == dict: if 'addr' in argument: msg.setAddress(argument['addr']) if 'args' in argument: msg.append(argument['args'], typehint) else: msg.append(argument, typehint) binary = OSCBlob(msg.getBinary()) self.message += binary self.typetags += 'b' def getBinary(self): """Returns the binary representation of the message """ binary = OSCString("#bundle") binary += OSCTimeTag(self.timetag) binary += self.message return binary def _reencapsulate(self, decoded): # print(decoded) if decoded[0] == "#bundle": msg = OSCBundle() msg.setTimeTag(decoded[1]) for submsg in decoded[2:]: msg.append(self._reencapsulate(submsg)) else: msg = OSCMessage(decoded[0]) tags = decoded[1].lstrip(',') for i in range(len(tags)): msg.append(decoded[2+i], tags[i]) return msg def values(self): """Returns a list of the OSCMessages appended so far """ # print("Bundle binary:", self.getBinary()) out = [] for decoded in decodeOSC(self.getBinary())[2:]: out.append(self._reencapsulate(decoded)) return out def __eq__(self, other): """Return True if two OSCBundles have the same timetag & content """ if not isinstance(other, self.__class__): return False return (self.timetag == other.timetag) and (self.typetags == other.typetags) and (self.message == other.message) def copy(self): """Returns a deep copy of this OSCBundle """ copy = super(OSCBundle, self).copy() copy.timetag = self.timetag return copy ###### # # OSCMessage encoding functions # ###### def OSCString(next): """Convert a string into a zero-padded OSC String. The length of the resulting string is always a multiple of 4 bytes. The string ends with 1 to 4 zero-bytes ('\x00') """ if sys.version_info[0] > 2: next = bytes(next.encode("UTF-8")) # this could be the problem? else: next = str(next) OSCstringLength = math.ceil((len(next)+1) / 4.0) * 4 return struct.pack(">%ds" % (OSCstringLength), next) def OSCBlob(next): """Convert a string into an OSC Blob. An OSC-Blob is a binary encoded block of data, prepended by a 'size' (int32). The size is always a mutiple of 4 bytes. The blob ends with 0 to 3 zero-bytes ('\x00') """ if type(next) in (bytes, str): OSCblobLength = math.ceil((len(next)) / 4.0) * 4 binary = struct.pack(">i%ds" % (OSCblobLength), OSCblobLength, next) # TODO RYAN else: binary = "" return binary def OSCArgument(next, typehint=None): """ Convert some Python types to their OSC binary representations, returning a (typetag, data) tuple. """ if not typehint: if type(next) in FloatTypes: binary = struct.pack(">f", float(next)) tag = 'f' elif type(next) in IntTypes: binary = struct.pack(">i", int(next)) tag = 'i' else: binary = OSCString(next) tag = 's' elif typehint == 'd': try: binary = struct.pack(">d", float(next)) tag = 'd' except ValueError: binary = OSCString(next) tag = 's' elif typehint == 'f': try: binary = struct.pack(">f", float(next)) tag = 'f' except ValueError: binary = OSCString(next) tag = 's' elif typehint == 'i': try: binary = struct.pack(">i", int(next)) tag = 'i' except ValueError: binary = OSCString(next) tag = 's' else: binary = OSCString(next) tag = 's' return (tag, binary) def OSCTimeTag(time): """Convert a time in floating seconds to its OSC binary representation """ if time > 0: fract, secs = math.modf(time) secs = secs - NTP_epoch binary = struct.pack('>LL', int(secs), int(fract * NTP_units_per_second)) else: binary = struct.pack('>LL', 0, 1) return binary ###### # # OSCMessage decoding functions # ###### def _readString(data): """Reads the next (null-terminated) block of data """ #length = string.find(data,"\0") #length = str(data).find("\x00") length = data.index(b"\x00") nextData = int(math.ceil((length+1) / 4.0) * 4) output = (data[0:length].decode(), data[nextData:]) return output def _readBlob(data): """Reads the next (numbered) block of data """ length = struct.unpack(">i", data[0:4])[0] nextData = int(math.ceil((length) / 4.0) * 4) + 4 return (data[4:length+4], data[nextData:]) def _readInt(data): """Tries to interpret the next 4 bytes of the data as a 32-bit integer. """ if(len(data)<4): print("Error: too few bytes for int", data, len(data)) rest = data integer = 0 else: integer = struct.unpack(">i", data[0:4])[0] rest = data[4:] return (integer, rest) def _readLong(data): """Tries to interpret the next 8 bytes of the data as a 64-bit signed integer. """ high, low = struct.unpack(">ll", data[0:8]) big = (int(high) << 32) + low rest = data[8:] return (big, rest) def _readTimeTag(data): """Tries to interpret the next 8 bytes of the data as a TimeTag. """ high, low = struct.unpack(">LL", data[0:8]) if (high == 0) and (low <= 1): time = 0.0 else: time = int(NTP_epoch + high) + float(low / NTP_units_per_second) rest = data[8:] return (time, rest) def _readFloat(data): """Tries to interpret the next 4 bytes of the data as a 32-bit float. """ if(len(data)<4): print("Error: too few bytes for float", data, len(data)) rest = data float = 0 else: float = struct.unpack(">f", data[0:4])[0] rest = data[4:] return (float, rest) def _readDouble(data): """Tries to interpret the next 8 bytes of the data as a 64-bit float. """ if(len(data)<8): print("Error: too few bytes for double", data, len(data)) rest = data float = 0 else: float = struct.unpack(">d", data[0:8])[0] rest = data[8:] return (float, rest) def decodeOSC(data): """Converts a binary OSC message to a Python list. """ table = {"i":_readInt, "f":_readFloat, "s":_readString, "b":_readBlob, "d":_readDouble, "t":_readTimeTag} decoded = [] address, rest = _readString(data) if address.startswith(","): typetags = address address = "" else: typetags = "" if address == "#bundle": time, rest = _readTimeTag(rest) decoded.append(address) decoded.append(time) while len(rest)>0: length, rest = _readInt(rest) decoded.append(decodeOSC(rest[:length])) rest = rest[length:] elif len(rest)>0: if not len(typetags): typetags, rest = _readString(rest) decoded.append(address) decoded.append(typetags) if typetags.startswith(","): #.encode("utf-8")): for tag in typetags[1:]: # print(tag, rest) value, rest = table[tag](rest) decoded.append(value) else: raise OSCError("OSCMessage's typetag-string lacks the magic ','") return decoded ###### # # Utility functions # ###### def hexDump(bytes): """ Useful utility; prints the string in hexadecimal. """ print("byte 0 1 2 3 4 5 6 7 8 9 A B C D E F") num = len(bytes) for i in range(num): if (i) % 16 == 0: line = "%02X0 : " % (i/16) line += "%02X " % ord(bytes[i]) if (i+1) % 16 == 0: print("%s: %s" % (line, repr(bytes[i-15:i+1]))) line = "" bytes_left = num % 16 if bytes_left: print("%s: %s" % (line.ljust(54), repr(bytes[-bytes_left:]))) def getUrlStr(*args): """Convert provided arguments to a string in 'host:port/prefix' format Args can be: - (host, port) - (host, port), prefix - host, port - host, port, prefix """ if not len(args): return "" if type(args[0]) == tuple: host = args[0][0] port = args[0][1] args = args[1:] else: host = args[0] port = args[1] args = args[2:] if len(args): prefix = args[0] else: prefix = "" if len(host) and (host != '0.0.0.0'): try: (host, _, _) = socket.gethostbyaddr(host) except socket.error: pass else: host = 'localhost' if type(port) == int: return "%s:%d%s" % (host, port, prefix) else: return host + prefix def parseUrlStr(url): """Convert provided string in 'host:port/prefix' format to it's components Returns ((host, port), prefix) """ if not (type(url) in str and len(url)): return (None, '') i = url.find("://") if i > -1: url = url[i+3:] i = url.find(':') if i > -1: host = url[:i].strip() tail = url[i+1:].strip() else: host = '' tail = url for i in range(len(tail)): if not tail[i].isdigit(): break else: i += 1 portstr = tail[:i].strip() tail = tail[i:].strip() found = len(tail) for c in ('/', '+', '-', '*'): i = tail.find(c) if (i > -1) and (i < found): found = i head = tail[:found].strip() prefix = tail[found:].strip() prefix = prefix.strip('/') if len(prefix) and prefix[0] not in ('+', '-', '*'): prefix = '/' + prefix if len(head) and not len(host): host = head if len(host): try: host = socket.gethostbyname(host) except socket.error: pass try: port = int(portstr) except ValueError: port = None return ((host, port), prefix) ###### # # OSCClient class # ###### class OSCClient(object): """Simple OSC Client. Handles the sending of OSC-Packets (OSCMessage or OSCBundle) via a UDP-socket """ # set outgoing socket buffer size sndbuf_size = 4096 * 8 def __init__(self, server=None): """Construct an OSC Client. - server: Local OSCServer-instance this client will use the socket of for transmissions. If none is supplied, a socket will be created. """ self.socket = None self.setServer(server) self.client_address = None def _setSocket(self, skt): """Set and configure client socket""" if self.socket != None: self.close() self.socket = skt self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.sndbuf_size) self._fd = self.socket.fileno() def _ensureConnected(self, address): """Make sure client has a socket connected to address""" if not self.socket: if len(address) == 4: address_family = socket.AF_INET6 else: address_family = socket.AF_INET self._setSocket(socket.socket(address_family, socket.SOCK_DGRAM)) self.socket.connect(address) def setServer(self, server): """Associate this Client with given server. The Client will send from the Server's socket. The Server will use this Client instance to send replies. """ if server == None: if hasattr(self,'server') and self.server: if self.server.client != self: raise OSCClientError("Internal inconsistency") self.server.client.close() self.server.client = None self.server = None return if not isinstance(server, OSCServer): raise ValueError("'server' argument is not a valid OSCServer object") self._setSocket(server.socket.dup()) self.server = server if self.server.client != None: self.server.client.close() self.server.client = self def close(self): """Disconnect & close the Client's socket """ if self.socket != None: self.socket.close() self.socket = None def __str__(self): """Returns a string containing this Client's Class-name, software-version and the remote-address it is connected to (if any) """ out = self.__class__.__name__ out += " v%s.%s-%s" % version addr = self.address() if addr: out += " connected to osc://%s" % getUrlStr(addr) else: out += " (unconnected)" return out def __eq__(self, other): """Compare function. """ if not isinstance(other, self.__class__): return False if self.socket and other.socket: sockEqual = cmp(self.socket._sock, other.socket._sock) else: sockEqual = (self.socket == None and other.socket == None) if not sockEqual: return False if self.server and other.server: return cmp(self.server, other.server) else: return self.server == None and other.server == None def __ne__(self, other): """Compare function. """ return not self.__eq__(other) def address(self): """Returns a (host,port) tuple of the remote server this client is connected to or None if not connected to any server. """ try: if self.socket: return self.socket.getpeername() else: return None except socket.error: return None def connect(self, address): """Bind to a specific OSC server: the 'address' argument is a (host, port) tuple - host: hostname of the remote OSC server, - port: UDP-port the remote OSC server listens to. """ try: self._ensureConnected(address) self.client_address = address except socket.error as e: self.client_address = None raise OSCClientError("SocketError: %s" % str(e)) if self.server != None: self.server.return_port = address[1] def sendto(self, msg, address, timeout=None): """Send the given OSCMessage to the specified address. - msg: OSCMessage (or OSCBundle) to be sent - address: (host, port) tuple specifing remote server to send the message to - timeout: A timeout value for attempting to send. If timeout == None, this call blocks until socket is available for writing. Raises OSCClientError when timing out while waiting for the socket. """ if not isinstance(msg, OSCMessage): raise TypeError("'msg' argument is not an OSCMessage or OSCBundle object") ret = select.select([],[self._fd], [], timeout) try: ret[1].index(self._fd) except: # for the very rare case this might happen raise OSCClientError("Timed out waiting for file descriptor") try: self._ensureConnected(address) self.socket.sendall(msg.getBinary()) if self.client_address: self.socket.connect(self.client_address) except socket.error as e: if e[0] in (7, 65): # 7 = 'no address associated with nodename', 65 = 'no route to host' raise e else: raise OSCClientError("while sending to %s: %s" % (str(address), str(e))) def send(self, msg, timeout=None): """Send the given OSCMessage. The Client must be already connected. - msg: OSCMessage (or OSCBundle) to be sent - timeout: A timeout value for attempting to send. If timeout == None, this call blocks until socket is available for writing. Raises OSCClientError when timing out while waiting for the socket, or when the Client isn't connected to a remote server. """ if not isinstance(msg, OSCMessage): raise TypeError("'msg' argument is not an OSCMessage or OSCBundle object") if not self.socket: raise OSCClientError("Called send() on non-connected client") ret = select.select([],[self._fd], [], timeout) try: ret[1].index(self._fd) except: # for the very rare case this might happen raise OSCClientError("Timed out waiting for file descriptor") try: self.socket.sendall(msg.getBinary()) except socket.error as e: raise OSCClientError("while sending: %s" % str(e)) ###### # # FilterString Utility functions # ###### def parseFilterStr(args): """Convert Message-Filter settings in '+ - ...' format to a dict of the form { '':True, '':False, ... } Returns a list: ['', filters] """ out = {} if type(args) in str: args = [args] prefix = None for arg in args: head = None for plus in arg.split('+'): minus = plus.split('-') plusfs = minus.pop(0).strip() if len(plusfs): plusfs = '/' + plusfs.strip('/') if (head == None) and (plusfs != "/*"): head = plusfs elif len(plusfs): if plusfs == '/*': out = { '/*':True } # reset all previous filters else: out[plusfs] = True for minusfs in minus: minusfs = minusfs.strip() if len(minusfs): minusfs = '/' + minusfs.strip('/') if minusfs == '/*': out = { '/*':False } # reset all previous filters else: out[minusfs] = False if prefix == None: prefix = head return [prefix, out] def getFilterStr(filters): """Return the given 'filters' dict as a list of '+' | '-' filter-strings """ if not len(filters): return [] if '/*' in list(filters.keys()): if filters['/*']: out = ["+/*"] else: out = ["-/*"] else: if False in list(filters.values()): out = ["+/*"] else: out = ["-/*"] for (addr, bool) in list(filters.items()): if addr == '/*': continue if bool: out.append("+%s" % addr) else: out.append("-%s" % addr) return out # A translation-table for mapping OSC-address expressions to Python 're' expressions if sys.version_info[0] > 2: OSCtrans = str.maketrans("{,}?","(|).") else: OSCtrans = string.maketrans("{,}?","(|).") def getRegEx(pattern): """Compiles and returns a 'regular expression' object for the given address-pattern. """ # Translate OSC-address syntax to python 're' syntax if type(pattern) is bytes: pattern = pattern.decode() pattern = pattern.replace(".", r"\.") # first, escape all '.'s in the pattern. pattern = pattern.replace("(", r"\(") # escape all '('s. pattern = pattern.replace(")", r"\)") # escape all ')'s. pattern = pattern.replace("*", r".*") # replace a '*' by '.*' (match 0 or more characters) pattern = pattern.translate(OSCtrans) # change '?' to '.' and '{,}' to '(|)' return re.compile(pattern) ###### # # OSCMultiClient class # ###### class OSCMultiClient(OSCClient): """'Multiple-Unicast' OSC Client. Handles the sending of OSC-Packets (OSCMessage or OSCBundle) via a UDP-socket This client keeps a dict of 'OSCTargets'. and sends each OSCMessage to each OSCTarget The OSCTargets are simply (host, port) tuples, and may be associated with an OSC-address prefix. the OSCTarget's prefix gets prepended to each OSCMessage sent to that target. """ def __init__(self, server=None): """Construct a "Multi" OSC Client. - server: Local OSCServer-instance this client will use the socket of for transmissions. If none is supplied, a socket will be created. """ super(OSCMultiClient, self).__init__(server) self.targets = {} def _searchHostAddr(self, host): """Search the subscribed OSCTargets for (the first occurence of) given host. Returns a (host, port) tuple """ try: host = socket.gethostbyname(host) except socket.error: pass for addr in list(self.targets.keys()): if host == addr[0]: return addr raise NotSubscribedError((host, None)) def _updateFilters(self, dst, src): """Update a 'filters' dict with values form another 'filters' dict: - src[a] == True and dst[a] == False: del dst[a] - src[a] == False and dst[a] == True: del dst[a] - a not in dst: dst[a] == src[a] """ if '/*' in list(src.keys()): # reset filters dst.clear() # 'match everything' == no filters if not src.pop('/*'): dst['/*'] = False # 'match nothing' for (addr, bool) in list(src.items()): if (addr in list(dst.keys())) and (dst[addr] != bool): del dst[addr] else: dst[addr] = bool def _setTarget(self, address, prefix=None, filters=None): """Add (i.e. subscribe) a new OSCTarget, or change the prefix for an existing OSCTarget. - address ((host, port) tuple): IP-address & UDP-port - prefix (string): The OSC-address prefix prepended to the address of each OSCMessage sent to this OSCTarget (optional) """ if address not in list(self.targets.keys()): self.targets[address] = ["",{}] if prefix != None: if len(prefix): # make sure prefix starts with ONE '/', and does not end with '/' prefix = '/' + prefix.strip('/') self.targets[address][0] = prefix if filters != None: if type(filters) in str: (_, filters) = parseFilterStr(filters) elif type(filters) != dict: raise TypeError("'filters' argument must be a dict with {addr:bool} entries") self._updateFilters(self.targets[address][1], filters) def setOSCTarget(self, address, prefix=None, filters=None): """Add (i.e. subscribe) a new OSCTarget, or change the prefix for an existing OSCTarget. the 'address' argument can be a ((host, port) tuple) : The target server address & UDP-port or a 'host' (string) : The host will be looked-up - prefix (string): The OSC-address prefix prepended to the address of each OSCMessage sent to this OSCTarget (optional) """ if type(address) in str: address = self._searchHostAddr(address) elif (type(address) == tuple): (host, port) = address[:2] try: host = socket.gethostbyname(host) except: pass address = (host, port) else: raise TypeError("'address' argument must be a (host, port) tuple or a 'host' string") self._setTarget(address, prefix, filters) def setOSCTargetFromStr(self, url): """Adds or modifies a subscribed OSCTarget from the given string, which should be in the ':[/] [+/]|[-/] ...' format. """ (addr, tail) = parseUrlStr(url) (prefix, filters) = parseFilterStr(tail) self._setTarget(addr, prefix, filters) def _delTarget(self, address, prefix=None): """Delete the specified OSCTarget from the Client's dict. the 'address' argument must be a (host, port) tuple. If the 'prefix' argument is given, the Target is only deleted if the address and prefix match. """ try: if prefix == None: del self.targets[address] elif prefix == self.targets[address][0]: del self.targets[address] except KeyError: raise NotSubscribedError(address, prefix) def delOSCTarget(self, address, prefix=None): """Delete the specified OSCTarget from the Client's dict. the 'address' argument can be a ((host, port) tuple), or a hostname. If the 'prefix' argument is given, the Target is only deleted if the address and prefix match. """ if type(address) in str: address = self._searchHostAddr(address) if type(address) == tuple: (host, port) = address[:2] try: host = socket.gethostbyname(host) except socket.error: pass address = (host, port) self._delTarget(address, prefix) def hasOSCTarget(self, address, prefix=None): """Return True if the given OSCTarget exists in the Client's dict. the 'address' argument can be a ((host, port) tuple), or a hostname. If the 'prefix' argument is given, the return-value is only True if the address and prefix match. """ if type(address) in str: address = self._searchHostAddr(address) if type(address) == tuple: (host, port) = address[:2] try: host = socket.gethostbyname(host) except socket.error: pass address = (host, port) if address in list(self.targets.keys()): if prefix == None: return True elif prefix == self.targets[address][0]: return True return False def getOSCTargets(self): """Returns the dict of OSCTargets: {addr:[prefix, filters], ...} """ out = {} for ((host, port), pf) in list(self.targets.items()): try: (host, _, _) = socket.gethostbyaddr(host) except socket.error: pass out[(host, port)] = pf return out def getOSCTarget(self, address): """Returns the OSCTarget matching the given address as a ((host, port), [prefix, filters]) tuple. 'address' can be a (host, port) tuple, or a 'host' (string), in which case the first matching OSCTarget is returned Returns (None, ['',{}]) if address not found. """ if type(address) in str: address = self._searchHostAddr(address) if (type(address) == tuple): (host, port) = address[:2] try: host = socket.gethostbyname(host) except socket.error: pass address = (host, port) if (address in list(self.targets.keys())): try: (host, _, _) = socket.gethostbyaddr(host) except socket.error: pass return ((host, port), self.targets[address]) return (None, ['',{}]) def clearOSCTargets(self): """Erases all OSCTargets from the Client's dict """ self.targets = {} def updateOSCTargets(self, dict): """Update the Client's OSCTargets dict with the contents of 'dict' The given dict's items MUST be of the form { (host, port):[prefix, filters], ... } """ for ((host, port), (prefix, filters)) in list(dict.items()): val = [prefix, {}] self._updateFilters(val[1], filters) try: host = socket.gethostbyname(host) except socket.error: pass self.targets[(host, port)] = val def getOSCTargetStr(self, address): """Returns the OSCTarget matching the given address as a ('osc://:[]', ['', ...])' tuple. 'address' can be a (host, port) tuple, or a 'host' (string), in which case the first matching OSCTarget is returned Returns (None, []) if address not found. """ (addr, (prefix, filters)) = self.getOSCTarget(address) if addr == None: return (None, []) return ("osc://%s" % getUrlStr(addr, prefix), getFilterStr(filters)) def getOSCTargetStrings(self): """Returns a list of all OSCTargets as ('osc://:[]', ['', ...])' tuples. """ out = [] for (addr, (prefix, filters)) in list(self.targets.items()): out.append(("osc://%s" % getUrlStr(addr, prefix), getFilterStr(filters))) return out def connect(self, address): """The OSCMultiClient isn't allowed to connect to any specific address. """ return NotImplemented def sendto(self, msg, address, timeout=None): """Send the given OSCMessage. The specified address is ignored. Instead this method calls send() to send the message to all subscribed clients. - msg: OSCMessage (or OSCBundle) to be sent - address: (host, port) tuple specifing remote server to send the message to - timeout: A timeout value for attempting to send. If timeout == None, this call blocks until socket is available for writing. Raises OSCClientError when timing out while waiting for the socket. """ self.send(msg, timeout) def _filterMessage(self, filters, msg): """Checks the given OSCMessge against the given filters. 'filters' is a dict containing OSC-address:bool pairs. If 'msg' is an OSCBundle, recursively filters its constituents. Returns None if the message is to be filtered, else returns the message. or Returns a copy of the OSCBundle with the filtered messages removed. """ if isinstance(msg, OSCBundle): out = msg.copy() msgs = list(out.values()) out.clearData() for m in msgs: m = self._filterMessage(filters, m) if m: # this catches 'None' and empty bundles. out.append(m) elif isinstance(msg, OSCMessage): if '/*' in list(filters.keys()): if filters['/*']: out = msg else: out = None elif False in list(filters.values()): out = msg else: out = None else: raise TypeError("'msg' argument is not an OSCMessage or OSCBundle object") expr = getRegEx(msg.address) for addr in list(filters.keys()): if addr == '/*': continue match = expr.match(addr) if match and (match.end() == len(addr)): if filters[addr]: out = msg else: out = None break return out def _prefixAddress(self, prefix, msg): """Makes a copy of the given OSCMessage, then prepends the given prefix to The message's OSC-address. If 'msg' is an OSCBundle, recursively prepends the prefix to its constituents. """ out = msg.copy() if isinstance(msg, OSCBundle): msgs = list(out.values()) out.clearData() for m in msgs: out.append(self._prefixAddress(prefix, m)) elif isinstance(msg, OSCMessage): out.setAddress(prefix + out.address) else: raise TypeError("'msg' argument is not an OSCMessage or OSCBundle object") return out def send(self, msg, timeout=None): """Send the given OSCMessage to all subscribed OSCTargets - msg: OSCMessage (or OSCBundle) to be sent - timeout: A timeout value for attempting to send. If timeout == None, this call blocks until socket is available for writing. Raises OSCClientError when timing out while waiting for the socket. """ for (address, (prefix, filters)) in list(self.targets.items()): if len(filters): out = self._filterMessage(filters, msg) if not out: # this catches 'None' and empty bundles. continue else: out = msg if len(prefix): out = self._prefixAddress(prefix, msg) binary = out.getBinary() ret = select.select([],[self._fd], [], timeout) try: ret[1].index(self._fd) except: # for the very rare case this might happen raise OSCClientError("Timed out waiting for file descriptor") try: while len(binary): sent = self.socket.sendto(binary, address) binary = binary[sent:] except socket.error as e: if e[0] in (7, 65): # 7 = 'no address associated with nodename', 65 = 'no route to host' raise e else: raise OSCClientError("while sending to %s: %s" % (str(address), str(e))) class OSCAddressSpace: def __init__(self): self.callbacks = {} def addMsgHandler(self, address, callback): """Register a handler for an OSC-address - 'address' is the OSC address-string. the address-string should start with '/' and may not contain '*' - 'callback' is the function called for incoming OSCMessages that match 'address'. The callback-function will be called with the same arguments as the 'msgPrinter_handler' below """ for chk in '*?,[]{}# ': if chk in address: raise OSCServerError("OSC-address string may not contain any characters in '*?,[]{}# '") if type(callback) not in (types.FunctionType, types.MethodType): raise OSCServerError("Message callback '%s' is not callable" % repr(callback)) if address != 'default': address = '/' + address.strip('/') self.callbacks[address] = callback def delMsgHandler(self, address): """Remove the registered handler for the given OSC-address """ del self.callbacks[address] def getOSCAddressSpace(self): """Returns a list containing all OSC-addresses registerd with this Server. """ return list(self.callbacks.keys()) def dispatchMessage(self, pattern, tags, data, client_address): """Attmept to match the given OSC-address pattern, which may contain '*', against all callbacks registered with the OSCServer. Calls the matching callback and returns whatever it returns. If no match is found, and a 'default' callback is registered, it calls that one, or raises NoCallbackError if a 'default' callback is not registered. - pattern (string): The OSC-address of the receied message - tags (string): The OSC-typetags of the receied message's arguments, without ',' - data (list): The message arguments """ if len(tags) != len(data): raise OSCServerError("Malformed OSC-message; got %d typetags [%s] vs. %d values" % (len(tags), tags, len(data))) expr = getRegEx(pattern) replies = [] matched = 0 for addr in list(self.callbacks.keys()): match = expr.match(addr) if match and (match.end() == len(addr)): reply = self.callbacks[addr](pattern, tags, data, client_address) matched += 1 if isinstance(reply, OSCMessage): replies.append(reply) elif reply != None: raise TypeError("Message-callback %s did not return OSCMessage or None: %s" % (self.server.callbacks[addr], type(reply))) if matched == 0: if 'default' in self.callbacks: reply = self.callbacks['default'](pattern, tags, data, client_address) if isinstance(reply, OSCMessage): replies.append(reply) elif reply != None: raise TypeError("Message-callback %s did not return OSCMessage or None: %s" % (self.server.callbacks['default'], type(reply))) else: raise NoCallbackError(pattern) return replies ###### # # OSCRequestHandler classes # ###### class OSCRequestHandler(DatagramRequestHandler): """RequestHandler class for the OSCServer """ def setup(self): """Prepare RequestHandler. Unpacks request as (packet, source socket address) Creates an empty list for replies. """ (self.packet, self.socket) = self.request self.replies = [] def _unbundle(self, decoded): """Recursive bundle-unpacking function""" if decoded[0] != "#bundle": self.replies += self.server.dispatchMessage(decoded[0], decoded[1][1:], decoded[2:], self.client_address) return now = time.time() timetag = decoded[1] if (timetag > 0.) and (timetag > now): time.sleep(timetag - now) for msg in decoded[2:]: self._unbundle(msg) def handle(self): """Handle incoming OSCMessage """ decoded = decodeOSC(self.packet) if not len(decoded): return self._unbundle(decoded) def finish(self): """Finish handling OSCMessage. Send any reply returned by the callback(s) back to the originating client as an OSCMessage or OSCBundle """ if self.server.return_port: self.client_address = (self.client_address[0], self.server.return_port) if len(self.replies) > 1: msg = OSCBundle() for reply in self.replies: msg.append(reply) elif len(self.replies) == 1: msg = self.replies[0] else: return self.server.client.sendto(msg, self.client_address) class ThreadingOSCRequestHandler(OSCRequestHandler): """Multi-threaded OSCRequestHandler; Starts a new RequestHandler thread for each unbundled OSCMessage """ def _unbundle(self, decoded): """Recursive bundle-unpacking function This version starts a new thread for each sub-Bundle found in the Bundle, then waits for all its children to finish. """ if decoded[0] != "#bundle": self.replies += self.server.dispatchMessage(decoded[0], decoded[1][1:], decoded[2:], self.client_address) return now = time.time() timetag = decoded[1] if (timetag > 0.) and (timetag > now): time.sleep(timetag - now) now = time.time() children = [] for msg in decoded[2:]: t = threading.Thread(target = self._unbundle, args = (msg,)) t.start() children.append(t) # wait for all children to terminate for t in children: t.join() ###### # # OSCServer classes # ###### class OSCServer(UDPServer, OSCAddressSpace): """A Synchronous OSCServer Serves one request at-a-time, until the OSCServer is closed. The OSC address-pattern is matched against a set of OSC-adresses that have been registered to the server with a callback-function. If the adress-pattern of the message machtes the registered address of a callback, that function is called. """ # set the RequestHandlerClass, will be overridden by ForkingOSCServer & ThreadingOSCServer RequestHandlerClass = OSCRequestHandler # define a socket timeout, so the serve_forever loop can actually exit. socket_timeout = 1 # DEBUG: print error-tracebacks (to stderr)? print_tracebacks = False def __init__(self, server_address, client=None, return_port=0): """Instantiate an OSCServer. - server_address ((host, port) tuple): the local host & UDP-port the server listens on - client (OSCClient instance): The OSCClient used to send replies from this server. If none is supplied (default) an OSCClient will be created. - return_port (int): if supplied, sets the default UDP destination-port for replies coming from this server. """ UDPServer.__init__(self, server_address, self.RequestHandlerClass) OSCAddressSpace.__init__(self) self.setReturnPort(return_port) self.error_prefix = "" self.info_prefix = "/info" self.socket.settimeout(self.socket_timeout) self.running = False self.client = None if client == None: self.client = OSCClient(server=self) else: self.setClient(client) def setClient(self, client): """Associate this Server with a new local Client instance, closing the Client this Server is currently using. """ if not isinstance(client, OSCClient): raise ValueError("'client' argument is not a valid OSCClient object") if client.server != None: raise OSCServerError("Provided OSCClient already has an OSCServer-instance: %s" % str(client.server)) # Server socket is already listening at this point, so we can't use the client's socket. # we'll have to force our socket on the client... client_address = client.address() # client may be already connected client.close() # shut-down that socket # force our socket upon the client client.setServer(self) if client_address: client.connect(client_address) if not self.return_port: self.return_port = client_address[1] def serve_forever(self): """Handle one request at a time until server is closed.""" self.running = True while self.running: self.handle_request() # this times-out when no data arrives. def close(self): """Stops serving requests, closes server (socket), closes used client """ self.running = False self.client.close() self.server_close() def __str__(self): """Returns a string containing this Server's Class-name, software-version and local bound address (if any) """ out = self.__class__.__name__ out += " v%s.%s-%s" % version addr = self.address() if addr: out += " listening on osc://%s" % getUrlStr(addr) else: out += " (unbound)" return out def __eq__(self, other): """Compare function. """ if not isinstance(other, self.__class__): return False return cmp(self.socket._sock, other.socket._sock) def __ne__(self, other): """Compare function. """ return not self.__eq__(other) def address(self): """Returns a (host,port) tuple of the local address this server is bound to, or None if not bound to any address. """ try: return self.socket.getsockname() except socket.error: return None def setReturnPort(self, port): """Set the destination UDP-port for replies returning from this server to the remote client """ if (port > 1024) and (port < 65536): self.return_port = port else: self.return_port = None def setSrvInfoPrefix(self, pattern): """Set the first part of OSC-address (pattern) this server will use to reply to server-info requests. """ if len(pattern): pattern = '/' + pattern.strip('/') self.info_prefix = pattern def setSrvErrorPrefix(self, pattern=""): """Set the OSC-address (pattern) this server will use to report errors occuring during received message handling to the remote client. If pattern is empty (default), server-errors are not reported back to the client. """ if len(pattern): pattern = '/' + pattern.strip('/') self.error_prefix = pattern def addDefaultHandlers(self, prefix="", info_prefix="/info", error_prefix="/error"): """Register a default set of OSC-address handlers with this Server: - 'default' -> noCallback_handler the given prefix is prepended to all other callbacks registered by this method: - ' serverInfo_handler - ' -> msgPrinter_handler - '/print' -> msgPrinter_handler and, if the used Client supports it; - '/subscribe' -> subscription_handler - '/unsubscribe' -> subscription_handler Note: the given 'error_prefix' argument is also set as default 'error_prefix' for error-messages *sent from* this server. This is ok, because error-messages generally do not elicit a reply from the receiver. To do this with the serverInfo-prefixes would be a bad idea, because if a request received on '/info' (for example) would send replies to '/info', this could potentially cause a never-ending loop of messages! Do *not* set the 'info_prefix' here (for incoming serverinfo requests) to the same value as given to the setSrvInfoPrefix() method (for *replies* to incoming serverinfo requests). For example, use '/info' for incoming requests, and '/inforeply' or '/serverinfo' or even just '/print' as the info-reply prefix. """ self.error_prefix = error_prefix self.addMsgHandler('default', self.noCallback_handler) self.addMsgHandler(prefix + info_prefix, self.serverInfo_handler) self.addMsgHandler(prefix + error_prefix, self.msgPrinter_handler) self.addMsgHandler(prefix + '/print', self.msgPrinter_handler) if isinstance(self.client, OSCMultiClient): self.addMsgHandler(prefix + '/subscribe', self.subscription_handler) self.addMsgHandler(prefix + '/unsubscribe', self.subscription_handler) def printErr(self, txt): """Writes 'OSCServer: txt' to sys.stderr """ sys.stderr.write("OSCServer: %s\n" % txt) def sendOSCerror(self, txt, client_address): """Sends 'txt', encapsulated in an OSCMessage to the default 'error_prefix' OSC-addres. Message is sent to the given client_address, with the default 'return_port' overriding the client_address' port, if defined. """ lines = txt.split('\n') if len(lines) == 1: msg = OSCMessage(self.error_prefix) msg.append(lines[0]) elif len(lines) > 1: msg = OSCBundle(self.error_prefix) for line in lines: msg.append(line) else: return if self.return_port: client_address = (client_address[0], self.return_port) self.client.sendto(msg, client_address) def reportErr(self, txt, client_address): """Writes 'OSCServer: txt' to sys.stderr If self.error_prefix is defined, sends 'txt' as an OSC error-message to the client(s) (see printErr() and sendOSCerror()) """ self.printErr(txt) if len(self.error_prefix): self.sendOSCerror(txt, client_address) def sendOSCinfo(self, txt, client_address): """Sends 'txt', encapsulated in an OSCMessage to the default 'info_prefix' OSC-addres. Message is sent to the given client_address, with the default 'return_port' overriding the client_address' port, if defined. """ lines = txt.split('\n') if len(lines) == 1: msg = OSCMessage(self.info_prefix) msg.append(lines[0]) elif len(lines) > 1: msg = OSCBundle(self.info_prefix) for line in lines: msg.append(line) else: return if self.return_port: client_address = (client_address[0], self.return_port) self.client.sendto(msg, client_address) ### # Message-Handler callback functions ### def handle_error(self, request, client_address): """Handle an exception in the Server's callbacks gracefully. Writes the error to sys.stderr and, if the error_prefix (see setSrvErrorPrefix()) is set, sends the error-message as reply to the client """ (e_type, e) = sys.exc_info()[:2] self.printErr("%s on request from %s: %s" % (e_type.__name__, getUrlStr(client_address), str(e))) if self.print_tracebacks: import traceback traceback.print_exc() # XXX But this goes to stderr! if len(self.error_prefix): self.sendOSCerror("%s: %s" % (e_type.__name__, str(e)), client_address) def noCallback_handler(self, addr, tags, data, client_address): """Example handler for OSCMessages. All registerd handlers must accept these three arguments: - addr (string): The OSC-address pattern of the received Message (the 'addr' string has already been matched against the handler's registerd OSC-address, but may contain '*'s & such) - tags (string): The OSC-typetags of the received message's arguments. (without the preceding comma) - data (list): The OSCMessage's arguments Note that len(tags) == len(data) - client_address ((host, port) tuple): the host & port this message originated from. a Message-handler function may return None, but it could also return an OSCMessage (or OSCBundle), which then gets sent back to the client. This handler prints a "No callback registered to handle ..." message. Returns None """ self.reportErr("No callback registered to handle OSC-address '%s'" % addr, client_address) def msgPrinter_handler(self, addr, tags, data, client_address): """Example handler for OSCMessages. All registerd handlers must accept these three arguments: - addr (string): The OSC-address pattern of the received Message (the 'addr' string has already been matched against the handler's registerd OSC-address, but may contain '*'s & such) - tags (string): The OSC-typetags of the received message's arguments. (without the preceding comma) - data (list): The OSCMessage's arguments Note that len(tags) == len(data) - client_address ((host, port) tuple): the host & port this message originated from. a Message-handler function may return None, but it could also return an OSCMessage (or OSCBundle), which then gets sent back to the client. This handler prints the received message. Returns None """ txt = "OSCMessage '%s' from %s: " % (addr, getUrlStr(client_address)) txt += str(data) self.printErr(txt) # strip trailing comma & space def serverInfo_handler(self, addr, tags, data, client_address): """Example handler for OSCMessages. All registerd handlers must accept these three arguments: - addr (string): The OSC-address pattern of the received Message (the 'addr' string has already been matched against the handler's registerd OSC-address, but may contain '*'s & such) - tags (string): The OSC-typetags of the received message's arguments. (without the preceding comma) - data (list): The OSCMessage's arguments Note that len(tags) == len(data) - client_address ((host, port) tuple): the host & port this message originated from. a Message-handler function may return None, but it could also return an OSCMessage (or OSCBundle), which then gets sent back to the client. This handler returns a reply to the client, which can contain various bits of information about this server, depending on the first argument of the received OSC-message: - 'help' | 'info' : Reply contains server type & version info, plus a list of available 'commands' understood by this handler - 'list' | 'ls' : Reply is a bundle of 'address ' messages, listing the server's OSC address-space. - 'clients' | 'targets' : Reply is a bundle of 'target osc://:[] [] [...]' messages, listing the local Client-instance's subscribed remote clients. """ if len(data) == 0: return None cmd = data.pop(0) reply = None if cmd in ('help', 'info'): reply = OSCBundle(self.info_prefix) reply.append(('server', str(self))) reply.append(('info_command', "ls | list : list OSC address-space")) reply.append(('info_command', "clients | targets : list subscribed clients")) elif cmd in ('ls', 'list'): reply = OSCBundle(self.info_prefix) for addr in list(self.callbacks.keys()): reply.append(('address', addr)) elif cmd in ('clients', 'targets'): if hasattr(self.client, 'getOSCTargetStrings'): reply = OSCBundle(self.info_prefix) for trg in self.client.getOSCTargetStrings(): reply.append(('target',) + trg) else: cli_addr = self.client.address() if cli_addr: reply = OSCMessage(self.info_prefix) reply.append(('target', "osc://%s/" % getUrlStr(cli_addr))) else: self.reportErr("unrecognized command '%s' in /info request from osc://%s. Try 'help'" % (cmd, getUrlStr(client_address)), client_address) return reply def _subscribe(self, data, client_address): """Handle the actual subscription. the provided 'data' is concatenated together to form a ':[] [] [...]' string, which is then passed to parseUrlStr() & parseFilterStr() to actually retreive , , etc. This 'long way 'round' approach (almost) guarantees that the subscription works, regardless of how the bits of the are encoded in 'data'. """ url = "" have_port = False for item in data: if (type(item) == int) and not have_port: url += ":%d" % item have_port = True elif type(item) in str: url += item (addr, tail) = parseUrlStr(url) (prefix, filters) = parseFilterStr(tail) if addr != None: (host, port) = addr if not host: host = client_address[0] if not port: port = client_address[1] addr = (host, port) else: addr = client_address self.client._setTarget(addr, prefix, filters) trg = self.client.getOSCTargetStr(addr) if trg[0] != None: reply = OSCMessage(self.info_prefix) reply.append(('target',) + trg) return reply def _unsubscribe(self, data, client_address): """Handle the actual unsubscription. the provided 'data' is concatenated together to form a ':[]' string, which is then passed to parseUrlStr() to actually retreive , & . This 'long way 'round' approach (almost) guarantees that the unsubscription works, regardless of how the bits of the are encoded in 'data'. """ url = "" have_port = False for item in data: if (type(item) == int) and not have_port: url += ":%d" % item have_port = True elif type(item) in str: url += item (addr, _) = parseUrlStr(url) if addr == None: addr = client_address else: (host, port) = addr if not host: host = client_address[0] if not port: try: (host, port) = self.client._searchHostAddr(host) except NotSubscribedError: port = client_address[1] addr = (host, port) try: self.client._delTarget(addr) except NotSubscribedError as e: txt = "%s: %s" % (e.__class__.__name__, str(e)) self.printErr(txt) reply = OSCMessage(self.error_prefix) reply.append(txt) return reply def subscription_handler(self, addr, tags, data, client_address): """Handle 'subscribe' / 'unsubscribe' requests from remote hosts, if the local Client supports this (i.e. OSCMultiClient). Supported commands: - 'help' | 'info' : Reply contains server type & version info, plus a list of available 'commands' understood by this handler - 'list' | 'ls' : Reply is a bundle of 'target osc://:[] [] [...]' messages, listing the local Client-instance's subscribed remote clients. - '[subscribe | listen | sendto | target] [ ...] : Subscribe remote client/server at , and/or set message-filters for messages being sent to the subscribed host, with the optional arguments. Filters are given as OSC-addresses (or '*') prefixed by a '+' (send matching messages) or a '-' (don't send matching messages). The wildcard '*', '+*' or '+/*' means 'send all' / 'filter none', and '-*' or '-/*' means 'send none' / 'filter all' (which is not the same as unsubscribing!) Reply is an OSCMessage with the (new) subscription; 'target osc://:[] [] [...]' - '[unsubscribe | silence | nosend | deltarget] : Unsubscribe remote client/server at If the given isn't subscribed, a NotSubscribedError-message is printed (and possibly sent) The given to the subscribe/unsubscribe handler should be of the form: '[osc://][][:][]', where any or all components can be omitted. If is not specified, the IP-address of the message's source is used. If is not specified, the is first looked up in the list of subscribed hosts, and if found, the associated port is used. If is not specified and is not yet subscribed, the message's source-port is used. If is specified on subscription, is prepended to the OSC-address of all messages sent to the subscribed host. If is specified on unsubscription, the subscribed host is only unsubscribed if the host, port and prefix all match the subscription. If is not specified on unsubscription, the subscribed host is unsubscribed if the host and port match the subscription. """ if not isinstance(self.client, OSCMultiClient): raise OSCServerError("Local %s does not support subsctiptions or message-filtering" % self.client.__class__.__name__) addr_cmd = addr.split('/')[-1] if len(data): if data[0] in ('help', 'info'): reply = OSCBundle(self.info_prefix) reply.append(('server', str(self))) reply.append(('subscribe_command', "ls | list : list subscribed targets")) reply.append(('subscribe_command', "[subscribe | listen | sendto | target] [ ...] : subscribe to messages, set filters")) reply.append(('subscribe_command', "[unsubscribe | silence | nosend | deltarget] : unsubscribe from messages")) return reply if data[0] in ('ls', 'list'): reply = OSCBundle(self.info_prefix) for trg in self.client.getOSCTargetStrings(): reply.append(('target',) + trg) return reply if data[0] in ('subscribe', 'listen', 'sendto', 'target'): return self._subscribe(data[1:], client_address) if data[0] in ('unsubscribe', 'silence', 'nosend', 'deltarget'): return self._unsubscribe(data[1:], client_address) if addr_cmd in ('subscribe', 'listen', 'sendto', 'target'): return self._subscribe(data, client_address) if addr_cmd in ('unsubscribe', 'silence', 'nosend', 'deltarget'): return self._unsubscribe(data, client_address) class ForkingOSCServer(ForkingMixIn, OSCServer): """An Asynchronous OSCServer. This server forks a new process to handle each incoming request. """ # set the RequestHandlerClass, will be overridden by ForkingOSCServer & ThreadingOSCServer RequestHandlerClass = ThreadingOSCRequestHandler class ThreadingOSCServer(ThreadingMixIn, OSCServer): """An Asynchronous OSCServer. This server starts a new thread to handle each incoming request. """ # set the RequestHandlerClass, will be overridden by ForkingOSCServer & ThreadingOSCServer RequestHandlerClass = ThreadingOSCRequestHandler ###### # # OSCError classes # ###### class OSCError(Exception): """Base Class for all OSC-related errors """ def __init__(self, message): self.message = message def __str__(self): return self.message class OSCClientError(OSCError): """Class for all OSCClient errors """ pass class OSCServerError(OSCError): """Class for all OSCServer errors """ pass class NoCallbackError(OSCServerError): """This error is raised (by an OSCServer) when an OSCMessage with an 'unmatched' address-pattern is received, and no 'default' handler is registered. """ def __init__(self, pattern): """The specified 'pattern' should be the OSC-address of the 'unmatched' message causing the error to be raised. """ self.message = "No callback registered to handle OSC-address '%s'" % pattern class NotSubscribedError(OSCClientError): """This error is raised (by an OSCMultiClient) when an attempt is made to unsubscribe a host that isn't subscribed. """ def __init__(self, addr, prefix=None): if prefix: url = getUrlStr(addr, prefix) else: url = getUrlStr(addr, '') self.message = "Target osc://%s is not subscribed" % url ###### # # OSC over streaming transport layers (usually TCP) # # Note from the OSC 1.0 specifications about streaming protocols: # # The underlying network that delivers an OSC packet is responsible for # delivering both the contents and the size to the OSC application. An OSC # packet can be naturally represented by a datagram by a network protocol such # as UDP. In a stream-based protocol such as TCP, the stream should begin with # an int32 giving the size of the first packet, followed by the contents of the # first packet, followed by the size of the second packet, etc. # # The contents of an OSC packet must be either an OSC Message or an OSC Bundle. # The first byte of the packet's contents unambiguously distinguishes between # these two alternatives. # ###### class OSCStreamRequestHandler(StreamRequestHandler, OSCAddressSpace): """ This is the central class of a streaming OSC server. If a client connects to the server, the server instantiates a OSCStreamRequestHandler for each new connection. This is fundamentally different to a packet oriented server which has a single address space for all connections. This connection based (streaming) OSC server maintains an address space for each single connection, because usually tcp server spawn a new thread or process for each new connection. This would generate severe multithreading synchronization problems when each thread would operate on the same address space object. Therefore: To implement a streaming/TCP OSC server a custom handler must be implemented which implements the setupAddressSpace member in which it creates its own address space for this very connection. This has been done within the testbench and can serve as inspiration. """ def __init__(self, request, client_address, server): """ Initialize all base classes. The address space must be initialized before the stream request handler because the initialization function of the stream request handler calls the setup member which again requires an already initialized address space. """ self._txMutex = threading.Lock() OSCAddressSpace.__init__(self) StreamRequestHandler.__init__(self, request, client_address, server) def _unbundle(self, decoded): """Recursive bundle-unpacking function""" if decoded[0] != "#bundle": self.replies += self.dispatchMessage(decoded[0], decoded[1][1:], decoded[2:], self.client_address) return now = time.time() timetag = decoded[1] if (timetag > 0.) and (timetag > now): time.sleep(timetag - now) for msg in decoded[2:]: self._unbundle(msg) def setup(self): StreamRequestHandler.setup(self) print("SERVER: New client connection.") self.setupAddressSpace() self.server._clientRegister(self) def setupAddressSpace(self): """ Override this function to customize your address space. """ pass def finish(self): StreamRequestHandler.finish(self) self.server._clientUnregister(self) print("SERVER: Client connection handled.") def _transmit(self, data): sent = 0 while sent < len(data): tmp = self.connection.send(data[sent:]) if tmp == 0: return False sent += tmp return True def _transmitMsg(self, msg): """Send an OSC message over a streaming socket. Raises exception if it should fail. If everything is transmitted properly, True is returned. If socket has been closed, False. """ if not isinstance(msg, OSCMessage): raise TypeError("'msg' argument is not an OSCMessage or OSCBundle object") try: binary = msg.getBinary() length = len(binary) # prepend length of packet before the actual message (big endian) len_big_endian = array.array('c', '\0' * 4) struct.pack_into(">L", len_big_endian, 0, length) len_big_endian = len_big_endian.tostring() if self._transmit(len_big_endian) and self._transmit(binary): return True return False except socket.error as e: if e[0] == errno.EPIPE: # broken pipe return False raise e def _receive(self, count): """ Receive a certain amount of data from the socket and return it. If the remote end should be closed in the meanwhile None is returned. """ chunk = self.connection.recv(count) if not chunk or len(chunk) == 0: return None while len(chunk) < count: tmp = self.connection.recv(count - len(chunk)) if not tmp or len(tmp) == 0: return None chunk = chunk + tmp return chunk def _receiveMsg(self): """ Receive OSC message from a socket and decode. If an error occurs, None is returned, else the message. """ # get OSC packet size from stream which is prepended each transmission chunk = self._receive(4) if chunk == None: print("SERVER: Socket has been closed.") return None # extract message length from big endian unsigned long (32 bit) slen = struct.unpack(">L", chunk)[0] # receive the actual message chunk = self._receive(slen) if chunk == None: print("SERVER: Socket has been closed.") return None # decode OSC data and dispatch msg = decodeOSC(chunk) if msg == None: raise OSCError("SERVER: Message decoding failed.") return msg def handle(self): """ Handle a connection. """ # set socket blocking to avoid "resource currently not available" # exceptions, because the connection socket inherits the settings # from the listening socket and this times out from time to time # in order to provide a way to shut the server down. But we want # clean and blocking behaviour here self.connection.settimeout(None) print("SERVER: Entered server loop") try: while True: decoded = self._receiveMsg() if decoded == None: return elif len(decoded) <= 0: # if message decoding fails we try to stay in sync but print a message print("OSC stream server: Spurious message received.") continue self.replies = [] self._unbundle(decoded) if len(self.replies) > 1: msg = OSCBundle() for reply in self.replies: msg.append(reply) elif len(self.replies) == 1: msg = self.replies[0] else: # no replies, continue receiving continue self._txMutex.acquire() txOk = self._transmitMsg(msg) self._txMutex.release() if not txOk: break except socket.error as e: if e[0] == errno.ECONNRESET: # if connection has been reset by client, we do not care much # about it, we just assume our duty fullfilled print("SERVER: Connection has been reset by peer.") else: raise e def sendOSC(self, oscData): """ This member can be used to transmit OSC messages or OSC bundles over the client/server connection. It is thread save. """ self._txMutex.acquire() result = self._transmitMsg(oscData) self._txMutex.release() return result """ TODO Note on threaded unbundling for streaming (connection oriented) transport: Threaded unbundling as implemented in ThreadingOSCServer must be implemented in a different way for the streaming variant, because contrary to the datagram version the streaming handler is instantiated only once per connection. This leads to the problem (if threaded unbundling is implemented as in OSCServer) that all further message reception is blocked until all (previously received) pending messages are processed. Each StreamRequestHandler should provide a so called processing queue in which all pending messages or subbundles are inserted to be processed in the future). When a subbundle or message gets queued, a mechanism must be provided that those messages get invoked when time asks for them. There are the following opportunities: - a timer is started which checks at regular intervals for messages in the queue (polling - requires CPU resources) - a dedicated timer is started for each message (requires timer resources) """ class OSCStreamingServer(TCPServer): """ A connection oriented (TCP/IP) OSC server. """ # define a socket timeout, so the serve_forever loop can actually exit. # with 2.6 and server.shutdown this wouldn't be necessary socket_timeout = 1 # this is the class which handles a new connection. Override this for a # useful customized server. See the testbench for an example RequestHandlerClass = OSCStreamRequestHandler def __init__(self, address): """Instantiate an OSCStreamingServer. - server_address ((host, port) tuple): the local host & UDP-port the server listens for new connections. """ self._clientList = [] self._clientListMutex = threading.Lock() TCPServer.__init__(self, address, self.RequestHandlerClass) self.socket.settimeout(self.socket_timeout) def serve_forever(self): """Handle one request at a time until server is closed. Had to add this since 2.5 does not support server.shutdown() """ self.running = True while self.running: self.handle_request() # this times-out when no data arrives. def start(self): """ Start the server thread. """ self._server_thread = threading.Thread(target=self.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() def stop(self): """ Stop the server thread and close the socket. """ self.running = False self._server_thread.join() self.server_close() # 2.6 only #self.shutdown() def _clientRegister(self, client): """ Gets called by each request/connection handler when connection is established to add itself to the client list """ self._clientListMutex.acquire() self._clientList.append(client) self._clientListMutex.release() def _clientUnregister(self, client): """ Gets called by each request/connection handler when connection is lost to remove itself from the client list """ self._clientListMutex.acquire() self._clientList.remove(client) self._clientListMutex.release() def broadcastToClients(self, oscData): """ Send OSC message or bundle to all connected clients. """ result = True for client in self._clientList: result = result and client.sendOSC(oscData) return result class OSCStreamingServerThreading(ThreadingMixIn, OSCStreamingServer): pass """ Implements a server which spawns a separate thread for each incoming connection. Care must be taken since the OSC address space is for all the same. """ class OSCStreamingClient(OSCAddressSpace): """ OSC streaming client. A streaming client establishes a connection to a streaming server but must be able to handle replies by the server as well. To accomplish this the receiving takes place in a secondary thread, because no one knows if we have to expect a reply or not, i.e. synchronous architecture doesn't make much sense. Replies will be matched against the local address space. If message handlers access code of the main thread (where the client messages are sent to the server) care must be taken e.g. by installing sychronization mechanisms or by using an event dispatcher which can handle events originating from other threads. """ # set outgoing socket buffer size sndbuf_size = 4096 * 8 rcvbuf_size = 4096 * 8 def __init__(self): self._txMutex = threading.Lock() OSCAddressSpace.__init__(self) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.sndbuf_size) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, self.rcvbuf_size) self.socket.settimeout(1.0) self._running = False def _receiveWithTimeout(self, count): chunk = str() while len(chunk) < count: try: tmp = self.socket.recv(count - len(chunk)) except socket.timeout: if not self._running: print("CLIENT: Socket timed out and termination requested.") return None else: continue except socket.error as e: if e[0] == errno.ECONNRESET: print("CLIENT: Connection reset by peer.") return None else: raise e if not tmp or len(tmp) == 0: print("CLIENT: Socket has been closed.") return None chunk = chunk + tmp return chunk def _receiveMsgWithTimeout(self): """ Receive OSC message from a socket and decode. If an error occurs, None is returned, else the message. """ # get OSC packet size from stream which is prepended each transmission chunk = self._receiveWithTimeout(4) if not chunk: return None # extract message length from big endian unsigned long (32 bit) slen = struct.unpack(">L", chunk)[0] # receive the actual message chunk = self._receiveWithTimeout(slen) if not chunk: return None # decode OSC content msg = decodeOSC(chunk) if msg == None: raise OSCError("CLIENT: Message decoding failed.") return msg def _receiving_thread_entry(self): print("CLIENT: Entered receiving thread.") self._running = True while self._running: decoded = self._receiveMsgWithTimeout() if not decoded: break elif len(decoded) <= 0: continue self.replies = [] self._unbundle(decoded) if len(self.replies) > 1: msg = OSCBundle() for reply in self.replies: msg.append(reply) elif len(self.replies) == 1: msg = self.replies[0] else: continue self._txMutex.acquire() txOk = self._transmitMsgWithTimeout(msg) self._txMutex.release() if not txOk: break print("CLIENT: Receiving thread terminated.") def _unbundle(self, decoded): if decoded[0] != "#bundle": self.replies += self.dispatchMessage(decoded[0], decoded[1][1:], decoded[2:], self.socket.getpeername()) return now = time.time() timetag = decoded[1] if (timetag > 0.) and (timetag > now): time.sleep(timetag - now) for msg in decoded[2:]: self._unbundle(msg) def connect(self, address): self.socket.connect(address) self.receiving_thread = threading.Thread(target=self._receiving_thread_entry) self.receiving_thread.start() def close(self): # let socket time out self._running = False self.receiving_thread.join() self.socket.close() def _transmitWithTimeout(self, data): sent = 0 while sent < len(data): try: tmp = self.socket.send(data[sent:]) except socket.timeout: if not self._running: print("CLIENT: Socket timed out and termination requested.") return False else: continue except socket.error as e: if e[0] == errno.ECONNRESET: print("CLIENT: Connection reset by peer.") return False else: raise e if tmp == 0: return False sent += tmp return True def _transmitMsgWithTimeout(self, msg): if not isinstance(msg, OSCMessage): raise TypeError("'msg' argument is not an OSCMessage or OSCBundle object") binary = msg.getBinary() length = len(binary) # prepend length of packet before the actual message (big endian) len_big_endian = array.array('c', '\0' * 4) struct.pack_into(">L", len_big_endian, 0, length) len_big_endian = len_big_endian.tostring() if self._transmitWithTimeout(len_big_endian) and self._transmitWithTimeout(binary): return True else: return False def sendOSC(self, msg): """Send an OSC message or bundle to the server. Returns True on success. """ self._txMutex.acquire() txOk = self._transmitMsgWithTimeout(msg) self._txMutex.release() return txOk def __str__(self): """Returns a string containing this Client's Class-name, software-version and the remote-address it is connected to (if any) """ out = self.__class__.__name__ out += " v%s.%s-%s" % version addr = self.socket.getpeername() if addr: out += " connected to osc://%s" % getUrlStr(addr) else: out += " (unconnected)" return out def __eq__(self, other): """Compare function. """ if not isinstance(other, self.__class__): return False isequal = cmp(self.socket._sock, other.socket._sock) if isequal and self.server and other.server: return cmp(self.server, other.server) return isequal def __ne__(self, other): """Compare function. """ return not self.__eq__(other) # vim:noexpandtab ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/Patterns/0000755000175100001770000000000014611211157017547 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/Generators.py0000644000175100001770000002445314611211152022235 0ustar00runnerdocker""" This module contains all the sub-classes of `GeneratorPattern` used in FoxDot. Unlike a `Pattern`, a `GeneratorPattern` does not contain a list that is iterated over or indexed but returns a value based on the index and an internal function. For example, `PRand` returns a random value from a list of values. It will always return the same value for the same index as it stores this in its internal cache. `Pattern` methods such as `rotate` or `palindrome` are not available from the `GeneratorPattern` class but slicing generators will return a `Pattern` object from which these methods can be called e.g. >>> gen = PRand([0,1,2]) >>> pat = gen[:5] P[0, 1, 0, 2, 1] >>> pat.rotate() P[1, 0, 2, 1, 0] Mathematical operations *do* work in the same way as they do in `Patterns`. >>> gen1 = PRand([0,1,2]) >>> gen2 = gen1 + 10 >>> gen1[:5] P[0, 2, 2, 1, 0] >>> gen2[:5] P[10, 12, 12, 11, 10] """ from renardo_lib.Patterns.Main import GeneratorPattern, Pattern, asStream, PatternInput import random class RandomGenerator(GeneratorPattern): __seed = None def __init__(self, *args, **kwargs): GeneratorPattern.__init__(self, *args, **kwargs) self.random = random def init_random(self, *args, **kwargs): """ To be called at the end of the __init__ """ if "seed" in kwargs: self.random = self.random.Random() self.random.seed(kwargs["seed"]) elif RandomGenerator.__seed is not None: self.random = self.random.Random() self.random.seed(RandomGenerator.__seed) pattern = self[:5000] self.__class__ = Pattern self.data = pattern.data return self @classmethod def set_override_seed(cls, seed): cls.__seed = seed return # Pseudo-inheritance def choice(self, *args, **kwargs): return self.random.choice(*args, **kwargs) def randint(self, *args, **kwargs): return self.random.randint(*args, **kwargs) def triangular(self, *args, **kwargs): return self.random.triangular(*args, **kwargs) class PRand(RandomGenerator): ''' Returns a random integer between start and stop. If start is a container-type it returns a random item for that container. ''' def __init__(self, start, stop=None, **kwargs): # If we're given a list, choose from that list -- TODO always use a list and use range RandomGenerator.__init__(self, **kwargs) self.args = (start, stop) self.kwargs = kwargs # Choosing from a list if hasattr(start, "__iter__"): self.data = Pattern(start) try: assert(len(self.data)>0) except AssertionError: raise AssertionError("{}: Argument size must be greater than 0".format(self.name)) self.choosing = True self.low = self.high = None else: # Choosing from a range self.choosing = False self.low = start if stop is not None else 0 self.high = stop if stop is not None else start try: assert((self.high - self.low)>=1) except AssertionError: raise AssertionError("{}: Range size must be greater than 1".format(self.name)) self.data = "{}, {}".format(self.low, self.high) self.init_random(**kwargs) def choose(self): return self.data[self.choice(range(self.MAX_SIZE))] def func(self, index): if self.choosing: # value = self.choice(self.data) value = self.choose() else: value = self.randint(self.low, self.high) return value def string(self): """ Used in PlayString to show a PRand in curly braces """ return "{" + self.data.string() + "}" class PWhite(RandomGenerator): ''' Returns random floating point values between 'lo' and 'hi' ''' def __init__(self, lo=0, hi=1, **kwargs): RandomGenerator.__init__(self, **kwargs) self.args = (lo, hi) self.low = float(lo) self.high = float(hi) self.mid = (lo + hi) / 2.0 self.data = "{}, {}".format(self.low, self.high) self.init_random(**kwargs) def func(self, index): return self.triangular(self.low, self.high, self.mid) class PxRand(PRand): def func(self, index): value = PRand.func(self, index) while value == self.last_value: value = PRand.func(self, index) self.last_value = value return self.last_value class PwRand(RandomGenerator): def __init__(self, values, weights, **kwargs): RandomGenerator.__init__(self, **kwargs) self.args = (values, weights) try: assert(all(type(x) == int for x in weights)) except AssertionError: e = "{}: Weights must be integers".format(self.name) raise AssertionError(e) self.data = Pattern(values) self.weights = Pattern(weights).stretch(len(self.data)) self.values = self.data.stutter(self.weights) self.init_random(**kwargs) def choose(self): return self.values[self.choice(range(self.MAX_SIZE))] def func(self, index): return self.choose() class PChain(RandomGenerator): """ An example of a Markov Chain generator pattern. The mapping argument should be a dictionary of keys whose values are a list/pattern of possible destinations. """ def __init__(self, mapping, **kwargs): assert isinstance(mapping, dict) RandomGenerator.__init__(self, **kwargs) self.args = (mapping,) self.last_value = 0 self.mapping = {} i = 0 for key, value in mapping.items(): self.mapping[key] = self._convert_to_list(value) # Use the first key to start with if i == 0: self.last_value = key i += 1 self.init_random(**kwargs) def func(self, *args, **kwargs): index = self.last_value if isinstance(self.last_value, GeneratorPattern): index = index.CACHE_HEAD if index in self.mapping: self.last_value = self.choice(self.mapping[index]) return self.last_value def _convert_to_list(self, value): if isinstance(value, list): return value elif isinstance(value, Pattern): return value.data return [value] class PZ12(GeneratorPattern): """ Implementation of the PZ12 algorithm for predetermined random numbers. Using an irrational value for p, however, results in a non-determined order of values. Experimental, only works with 2 values. """ def __init__(self, tokens=[1,0], p=[1, 0.5]): GeneratorPattern.__init__(self) self.data = tokens self.probs = [value / max(p) for value in p] self._prev = [] self.dearth = [0 for n in self.data] def _count_values(self, token): return sum([self._prev[i] == token for i in range(len(self._prev))]) def func(self, index): index = len(self._prev) for i, token in enumerate(self.data): d0 = self.probs[i] * (index + 1) d1 = self._count_values(token) self.dearth[i] = d0-d1 i = self.dearth.index(max(self.dearth)) value = self.data[i] self._prev.append(value) return value class PTree(RandomGenerator): """ Takes a starting value and two functions as arguments. The first function, f, must take one value and return a container-type of values and the second function, choose, must take a container-type and return a single value. In essence you are creating a tree based on the f(n) where n is the last value chosen by choose. """ def __init__(self, n=0, f=lambda x: (x + 1, x - 1), choose=lambda x: random.choice(x), **kwargs): RandomGenerator.__init__(self, **kwargs) self.args=(n, f, choose) self.f = f self.choose = choose self.values = [n] self.init_random(**kwargs) def func(self, index): self.values.append( self.choose(self.f( self.values[-1] )) ) return self.values[-1] class PWalk(RandomGenerator): def __init__(self, max=7, step=1, start=0, **kwargs): RandomGenerator.__init__(self, **kwargs) self.args = (max, step, start) self.max = abs(max) self.min = self.max * -1 self.step = PatternInput(step).transform(abs) self.start = start self.data = [self.start, self.step, self.max] self.directions = [lambda x, y: x + y, lambda x, y: x - y] self.last_value = None self.init_random(**kwargs) def func(self, index): if self.last_value is None: self.last_value = self.start else: if self.last_value >= self.max: # force subtraction f = self.directions[1] elif self.last_value <= self.min: # force addition f = self.directions[0] else: f = self.choice(self.directions) self.last_value = f(self.last_value, self.step[index]) return self.last_value class PDelta(GeneratorPattern): def __init__(self, deltas, start=0): GeneratorPattern.__init__(self) self.deltas = asStream(deltas) self.start = start self.value = start def func(self, index): if index == 0: return self.start self.value += float(self.deltas[index - 1]) return self.value class PSquare(GeneratorPattern): ''' Returns the square of the index being accessed ''' def func(self, index): return index * index class PIndex(GeneratorPattern): ''' Returns the index being accessed ''' def func(self, index): return index class PFibMod(GeneratorPattern): """ Returns the fibonacci sequence -- maybe a bad idea""" def func(self, index): if index < 2: return index a = self.cache.get(index-1, self.getitem(index-1)) b = self.cache.get(index-2, self.getitem(index-2)) return a + b ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/Main.py0000644000175100001770000015013214611211152021002 0ustar00runnerdocker""" Contains classes `Pattern` and `PGroup` and the base class for `GeneratorPattern` (see Generators.py). """ from random import choice, shuffle from renardo_lib.Patterns.Operations import ( PAdd, PSub2, PMul, PDiv, PDiv2, PFloor, PSub, PFloor2, PMod, PPow, PMod2, PPow2, PEq, Div, rDiv, Add, Sub, rSub, Mul, Mod, rMod, Nil, PNe ) from renardo_lib.Utils import LCM, dots, modi import functools import inspect # Decorator functions for nested expansion of pattern functions and methods def loop_pattern_func(f): ''' Decorator for allowing any Pattern function to create multiple Patterns by using Patterns or TimeVars as arguments ''' @functools.wraps(f) def new_function(*args): # Return any functions that use TimeVars as PvarGenerators timevars = [arg for arg in args if isinstance(arg, Pattern.TimeVar)] if len(timevars) > 0: return Pattern.TimeVar.CreatePvarGenerator(f, *args) # Loop the pattern with different values pat = Pattern() # Force pattern types if using lists/tuples args = [PatternFormat(arg) for arg in args] # Continually extend the pattern for i in range(LCM(*[len(arg) for arg in args if (hasattr(arg, '__len__') and not isinstance(arg, PGroup))])): pat |= f(*[(arg[i] if isinstance(arg, Pattern) else arg) for arg in args]) return pat new_function.argspec = inspect.getfullargspec(f) return new_function # TODO -- if it isn't looped, return the original if it is a group def loop_pattern_method(f): ''' Decorator for allowing any Pattern method to create multiple (or rather, longer) Patterns by using Patterns as arguments ''' @functools.wraps(f) def new_function(self, *args): # Return any functions that use TimeVars as PvarGenerators timevars = [arg for arg in args if isinstance(arg, Pattern.TimeVar)] if len(timevars) > 0: return Pattern.TimeVar.CreatePvarGenerator(f, *args, pattern=self) pat = Pattern() # Force pattern types if using lists/tuples args = [PatternFormat(arg) for arg in args] for i in range(LCM(*[len(arg) for arg in args if (hasattr(arg, '__len__') and not isinstance(arg, PGroup))])): pat |= f(self, *[(modi(arg, i) if not isinstance(arg, PGroup) else arg) for arg in args]) return pat new_function.argspec = inspect.getfullargspec(f) return new_function def PatternMethod(f): ''' Decorator that makes a function into a metaPattern method''' setattr(metaPattern, f.__name__, f) return def StaticPatternMethod(f): ''' Decorator that makes a function into a metaPattern static method''' setattr(metaPattern, f.__name__, staticmethod(f)) return def ClassPatternMethod(f): ''' Decorator that makes a function into a metaPattern class method''' setattr(metaPattern, f.__name__, classmethod(f)) return # Begin Pattern Abstratct Base Class class metaPattern(object): """ Abstract base class for Patterns """ WEIGHT = -1 # data = None bracket_style = "[]" debugging = False meta = [] def __init__(self, *args): if len(args): data = args[0] if type(data) is str: self.fromString(data) elif type(data) is tuple: self.data = PGroup(data) self.make() elif isinstance(data, self.__class__): self.data = data.data else: self.data = data self.make() else: self.data = [] def new(self, data): """ Returns a new pattern object with this Pattern's class type """ return self.__class__(data + self.meta) def transform(self, func): """ Recursively transforms values and nested patterns """ output = [] for item in self.data: if isinstance(item, (metaPattern, GeneratorPattern)): output.append(item.transform(func)) else: output.append(func(item)) return self.__class__(output) def int(self): return self.transform(int) def float(self): return self.transform(float) def str(self): return self.transform(str) @classmethod def get_methods(cls): """ Returns the methods associated with the `Pattern` class as a list """ return [attr for attr in dir(cls) if callable(getattr(cls, attr))] def get_data(self): """ Returns self.data if data is not a single instance of this class, in which case self.data[0].data is returned """ return self.data @classmethod def help(cls): """ Prints the Pattern class docstring to the console """ return print(cls.__doc__) def __len__(self): """ Returns the *expanded* length of the pattern such that if the pattern is laced, the value is the length of the list multiplied by the lowest-common-multiple of the lengths of nested patterns. e.g. the following are identical: ``` >>> print( len(P[0,1,2,[3,4]]) ) 8 >>> print( len(P[0,1,2,3,0,1,2,4]) ) 8 ``` """ lengths = [1] n = 0 for item in self.data: if isinstance(item, EmptyItem): continue elif isinstance(item, Pattern): lengths.append(len(item)) n += 1 return LCM(*lengths) * n def __str__(self): try: if len(self.data) > 20: val = self.data[:8] + [dots()] + self.data[-8:] else: val = self.data except AttributeError: val = self.data return "P" + self.bracket_style[:-1] + ( repr(val)[1:-1] ) + self.bracket_style[-1] def __repr__(self): return str(self) # Conversion methods def string(self): """ Returns a PlayString in string format from the Patterns values """ string = "" for item in self.data: if isinstance(item, (PGroup, GeneratorPattern)): string += item.string() elif isinstance(item, Pattern): string += "(" + "".join([(s.string() if hasattr(s, "string") else str(s)) for s in item.data]) + ")" else: string += str(item) return string def asGroup(self): """ Returns the Pattern as a PGroup """ return PGroup(self.data) def group(self): """ Returns the Pattern as a PGroup """ return PGroup(self.data) # TODO -- this is super hacky vv def convert_data(self, dtype=float, *args, **kwargs): """ Makes a true copy and converts the data to a given data type """ new = map((lambda x: x.convert_data(dtype, *args, **kwargs) if isinstance(x, metaPattern) else dtype(x, *args, **kwargs)), self.data) return self.true_copy(list(new)) def copy(self): """ Returns a copy of the Pattern such that alterations to the Pattern.data do not affect the original. """ return self.new(self.data[:]) def true_copy(self, new_data=None): """ Returns a copy of the Pattern such that items within the Pattern hold the same state as the original. """ new = self.__class__() new.__dict__ = self.__dict__.copy() if new_data is not None: new.data = new_data return new # Pattern container methods def __getitem__(self, key): """ Calls self.getitem(). Is overridden in `FoxDot.lib.TimeVar` for indexing with TimeVars """ return self.getitem(key) def getitem(self, key, get_generator=False): """ Called by __getitem__() """ # We can get multiple values by indexing with a pattern or tuple if isinstance(key, (metaPattern, tuple)): val = self.new([self.getitem(n) for n in key]) # We can get items using a slice elif isinstance(key, slice): val = self.getslice(key.start, key.stop, key.step) else: # Get the "nested" single value i = key % len(self.data) val = self.data[i] if isinstance(val, (Pattern, Pattern.Pvar)) or ( isinstance(val, GeneratorPattern) and not get_generator ): j = key // len(self.data) val = val.getitem(j, get_generator) elif isinstance(val, GeneratorPattern) and get_generator: return val return val def __setitem__(self, key, value): if isinstance(key, slice): self.data[key] = Format(value) # TODO - make sure this works else: i = key % len(self.data) if isinstance(self.data[i], metaPattern): j = key // len(self.data) self.data[i][j] = value else: if key >= len(self.data): self.data[i] = Pattern([self.data[i], Format(value)]).stutter([key // len(self.data) , 1]) else: self.data[i] = Format(value) return def setitem(self, key, value): self.data[key] = Format(value) def __iter__(self): """ Returns a generator object for this Pattern """ for i in range(len(self)): yield self.getitem(i) def items(self): """ Returns a generator object equivalent to using enumerate() """ for i, value in enumerate(self): yield i, value def getslice(self, start, stop, step=1): """ Called when using __getitem__ with slice notation """ start = start if start is not None else 0 stop = stop if stop is not None else len(self) step = step if step is not None else 1 if stop < start: stop = (len(self.data) + stop) return Pattern([self[i] for i in range(start, stop, step) ]) def __setslice__(self, i, j, item): """ Only works in Python 2 - maybe get rid? """ self.data[i:j] = Format(item) # Integer returning def count(self, item): """ Returns the number of occurrences of item in the Pattern""" return self.data.count(item) def __add__(self, other): if isinstance(other, GeneratorPattern): return other.__radd__(self) return PAdd(self, other) def __radd__(self, other): if isinstance(other, GeneratorPattern): return other.__add__(self) return PAdd(self, other) def __sub__(self, other): if isinstance(other, GeneratorPattern): return other.__rsub__(self) return PSub(self, other) def __rsub__(self, other): if isinstance(other, GeneratorPattern): return other.__sub__(self) return PSub2(self, other) def __mul__(self, other): if isinstance(other, GeneratorPattern): return other.__rmul__(self) return PMul(self, other) def __rmul__(self, other): if isinstance(other, GeneratorPattern): return other.__mul__(self) return PMul(self, other) def __truediv__(self, other): if isinstance(other, GeneratorPattern): return other.__rtruediv__(self) return PDiv(self, other) def __rtruediv__(self, other): if isinstance(other, GeneratorPattern): return other.__truediv__(self) return PDiv2(self, other) def __floordiv__(self, other): if isinstance(other, GeneratorPattern): return other.__rfloordiv__(self) return PFloor(self, other) def __rfloordiv__(self, other): if isinstance(other, GeneratorPattern): return other.__floordiv__(self) return PFloor2(self, other) def __mod__(self, other): if isinstance(other, GeneratorPattern): return other.__rmod__(self) return PMod(self, other) def __rmod__(self, other): if isinstance(other, GeneratorPattern): return other.__mod__(self) return PMod2(self, other) def __pow__(self, other): if isinstance(other, GeneratorPattern): return other.__rpow__(self) return PPow(self, other) def __rpow__(self, other): if isinstance(other, GeneratorPattern): return other.__pow__(self) return PPow2(self, other) def __xor__(self, other): if isinstance(other, GeneratorPattern): return other.__rxor__(self) return PPow(self, other) def __rxor__(self, other): if isinstance(other, GeneratorPattern): return other.__xor__(self) return PPow2(self, other) def __abs__(self): return self.new([abs(item) for item in self]) def __bool__(self): """ Returns True if *any* value in the Pattern are greater than zero """ # NOTE: this used to be ALL return all([bool(item > 0) for item in self]) def __nonzero__(self): return self.__bool__() def abs(self): return abs(self) def __invert__(self): """ Using the ~ symbol as a prefix to a Pattern will reverse it. >>> a = P[:4] >>> print(a, ~a) P[0, 1, 2, 3], P[3, 2, 1, 0] """ return self.mirror() # Piping patterns together using the '|' operator def __or__(self, other): """ Use the '|' symbol to 'pipe' Patterns into on another """ return self.concat(other) def __ror__(self, other): """ Use the '|' symbol to 'pipe' Patterns into on another """ return asStream(other).concat(self) # Zipping patterns together using the '&' operator def __and__(self, other): return self.zip(other) def __rand__(self, other): return asStream(other).zip(self) # Comparisons --> this might be a tricky one def __eq__(self, other): return PEq(self, other) def __ne__(self, other): return PNe(self, other) def eq(self, other): return self.new([int(value == modi(asStream(other), i)) for i, value in enumerate(self)]) def ne(self, other): return self.new([int(value != modi(asStream(other), i)) for i, value in enumerate(self)]) # def gt(self, other): # return self.__class__([int(value > modi(asStream(other), i)) for i, value in enumerate(self)]) # def lt(self, other): # return self.__class__([int(value < modi(asStream(other), i)) for i, value in enumerate(self)]) # def ge(self, other): # return self.__class__([int(value >= modi(asStream(other), i)) for i, value in enumerate(self)]) # def le(self, other): # return self.__class__([int(value <= modi(asStream(other), i)) for i, value in enumerate(self)]) def __gt__(self, other): #return self.__class__([int(value > modi(asStream(other), i)) for i, value in enumerate(self)]) values = [] other = asStream(other) for i, value in enumerate(self): # possibly LCM in future value = value > other[i] if not isinstance(value, PGroup): value = int(value) values.append(value) return self.new(values) def __ge__(self, other): #return self.__class__([int(value >= modi(asStream(other), i)) for i, value in enumerate(self)]) values = [] other = asStream(other) for i, value in enumerate(self): # possibly LCM in future value = value >= other[i] if not isinstance(value, PGroup): value = int(value) values.append(value) return self.new(values) def __lt__(self, other): #return self.__class__([int(value < modi(asStream(other), i)) for i, value in enumerate(self)]) values = [] other = asStream(other) for i, value in enumerate(self): # possibly LCM in future value = value < other[i] if not isinstance(value, PGroup): value = int(value) values.append(value) return self.new(values) def __le__(self, other): #return self.__class__([int(value <= modi(asStream(other), i)) for i, value in enumerate(self)]) values = [] other = asStream(other) for i, value in enumerate(self): # possibly LCM in future value = value <= other[i] if not isinstance(value, PGroup): value = int(value) values.append(value) return self.new(values) # Methods that return augmented versions of original def shuffle(self, n=1): """ Returns a new Pattern with shuffled contents. Note: nested patterns stay together. To shuffle the contents of nested patterns, use `deep_shuffle` or `true_shuffle`. """ items = [] for i in range(n): data = self.data[:] shuffle(data) items.extend(data) return self.new(items) def deep_shuffle(self, n=1): """ Returns a new Pattern with shuffled contents and shuffles any nested patterns. To shuffle the contents of nested patterns with the rest of the Pattern's contents, use `true_shuffle`. """ items = [] for i in range(n): data = [(item if not isinstance(item, metaPattern) else item) for item in self.data[:]] shuffle(data) items.extend(data) return self.new(items) def true_shuffle(self, n=1): """ Returns a new Pattern with completely shuffle contents such that nested Patterns are shuffled within the larger Pattern """ items = [] for i in range(n): data = list(self) shuffle(data) items.extend(data) return self.new(items) def reverse(self): """ Reverses the contents of the Pattern. Nested patterns are not reversed. To reverse the contents of nester patterns use `Pattern.mirror()` """ new = self.new(self.data[:]) new.data.reverse() return new def sort(self, *args, **kwargs): """ Used in place of sorted(pattern) to force type """ return self.new(sorted(self.data, *args, **kwargs)) def mirror(self): """ Reverses the pattern. Differs to `Pattern.reverse()` in that all nested patters are also reversed. """ new = [] for i in range(len(self.data), 0, -1): value = self.data[i-1] if hasattr(value, 'mirror'): value = value.mirror() new.append(value) return self.new(new) def stutter(self, n=2, strict=False): """ Returns a new Pattern with each item repeated by `n`. Use a list of numbers for stutter different items by different amount. e.g. ``` >>> P[0, 1, 2, 3].stutter([1,3]) P[0, 1, 1, 1, 2, 3, 3, 3] ``` Use strict=True to force generator patterns to return the same value `n` times in a row. """ n = asStream(n) lrg = max(len(self.data), len(n)) new = [] for i in range(lrg): for j in range(modi(n,i)): item = modi(self.data,i) if strict and isinstance(item, GeneratorPattern): item = item.copy() new.append(item) return self.new(new) def arp(self, arp_pattern): """ Return a new Pattern with each item repeated len(arp_pattern) times and incremented by arp_pattern. Useful for arpeggiating. e.g. ``` >>> P[0, 1, 2, 3].arp([0, 2]) P[0, 2, 1, 3, 2, 4, 3, 5] ``` """ return self.stutter(len(arp_pattern)) + arp_pattern def splice(self, seq, *seqs): """ Takes at least list / Pattern and creates a new Pattern by adding a value from each pattern in turn to the new pattern. e.g. ``` >>> P[0,1,2,3].splice([4,5,6,7],[8,9]) P[0,4,8,1,5,9,2,6,8,3,7,9] ``` """ sequences = (self, asStream(seq)) + tuple(asStream(s) for s in seqs) size = LCM(*[len(s) for s in sequences]) new = [] for i in range(size): for seq in sequences: new.append(modi(seq, i)) return self.new(new) def invert(self): """ Inverts the values with the Pattern. """ new = [] lrg = float(max(self.data)) for item in self.data: try: new.append(item.invert()) except: new.append((((item / lrg) * -1) + 1) * lrg) return self.new(new) def shufflets(self, n): """ Returns a Pattern of 'n' number of PGroups made from shuffled versions of the original Pattern """ new = self.data[:] return Pattern([Pattern(new).shuffle().asGroup() for i in range(n)]) # Loop methods @loop_pattern_method def pivot(self, i): """ Mirrors and rotates the Pattern such that the item at index 'i' is in the same place """ if len(self) > 0: mid = len(self) / 2 if i > mid: i = len(self) - i - 1 new = self.mirror().rotate((2*(i % len(self)))+1) else: new = self.rotate((2*(i % len(self)))+1).mirror() else: new = self.copy() return new @loop_pattern_method def accum(self, n=None): """ Returns a Pattern that is equivalent to list of sums of that Pattern up to that index.""" if n is None: n = len(self) new = [0] for i in range(n-1): new.append( new[-1] + self[i] ) return self.new(new) @loop_pattern_method def stretch(self, size): """ Stretches (repeats) the contents until len(Pattern) == size """ new = [] for n in range(size): new.append( modi(self.data, n) ) new = self.new(new) return new @loop_pattern_method def trim(self, size): """ Shortens a pattern until it's length is equal to size - cannot be greater than the length of the current pattern """ new = [] for n in range(min(len(self), size)): new.append( modi(self.data, n) ) new = self.new(new) return new @loop_pattern_method def ltrim(self, size): """ Like trim but removes items from the start of the pattern""" new = [] data = self.mirror().data for n in range(min(len(self), size)): new.append( modi(data, n) ) new = self.new(new).mirror() return new @loop_pattern_method def loop(self, n, f=None): """ Repeats this pattern n times """ assert n > 0, ".loop() parameter must be greater than 0" new = values = list(self) for i in range(n - 1): if callable(f): values = [f(x) for x in values] new += list(values) return self.new(new) @loop_pattern_method def duplicate(self, n): """ Repeats this pattern n times but keep nested pattern values """ new = [] for i in range(n): new += self.data return self.new(new) @loop_pattern_method def iter(self, n): """ Repeats this pattern n times but doesn't take nested pattern into account for length""" return self[:len(self.data)*n] #new = [] #for i in range(len(self.data) * n): # new += self[i] #return self.__class__(new) @loop_pattern_method def swap(self, n=2): new = [] for pair in [list(val) for val in [reversed(self[i:i+n]) for i in range(0, len(self), n)]]: for item in pair: new.append(item) return self.new(new) @loop_pattern_method def rotate(self, n=1): n = int(n) new = self.data[n:] + self.data[0:n] return self.new(new) @loop_pattern_method def sample(self, n): """ Returns an n-length pattern from a sample""" return self.new(random.sample(list(self), n)) @loop_pattern_method def palindrome(self, a=0, b=None): """ Returns the original pattern with mirrored version of itself appended. a removes values from the middle of the pattern, if positive. b removes values from the end of the pattern, should be negative. e.g. >>> P[:4].palindrome() P[0, 1, 2, 3, 3, 2, 1, 0] >>> P[:4].palindrome(1) P[0, 1, 2, 3, 2, 1, 0] >>> P[:4].palindrome(-1) P[0, 1, 2, 3, 3, 2, 1] >>> P[:4].palindrome(1,-1) P[0, 1, 2, 3, 2, 1] """ a = int(a) if a < 0: a, b = 0, a return self | self.mirror()[a:b] def alt(self, other): """ Returns Pattern(other) """ return self.__class__(other) def norm(self): """ Returns the pattern with all values between 0 and 1 """ pos = self - min(self) return pos / max(pos) def undup(self): """ Removes any consecutive duplicate numbers from a Pattern """ new = [] last_val = None for value in self: if value != last_val: new.append(value) last_val = value return self.new(new) def add(self, other): return self + other @loop_pattern_method def limit(self, func, value): """ Returns a new Pattern generated by adding elements from this Pattern to a new list and repeatedly calling `func()` on this list until `func(l)` is greater than `value` e.g. ``` >>> print( P[0, 1, 2, 3].limit(sum, 10) ) P[0, 1, 2, 3, 0, 1, 2] ``` """ new = [] i = 0 while func(new) < value: new.append(self[i]) i+=1 return self.new(new) # Methods that take a non number / pattern argument def replace(self, sub, repl): """ Replaces any occurrences of "sub" with "repl" """ new = [] for item in self.data: if isinstance(item, metaPattern): new.append(item.replace(sub, repl)) elif item == sub: new.append(repl) else: new.append(item) return self.new(new) def submap(self, mapping): """ Similar to Pattern.replace, but takes a dictionary of values """ new = [] for item in self.data: if isinstance(item, metaPattern): new.append(item.submap(mapping)) else: new.append(mapping.get(item, item)) return self.new(new) def compress(self, selector): """ Removes values from the pattern if the same index in selector is 0. Similar to .select() but maximum length of the new Pattern is the length of the initial Pattern. """ s = asStream(selector) return self.new([self[i] for i in range(len(self)) if s[i]]) def select(self, selector): """ Removes values from the pattern if the same index in selector is 0 """ s = asStream(selector) # Don't do anything if all values are 1 if all([value == 1 for value in s]): return self return self.new([self[i] for i in range(LCM(len(self), len(s))) if s[i]]) def layer(self, method, *args, **kwargs): """ Zips a pattern with a modified version of itself. Method argument can be a function that takes this pattern as its first argument, or the name of a Pattern method as a string. """ if callable(method): #func = method #args = [self.data] + list(args) #func = return self.zip(list(map(method, self.data))) else: func = getattr(self, method) assert callable(func) return self.zip(func(*args, **kwargs)) def every(self, n, method, *args, **kwargs): """ Returns the pattern looped n-1 times then appended with the version returned when method is called on it. """ return self.loop(n-1).concat(getattr(self, method).__call__(*args, **kwargs)) def map(self, func): """ Returns a Pattern that calls `func` on each item """ return self.new([(item.map(func) if isinstance(item, metaPattern) else func(item)) for item in self.data]) def extend(self, seq): """ Should return None """ self.data.extend(map(convert_nested_data, seq)) return def append(self, item): """ Converts a new item to PGroup etc and appends """ self.data.append(convert_nested_data(item)) return def i_rotate(self, n=1): self.data = self.data[n:] + self.data[0:n] return self def i_reverse(self): self.data.reverse() return self def i_sort(self): self.data = Pattern(sorted(self.data)) return self def i_shuf(self): shuffle(self.data) return self def set(self, index, value): self.data[index] = asStream(value) return self # Boolean tests def startswith(self, prefix): """ Returns True if the first item in the Pattern is equal to prefix """ return self.data[0] == prefix def all(self, func=(lambda x: bool(x))): """ Returns true if all of the patterns contents satisfies func(x) - default is nonzero """ if len(self.data) == 0: return False for item in self.data: if not func(item): return False return True # Extension methods def concat(self, data): """ Concatonates this patterns stream with another """ new = Pattern() if isinstance(data, Pattern): new.data = self.data + data.data elif isinstance(data, (list, str, range)): new.data = list(self.data) new.data.extend(map(convert_nested_data, data)) else: new.data = list(self.data) new.append(data) return new def zipx(self, other): """ Returns a `Pattern` of `PGroups`, where each `PGroup` contains the i-th element from each of the argument sequences. The length of the pattern is the lowest common multiple of the lengths of the two joining patterns. """ new = [] other = asStream(other) for i in range(LCM(len(self.data), len(other.data))): item1 = self.data[i % len(self.data)] item2 = other.data[i % len(other.data)] new.append((item1, item2)) return self.new(new) def zip(self, other, dtype=None): """ Zips two patterns together. If one item is a tuple, it extends the tuple / PGroup i.e. arrow_zip([(0,1),3], [2]) -> [(0,1,2),(3,2)] """ output = Pattern() other = asStream(other) dtype = PGroup if dtype is None else dtype for i in range(LCM(len(self), len(other))): item1 = self.getitem(i, get_generator=True) item2 = other.getitem(i, get_generator=True) if all([x.__class__== PGroup for x in (item1, item2)]): new_item = dtype(item1.data + item2.data) elif item1.__class__ == PGroup: new_item = dtype(item1.data + [item2]) elif item2.__class__ == PGroup: new_item = dtype([item1] + item2.data) else: new_item = dtype(item1, item2) output.append(new_item) return output def deepzip(self, other): new = [] other = asStream(other) for i in range(LCM(len(self.data), len(other.data))): p1 = self.data[i % len(self.data)] p2 = other.data[i % len(other.data)] if isinstance(p1, metaPattern): value = p1.deepzip(p2) elif isinstance(p2, metaPattern): value = p2.deeprzip(p1) else: value = (p1, p2) new.append(value) return self.new(new) def deeprzip(self, other): new = [] other = asStream(other) for i in range(LCM(len(self.data), len(other.data))): p1 = self.data[i % len(self.data)] p2 = other.data[i % len(other.data)] if isinstance(p1, metaPattern): value = p1.deeprzip(p2) elif isinstance(p2, metaPattern): value = p2.deepzip(p1) else: value = (p2, p1) new.append(value) return self.new(new) # Returns individual elements / slices def choose(self): """ Returns one randomly selected item """ return choice(self.data) def get_behaviour(self): return None # Automatic expansion of nested patterns def make(self): """ This method automatically laces and groups the data """ #: Force data into an iterable form if isinstance(self.data, (str, range)): self.data = list(self.data) elif not isinstance(self.data, PatternType): # not sure about PlayString data self.data = [self.data] self.data = list(map(convert_nested_data, self.data)) # If this only contains a pattern, its redundant to use this as a container if len(self.data) == 1: if isinstance(self.data[0], Pattern): self.data = self.data[0].data # Replace this pattern with a Pvar if it is the only item in the Pattern itself elif isinstance(self.data[0], Pattern.Pvar): # SUPER HACKY self.__class__ = self.data[0].__class__ self.__dict__ = self.data[0].__dict__.copy() return self class Pattern(metaPattern): """ Base type pattern """ WEIGHT = 0 debug = False class Cycle(Pattern): """ Special Case pattern class for cycling values in "every" """ def __init__(self, *args): Pattern.__init__(self, list(args)) def __str__(self): return "Cycle({})".format(Pattern.__str__(self)) class PGroup(metaPattern): """ Class to represent any groupings of notes as denoted by brackets. PGroups should only be found within a Pattern object. """ WEIGHT = 2 bracket_style = "()" # set this value to negative how many trailing values you don't want treated as "normal" ignore = 0 def __init__(self, seq=[], *args): if not args: if isinstance(seq, metaPattern): seq = seq.data elif isinstance(seq, tuple): seq = list(seq) else: seq = [seq] + list(args) metaPattern.__init__(self, seq) # If the PGroup contains patterns, invert it to a Pattern of PGroups l = [len(p) for p in self.data if isinstance(p, Pattern)] if len(l) > 0: new_data = [] for key in range(LCM(*l)): new_data.append(self.__class__([item.getitem(key) if isinstance(item, Pattern) else item for item in self.data])) self.__class__ = Pattern self.data = new_data def merge(self, value): """ Merge values into one PGroup """ if hasattr(value, "__len__"): new_data = list(value) else: new_data = [value] return self.new(list(self.data) + new_data) def flatten(self): """ Returns a nested PGroup as un-nested e.g. :: >>> P(0,(3,5)).flatten() P(0, 3, 5) """ values = [] for item in self: if isinstance(item, PGroup): values.extend(list(item)) else: values.append(item) return PGroup(values) def concat(self, data): """ Concatonates this patterns stream with another """ new = PGroup() if isinstance(data, PGroup): new.data = self.data + data.data # Creates a pattern elif isinstance(data, Pattern): args = list(self.data) args.append(data) new = PGroup(*args) elif isinstance(data, (list, str, range)): new.data = list(self.data) new.data.extend(map(convert_nested_data, data)) else: new.data = list(self.data) new.append(data) return new def _get_step(self, dur): return dur def _get_delay(self, delay): return 0 def _get_sample(self): return 0 def calculate_time(self, dur): """ Returns a PGroup of durations to use as the delay argument when this is a sub-class of `PGroupPrime` """ values = [] step = self._get_step(dur) for i, item in enumerate(self): delay = self._get_delay( i * step ) if isinstance(item, PGroup): delay += item.calculate_time( step ) values.append( delay ) return PGroup(values) def calculate_sample(self): values = [] for item in self.data: if isinstance(item, PGroup): sample = item.calculate_sample() else: sample = None values.append(sample) if all([v is None for v in values]): return None else: return self.__class__(values) # could cause adding issues def get_behaviour(self): """ Returns a function that changes a player event dictionary """ def action(event, key): this_delay = self.calculate_time(float(event['dur'])) return self._update_event(event, key, this_delay) return action def _update_event(self, event, key, delay): sample = self.calculate_sample() event = self._update_sample(event, sample) event = self._update_delay(event, delay) return event @staticmethod def _update_delay(event, delay): """ Updates the delay value in the event dictionary """ event["delay"] = sum_delays(event["delay"], delay) return event @staticmethod def _update_sample(event, sample): """ Updates the sample value in the event dictionary """ if isinstance(sample, PGroup): new_sample = sample.replace(None, 0) old_sample = event["sample"] * (sample == None) event["sample"] = new_sample + old_sample elif sample is not None: event["sample"] = sample return event def has_behaviour(self): """ Returns True if this is a PGroupPrime or any elements are instances of PGroupPrime or its sub-classes""" for value in self: if isinstance(value, PGroup) and value.has_behaviour(): return True else: return False def get_name(self): return self.__class__.__name__ def ne(self, other): """ Not equals operator """ values = [] other = PatternFormat(other) if isinstance(other, Pattern): return other.ne(self) for i, item in enumerate(self.data): # possibly LCM? item = item != modi(other,i) if not isinstance(item, metaPattern): item = int(item) values.append(item) #return self.__class__(values) return PGroup(values) def __ne__(self, other): return self.ne(other) def eq(self, other): """ equals operator """ values = [] other = PatternFormat(other) # bad function name if isinstance(other, Pattern): return other.eq(self) for i, item in enumerate(self.data): # possibly LCM? item = item == modi(other,i) if not isinstance(item, metaPattern): item = int(item) values.append(item) # return self.__class__(values) return PGroup(values) def __hash__(self): return hash( self.__key() ) def __key(self): """ Returns a tuple of information to identify this Pattern """ return (self.__class__, tuple(self.data)) def __eq__(self, other): return self.eq(other) def __gt__(self, other): values = [] other = PatternFormat(other) if isinstance(other, Pattern): return other < self for i, item in enumerate(self): # possibly LCM item = item > modi(other,i) if not isinstance(item, metaPattern): item = int(item) values.append(item) return self.new(values) def __lt__(self, other): values = [] other = PatternFormat(other) if isinstance(other, Pattern): return other > self for i, item in enumerate(self): # possibly LCM item = item < modi(other,i) if not isinstance(item, metaPattern): item = int(item) values.append(item) return self.new(values) def __ge__(self, other): values = [] other = PatternFormat(other) if isinstance(other, Pattern): return other <= self for i, item in enumerate(self): # possibly LCM item = item >= modi(other,i) if not isinstance(item, metaPattern): item = int(item) values.append(item) return self.new(values) def __le__(self, other): values = [] other = PatternFormat(other) if isinstance(other, Pattern): return other >= self for i, item in enumerate(self): # possibly LCM item = item <= modi(other,i) if not isinstance(item, metaPattern): item = int(item) values.append(item) return self.new(values) import random class GeneratorPattern: """ Used for when a Pattern does not generate a set length pattern, e.g. random patterns """ MAX_SIZE = 65536 debugging = False def __init__(self, **kwargs): # Set the seed if a random pattern self.args = tuple() self.kwargs = kwargs self.mod = Pattern() self.mod_functions = [] self.name = self.__class__.__name__ self.parent = None self.last_value = None self.data = [] self.index = 0 self.cache = {} def __repr__(self): """ String version is the name of the class and its arguments """ return "{}({})".format(self.name, self.data) @classmethod def help(cls): return print(cls.__doc__) def getitem(self, index=None, *args): """ Calls self.func(index) to get an item if index is not in self.history, otherwise returns self.history[index] """ if index is None: index, self.index = self.index, self.index + 1 # If we have already accessed by this index, return the value if index in self.cache: return self.cache[index] else: # Calculate new value value = self.func(index) # Store if we refer to the same index self.cache[index] = value return value @property def CACHE_HEAD(self): ''' Returns the last value used if it exists ''' return self.cache.get(self.index - 1) def new(self, other, func=Nil): """ Creates a new `GeneratorPattern` that references this pattern but returns a modified value based on func. """ new = GeneratorPattern() new.parent = self new.name = new.parent.name new.other = asStream(other) # We want to store the pattern I think? new.data = "{} {}".format(func.__name__, other) new.func = lambda index: func(new.parent.getitem(index), new.other[index]) return new def func(self, index): return index @staticmethod def from_func(pattern_generator_func): """ Create a generator which invokes a given function to generate items. The given function should take and integer argument and return a pattern item. """ class CustomGeneratorPattern(GeneratorPattern): def func(self, index): return pattern_generator_func(index) return CustomGeneratorPattern() def __int__(self): return int(self.getitem()) def __float__(self): return float(self.getitem()) # Arithmetic operations create new GeneratorPatterns def __add__(self, other): return self.new(other, Add) def __radd__(self, other): return self.new(other, Add) def __sub__(self, other): return self.new(other, Sub) def __rsub__(self, other): return self.new(other, rSub) def __mul__(self, other): return self.new(other, Mul) def __rmul__(self, other): return self.new(other, Mul) def __div__(self, other): return self.new(other, Div) def __truediv__(self, other): return self.new(other, Div) def __rdiv__(self, other): return self.new(other, rDiv) def __rtruediv__(self, other): return self.new(other, rDiv) def __mod__(self, other): return self.new(other, Mod) def __rmod__(self, other): return self.new(other, rMod) # Container methods def __iter__(self): for i in range(self.MAX_SIZE): yield self[i] def __getitem__(self, key): if type(key) is int: return self.getitem(key) elif type(key) is slice: a = key.start if key.start else 0 b = key.stop c = key.step if key.step else 1 return Pattern([self[i] for i in range(a, b, c)]) def dup(self, n=2): """ Returns a PGroup with n lots of the Generator """ return PGroup([self.__class__(*self.args, **self.kwargs) for i in range(n)]) def transform(self, func): """ Use func, which should take 1 argument, to transform the values in a generator pattern. Trivial example: myGenerator.transform(lambda x: 0 if x in (0,1,2) else 3) """ return self.new(None, lambda a, b: func(a)) def map(self, mapping, default=0): """ Using .transform() to map values via a dictionary :: a = PRand([0,1]) b = a.map({0: 16, 1: 25}) """ return self.transform( lambda value: mapping.get(value, default) ) def copy(self): ''' Returns a new Pattern Generator with same inputs ''' return self.__class__(*self.args, **self.kwargs) # TODO - handle callables # funcs = {} # for key, value in mapping.items(): # # We can map using a function # if callable(key) and callable(value): # funcs[partial(lambda: key(self.now()))] = partial(lambda: value(self.now())) # elif callable(key) and not callable(value): # funcs[partial(lambda: key(self.now()))] = partial(lambda e: e, value) # elif callable(value): # funcs[partial(lambda e: self.now() == e, key)] = partial(lambda: value(self.now())) # else: # # one-to-one mapping # funcs[partial(lambda e: self.now() == e, key)] = partial(lambda e: e, value) # def mapping_function(a, b): # for func, result in funcs.items(): # if bool(func()) is True: # value = result() # break # else: # value = default # return value # new = self.child(0) # new.calculate = mapping_function # return new class PatternContainer(metaPattern): def getitem(self, key, *args): key = key % len(self) return self.data[key] def __len__(self): return len(self.data) def __str__(self): return str(self.data) def __repr__(self): return str(self) class EmptyItem(object): """ Can be used in a pattern and and is essentially not there """ def __init__(self): pass def __repr__(self): return "_" """ Utility functions and data """ # Used to force any non-pattern data into a Pattern PatternType = (Pattern, list) def asStream(data): """ Forces any data into a [pattern] form """ return data if isinstance(data, Pattern) else Pattern(data) def PatternFormat(data): """ If data is a list, returns Pattern(data). If data is a tuple, returns PGroup(data). Returns data if neither. """ if isinstance(data, list): return Pattern(data) if isinstance(data, tuple): return PGroup(data) return data def PatternInput(data): if isinstance(data, GeneratorPattern): return data return asStream(data) Format = PatternFormat ## TODO - Remove this def convert_nested_data(data): """ Converts a piece of data in a pattern to a PGroup/Pattern as appropriate """ from renardo_lib.Constants import NoneConst if isinstance(data, (int, float)): return data elif data == None: return NoneConst() elif type(data) is tuple: return PGroup(data) elif type(data) is list or (type(data) is str and len(data) > 1): return Pattern(data) else: return data def patternclass(a, b): return PGroup if isinstance(a, PGroup) and isinstance(b, PGroup) else Pattern def Convert(*args): """ Returns tuples/PGroups as PGroups, and anything else as Patterns """ PatternTypes = [] for val in args: if isinstance(val, (Pattern, PGroup)): PatternTypes.append(val) elif isinstance(val, tuple): PatternTypes.append(PGroup(val)) else: PatternTypes.append(Pattern(val)) return PatternTypes if len(PatternTypes) > 0 else PatternTypes[0] def asPattern(item): if isinstance(item, metaPattern): return item if isinstance(item, list): return Pattern(item) if isinstance(item, tuple): return PGroup(item) return Pattern(item) def pattern_depth(pat): """ Returns the level of nested arrays """ total = 1 for item in pat: if isinstance(item, PGroup): depth = pattern_depth(item) if depth + 1 > total: total = depth + 1 return total def equal_values(this, that): """ Returns True if this == that """ comp = this == that if isinstance(comp, metaPattern): return all(list(comp)) else: return comp def group_modi(pgroup, index): """ Returns value from pgroup that modular indexes nested groups """ std_type = (int, float, str, bool) if isinstance(pgroup, Pattern.TimeVar) and isinstance(pgroup.now(), std_type): return pgroup elif isinstance(pgroup, std_type): return pgroup try: return group_modi(pgroup[index % len(pgroup)], index // len(pgroup)) except(TypeError, AttributeError, ZeroDivisionError): return pgroup def get_avg_if(item1, item2, func = lambda x: x != 0): if isinstance(item1, PGroup): result = item1.avg_if(item2, func) elif isinstance(item2, PGroup): result = item2.avg_if(item1, func) else: result = avg_if_func(item1, item2, func) return result def sum_delays(a, b): if bool(a == b): return a if not isinstance(a, PGroup): a = PGroup(a) if not isinstance(b, PGroup): b = PGroup(b) sml, lrg = sorted((a, b), key=lambda x: len(x)) if all([item in lrg for item in sml]): value = lrg else: value = a + b return value if len(value) > 1 else value[0] def force_pattern_args(f): """ Wrapper for forcing arguments to be a Pattern """ def new_func(*args, **kwargs): new_args = tuple(x if isinstance(x, metaPattern) else PGroup(x) for x in args) new_kwargs = { key: value if isinstance(value, metaPattern) else value for key, value in kwargs.items() } return f(*new_args, **new_kwargs) return new_func ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/Operations.py0000644000175100001770000000551614611211152022246 0ustar00runnerdockerfrom renardo_lib.Utils import LCM import itertools """ Module for key operations on Python lists or FoxDot Patterns """ def DominantPattern(*patterns): return min((p for p in patterns if hasattr(p, "WEIGHT")), key = lambda x: x.WEIGHT) class POperand: def __init__(self, func): self.operate = func def __call__(self, A, B): """ A is always a Pattern or PGroup.""" # If the first pattern is empty, return the other as a pattern if len(A) == 0: return A.__class__(B) # Get the dominant pattern type and convert B key = DominantPattern(A, B) cls = key.__class__ # Instead of coverting the dominant to its own class, make a true_copy? A = cls(A) B = cls(B) # Calculate total length before operations i, length = 0, LCM(len(A.get_data()), len(B.get_data())) gen_a = itertools.cycle(A.get_data()) gen_b = itertools.cycle(B.get_data()) P1 = [] while i < length: try: try: val = self.operate(next(gen_a), next(gen_b)) except TypeError as e: raise TypeError("Cannot operate on {!r} and {!r}".format(A, B)) except ZeroDivisionError: val = 0 P1.append(val) i += 1 # Copy the dominant pattern and set the new data vals return key.true_copy(P1) # General operations def Nil(a, b): return a def Add(a, b): return a + b def Sub(a, b): return a - b def Mul(a, b): return a * b def Div(a, b): return a / b def Mod(a, b): return a % b def Pow(a, b): return a ** b def Get(a, b): try: return a[b] except TypeError: return a def FloorDiv(a, b): return a // b def Xor(a, b): return a ^ b def Or(a, b): return a | b def rAdd(a, b): return b + a def rGet(a, b): try: return b[a] except TypeError: return b def rSub(a, b): return b - a def rMul(a, b): return b * a def rDiv(a, b): return b / a def rMod(a, b): return b % a def rPow(a, b): return b ** a def rFloorDiv(a, b): return b // a def rXor(a, b): return b ^ a def rOr(a, b): return b | a # Pattern operations PAdd = POperand(Add) PSub = POperand(Sub) PSub2 = POperand(rSub) PMul = POperand(Mul) PDiv = POperand(Div) PDiv2 = POperand(rDiv) PFloor = POperand(FloorDiv) PFloor2 = POperand(rFloorDiv) PMod = POperand(Mod) PMod2 = POperand(rMod) PPow = POperand(Pow) PPow2 = POperand(rPow) PGet = POperand(Get) # Pattern comparisons -> need to maybe have a equals func? PEq = lambda a, b: (all([int(a[i]==b[i]) for i in range(len(a))]) if len(a) == len(b) else False) if a.__class__ == b.__class__ else False PNe = lambda a, b: (any([int(a[i]!=b[i]) for i in range(len(a))]) if len(a) == len(b) else True) if a.__class__ == b.__class__ else True././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/PGroups.py0000644000175100001770000001776014611211152021526 0ustar00runnerdockerfrom renardo_lib.Patterns.Main import PGroup, PatternMethod, GeneratorPattern, sum_delays from renardo_lib.Utils import modi, LCM class PGroupPrime(PGroup): WEIGHT = 1 """ Base class for PGroups with "behavior" that affect a Player's event dictionary """ def change_state(self): """ To be overridden by any PGroupPrime that changes state after access by a Player """ return def convert_data(self, *args, **kwargs): self.change_state() return PGroup.convert_data(self, *args, **kwargs) def has_behaviour(self): return True def _get_step(self, dur): return float(dur) / len(self) def _get_delay(self, delay): return delay class metaPGroupPrime(PGroupPrime): """ Base class for PGroups that take any extra arguments to be stored """ WEIGHT = 3 def __init__(self, *args, **kwargs): PGroupPrime.__init__(self, *args, **kwargs) if isinstance(self, PGroup): self.meta = self.data[self.ignore:] self.data = self.data[:self.ignore] class PGroupStar(PGroupPrime): """ Stutters the values over the length of and event's 'dur' """ bracket_style="*()" class PGroupPlus(PGroupPrime): """ Stutters the values over the length of and event's 'sus' """ bracket_style="+()" def get_behaviour(self): """ Returns a function that modulates a player event dictionary """ def action(event, key): this_delay = self.calculate_time(float(event['sus'])) return self._update_event(event, key, this_delay) return action class PGroupPow(PGroupPrime): """ Stutters a shuffled version the values over the length of and event's 'dur' """ bracket_style="**()" def calculate_time(self, dur): return PGroupPrime.calculate_time(self, dur).shuffle() class PGroupDiv(PGroupPrime): """ Stutter every other request """ bracket_style="/()" counter = 0 def __init__(self, *args, **kwargs): PGroupPrime.__init__(self, *args, **kwargs) def change_state(self): self.counter += 1 def calculate_time(self, dur): if self.counter % 2 == 1: return PGroupPrime.calculate_time(self, dur) else: return 0 class PGroupMod(PGroupPlus): """ OBSOLETE -------- Useful for when you want many nested groups. This PGroup flattens the original but the delay times are calculated in the same way as if the values were neseted """ bracket_style="%()" def __len__(self): return len([item for item in self]) def getitem(self, index): return list(self)[index] def _get_step(self, dur): return float(dur) / len(self.data) def calculate_time(self, dur): """ Returns a PGroup of durations to use as the delay argument when this is a sub-class of `PGroupPrime` """ values = [] step = self._get_step(dur) for i, item in enumerate(self.data): delay = self._get_delay( i * step ) if hasattr(item, "calculate_time"): delay += item.calculate_time( step ) if isinstance(delay, PGroup): values.extend(list(delay)) else: values.append( delay ) return PGroup(values) def __iter__(self): return self.get_iter(self.data) @staticmethod def get_iter(group): """ Recursively unpacks nested PGroup into an un-nested group""" for item in group: if isinstance(item, PGroup): for sub in PGroupMod.get_iter(item.data): yield sub else: yield item class PGroupOr(metaPGroupPrime): """ Used to specify `sample` values, usually from within a play string using values between "bar" signs e.g. "|x2|" """ bracket_style="|()" ignore = -1 def __init__(self, seq=[]): metaPGroupPrime.__init__(self, seq) # May be changed to a Pattern if self.__class__ is not PGroupOr: return self.data = self.data[:1] # Make sure we only have 1 element for data def calculate_sample(self): sample = self.meta[0] if isinstance(sample, PGroupPrime): sample = PGroup(sample) elif isinstance(sample, GeneratorPattern): sample = sample.getitem() return sample def calculate_time(self, *args, **kwargs): """ Return a single value, as its always "length" 1 """ char_delay = PGroupPrime.calculate_time(self, *args, **kwargs)[0] samp_delay = self.meta[0].calculate_time(*args, **kwargs) if isinstance(self.meta[0], PGroup) else 0 return sum_delays(char_delay, samp_delay) def _get_delay(self, *args, **kwargs): return 0 def _get_step(self, dur): return dur #class PGroupFloorDiv(PGroupPrime): # """ Unused """ # bracket_style="//()" #class PGroupSub(PGroupPrime): # """ Unused """ # bracket_style="-()" class PGroupXor(metaPGroupPrime): """ The delay of this PGroup is specified by the last value (not included in the data) """ bracket_style="^()" ignore = -1 def __init__(self, seq=[]): if isinstance(seq, self.__class__): self.data = seq.data self.meta = seq.meta return metaPGroupPrime.__init__(self, seq) # May be changed to a Pattern if self.__class__ is not PGroupXor: return # Make sure we have at least 1 item of data if len(self.data) == 0 and len(self.meta) == 1: self.data = self.meta self.meta = [0] def _get_step(self, dur): return self.meta[0] def _get_delay(self, delay): return delay class PGroupAnd(PGroupPrime): """ Unused """ bracket_style="&()" delay = 0 def __init__(self, args): PGroupPrime.__init__(self, args[0]) if len(args) > 0: self.delay = args[1] def calculate_step(self, i, dur): return i * self.delay # Define any pattern methods that use PGroupPrimes @PatternMethod def offadd(self, value, dur=0.5): return self + PGroupXor((0, value, dur)) @PatternMethod def offmul(self, value, dur=0.5): #return self * PGroupXor(1, value).set_delay(dur) return self * PGroupXor((1, value, dur)) @PatternMethod def offlayer(self, method, dur=0.5, *args, **kwargs): """ Zips a pattern with a modified version of itself. Method argument can be a function that takes this pattern as its first argument, or the name of a Pattern method as a string. """ if callable(method): func = method args = [self] + list(args) else: func = getattr(self, method) assert callable(func) return self.zip(func(*args, **kwargs), dtype=lambda a, b: PGroupXor([a, b, dur])) @PatternMethod def amen(self, size=2): """ Merges and laces the first and last two items such that a drum pattern "x-o-" would become "(x[xo])-o([-o]-)" """ new = [] for n in range( LCM(len(self), 4) ): if n % 4 == 0: new.append([self[n], PGroupPlus(self[n], modi(self, n + size))]) elif n % 4 == size: new.append( [self[n]]*3+[self[n-1]] ) elif n % 4 == size + 1: new.append( [PGroupPlus(self[n], self[n-1]), [self[n], self[n-1]] ] ) else: new.append(self[n]) return self.__class__(new) @PatternMethod def bubble(self, size=2): """ Merges and laces the first and last two items such that a drum pattern "x-o-" would become "(x[xo])-o([-o]-)" """ new = [] for n in range(len(self.data)): if n % 4 == 0: new.append([self.data[n], PGroupPlus(self.data[n], modi(self.data, n + size))]) elif n % 4 == 2: new.append( [self.data[n]]*3+[self.data[n-1]] ) elif n % 4 == 3: new.append( [PGroupPlus(self.data[n], self.data[n-1]), [self.data[n], self.data[n-1]] ] ) else: new.append(self.data[n]) return self.__class__(new)././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/Parse.py0000644000175100001770000001414114611211152021167 0ustar00runnerdocker""" Patterns.Parse.py ================= Handles the parsing of Sample Player Object Strings """ import re from renardo_lib.Patterns.PlayString import PlayString, ParseError from renardo_lib.Patterns.Generators import PRand from renardo_lib.Patterns.PGroups import PGroupOr, PGroupPlus from renardo_lib.Patterns.Main import Pattern, metaPattern, PatternMethod, PGroup, GeneratorPattern from renardo_lib.Utils import modi, LCM re_nests = r"\((.*?)\)" re_square = r"\[.*?\]" re_curly = r"\{.*?\}" re_arrow = r"<.*?>" square_type = PGroupPlus braces_type = PRand bar_type = PGroupOr def ParsePlayString(string, flat=False): """ Returns the parsed play string used by sample player """ output, _ = feed(string) return output def convert_to_int(data): """ Recursively calls until all nested data contains only integers """ if isinstance(data, (int, float, str)): return int(data) elif isinstance(data, (list, tuple)): return data.__class__([convert_to_int(item) for item in data]) elif isinstance(data, GeneratorPattern): return data.transform(convert_to_int) elif isinstance(data, metaPattern): return data.convert_data(convert_to_int) return int(data) def arrow_zip(pat1, pat2): """ Zips two patterns together. If one item is a tuple, it extends the tuple / PGroup i.e. arrow_zip([(0,1),3], [2]) -> [(0,1,2),(3,2)] """ output = Pattern() for i in range(LCM(len(pat1), len(pat2))): item1 = pat1.getitem(i, get_generator=True) item2 = pat2.getitem(i, get_generator=True) if all([x.__class__== PGroup for x in (item1, item2)]): new_item = PGroup(item1.data + item2.data) elif item1.__class__ == PGroup: new_item = PGroup(item1.data + [item2]) elif item2.__class__ == PGroup: new_item = PGroup([item1] + item2.data) else: new_item = (item1, item2) output.append(new_item) return output def feed(string): """ Used to recursively parse nested strings, returns a list object (not Pattern), and a boolean denoting if the list contains a nested list """ string = PlayString(string) items = [] # The actual pattern layer_pattern = False contains_nest = False i = 0 while i < len(string): char = string[i] # look for a '<>' if char == "<": # Parse the contents of the brackets if found j = string.index(">", start=i+1) s = string[i+1:j] i = j chars, _ = feed(s) if len(chars) == 0: e = "Empty '<>' brackets in string" raise ParseError(e) # If we know we are layering, zip the last item if layer_pattern: items[-1] = items[-1].zip( Pattern(chars) ) else: items.append(Pattern(chars)) layer_pattern = True contains_nest = True # Look for || for specifying sample numbers elif char == "|": # Parse the contents of the brackets if found j = string.next_char_index("|", start=i+1) s = string[i+1:j] i = j chars, _ = feed(s) if len(chars) == 0: e = "Empty '||' delimeters in string" raise ParseError(e) try: assert(len(chars) == 2) except AssertionError: e = "'||' delimeters must contain exactly 2 elements" raise ParseError(e) # First is our list of sample chars samp_chr = chars[0] # Next is a list of integers for sample kw samp_num = convert_to_int(chars[1]) # print(samp_chr, samp_num) items.append(bar_type((samp_chr, samp_num))) # Look for a '()' elif char == "(": # Parse the contents of the brackets if found j = string.index(")", start=i+1) s = string[i+1:j] i = j chars, _ = feed(s) if len(chars) == 0: e = "Empty '()' brackets in string" raise ParseError(e) items.append( chars ) # add the nested list layer_pattern = False contains_nest = True # Look for a '{}' elif char == "{": # Parse the contents of the brackets if found j = string.index("}", start=i+1) s = string[i+1:j] i = j chars, _ = feed(s) if len(chars) == 0: e = "Empty '{}' brackets in string" raise ParseError(e) items.append( braces_type(chars) ) layer_pattern = False # Look for a '[]' elif char == "[": j = string.index("]", start=i+1) s = string[i+1:j] i = j chars, contains_nest = feed(s) if len(chars) == 0: e = "Empty '[]' brackets in string" raise ParseError(e) # Un-nest if contains_nest: # May contain sub-nests, so re-parse with calculated duration new_chars = [] largest_item = max([len(ch) for ch in chars]) for num in range(largest_item): new_chars.append(square_type([modi(ch, num) for ch in chars])) items.append( new_chars ) layer_pattern = False else: new_chars = [] for char in chars: new_chars.append(char) items.append( square_type(new_chars) ) layer_pattern = False # Add single character to list elif char not in ")]}>|": items.append( char ) layer_pattern = False # Increase iterator i += 1 return items, contains_nest @PatternMethod def fromString(self, string): self.data = ParsePlayString(string) self.make() return self ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/PlayString.py0000644000175100001770000000274314611211152022216 0ustar00runnerdocker re_nests = r"\((.*?)\)" re_square = r"\[.*?\]" re_curly = r"\{.*?\}" re_chars = r"[^[\](){}]" br_pairs = {"(":")", ")":"(", "[":"]", "]":"[", "{":"}", "}":"{"} class ParseError(Exception): pass class PlayString: """ Container for character objects """ contains_nest = False def __init__(self, string): self.string = list(string) self.original = str(string) def __repr__(self): return repr(self.string) def __len__(self): return len(self.string) def __getitem__(self, key): return self.string[key] def __setitem__(self, key, value): self.string[key] = value def index(self, sub, start=0): """ Returns the index of the closing bracket """ br = "([{<"[")]}>".index(sub)] count = 0 for i in range(start, len(self.string)): char = self.string[i] if char == br: count += 1 elif char == sub: if count > 0: count -= 1 else: return i err = "Closing bracket {!r} missing in string {!r}".format(sub, "".join(self.original)) raise ParseError(err) def next_char_index(self, char, start=0): try: return self.string[start:].index(char) + start except IndexError: raise ParseError("No {!r} character found in string {!r}".format(char, self.original))././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/Sequences.py0000644000175100001770000002616114611211152022055 0ustar00runnerdocker""" Sequences.py ------------ All patterns inherit from Base.Pattern. There are two types of pattern: 1. Container types * Similar to lists but with different mathematical operators 2. Generator types * Similar to generators but can be indexed (returns values based on functions) """ import random import math from renardo_lib.Patterns.Main import Pattern, asStream, loop_pattern_func from renardo_lib.Patterns.PGroups import ( PGroupAnd, GeneratorPattern, PGroup, PGroupStar, PGroupPow, PGroupXor, PGroupOr, PGroupPlus, PGroupDiv, modi ) from renardo_lib.Patterns.Operations import LCM from renardo_lib.Patterns.Generators import PRand from renardo_lib.Utils import sliceToRange, EuclidsAlgorithm, PulsesToDurations MAX_SIZE = 2048 #==============================# # 1. P[] & P() # #==============================# class __pattern__(object): ''' Used to define lists as patterns: `P[1,2,3]` is equivalent to `Pattern([1,2,3])` and `P(1,2,3)` is equivalent to `Pattern((1,2,3))` and `P+(1,2,3)` is equivalient to `Pattern((1,2,3))`. Ranges can be created using slicing, e.g. `P[1:6:2]` will generate the range 1 to 6 in steps of 2, thus creating the Pattern `[1, 3, 5]`. Slices can be combined with other values in a Pattern such that `P[0,2,1:10]` will return the Pattern `P[0, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9]` ''' def __getitem__(self, args): if isinstance(args, Pattern): return args elif isinstance(args, (Pattern.TimeVar, Pattern.PlayerKey)): data = [args] elif hasattr(args, '__iter__') and not isinstance(args, (str, bytes, GeneratorPattern, PGroup)): data = [] for item in args: if type(item) is slice: data.extend(sliceToRange(item)) else: data.append(item) elif type(args) is slice: data = sliceToRange(args) else: data = args return Pattern(data) def __call__(self, *args): return PGroup(args if len(args) > 1 else args[0]) def __mul__(self, other): """ P*[0,1,2] returns PRand([0,1,2]) P*(0,1,2) returns PGroupStar(0,1,2) """ if isinstance(other, (list, Pattern)): return PRand(list(other)) else: return PGroupStar(other) def __pow__(self, other): """ P**(x1, x2,...,xn) - Returns scrambled version """ return PGroupPow(other) def __xor__(self, other): """ P^(x1, x2,..., dur) - Returns a PGroup that delays each value by dur * n """ return PGroupXor(other) def __or__(self, other): """ P|("x", 2) """ return PGroupOr(other) def __add__(self, other): return PGroupPlus(other) def __radd__(self, other): return self + other def __truediv__(self, other): return PGroupDiv(other) def __mod__(self, other): if isinstance(other, list): return Pattern().fromString(other[0], flat=True) return PGroupMod(other) def __and__(self, other): return PGroupAnd(other) def __invert__(self): return __reverse_pattern__() class __reverse_pattern__(__pattern__): def __getattr__(self, name): return ~object.__getattr__(self, name) # This is a pattern creator P = __pattern__() #================================# # 2. Pattern Functions # #================================# #: Pattern functions that take patterns as arguments def PShuf(seq): ''' PShuf(seq) -> Returns a shuffled version of seq''' return Pattern(seq).shuffle() def PAlt(pat1, pat2, *patN): ''' Returns a Pattern generated by alternating the values in the given sequences ''' data = [] item = [asStream(p) for p in [pat1, pat2] + list(patN)] size = LCM(*[len(i) for i in item]) for n in range(size): for i in item: data.append(modi(i,n)) return Pattern(data) def PStretch(seq, size): ''' Returns 'seq' as a Pattern and looped until its length is 'size' e.g. `PStretch([0,1,2], 5)` returns `P[0, 1, 2, 0, 1]` ''' return Pattern(seq).stretch(size) def PPairs(seq, func=lambda n: 8-n): """ Laces a sequence with a second sequence obtained by performing a function on the original. By default this is `lambda n: 8 - n`. """ i = 0 data = [] for item in seq: data.append(item) data.append(func(item)) i += 1 if i >= MAX_SIZE: break return Pattern(data) def PZip(pat1, pat2, *patN): ''' Creates a Pattern that 'zips' together multiple patterns. `PZip([0,1,2], [3,4])` will create the Pattern `P[(0, 3), (1, 4), (2, 3), (0, 4), (1, 3), (2, 4)]` ''' l, p = [], [] for pat in [pat1, pat2] + list(patN): p.append(P[pat]) l.append(len(p[-1])) length = LCM(*l) return Pattern([tuple(pat[i] for pat in p) for i in range(length)]) def PZip2(pat1, pat2, rule=lambda a, b: True): ''' Like `PZip` but only uses two Patterns. Zips together values if they satisfy the rule. ''' length = LCM(len(pat1), len(pat2)) data = [] i = 0 while i < length: a, b = modi(pat1,i), modi(pat2,i) if rule(a, b): data.append((a,b)) i += 1 return Pattern(data) @loop_pattern_func def PStutter(x, n=2): """ PStutter(seq, n) -> Creates a pattern such that each item in the array is repeated n times (n can be a pattern) """ return Pattern([x for i in range(n)]) @loop_pattern_func def PSq(a=1, b=2, c=3): ''' Returns a Pattern of square numbers in the range a to a+c ''' return Pattern([x**b for x in range(a,a+c)]) @loop_pattern_func def P10(n): ''' Returns an n-length Pattern of a randomly generated series of 1's and 0's ''' return Pattern([random.choice((0,1)) for i in range(int(n))]) @loop_pattern_func def PStep(n, value, default=0): ''' Returns a Pattern that every n-term is 'value' otherwise 'default' ''' return Pattern([default] * (n-1) + [value]) @loop_pattern_func def PSum(n, total, **kwargs): """ Returns a Pattern of length 'n' that sums to equal 'total' e.g. PSum(3,8) -> P[3, 3, 2] PSum(5,4) -> P[1, 0.75, 0.75, 0.75, 0.75] """ lim = kwargs.get("lim", 0.125) data = [total + 1] step = 1 while sum(data) > total: data = [step for x in range(n)] step *= 0.5 i = 0 while sum(data) < total and step >= lim: if sum(data) + step > total: step *= 0.5 else: data[i % n] += step i += 1 return Pattern(data) @loop_pattern_func def PRange(start, stop=None, step=1): """ Returns a Pattern equivalent to ``Pattern(range(start, stop, step))`` """ if stop is None: start, stop = 0, start if start == stop: return Pattern(start) if (start > stop and step > 0) or (start < stop and step < 0): step = step*-1 return Pattern(list(range(start, stop, step))) @loop_pattern_func def PTri(start, stop=None, step=1): """ Returns a Pattern equivalent to ``Pattern(range(start, stop, step))`` with its reversed form appended.""" if stop is None: start, stop = 0, start pat = PRange(start, stop, step) return pat | pat.reverse()[1:-1] @loop_pattern_func def PSine(n=16): """ Returns values of one cycle of sine wave split into 'n' parts """ i = (2 * math.pi) / n return Pattern([math.sin(i * j) for j in range(int(n))]) @loop_pattern_func def PEuclid(n, k): ''' Returns the Euclidean rhythm which spreads 'n' pulses over 'k' steps as evenly as possible. e.g. `PEuclid(3, 8)` will return `P[1, 0, 0, 1, 0, 0, 1, 0]` ''' return Pattern( EuclidsAlgorithm(n, k) ) @loop_pattern_func def PEuclid2(n, k, lo, hi): ''' Same as PEuclid except it returns an array filled with 'lo' value instead of 0 and 'hi' value instead of 1. Can be used to generate characters patterns used to play sample like play(PEuclid2(3,8,'-','X')) will be equivalent to play(P['X', '-', '-', 'X', '-', '-', 'X', '-']) that's like saying play("X--X--X-") ''' return Pattern( EuclidsAlgorithm(n, k, lo, hi) ) @loop_pattern_func def PBern(size=16, ratio=0.5): """ Returns a pattern of 1s and 0s based on the ratio value (between 0 and 1). This is called a Bernoulli sequence. """ return Pattern([int(random.random() < ratio) for n in range(size)]) def PBeat(string, start=0, dur=0.5): """ Returns a Pattern of durations based on an input string where non-whitespace denote a pulse e.g. :: >>> PBeat("x xxx x") P[1, 0.5, 0.5, 1, 0.5] """ data = [int(char != " ") for char in list(string)] pattern = Pattern(PulsesToDurations( data )) if start != 0: pattern = pattern.rotate(int(start)) return pattern * dur @loop_pattern_func def PDur(n, k, start=0, dur=0.25): """ Returns the *actual* durations based on Euclidean rhythms (see PEuclid) where dur is the length of each step. :: >>> PDur(3, 8) P[0.75, 0.75, 0.5] >>> PDur(5, 16) P[0.75, 0.75, 0.75, 0.75, 1] """ # If we have more pulses then steps, double the steps and decrease the duration while n > k: k = k * 2 dur = dur / 2 pattern = Pattern(PulsesToDurations( EuclidsAlgorithm(n, k) )) if start != 0: pattern = pattern.rotate(int(start)) return pattern * dur @loop_pattern_func # forces it into a stream instead of Group def PDelay(*args): return PDur(*args).accum().group() @loop_pattern_func def PStrum(n=4): """ Returns a pattern of durations similar to how you might strum a guitar """ return (Pattern([1,1/2]).stutter([1,n + 1])|Pattern([1.5,1/2]).stutter([1,n])|1) def PQuicken(dur=1/2, stepsize=3, steps=6): """ Returns a PGroup of delay amounts that gradually decrease """ delay = [] count = 0 for i in range(steps): for j in range(stepsize-1): delay.append( count ) count += dur / stepsize dur /= stepsize return PGroup(delay) def PRhythm(durations): """ Converts all tuples/PGroups into delays calculated using the PDur algorithm. e.g. PRhythm([1,(3,8)]) -> P[1,(2,0.75,1.5)] *work in progress* """ if len(durations) == 1: item = durations[0] if isinstance(item, (tuple, PGroup)): return PDur(*item) else: return durations else: durations = asStream(durations).data output = Pattern() for i in range(len( asStream(durations).data ) ): item = durations[i] if isinstance(item, (list, Pattern)): value = PRhythm(item) elif isinstance(item, (tuple, PGroup)): dur = PDur(*item) value = PGroup(sum(dur)|dur.accum()[1:]) else: value = item output.append(value) return output def PJoin(patterns): """ Joins a list of patterns together """ data = [] for pattern in patterns: data.extend(pattern) return Pattern(data) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/Utils.py0000644000175100001770000000520614611211152021217 0ustar00runnerdockerfrom renardo_lib.Patterns.Main import Pattern, asStream, PGroup from renardo_lib.Patterns.Sequences import PDur # Other useful functions that don't return a single pattern def CalculateEuclideanDelay(durations): """ Calculates a pattern of durations and delays using nested tuples/PGroups and the PDur algorithm -- currently not implemented. """ durs, dels = Pattern(), Pattern() for item in asStream(durations).data: # If it's a pattern / list, calc the delays if isinstance(item, (list, Pattern)): a, b = CalculateEuclideanDelay(item) durs.append(a) dels.append(b) # if it's a tuple/PGroup, calculate the PDur elif isinstance(item, (tuple, PGroup)): dur = PDur(*item) durs.append(sum(dur)) dels.append(dur.accum().group()) # If neither, just add the duration and a zero delay else: durs.append(item) dels.append(0) return durs, dels def CalculateDelaysFromDur(durations): """ Used to calculate delays when the `dur` argument is given tuples. It replicates two events. """ # If it's a PvarGenerator, this needs more work #if isinstance(durations, Pattern.PvarGenerator): # durs = durations.transform(lambda a, b: CalculateDelaysFromDur(b.now())[0]) # dels = durations.transform(lambda a, b: CalculateDelaysFromDur(b.now())[1]) # could be more efficient? # return durs, dels # If its a Pvar, create a new Pvar that uses this function as its transformation function if isinstance(durations, Pattern.Pvar): durs = durations.transform(lambda a, b: CalculateDelaysFromDur(a)[0]) dels = durations.transform(lambda a, b: CalculateDelaysFromDur(a)[1]) return durs, dels # Continue if not a pvargenerator durs, dels = Pattern(), Pattern() for item in asStream(durations).data: # If it's a pattern / list, calc the delays if isinstance(item, (list, Pattern)): a, b = CalculateDelaysFromDur(item) durs.append(a) dels.append(b) # if it's a tuple/PGroup, first dur as dur and then differences as delays elif isinstance(item, (tuple, PGroup)): if len(item) > 1: dur = min(item) durs.append(dur) dels.append(PGroup([offset - dur for offset in item])) else: durs.append(item[0]) dels.append(0) # If neither, just add the duration and a zero delay else: durs.append(item) dels.append(0) return durs, dels.rotate(-1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Patterns/__init__.py0000644000175100001770000000576414611211152021667 0ustar00runnerdocker""" A `Pattern` object is a container-like object, similar to Python lists, but with slightly different behaviour. The two most notable differences are how they behave when used with arithmetic operators and how they behave when indexed. A `Pattern` can be created by instantiating the class like so: myPattern = Pattern([0,1,2,3]) This returns an a `Pattern` with the contents `[0,1,2,3]`. This is simply written as `P[0,1,2,3]`. You can also use this shorthand to create a pattern: myPattern = P[0,1,2,3] When using this method of instantiating a `Pattern` you can use Python slices to generate a range of numbers. The following creates the pattern `P[0,1,2,3,4,6,8,10]`: myPattern = P[0:4,4:12:2] Nested lists in a `Pattern` are treated not as single elements but as alternating values when indexing the `Pattern` with values greater than the apparent length of the `Pattern`. The following two `Pattern` objects are identical: >>> a = P[0,1,2,[3,4]] >>> b = P[0,1,2,3,0,1,2,4] >>> a[3], b[3] 3, 3 >>> a[7], b[7] 4, 4 >>> a == b True No matter what the index, the `Pattern` will return a value, usually `pat[i % len(pat)]` where `i` is the index and `pat` is a `Pattern`. Nested values are accessed in turn depending on how large the index is. Nested `tuples` become instances of the `PGroup` class when used in a `Pattern`, which are containers with similar behaviour to the `Pattern` class but are not accessed alternatively when nested, but all values are returned. You can instantiate a `PGroup` in similar manner to instantiating a `Pattern` myGroup1 = PGroup([0,1,2]) myGroup2 = P(0,1,2) If I try and instantiate a `PGroup` with a `list` or `Pattern` as an element then a `Pattern` of `PGroups` is returned instead, alternating the values in the slot that was a list: >>> P(0,1,[2,3,4]) P[P(0, 1, 2), P(0, 1, 3), P(0, 1, 4)] Similar to `numpy` arrays, arithmetic operations are performed on all elements of a `Pattern`, including nested `Patterns` and `PGroups`. If I use a `list` or `Pattern` of values in an operation (we will use addition as an example) then each value is added in sequence until all values are added together: # Basic addition >>> P[0, 1, [2, 3], 4, (5,6)] + 2 P[2, 3, P[4, 5], 6, P(7, 8)] # Using a Pattern of values >>> P[0, 1, [2, 3], 4, (5,6)] + P[2, 4] P[2, 5, P[4, 5], 8, P(7, 8), 4, 3, P[6, 7], 6, P(9, 10)] `Patterns` also have many useful methods for manipulating the order of values, such as `palindrome` or `rotate`, and can be "chained" together as these don't affect the order in place and return the augmented version of the `Pattern`. """ from renardo_lib.Patterns.Main import * from renardo_lib.Patterns.Operations import * from renardo_lib.Patterns.Sequences import * from renardo_lib.Patterns.PGroups import * from renardo_lib.Patterns.Generators import * from renardo_lib.Patterns.PlayString import * from renardo_lib.Patterns.Parse import * from renardo_lib.Patterns.Utils import * ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Players.py0000644000175100001770000020220714611211152017736 0ustar00runnerdocker""" Players are what make FoxDot make music. They are similar in design to SuperCollider's `PDef` and `PBind` combo but with slicker syntax. FoxDot uses SuperCollider to *actually* make the sound and does so by triggering predefined `SynthDefs` - sort of like definitions of a digital instruments. To have a look at the list of `SynthDefs`, you can just `print` them to the console: :: print(SynthDefs) Each one of these represents a `SynthDef` *object*. These objects are then given to Players to play - like giving an instrument to someone in your orchestra. To give someone the instrument, `pads`, you use a double arrow some code syntax like this: :: p1 >> pads() To stop a Player, use the `stop` method e.g. `p1.stop()`. If you want to stop all players, you can use the command `Clock.clear()` or the keyboard shortcut `Ctrl+.`, which executes this command. `p1` is the name of a predefined player object. At startup, FoxDot reserves all one- and two-character variable names, such as `x`, `p1`, or `bd` for player objects but these can be repurposed if you like. If you want to use a variable name for a player object with more than two characters, you just instantiate a new `Player` object: :: foo = Player() foo >> pads() Changing parameters ------------------- By default, player objects play the first note of their default scale (more below) with a duration of 1 beat per note. To change the pitch just give the `SynthDef` a list of numbers. :: p1 >> pads([0,7,6,4]) Play multiple pitches together by putting them in round brackets: :: p1 >> pads([0,2,4,(0,2,4)]) When you start FoxDot up, your clock is ticking at 120bpm and your player objects are all playing in the major scale. With 8 pitches in the major scale, the 0 refers to the first pitch and the 7 refers to the pitch one octave higher because Python, like most programming languages, uses zero-indexing. To change your scale you can specify a new scale as a keyword argument (see the documentation on `Scales` for more information on scales) or change the default scale for all player objects. :: # Changing scale as a keyword argument p1 >> pads([0,7,6,4], scale=Scale.minor) # Changing the default scalew (the following are equivalent) Scale.default.set("minor") Scale.default.set(Scale.minor) Scale.default.set([0,2,3,5,7,8,10]) # See a list of scales print Scale.names() # Change the tempo (this takes effect at the next bar) Clock.bpm = 144 To change the rhythm of your player object, specify the durations using the `dur` keyword. Other keywords can be specified, such as `oct` for the octave and `sus` for the sustain, which is the same as the duration by default. :: p1 >> pads([0,7,6,4], dur=[1,1/2,1/4,1/4], oct=6, sus=1) # See a list of possible keyword arguments print(Player.get_attributes()) Using the `play` SynthDef ------------------------- There is a special case SynthDef object called `play` which allows you to play short audio files rather than specify pitches. In this case you use a string of characters as the first argument where each character refers to a different folder of audio files. You can see more information by evaluating `print(Samples)`. The following line of code creates a basic drum beat: :: d1 >> play("x-o-") To play multiple patterns simultaneously, you can create a new `play` object. This is useful if you want to have different attributes for each player. :: bd >> play("x( x) ", dur=1) hh >> play("---[--]", dur=[1/2,1/2,1/4], rate=4) sn >> play(" o ", rate=(.9,1), pan=(-1,1)) Grouping characters in round brackets laces the pattern so that on each play through of the sequence of samples, the next character in the group's sample is played. The sequence `(xo)---` would be played back as if it were entered `x---o---`. Using square brackets will force the enclosed samples to played in the same time span as a single character e.g. `--[--]` will play two hi-hat hits at a half beat then two at a quarter beat. You can play a random sample from a selection by using curly braces in your Play String like so: :: d1 >> play("x-o{-[--]o[-o]}") FoxDot Player Object Keywords ----------------------------- dur - Durations (defaults to 1 and 1/2 for the Sample Player) sus - Sustain (defaults to `dur`) amp - Amplitude (defaults to 1) rate - Variable keyword used for misc. changes to a signal. E.g. Playback rate of the Sample Player (defaults to 1) delay - A duration of time to wait before sending the information to SuperCollider (defaults to 0) sample - Special keyword for Sample Players; selects another audio file from the bank of samples for a sample character. """ from copy import copy, deepcopy from renardo_lib.Settings import SamplePlayer, LoopPlayer, SYNTHDEF_DIR from renardo_lib.SCLang.SynthDef import SynthDefProxy, SynthDef, SynthDefs from renardo_lib.Effects import FxList from renardo_lib.Buffers import Samples from renardo_lib.Key import PlayerKey, NumberKey from renardo_lib.Repeat import Repeatable from renardo_lib.Patterns import * from renardo_lib.Root import Root from renardo_lib.Scale import Scale, get_freq_and_midi from renardo_lib.Bang import Bang from renardo_lib.TimeVar import TimeVar, mapvar, linvar, inf, var from renardo_lib.Code import WarningMsg from renardo_lib.Utils import get_first_item class EmptyPlayer(object): """ Place holder for Player objects created at run-time to reduce load time. """ def __init__(self, name): self.name = name def __repr__(self): return "<{} - Unassigned>".format(self.name) def __rshift__(self, *args, **kwargs): """ Converts an EmptyPlayer to a Player. """ self.__class__ = Player self.__init__(self.name) self.__rshift__(*args, **kwargs) return self def __invert__(self): return self.reset() def __getattribute__(self, name): """ Tries to return the correct attr; if not init the Player and try again """ try: return object.__getattribute__(self, name) except AttributeError: self.__class__ = Player self.__init__(self.name) try: return self.__getattribute__(name) except AttributeError: return self.__getattr__(name) # use getattr to make sure we return player key class Player(Repeatable): """ FoxDot generates music by creating instances of `Player` and giving them instructions to follow. At startup FoxDot creates many instances of `Player` and assigns them to any valid two character variable. This is so that when you start playing you don't have to worry about typing `myPlayer = Player()` and `myPlayer_2 = Player()` every time you want to do something new. Of course there is nothing stopping you from doing that if yo so wish. Instances of `Player` are given instructions to generate music using the `>>` syntax, overriding the bitshift operator, and should be given an instance of `SynthDefProxy`. A `SynthDefProxy` is created when calling an instance of `SynthDef` - these are the "instruments" used by player objects and are written in SuperCollider code. You can see more information about these in the `SCLang` module. Below describes how to assign a `SynthDefProxy` of the `SynthDef` `pads` to a `Player` instance called `p1`: :: # Calling pads as if it were a function returns a # pads SynthDefProxy object which is assigned to p1 p1 >> pads() # You could store several instances and assign them at different times proxy_1 = pads([0,1,2,3], dur=1/2) proxy_2 = pads([4,5,6,7], dur=1) p1 >> proxy_1 # Assign the first to p1 p1 >> proxy_2 # This replaces the instructions being followed by p1 """ # Set private values debug = 0 __vars = [] __init = False # Really need to tidy this up keywords = ('degree', 'oct', 'freq', 'dur', 'delay', 'buf', 'blur', 'amplify', 'scale', 'bpm', 'sample', 'spack', "env") envelope_keywords = ("atk", "decay", "rel", "legato", "curve", "gain") # Base attributes base_attributes = ('sus', 'fmod', 'pan', 'rate', 'amp', 'midinote', 'channel') required_keys = ("amp", "sus") internal_keywords = tuple(value for value in keywords if value != "degree") # Aliases alias = { "pitch" : "degree", "char" : "degree" } fx_attributes = FxList.all_kwargs() fx_keys = FxList.kwargs() # Load default sample bank samples = Samples # Set in __init__.py metro = None default_scale = Scale.default default_root = Root.default() # TODO//remove callable after_update_methods = ["stutter"] # Tkinter Window widget = None def __init__(self, name=None): # Inherit from repeatable i.e. x.every Repeatable.__init__(self) self.method_synonyms["->"] = "rshift" self.method_synonyms["<-"] = "lshift" # General setup self.synthdef = None self.id = name #self.current_event_size = 0 #self.current_event_length = 0 #self.current_event_depth = 0 # Stopping flag self.stopping = False self.stop_point = 0 # Reference to other objects in the clock played at the same time self.queue_block = None self.bus = None # The string representation of the degree of the player self.playstring = "" # Information used in generating OSC messages self.buf_delay = [] self.timestamp = 0 # self.condition = lambda: True # self.sent_messages = [] # Visual feedback information self.envelope = None self.line_number = None self.whitespace = None self.do_bang = False self.bang_kwargs = {} # Keeps track of which note to play etc self.event_index = 0 self.event_n = 0 self.notes_played = 0 self.event = {} self.accessed_keys = [] # Used for checking clock updates self.current_dur = None self.old_pattern_dur = None self.old_dur = None self.isplaying = False self.isAlive = True # These dicts contain the attribute and modifier values that are sent to SuperCollider self.attr = {} self.modifier = Pattern() self.mod_data = 0 self.filename = None # Keyword arguments that are used internally self.scale = None self.offset = 0 self.following = None # List the internal variables we don't want to send to SuperCollider self.__vars = list(self.__dict__.keys()) self.__init = True self.reset() # Class methods @classmethod def help(cls): return print(cls.__doc__) @classmethod def get_attributes(cls): """ Returns a list of possible keyword arguments for FoxDot players""" return cls.keywords + cls.base_attributes @classmethod def get_fxs(cls): """ Returns a list of possible keyword arguments for FoxDot effects """ return cls.fx_attributes @classmethod def Attributes(cls): """ To be replaced by `Player.get_attributes()` """ return cls.get_attributes() @classmethod def set_clock(cls, tempo_clock): cls.metro = tempo_clock # Should this also be instance method? @classmethod def set_sample_bank(cls, sample_bank): cls.samples = sample_bank def __hash__(self): return hash(self.id) # could be problematic if there are id clashes? # Player Object Manipulation def __rshift__(self, other): """ Handles the allocation of SynthDef objects using >> syntax, other must be an instance of `SynthDefProxy`, which is usually created when calling a `SynthDef` """ if isinstance(other, SynthDefProxy): # Call the update method self.update(other.name, other.degree, **other.kwargs) # self.update_pattern_root('sample' if self.synthdef == SamplePlayer else 'degree') for method, arguments in other.methods: args, kwargs = arguments getattr(self, method).__call__(*args, **kwargs) # Add the modifier (check if not 0 to stop adding 0 to values) if (not isinstance(other.mod, (int, float))) or (other.mod != 0): self + other.mod return self raise TypeError("{} is an innapropriate argument type for PlayerObject".format(other)) return self def test_for_circular_reference(self, value, attr, last_player=None, last_attr=None): """ Used to raise an exception if a player's attribute refers to itself e.g. `p1 >> pads(dur=p1.dur)` """ # We are setting self.attr to value, check if value depends on self.attr if isinstance(value, PGroup): for item in value: self.test_for_circular_reference(item, attr, last_player, last_attr) elif isinstance(value, PlayerKey): # If the Player key relies on this player.attr, raise error if value.cmp(self, attr): ident_self = value.name() if last_player is not None: ident_other = "{}.{}".format(last_player.id, last_attr) else: ident_other = ident_self err = "Circular reference found: {} to itself via {}".format(ident_self, ident_other) raise ValueError(err) elif last_player == value.player and last_attr == value.attr: return else: # Go through the player key's for item in value.get_player_attribute(): self.test_for_circular_reference(item, attr, value.player, value.attr) return def __setattr__(self, name, value): # Possibly replace with slots? if self.__init: # Force the data into a Pattern if the attribute is used with SuperCollider if name not in self.__vars: # Get any alias name = self.alias.get(name, name) value = asStream(value) for item in value: self.test_for_circular_reference(item, name) # Update the attribute dict if no error self.attr[name] = value # Remove from the stored pattern dict / call those self.update_pattern_root(name) # keep track of what values we change with +- if (self.synthdef == SamplePlayer and name == "sample") or (self.synthdef == SamplePlayer and name == "spack") or (self.synthdef != SamplePlayer and name == "degree"): self.modifier = value # Update any playerkey if name in self.__dict__: if isinstance(self.__dict__[name], PlayerKey): self.__dict__[name].update_pattern() # self.update_player_key(name, 0, 0) return self.__dict__[name] = value return def __getattr__(self, name): try: # This checks for aliases, not the actual keys name = self.alias.get(name, name) if name in self.attr and name not in self.__dict__: # Return a Player key self.update_player_key(name, self.now(name), 0) item = self.__dict__[name] # If returning a player key, keep track of which are being accessed if isinstance(item, PlayerKey) and name not in self.accessed_keys: self.accessed_keys.append(name) return item except KeyError: err = "Player Object has no attribute '{}'".format(name) raise AttributeError(err) return def __getattribute__(self, name): # This checks for aliases, not the actual keys name = Player.alias.get(name, name) item = object.__getattribute__(self, name) if isinstance(item, PlayerKey): if name not in self.accessed_keys: self.accessed_keys.append(name) return item def __getitem__(self, name): if self.__init: if name not in self.__vars: return self.attr[name] pass return self.__dict__[name] def __eq__(self, other): return self is other def __ne__(self, other): return not self is other # --- Startup methods def reset(self): """ Sets all Player attributes to 0 unless their default is specified by an effect. Also can be called by using a tilde before the player variable. E.g. ~p1 """ # Add all keywords to the dict, then set non-zero defaults reset = [] for key in Player.Attributes(): if key not in ("scale", "dur", "sus", "blur", "amp", "amplify", "degree", "oct", "bpm"): setattr(self, key, 0) reset.append(key) # Set any non zero defaults for effects, e.g. verb=0.25 for key in Player.fx_attributes: value = FxList.defaults[key] setattr(self, key, value) reset.append(key) # Set SynthDef defaults if self.synthdef in SynthDefs: synth = SynthDefs[self.synthdef] for key in ("atk", "decay", "rel"): setattr(self, key, synth.defaults[key]) reset.append(key) # Any other attribute that might have been used - set to 0 for key in self.attr: if key not in reset: setattr(self, key, 0) # Set any non-zero values for FoxDot # Sustain & Legato self.sus = 0.5 if self.synthdef == SamplePlayer else 1 self.blur = 1 # Amplitude self.amp = 1 self.amplify = 1 # Duration of notes self.dur = 0.5 if self.synthdef == SamplePlayer else 1 # Degree of scale / Characters of samples self.degree = " " if self.synthdef is SamplePlayer else 0 # Octave of the note self.oct = 5 # Tempo self.bpm = None # Stop calling any repeating methods self.stop_calling_all() return self def __invert__(self): """ Using the ~ syntax resets the player """ return self.reset() # --- Update methods def __call__(self, **kwargs): """ Sends the next osc message event to SuperCollider and schedules this Player in the clock based on the current clock time and this player's current duration value. """ # If stopping, kill the event if self.stopping and self.metro.now() >= self.stop_point: self.kill() return # If the duration has changed, work out where the internal markers should be # -- This could be in its own private function force_count = kwargs.get("count", False) dur_updated = self.dur_updated() if dur_updated or force_count is True: try: self.event_n, self.event_index = self.count(self.event_index if not force_count else None) except TypeError as e: print(e) print("TypeError: Innappropriate argument type for 'dur'") # Get the current state self.get_event() # Play the note if not isinstance(self.event["dur"], rest): try: self.send(verbose=(self.metro.solo == self and kwargs.get('verbose', True))) except Exception as err: print("Error in Player {}: {}".format(self.id, err)) # If using custom bpm dur = self.event["dur"] if self.event['bpm'] is not None: try: tempo_shift = float(self.metro.bpm) / float(self.event['bpm']) except (AttributeError, TypeError, ZeroDivisionError): tempo_shift = 1 dur *= tempo_shift # Schedule the next event (could move before get_event and use the index for get_event) self.event_index = self.event_index + dur self.metro.schedule(self, self.event_index, kwargs={}) # Change internal marker self.event_n += 1 self.notes_played += 1 return def count(self, time=None, event_after=False): """ Counts the number of events that will have taken place between 0 and `time`. If `time` is not specified the function uses self.metro.now(). Setting `event_after` to `True` will find the next event *after* `time`""" n = 0 acc = 0 dur = 0 now = (time if time is not None else self.metro.now()) if self.current_dur is None: self.current_dur = self.rhythm() durations = list(map(get_first_item, self.current_dur)) # careful here total_dur = float(sum(durations)) if total_dur == 0: WarningMsg("Player object has a total duration of 0. Set to 1") durations = [1] total_dur = 1 self.dur = 1 acc = now - (now % total_dur) try: n = int(len(durations) * (acc / total_dur)) except TypeError as e: WarningMsg(e) self.stop() return 0, 0 if acc != now: while True: dur = float(modi(durations, n)) if acc + dur == now: acc += dur n += 1 break elif acc + dur > now: if event_after: acc += dur n += 1 break else: acc += dur n += 1 # Returns value for self.event_n and self.event_index return n, acc def dur_updated(self): """ Returns True if the players duration has changed since the last call """ self.current_dur = self.rhythm() if self.current_dur != self.old_dur: self.old_dur = self.current_dur return True return False def rhythm(self): """ Returns the players array of durations at this point in time """ return list(map(lambda x: x if isinstance(x, (int, float)) else self.unpack(x), self.attr["dur"])) def update(self, synthdef, degree, **kwargs): """ Updates the attributes of the player. Called using the >> syntax. """ # SynthDef name self.synthdef = synthdef # Make sure all values are reset to start if "filename" in kwargs: self.filename = kwargs["filename"] del kwargs["filename"] if self.isplaying is False: self.reset() # If there is a designated solo player when updating, add this at next bar if self.metro.solo.active() and self.metro.solo != self: self.metro.schedule(lambda *args, **kwargs: self.metro.solo.add(self), self.metro.next_bar()) # Update the attribute values special_cases = ["scale", "root", "dur"] # Set the degree if synthdef == SamplePlayer: if type(degree) == str: self.playstring = degree else: self.playstring = None if degree is not None: setattr(self, "degree", degree if degree != "" else " ") elif degree is not None: self.playstring = str(degree) # this doesn't work for var! setattr(self, "degree", degree) else: setattr(self, "degree", 0) # Set special case attributes self.scale = kwargs.get("scale", self.__class__.default_scale ) self.root = kwargs.get("root", self.__class__.default_root ) # If only duration is specified, set sustain to that value also if "dur" in kwargs: # If we use tuples / PGroups in setting duration, use it to modify delay using the PDur algorithm setattr(self, "dur", kwargs["dur"]) if "sus" not in kwargs: self.sus = self.attr['dur'] # Set any other attributes for name, value in kwargs.items(): if name not in special_cases: setattr(self, name, value) # Calculate new position if not already playing if self.isplaying is False: # Add to clock self.isplaying = True self.stopping = False # If we want to update now, set the start point to now after = True if self.metro.now_flag: start_point = self.metro.now() after = False elif kwargs.get("quantise", True) == False: start_point = self.metro.now() else: start_point = self.metro.next_bar() self.event_n = 0 self.event_n, self.event_index = self.count(start_point, event_after=after) self.metro.schedule(self, self.event_index) return self def often(self, *args, **kwargs): """ Calls a method every 1/2 to 4 beats using `every` """ return self.every(PRand(1, 8)/2, *args, **kwargs) def sometimes(self, *args, **kwargs): """ Calls a method every 4 to 16 beats using `every` """ return self.every(PRand(8, 32)/2, *args, **kwargs) def rarely(self, *args, **kwargs): """ Calls a method every 16 to 32 beats using `every` """ return self.every(PRand(32, 64)/2, *args, **kwargs) def get_timestamp(self, beat=None): if beat is not None: timestamp = self.metro.osc_message_time() - self.metro.beat_dur(self.metro.now() - beat) else: timestamp = self.metro.osc_message_time() return timestamp def stutter(self, amount=None, _beat_=None, **kwargs): """ Plays the current note n-1 times. You can specify keywords. """ timestamp = self.get_timestamp(_beat_) # Get the current values (this might be called between events) n = int(kwargs.get("n", amount if amount is not None else 2)) ahead = int(kwargs.get("ahead", 0)) for key in ("ahead", "n"): if key in kwargs: del kwargs[key] # Only send if n > 1 and the player is playing if self.metro.solo == self and n > 1: new_event = {} attributes = self.attr.copy() attr_keys = set(list(self.attr.keys()) + list(kwargs.keys())) for key in attr_keys: if key in kwargs: item = kwargs[key] if isinstance(item, PGroupPrime): new_event[key] = self.unpack(item) elif isinstance(item, PGroup): new_event[key] = self.unpack(PGroup([item])) else: new_event[key] = self.unpack(PGroup(item)) elif len(attributes[key]) > 0: new_event[key] = self.now(key, ahead) new_event = self.unduplicate_durs(new_event) dur = float(kwargs.get("dur", new_event["dur"])) / n new_event["dur"] = dur # Get PGroup delays new_event["delay"] = PGroup([dur * (i+1) for i in range(max(n, self.get_event_length(new_event)))]) new_event = self.get_prime_funcs(new_event) self.send(timestamp=timestamp, **new_event) return self def jump(self, ahead=1, _beat_=None, **kwargs): """ Plays an event ahead of time. """ timestamp = self.get_timestamp(_beat_) if self.metro.solo == self: new_event = {} attributes = copy(self.attr) for key in attributes: if key in kwargs: new_event[key] = self.unpack(PGroup(kwargs[key])) elif len(attributes[key]) > 0: new_event[key] = self.now(key, ahead) new_event = self.unduplicate_durs(new_event) new_event = self.get_prime_funcs(new_event) self.send(timestamp=timestamp, **new_event) return self def lshift(self, n=1): """ Plays the event behind """ self.event_n -= (n+1) return self def rshift(self, n=1): """ Plays the event in front """ self.event_n += n return self # Preset methods def spread(self, on=0.125): """ Sets pan to (-1, 1) and pshift to (0, 0.125)""" if on != 0: self.pan=(-1,1) self.pshift=(0,on) else: self.pan=0 self.pshift=0 return self def unison(self, unison=2, detune=0.125): """ Like spread(), but can specify number of voices(unison) Sets pan to (-1,-0.5,..,0.5,1) and pshift to (-0.125,-0.0625,...,0.0625,0.125) If unison is odd, an unchanged voice is added in the center Eg : p1.unison(4, 0.5) => pshift=(-0.5,-0.25,0.25,0.5), pan=(-1.0,-0.5,0.5,1.0) p1.unison(5, 0.8) => pshift=(-0.8,-0.4,0,0.4,0.8), pan=(-1.0,-0.5,0,0.5,1.0) """ if unison != 0: pan=[] pshift=[] uni = int(unison if unison%2==0 else unison-1) for i in range(1,int(uni/2)+1): pan.append(2*i/uni) pan.insert(0, -2*i/uni) for i in range(1, int(uni/2)+1): pshift.append(detune*(i/(uni/2))) pshift.insert(0,detune*-(i/(uni/2))) if unison%2!=0 and unison > 1: pan.insert(int(len(pan)/2), 0) pshift.insert(int(len(pan)/2), 0) self.pan = tuple(pan) self.pshift = tuple(pshift) else: self.pan=0 self.pshift=0 return self def seconds(self): """ Sets the player bpm to 60 so duration will be measured in seconds """ self.bpm=60 return self def slider(self, start=0, on=1): """ Creates a glissando effect between notes """ if on: if start: self.slide=[1,0] self.slidefrom=[0,1] else: self.slide=[0,1] self.slidefrom=[1,0] self.slidedelay=0.75 else: self.slide=0 self.slidefrom=0 self.slidedelay=0 return self def penta(self, switch=1): """ Shorthand for setting the scale to the pentatonic mode of the default scale """ if switch: self.scale = self.__class__.default_scale.pentatonic else: self.scale = self.__class__.default_scale return self def alt_dur(self, dur): """ Used to set a duration that changes linearly over time. You should use a `linvar` but any value can be used. This sets the `dur` to 1 and uses the `bpm` attribute to seemingly alter the durations """ self.dur = 1 self.bpm = self.metro.bpm*(1/(dur)) return self def reverse(self): """ Reverses every attribute stream """ for attr in self.attr: try: self.attr[attr] = self.attr[attr].pivot(self.event_n) except AttributeError: pass return self def shuffle(self): """ Shuffles the degree of a player. """ # If using a play string for the degree #if self.synthdef == SamplePlayer and self.playstring is not None: # # Shuffle the contents of playgroups among the whole string # new_play_string = PlayString(self.playstring).shuffle() # new_degree = Pattern(new_play_string).shuffle() #else: #new_degree = self.attr['degree'].shuffle() new_degree = self.previous_patterns["degree"].root.shuffle() self._replace_degree(new_degree) return self def rotate(self, n=1): """ Rotates the values in the degree by 'n' """ #self._replace_degree(self.attr['degree'].rotate(n)) new_degree = self.previous_patterns["degree"].root.rotate(n) self._replace_degree(new_degree) return self def attrmap(self, key1, key2, mapping): """ Sets the attribute for self.key2 to self.key1 altered with a mapping dictionary. """ self.attr[key2] = self.attr[key1].map(mapping) return self def smap(self, kwargs): """ Like map but maps the degree to the sample attribute """ self.attrmap("degree", "sample", kwargs) return self def map(self, other, mapping, otherattr="degree"): """ p1 >> pads().map(b1, {0: {oct=[4,5], dur=PDur(3,8), 2: oct}) """ # Convert dict to {"oct": {4}} # key is the value of player key, attr is for key, minimap in mapping.items(): for attr, value in minimap.items(): setattr(self, attr, mapvar(getattr(other, attr), value)) return self # --- Misc. Standard Object methods def __int__(self): return int(self.now('degree')) def __float__(self): return float(self.now('degree')) def __add__(self, data): """ Change the degree modifier stream """ self.mod_data = data if self.synthdef == SamplePlayer: # self.attr['sample'] = self.modifier + self.mod_data self.sample = self.modifier + self.mod_data else: #self.attr['degree'] = self.modifier + self.mod_data self.degree = self.modifier + self.mod_data return self def __sub__(self, data): """ Change the degree modifier stream """ self.mod_data = 0 - data if self.synthdef == SamplePlayer: self.attr['sample'] = self.modifier + self.mod_data else: self.attr['degree'] = self.modifier + self.mod_data return self def __mul__(self, data): return self def __div__(self, data): return self # --- Data methods def __iter__(self): for _, value in self.event.items(): yield value def number_of_layers(self, **kwargs): """ Returns the deepest nested item in the event """ num = 1 for attr, value in self.event.items(): value = kwargs.get(attr, value) if isinstance(value, PGroup): l = pattern_depth(value) else: l = 1 if l > num: num = l return num def largest_attribute(self, **kwargs): """ Returns the length of the largest nested tuple in the current event dict """ size = 1 values = [] for attr, value in self.event.items(): value = kwargs.get(attr, value) l = get_expanded_len(value) if l > size: size = l return size def get_event_length(self, event=None, **kwargs): """ Returns the largest length value in the event dictionary """ if event is None: event = self.event if kwargs: event = event.copy() event.update(kwargs) max_val = 0 for attr, value in event.items(): if isinstance(value, PGroup): l = len(value) else: l = 1 if l > max_val: max_val = l return max_val def number_attr(self, attr): """ Returns true if the attribute should be a number """ return not (self.synthdef == SamplePlayer and attr in ("degree", "freq")) def update_player_key(self, key, value, time): """ Forces object's dict uses PlayerKey instances """ if (key not in self.__dict__) or (not isinstance(self.__dict__[key], PlayerKey)): self.__dict__[key] = PlayerKey(value, player=self, attr=key) else: # Force values if not playing if self.isplaying is False: self.__dict__[key].set(value, time) else: self.__dict__[key].update(value, time) return def update_all_player_keys(self, ignore=[], event=None, **kwargs): """ Updates the internal values of player keys that have been accessed e.g. p1.pitch. If there is a delay, then schedule a function to update the values in the future. """ # Don't bother if no keys are being accessed if len(self.accessed_keys) == 0: return if event is None: event = self.event delay = event.get("delay", 0) if isinstance(delay, PGroup): event_size = self.get_event_length(event, **kwargs) delays = itertools.cycle(delay) for i in range(event_size): delay = next(delays) # recursively unpack new_event = {} for new_key, new_value in event.items(): if new_key in self.accessed_keys: new_value = kwargs.get(new_key, new_value) if isinstance(new_value, PGroup): new_event[new_key] = new_value[i] else: new_event[new_key] = new_value if isinstance(delay, PGroup): # Recursively unpack and send messages for i in range(self.get_event_length(new_event)): self.update_all_player_keys(event=new_event, ignore=ignore, **kwargs) else: self.update_player_key_from_event(new_event, time=self.event_index, ignore=ignore, delay=delay, **kwargs) else: self.update_player_key_from_event(event, time=self.event_index, ignore=ignore, delay=delay, **kwargs) return def update_player_key_from_event(self, event, time=None, delay=0, ignore=[], **kwargs): timestamp = self.event_index if time is None else time if delay == 0: for key in (x for x in self.accessed_keys if x not in ignore): self.update_player_key(key, kwargs.get(key, event.get(key, 0)), timestamp) else: func_args = (event, timestamp + delay, 0, ignore) self.metro.schedule(self.update_player_key_from_event, timestamp + delay, args=func_args, kwargs=kwargs) return def update_player_key_relation(self, item): """ Called during 'now' to update any Players that a player key is related to before using that value """ # If this *is* the parent, just get the current value if item.parent is self: self.update_player_key(item.attr, self.now(item.attr), 0) # If the parent is in the same queue block, make sure its values are up-to-date elif self.queue_block is not None: # Try and find the item in the queue block try: queue_item = self.queue_block[item.player] except KeyError: queue_item = None # Update the parent with an up-to-date value if queue_item is not None and queue_item.called is False: item.player.update_player_key(item.attr, item.player.now(item.attr), 0) return item.now() # --- Methods for preparing and sending OSC messages to SuperCollider def unpack(self, item): """ Converts a pgroup to floating point values and updates and time var or playerkey relations """ if isinstance(item, GeneratorPattern): # "pop" value from the generator item = item.getitem() # could be renamed to "next" if isinstance(item, TimeVar): # Get current value if TimeVar item = item.now() if isinstance(item, NumberKey): # Update any relationships to the number key if necessary item = self.update_player_key_relation(item) if isinstance(item, PGroup): # Make sure any values in the PGroup have their "now" methods called item = item.convert_data(self.unpack) return item def get_key(self, key, i, **kwargs): return group_modi(kwargs.get(key, self.event[key]), i) # Private method def now(self, attr="degree", x=0, **kwargs): """ Calculates the values for each attr to send to the server at the current clock time """ index = self.event_n + x try: if len(self.attr[attr]) > 0: attr_value = kwargs.get(attr, self.attr[attr][index]) else: attr_value = 0 # maybe have a dict of defaults? # Debugging except KeyError as e: print(attr, self.attr[attr], index) raise(e) except ZeroDivisionError as e: print(self, attr, self.attr[attr], index) raise(e) # Force and timevar etc into floats if attr_value is not None and (not isinstance(attr_value, (int, float))): attr_value = self.unpack(attr_value) return attr_value def get_prime_funcs(self, event): """ Finds and PGroupPrimes in event and returns the modulated event dictionary """ prime_keys = ("degree", "sample") # Go through priority keys for key in prime_keys: self.apply_prime_funcs(event, key) # Then do the rest (skipping prime) for key in event: if key not in prime_keys: self.apply_prime_funcs(event, key) return event @staticmethod def apply_prime_funcs(event, key): value = event[key] if isinstance(value, PGroup) and value.has_behaviour(): func = value.get_behaviour() event = func(event, key) return event def unduplicate_durs(self, event): """ Converts values stored in event["dur"] in a tuple/PGroup into delays """ # If there are more than one dur then add to the delay if "dur" in event: try: if len(event['dur']) > 1: init_dur = event["dur"][0] offset = PGroup(0|event['dur'][1:]) event["delay"] = event["delay"] + offset event["dur"] = float(init_dur) elif len(event['dur']) == 1: event["dur"] = float(event["dur"][0]) except TypeError: pass if "sus" in event: try: # Also update blur / sus if len(event['sus']) > 1: min_sus = min(event['sus']) if min(event['sus']) else 1 offset = PGroup([(sus / min_sus) for sus in event["sus"]]) event["blur"] = event["blur"] * offset event["sus"] = float(min_sus) elif len(event['sus']) == 1: event["sus"] = float(event["sus"][0]) except TypeError: pass return event def get_event(self): """ Returns a dictionary of attr -> now values """ self.event = dict(map(lambda attr: (attr, self.now(attr)), self.attr.keys())) self.event = self.unduplicate_durs(self.event) self.event = self.get_prime_funcs(self.event) # Update internal player keys / schedule future updates self.update_all_player_keys() return self def send(self, timestamp=None, verbose=True, **kwargs): """ Goes through the current event and compiles osc messages and sends to server via the tempo clock """ timestamp = timestamp if timestamp is not None else self.queue_block.time # self.do_bang = False for i in range(self.get_event_length(**kwargs)): self.send_osc_message(self.event, i, timestamp=timestamp, verbose=verbose, **kwargs) # if self.do_bang: # self.bang() return def send_osc_message(self, event, index, timestamp=None, verbose=True, **kwargs): """ Compiles and sends an individual OSC message created by recursively unpacking nested PGroups """ packet = {} event=event.copy() event.update(kwargs) for key, value in event.items(): # If we can index a value, trigger a new OSC message to send OSC messages for each # value = kwargs.get(key, value) if isinstance(value, PGroup): new_event = {} for new_key, new_value in event.items(): # new_value = kwargs.get(new_key, new_value) if isinstance(new_value, PGroup): new_event[new_key] = new_value[index] else: new_event[new_key] = new_value # Recursively unpack and send messages for i in range(self.get_event_length(new_event)): self.send_osc_message(new_event, i, timestamp, verbose) return else: # If it is a number, use the numbers (check for kwargs override) packet[key] = value # Special case modulations if ("amp" in packet) and ("amplify" in packet): packet["amp"] = packet["amp"] * packet["amplify"] # Send compiled messages self.push_osc_to_server(packet, timestamp, verbose, **kwargs) return def push_osc_to_server(self, packet, timestamp, verbose=True, **kwargs): """ Adds message head, calculating frequency then sends to server if verbose is True and amp/bufnum values meet criteria """ # Do any calculations e.g. frequency message = self.new_message_header(packet, **kwargs) # Only send if amp > 0 etc if verbose and (message["amp"] > 0) and ((self.synthdef != SamplePlayer and message["freq"] != None) or (self.synthdef == SamplePlayer and message["buf"] > 0)): # Need to send delay and synthdef separately delay = self.metro.beat_dur(message.get("delay", 0)) synthdef = self.get_synth_name(message.get("buf", 0)) # to send to play1 or play2 compiled_msg = self.metro.server.get_bundle(synthdef, message, timestamp = timestamp + delay) # We can set a condition to only send messages self.queue_block.append_osc_message(compiled_msg) # self.do_bang = True return def new_message_header(self, event, **kwargs): """ Returns the header of an osc message to be added to by osc_message() """ # Let SC know the duration of 1 beat so effects can use it and adjust sustain too beat_dur = self.metro.beat_dur() message = {"beat_dur": beat_dur, "sus": kwargs.get("sus", event["sus"]) * beat_dur} if self.synthdef == SamplePlayer: degree = kwargs.get("degree", event['degree']) sample = kwargs.get("sample", event["sample"]) spack = kwargs.get("spack", event["spack"]) rate = kwargs.get("rate", event["rate"]) if rate < 0: sus = kwargs.get("sus", event["sus"]) pos = self.metro.beat_dur(sus) else: pos = 0 buf = self.samples.getBufferFromSymbol( str(degree), spack, sample).bufnum message.update({'buf': buf, 'pos': pos}) # Update player key if "buf" in self.accessed_keys: self.buf = buf elif self.synthdef == LoopPlayer: pos = kwargs.get("degree", event["degree"]) buf = kwargs.get("buf", event["buf"]) # Get a user-specified tempo given_tempo = kwargs.get("tempo", self.event.get("tempo", self.metro.bpm)) if given_tempo in (None, 0): tempo = 1 else: tempo = self.metro.bpm / given_tempo # Set the position in "beats" pos = pos * tempo * self.metro.beat_dur(1) # If there is a negative rate, move the pos forward rate = kwargs.get("rate", event["rate"]) if rate == 0: rate = 1 # Adjust the rate to a given tempo rate = float(tempo * rate) if rate < 0: sus = kwargs.get("sus", event["sus"]) pos += self.metro.beat_dur(sus) message.update( {'pos': pos, 'buf': buf, 'rate': rate} ) else: degree = kwargs.get("degree", event["degree"]) octave = kwargs.get("oct", event["oct"]) root = kwargs.get("root", event["root"]) spack = kwargs.get("spack", event["spack"]) scale = kwargs.get("scale", self.scale) if degree == None: freq, midinote = None, None else: freq, midinote = get_freq_and_midi(degree, octave, root, scale) message.update({'freq': freq, 'midinote': midinote}) # Updater player key if "freq" in self.accessed_keys: self.freq = freq if "midinote" in self.accessed_keys: self.midinote = midinote # Update the dict with other values from the event event.update(message) # Remove keys we dont need del event["bpm"] return event def set_queue_block(self, queue_block): """ Gives this player object a reference to the other items that are scheduled at the same time """ self.queue_block = queue_block return def get_synth_name(self, buf=0): """ Returns the real SynthDef name of the player. Useful only for "play" as there is a play1 and play2 SynthDef for playing audio files with one or two channels respectively. """ if self.synthdef == SamplePlayer: numChannels = self.samples.getBuffer(buf).channels if numChannels == 1: synthdef = "play1" else: synthdef = "play2" else: synthdef = str(self.synthdef) return synthdef def addfx(self, **kwargs): """ Not implemented - add an effect to the SynthDef bus on SuperCollider after it has been triggered. """ return self #: Methods for stop/starting players def kill(self): """ Removes this object from the Clock and resets itself""" self.isplaying = False self.stopping = True self.reset() if self in self.metro.playing: self.metro.playing.remove(self) return def stop(self, N=0): """ Removes the player from the Tempo clock and changes its internal playing state to False in N bars time - When N is 0 it stops immediately""" self.stopping = True self.stop_point = self.metro.now() if N > 0: self.stop_point = self.metro.next_bar() + ((N-1) * self.metro.bar_length()) else: self.kill() return self def pause(self): self.isplaying = False return self def play(self): self.isplaying = True self.stopping = False self.isAlive = True self.__call__() return self # Methods for collaborative performance # # e.g. follow # def accompany(self, other, values=[0,2,4], debug=False): """ Similar to "follow" but when the value has changed """ if isinstance(other, self.__class__): self.degree = other.degree.accompany() return self def follow(self, other=False): """ Takes a Player object and then follows the notes """ if isinstance(other, self.__class__): self.degree = other.degree return self def versus(self, other_key, rule=lambda x, y: x > y, attr=None): """ Sets the 'amplify' key for both players to be dependent on the comparison of keys """ # Get reference to the second player object other = other_key.player # Get the attribute from the key to versus this_key = getattr(self, other_key.attr if attr is None else attr) # Set amplifications based on the rule self.amplify = this_key.transform(lambda value: rule(value, other_key.now())) other.amplify = this_key.transform(lambda value: not rule(value, other_key.now())) return self def reload(self): """ If this is a 'play' or 'loop' SynthDef, reload the filename used""" if self.synthdef == LoopPlayer: Samples.reload(self.filename) return self def only(self): """ Stops all players except this one """ for player in list(self.metro.playing): if player is not self: player.stop() return self def solo(self, action=1): """ Silences all players except this player. Undo the solo by using `Player.solo(0)` """ action=int(action) if action == 0: self.metro.solo.reset() elif action == 1: self.metro.solo.set(self) elif action == 2: pass return self def versus_old(self, other, key = lambda x: x.freq, f=max): """ Takes another Player object and a function that takes two player arguments and returns one, default is the higher pitched """ if other is not None: # make sure it's using another player assert(other.__class__ == self.__class__) def func(x, y): return f(x, y, key=key) self.condition = lambda: func(self, other) == self other.condition = lambda: func(self, other) == other self._versus = other else: self.condition = lambda: True self._versus.condition = lambda: True self._versus = None return self # def versus(self, other, func = lambda a, b: a > b): # self.amp = self.pitch > other.pitch # other.amp = other.pitch > self.pitch # return self # Utils def num_key_references(self): """ Returns the number of 'references' for the attr which references the most other players """ num = 0 for attr in self.attr.values(): if isinstance(attr, PlayerKey): if attr.num_ref > num: num = attr.num_ref return num def _replace_degree(self, new_degree): # Update the GUI if possible #if self.widget: # if self.synthdef == SamplePlayer: # if self.playstring is not None: # # Replace old_string with new string (only works with plain string patterns) # new_string = new_degree.string() # self.widget.addTask(target=self.widget.replace, args=(self.line_number, self.playstring, new_string)) # self.playstring = new_string # else: # # Replaces the degree pattern in the widget (experimental) # # self.widget.addTask(target=self.widget.replace_re, args=(self.line_number,), kwargs={'new':str(new_degree)}) # self.playstring = str(new_degree) setattr(self, 'degree', new_degree) return def multiply(self, n=2): self.attr['degree'] = self.attr['degree'] * n return self def degrade(self, amount=0.5): """ Sets the amp modifier to a random array of 0s and 1s amount=0.5 weights the array to equal numbers """ if float(amount) <= 0: self.amplify = 1 else: self.amplify = PwRand([0, self.attr["amplify"]],[int(amount*10), max(10 - int(amount),0)]) return self def changeSynth(self, list_of_synthdefs): new_synth = choice(list_of_synthdefs) if isinstance(new_synth, SynthDef): new_synth = str(new_synth.name) self.synthdef = new_synth return self """ Modifier Methods ---------------- Other modifiers for affecting the playback of Players """ def offbeat(self, dur=1): """ Off sets the next event occurence """ self.dur = abs(dur) self.delay = abs(dur) / 2 return self def strum(self, dur=0.025): """ Adds a delay to a Synth Envelope """ x = self.largest_attribute() if x > 1: self.delay = asStream([tuple(a * dur for a in range(x))]) else: self.delay = asStream(dur) return self def __repr__(self): if self.id is not None: return "<{} - {}>".format(self.id, self.synthdef) else: return "a '{}' Player Object".format(self.synthdef) def get_extra_attributes(self): """ Returns a dict of specific keyword arguments for a particular FoxDot player """ filename = SYNTHDEF_DIR + f"/{self.id}.scd" file = open(filename, "r") contents = file.read() file.close() if "arg" in contents: arg_start = "arg" arg_end = "var" else: arg_start = "|" arg_end = "var" idx1 = contents.index(arg_start) idx2 = contents.index(arg_end) args = "" # getting elements in between for idx in range(idx1 + len(arg_start), idx2-3): args = args + contents[idx] args = "".join(args.split()) xtra_args = args.split(",") temp_args = {} for arg in xtra_args: if "=" in arg: a, b = arg.split("=") temp_args[a] = b self.extra_attr[a] = b for k in self.default_args: if k in temp_args.keys(): del self.extra_attr[k] return self.extra_attr def info(self): s = "Player Instance using '%s' \n\n" % self.synthdef s += "ATTRIBUTES\n" s += "----------\n\n" for attr, val in self.attr.items(): s += "\t{}\t:{}\n".format(attr, val) self.get_extra_attributes() for attr, val in self.extra_attr.items(): s += "\t{}\t:{}\n".format(attr, val) return s def bang(self, **kwargs): """ Triggered when sendNote is called. Responsible for any action to be triggered by a note being played. Default action is underline the player """ if kwargs: self.bang_kwargs = kwargs elif self.bang_kwargs: bang = Bang(self, self.bang_kwargs) return self # TODO: split this file (by classes) # TODO: externalize player methods like in hacked_foxdot codebase # TODO: use a volume sc effect / 3rd parameter for fades (to make it work with loop synthdef) # TODO: parametrise duration with bar length automatically # TODO: debug eclipse smooth feature def fade(self, dur=8, fvol=1, ivol=None, autostop=True): if ivol == None: ivol = float(self.amplify) self.amplify = linvar([ivol, fvol], [dur, inf], start=self.metro.mod(4)) def static_final_value(): if fvol == 0 and autostop: self.stop() else: self.amplify = fvol self.metro.schedule(static_final_value, self.metro.next_bar()+dur+1) return self def fadein(self, dur=8, fvol=1, ivol=0, autostop=True): self.fade(dur=dur, fvol=fvol, ivol=ivol, autostop=autostop) return self def fadeout(self, dur=4, fvol=0, ivol=1, autostop=True): self.fade(dur=dur, fvol=fvol, ivol=ivol, autostop=autostop) return self def solofade(self, dur=16, fvol=0, ivol=None, autostop=False): for player in list(self.metro.playing): if player is not self: # and not player.always_on: player.fade(dur, ivol, fvol, autostop) return self def solofadeout(self, dur=16, fvol=0, ivol=None, autostop=False): self.solofade(dur, ivol, fvol, autostop=autostop) return self def solofadein(self, dur=16, fvol=1, ivol=None, autostop=False): self.solofade(dur, ivol, fvol, autostop=autostop) return self def eclipse(self, dur=4, total=16, leftshift=0, smooth=0): """periodic pause of the player: pause 4 beats every 16""" if smooth == 0: self.amplify = var([1, 0, 1], [leftshift, dur, total - leftshift - dur]) else: self.amplify = linvar([1, 0, 0, 0, 1, 1], [leftshift, smooth * dur, dur - smooth * dur, smooth * dur, total - leftshift - dur - smooth * dur]) return self ###### GROUP OBJECT class Group: metro = None def __init__(self, *args): self.players = list(args) def add(self, other): self.players.append(other) def __len__(self): return len(self.players) def __str__(self): return str(self.players) def solo(self, arg=True): if self.metro is None: self.__class__.metro = Player.metro if arg: self.metro.solo.set(self.players[0]) for player in self.players[1:]: self.metro.solo.add(player) else: self.metro.solo.reset() return self def only(self): if self.metro is None: self.__class__.metro = Player.metro for player in list(self.metro.playing): if player not in self.players: player.stop() return self def iterate(self, dur=4): if dur == 0 or dur is None: self.amplify=1 else: delay, on = 0, float(dur) / len(self.players) for player in self.players: player.amplify=TimeVar([0,1,0],[delay, on, dur-delay]) delay += on return def __setattr__(self, name, value): try: for p in self.players: try: setattr(p, name, value) except: WarningMsg("'%s' object has no attribute '%s'" % (str(p), name)) except KeyError : self.__dict__[name] = value return self def __getattr__(self, name): """ Returns a Pattern object containing the desired attribute for each player in the group """ if name == "players": return self.__dict__["players"] attributes = GroupAttr() for player in self.players: if hasattr(player, name): attributes.append(getattr(player, name)) return attributes class GroupAttr(list): def __call__(self, *args, **kwargs): for p in self: if callable(p): p.__call__(*args, **kwargs) class rest(object): ''' Represents a rest when used with a Player's `dur` keyword ''' def __init__(self, dur=1): self.dur = dur if not isinstance(dur, self.__class__) else dur.dur def __repr__(self): return "".format(self.dur) def __add__(self, other): return rest(self.dur + other) def __radd__(self, other): return rest(other + self.dur) def __sub__(self, other): return rest(self.dur - other) def __rsub__(self, other): return rest(other - self.dur) def __mul__(self, other): return rest(self.dur * other) def __rmul__(self, other): return rest(other * self.dur) def __div__(self, other): return rest(self.dur / other) def __rdiv__(self, other): return rest(other / self.dur) def __truediv__(self, other): return rest(float(self.dur) / other) def __rtruediv__(self, other): return rest(other / float(self.dur)) def __mod__(self, other): return rest(self.dur % other) def __rmod__(self, other): return rest(other % self.dur) def __eq__(self, other): return (self.dur == other) def __ne__(self, other): return (self.dur != other) def __lt__(self, other): return (self.dur < other) def __le__(self, other): return (self.dur <= other) def __gt__(self, other): return (self.dur > other) def __ge__(self, other): return (self.dur >= other) def __int__(self): return int(self.dur) def __float__(self): return float(self.dur) class PlayerKeyException(Exception): pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Repeat.py0000644000175100001770000003503614611211152017543 0ustar00runnerdockerimport inspect from renardo_lib.Code import WarningMsg from renardo_lib.Patterns import Pattern, Cycle, asStream from renardo_lib.Utils import modi from renardo_lib.TimeVar import var class MethodList: """ Class for holding information about the order of which methods have been called on Player attributes. `root` is the original Pattern. """ def __init__(self, root): self.root=root self.list_of_methods = [] def get_root_pattern(self): return self.root def set_root_pattern(self, new): self.root = new def add_method(self, method_name, args, kwargs): self.list_of_methods.append((method_name, args, kwargs)) def update(self, method, args, kwargs): """ Updates the args and kwargs for a repeated method """ for i, info in enumerate(self.list_of_methods): name, _, _ = info if name == method: self.list_of_methods[i] = (method, args, kwargs) return raise ValueError def remove(self, method): """ Removes a method (should be a string) from the list of methods """ for i, info in enumerate(self.list_of_methods): name, args, kwargs = info if name == method: self.list_of_methods.pop(i) return raise ValueError def __repr__(self): return repr(self.list_of_methods) def __contains__(self, method): """ Returns true if the method is in the list of methods """ for name, args, kwargs in self.list_of_methods: if name == method: return True return False def __iter__(self): for value in self.list_of_methods: yield value class Repeatable(object): after_update_methods = [] method_synonyms = {} def __init__(self): self.repeat_events = {} self.previous_patterns = {} # not a good name - TODO change def update_pattern_root(self, attr): """ Update the base attribute pattern that methods are applied to """ if attr not in self.previous_patterns: self.previous_patterns[attr] = MethodList(self.attr[attr]) else: self.previous_patterns[attr].set_root_pattern( self.attr[attr] ) self.update_pattern_methods(attr) return def update_pattern_methods(self, attr): """ Update the 'current' version of a pattern based on its root and methods stored """ if attr not in self.previous_patterns: self.previous_patterns[attr] = MethodList(self.attr[attr]) result = self.previous_patterns[attr].get_root_pattern() # For each method in the list, call on the pattern for method, args, kwargs in self.previous_patterns[attr]: call_pattern_method = getattr(Pattern, method) result = call_pattern_method(result, *args, **kwargs) self.attr[attr] = result return def get_attr_and_method_name(self, cmd): """ Returns the attribute and method name from a string in the form `"attr.method"` would return `"attr"` and `"method"`. If attr is not present, it returns `"degree"` in place. """ if cmd in self.method_synonyms: attr = [ self.method_synonyms[cmd] ] else: attr = cmd.split(".") # We can also schedule attribute methods if len(attr) == 1: attr_name = "degree" method_name = attr[0] elif len(attr) == 2: attr_name = attr[0] method_name = attr[1] return attr_name, method_name def is_pattern_method(self, method_name, attr="degree"): """ Returns True if the method is a valid method of `Pattern` """ if attr == "degree" and hasattr(self, method_name): return False elif hasattr(Pattern, method_name): return True else: return False def is_player_method(self, method_name, attr="degree"): """ Returns True if the method is a valid method of `Player` """ return hasattr(self, method_name) and attr == "degree" def get_method_by_name(self, cmd): """ Returns the attribute name and method based on `cmd` which is a string. Should be in form `"attr.method"`. """ attr_name, method_name = self.get_attr_and_method_name(cmd) # Just get the player method if a valid player method if self.is_player_method(method_name, attr_name): method = getattr(self, method_name) # If its a Pattern method, create a "new" function that acts as a method elif self.is_pattern_method(method_name, attr_name): def method(*args, **kwargs): # If there are no "old" patterns held in memory, use the pattern method and store if attr_name not in self.previous_patterns: self.previous_patterns[attr_name] = MethodList(self.attr[attr_name]) # store the root # If this has already been called, "undo it" if method_name in self.previous_patterns[attr_name]: self.previous_patterns[attr_name].remove(method_name) # If not, add it to the list else: self.previous_patterns[attr_name].add_method(method_name, args, kwargs) # Update the attribute self.update_pattern_methods(attr_name) return method.__name__ = cmd # for debugging purposes else: # Raise TypeError if not a method err = "{} is not a valid method for type {}".format(cmd, self.__class__) raise(TypeError(err)) assert callable(method) return attr_name, method def after(self, n, cmd, *args, **kwargs): """ Schedule self.cmd(args, kwargs) in 'n' beats time ``` # Stop the player looping after 16 beats p1 >> pads().after(16, "stop") ``` """ quantise = kwargs.get("quantise", True) try: event = lambda: getattr(self, cmd)(*args, **kwargs) if not quantise: time = self.metro.now() + n else: time = self.metro.next_bar() + n self.metro.schedule( event, time ) except: pass return self def every(self, occurence, cmd, *args, **kwargs): """ Every n beats, call a method (defined as a string) on the object and use the args and kwargs. To call the method every n-th beat of a timeframe, use the `cycle` keyword argument to specify that timeframe. :: # Call the shuffle method every 4 beats p1.every(4, 'shuffle') # Call the stutter method on the 5th beat of every 8 beat cycle p1.every(5, 'stutter', 4, cycle=8) # If the method is not valid but *is* a valid Pattern method, that is called and reverted p1.every(4, 'palindrome') """ try: attr, method = self.get_method_by_name(cmd) except AttributeError: WarningMsg("{} is not a valid method for type {}".format(cmd, self.__class__)) return self # Collect the cycle length cycle = None ident = None if "cycle" in kwargs: cycle = kwargs["cycle"] del kwargs["cycle"] if "ident" in kwargs: ident = kwargs["ident"] del kwargs["ident"] # Convert `Cycles` to `var`-- should they be Pvar? attr_name, method_name = self.get_attr_and_method_name(cmd) # Just get the player method if a valid player method if self.is_player_method(method_name, attr_name): cycle_dur = occurence else: cycle_dur = occurence * 2 args, kwargs = self.convert_cycles(args, kwargs, cycle_dur) # If the method call already exists, just update it (should be in a function) if ident is not None: cmd = "{}-{}".format(cmd, ident) if cmd in self.repeat_events: # Work out whether the method needs calling or not call = self.repeat_events[cmd] # Update the time details call.update(occurence, cycle, args, kwargs) attr, method_name = self.get_attr_and_method_name(cmd) if self.is_pattern_method(method_name, attr): # if n is even, it means the method is active # TODO -- put this in a class mate n, acc = call.count() if n % 2 == 1: if method_name in self.previous_patterns[attr]: self.previous_patterns[attr].remove(method_name) else: if method_name in self.previous_patterns[attr]: self.previous_patterns[attr].update(method_name, args, kwargs) # Update the attribute self.update_pattern_methods(attr) if not call.isScheduled(): call.schedule() else: self.repeat_events[cmd] = MethodCall(self, method, occurence, cycle, args, kwargs) self.repeat_events[cmd].schedule() return self def stop_calling_all(self): """ Stops all repeated methods. """ for method in list(self.repeat_events.keys()): self.never(method) return self def never(self, cmd, ident=None): """ Stops calling cmd on repeat """ attr, method = self.get_attr_and_method_name(cmd) if ident is not None: cmd = "{}-{}".format(cmd, ident) try: # If it a pattern method, undo it if method in self.previous_patterns[attr]: self.previous_patterns[attr].remove(method) self.update_pattern_methods(attr) self.repeat_events[cmd].stop() del self.repeat_events[cmd] except KeyError: err = "Player method '{}' not active".format(cmd) raise KeyError(err) return self @staticmethod def convert_cycles(args, kwargs, occurence): """ Converts any values that are instances of `Cycle` to a `var` with the same duration as the frequency of the every call (occurrence) """ args = [(var(value, occurence) if isinstance(value, Cycle) else value) for value in args] kwargs = {key: (var(value, occurence) if isinstance(value, Cycle) else value) for key, value in kwargs.items()} return args, kwargs class MethodCall: """ Class to represent an object's method call that, when called, schedules itself in the future """ def __init__(self, parent, method, n, cycle=None, args=(), kwargs={}): self.parent = parent self.method = method self.update(n, cycle, args, kwargs) self.after_update = False self.stopping = False def update(self, n, cycle=None, args=(), kwargs={}): """ Updates the values of the MethodCall. Re-adjusts the index if cycle has been changed """ if cycle is not None: self.when = asStream(cycle) self.cycle = asStream(n) else: self.when = asStream(n) self.cycle = None self.args = args self.kwargs = kwargs # Check if a method has the _beat_ keyword argument if "_beat_" in inspect.getfullargspec(self.method).args: self.kwargs["_beat_"] = None self.i, self.next = self.count() self.offset = float(modi(self.cycle, self.i)) if self.cycle is not None else 0 return self def count(self): """ Counts the number of times this method would have been called between clock start and now """ n = 0; acc = 0; dur = 0 now = float(self.parent.metro.now()) # Get durations durations = self.when # if self.cycle is None else asStream(self.cycle) total_dur = float(sum(durations)) # How much time left to fit remainder in try: acc = now - (now % total_dur) except ZeroDivisionError: acc = 0 # n is the index to return for calculating self.when[n] # acc is when to start n = int(len(durations) * (acc / total_dur)) if acc != now: while True: dur = float(durations[n]) acc += dur n += 1 if acc >= now: break return n, acc def __repr__(self): return "".format(self.method.__name__, self.parent) def __call__(self, *args, **kwargs): """ Proxy for parent object __call__, calls the enclosed method and schedules it in the future. """ assert self.method is not None # Return without scheduling if stopping if self.stopping: return # Give the method a reference to when OSC messages should send self.assign_beat() # Call the method self.call_method() # Update the next time to schedule self.next += float(self.when[self.i]) if self.cycle is not None: self.offset = float(modi(self.cycle, self.i)) # Re-schedule the method call self.schedule() # Increase the index to get the next duration self.i += 1 return def assign_beat(self): if "_beat_" in self.kwargs: self.kwargs["_beat_"] = self.get_next() return def call_method(self): """ Calls the method. Prints to the console with error info. """ try: self.method.__call__(*self.args, **self.kwargs) except Exception as e: print("{} in '{}': {}".format(e.__class__.__name__, self.method.__name__, e)) return def get_next(self): """ Returns the beat that the next occurrence of this method call is due """ return self.next + self.offset def schedule(self): """ Schedules the method to be called in the clock """ self.parent.metro.schedule(self, self.get_next()) def isScheduled(self): """ Returns True if this is in the Tempo Clock """ return self in self.parent.metro def stop(self): self.stopping = True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Root.py0000644000175100001770000000420514611211152017240 0ustar00runnerdockerfrom renardo_lib.Utils import modi from renardo_lib.TimeVar import TimeVar CHROMATIC_NOTES = ["C"," ","D"," ","E","F"," ","G"," ","A"," ","B"] class Note: def __init__(self, index): self.char = None self.num = None self.set(index) def __str__(self): return str(self.num) def __repr__(self): return str(self.num) def __float__(self): return float(self.num) def __int__(self): return int(self.num) def set(self, index): if type(index) is str: char = index.title() if len(char) == 1: mod = 0 elif len(char) == 2 and char[1] == "#": mod = 1 elif len(char) == 2 and char[1] == "b": mod = -1 else: raise TypeError("Could not convert string '%s' to Note" % index) self.char = char self.num = (CHROMATIC_NOTES.index(char[0]) + mod) % len(CHROMATIC_NOTES) if type(index) is int: self.num = index self.char = modi(CHROMATIC_NOTES, index) if type(index) is float: self.num = index self.char = "" if isinstance(index, TimeVar): self.num = index self.char = "" def __iadd__(self, other): self.num += other def __isub__(self, other): self.num -= other def __add__(self, other): return self.num + other def __sub__(self, other): return self.num - other def __radd__(self, other): return other + self.num def __rsub__(self, other): return other - self.num def __call__(self, *args): if len(args) > 0: self.set(args[0]) return self class __root__: def __init__(self): self.default = Note("C") def __setattr__(self, key, value): if key == "default" and key in vars(self): self.default.set(value) else: self.__dict__[key] = value return def reset(self): """ Sets the root to 0 """ self.default = 0 Root = __root__() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/SCLang/0000755000175100001770000000000014611211157017056 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/SCLang/Env.py0000644000175100001770000000555414611211152020164 0ustar00runnerdockerfrom renardo_lib.SCLang.SCLang import instance, cls class EnvGen(instance): value = "Env" doneAction = 2 def __init__(self, value=None): self.value = self.value if value is None else value def __str__(self): return str( cls("EnvGen").ar(instance(self.__attr__()), doneAction=self.doneAction)) def __attr__(self): """ Converts the attr dict to SCLang arguments """ args = ",".join(["{}: {}".format(str(key), str(value)) for key, value in self.attr.items()]) return self.value + "(" + args + ")" class adsr: # todo: make this the only one and just put in the synthdef def __str__(self): return "EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\\sin), doneAction: 0)" class env(EnvGen): def __init__(self, sus=None, amp=None, curve="'lin'", doneAction=0): self.attr={} self.attr['times'] = [instance("sus") / 2]*2 if sus is None else sus self.attr['levels'] = [0] + ([instance("amp")] if amp is None else amp) + [0] self.attr['curve'] = curve self.doneAction = doneAction class mask(EnvGen): def __init__(self, sus=None, amp=None, curve="'lin'", doneAction=0): self.attr={} self.attr['times'] = [0.01, instance("sus") - 0.01, 0.01] if sus is None else sus self.attr['levels'] = [0,1,1,0] self.attr['curve'] = curve self.doneAction = doneAction class perc(EnvGen): value = "Env.perc" def __init__(self, atk=0.01, sus=None, amp=None, curve=0, doneAction=0): self.attr={} self.attr['attackTime'] = atk self.attr['releaseTime'] = instance("sus") if sus is None else sus self.attr['level'] = instance("amp") if amp is None else amp self.attr['curve'] = curve self.doneAction = doneAction class linen(perc): value = "Env.linen" class sine(EnvGen): value = "Env.sine" def __init__(self, dur=instance("sus"), amp=instance("amp"), doneAction=0): self.attr={} self.attr['dur'] = dur self.attr['level'] = amp self.doneAction = doneAction class ramp(EnvGen): def __init__(self, sus=None, amp=[1,1], curve="'step'", doneAction=0): self.attr={} self.attr['times'] = [instance("sus")] if sus is None else sus self.attr['levels'] = [instance("amp") * val for val in amp] self.attr['curve'] = curve self.doneAction = doneAction class reverse(EnvGen): def __init__(self, sus=None, amp=None, curve="'exp'", doneAction=0): self.attr={} self.attr['times'] = [instance("sus") if sus is None else sus, 0.001] self.attr['levels'] = [0.0001] + ([instance("amp")] if amp is None else amp) + [0] self.attr['curve'] = curve self.doneAction = doneAction amp = instance("amp") sus = instance("sus")././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/SCLang/SCLang.py0000644000175100001770000001274314611211152020541 0ustar00runnerdocker""" SCLang.py """ def format_args(args=[], kwargs={}, delim=': '): return ", ".join([str(a) for a in args] + ["%s%s%s" % (key, delim, value) for key, value in kwargs.items()]) class cls: def __init__(self, name, **kwargs): self.name = name self.ref = kwargs.get("ref", "") def __str__(self): return str(self.name) def __repr__(self): return str(self.name) def __call__(self, *args, **kwargs): return instance("{}({}{})".format(self.name, self.ref, format_args(args, kwargs))) def ar(self, *args, **kwargs): return instance("{}.ar({}{})".format(self.name, self.ref, format_args(args, kwargs))) def kr(self, *args, **kwargs): return instance("{}.kr({}{})".format(self.name, self.ref, format_args(args, kwargs))) def ir(self, *args, **kwargs): return instance("{}.ir({}{})".format(self.name, self.ref, format_args(args, kwargs))) class instance: defaults = {} shortarg = {} def __init__(self, string): self.value = str(string) def __repr__(self): return str(self.value) def __str__(self): return str(self.value) def __add__(self, other): return instance("(%s)" % (str(self) + " + " + str(other))) def __sub__(self, other): return instance("(%s)" % (str(self) + " - " + str(other))) def __mul__(self, other): return instance("(%s)" % (str(self) + " * " + str(other))) def __div__(self, other): return instance("(%s)" % (str(self) + " / " + str(other))) def __pow__(self, other): return instance("(%s)" % (str(self) + " ** " + str(other))) def __xor__(self, other): return instance("(%s)" % (str(self) + " ** " + str(other))) def __truediv__(self, other): return self.__div__(other) def __getitem__(self, other): return instance("(%s)" % (str(self) + "[" + str(other) + "]")) def __radd__(self, other): return instance("(%s)" % (str(other) + " + " + str(self))) def __rsub__(self, other): return instance("(%s)" % (str(other) + " - " + str(self))) def __rmul__(self, other): return instance("(%s)" % (str(other) + " * " + str(self))) def __rdiv__(self, other): return instance("(%s)" % (str(other) + " / " + str(self))) def __rpow__(self, other): return instance("(%s)" % (str(other) + " ** " + str(self))) def __rxor__(self, other): return instance("(%s)" % (str(other) + " ** " + str(self))) def __rtruediv__(self, other): return self.__rdiv__(other) def __mod__(self, other): return instance(str(self.value) % str(other)) if "%" in self.value else self def __coerce__(self, other): try: self = instance(str(self)) other = instance(str(other)) return (self, other) except: return def __getattr__(self, name, *args, **kwargs): return self.custom('.' + name, *args, **kwargs) def string(self): return str(self.value) + "{}" def custom(self, name): return self.__class__(self.string().format(name)) def __call__(self, *args, **kwargs): for arg in set(list(self.defaults.keys()) + list(self.shortarg.keys())): if arg in self.shortarg: if self.shortarg[arg] in kwargs: kwargs[arg] = kwargs.get( self.shortarg[arg], self.default[arg]) del kwargs[self.shortarg[arg]] continue if arg in self.defaults: kwargs[arg] = kwargs.get(arg, self.defaults[arg]) value = self.string().format("({})".format(format_args(args, kwargs))) return self.__class__(value) # UGens SinOsc = cls("SinOsc") SinOscFB = cls("SinOscFB") Saw = cls("Saw") LFSaw = cls("LFSaw") VarSaw = cls("VarSaw") LFTri = cls("LFTri") LFPar = cls("LFPar") PlayBuf = cls("PlayBuf") LFNoise0 = cls("LFNoise0") LFNoise1 = cls("LFNoise1") LFNoise2 = cls("LFNoise2") Gendy1 = cls("Gendy1") Gendy2 = cls("Gendy2") Gendy3 = cls("Gendy3") Gendy4 = cls("Gendy4") Gendy5 = cls("Gendy5") Formant = cls("Formant") Pulse = cls("Pulse") LFPulse = cls("LFPulse") PMOsc = cls("PMOsc") Crackle = cls("Crackle") LFCub = cls("LFCub") PinkNoise = cls("PinkNoise") Impulse = cls("Impulse") Blip = cls("Blip") Klank = cls("Klank", ref="`") Resonz = cls("Resonz") Squiz = cls("Squiz") # Other K2A = cls("K2A") Out = cls("Out") AudioIn = cls("AudioIn") Lag = cls("Lag") Vibrato = cls("Vibrato") Line = cls("Line") XLine = cls("XLine") FreeVerb = cls("FreeVerb") GVerb = cls("GVerb") Pan2 = cls("Pan2") LPF = cls("LPF") RLPF = cls("RLPF") BPF = cls("BPF") HPF = cls("HPF") RHPF = cls("RHPF") DelayC = cls("DelayC") DelayN = cls("DelayN") DelayL = cls("DelayL") CombN = cls("CombN") CombL = cls("CombL") CombC = cls("CombC") Crackle = cls("Crackle") Limiter = cls("Limiter") Ringz = cls("Ringz") Dust = cls("Dust") Formlet = cls("Formlet") ClipNoise = cls("ClipNoise") BufRateScale = cls("BufRateScale") BufSampleRate = cls("BufSampleRate") BufFrames = cls("BufFrames") BufChannels = cls("BufChannels") BufFrames = cls("BufFrames") BufDur = cls("BufDur") # sc3 Plugins BufGrain = cls("BufGrain") Decimator = cls("Decimator") SmoothDecimator = cls("SmoothDecimator") CrossoverDistortion = cls("CrossoverDistortion") Disintegrator = cls("Disintegrator") MdaPiano = cls("MdaPiano") # Array manipulation emulator functions def stutter(array, n): return [item for item in array for i in range(n)] def dup(x): return [x, x] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/SCLang/SynthDef.py0000644000175100001770000002457114611211152021160 0ustar00runnerdockerimport os from renardo_lib.SCLang.SCLang import instance, format_args from renardo_lib.SCLang import Env from renardo_lib.ServerManager import Server from renardo_lib.Settings import SYNTHDEF_DIR from renardo_lib.Code import WarningMsg # Container for SynthDefs class SynthDict(dict): module = None server = None def __init__(self, **kwargs): dict.__init__(self, kwargs) def __str__(self): return str(list(self.keys())) def __repr__(self): return str(list(self.keys())) def __call__(self, name): return self[name] def reload(self): for key, item in self.items(): item.load() return def set_server(self, serv): self.server = serv self.server.synthdefs = self return # Create container for SynthDefs SynthDefs = SynthDict() # SynthDef Base Class class SynthDefBaseClass(object): server = Server bus_name = 'bus' var = ['osc', 'env'] defaults = {} container = SynthDefs default_env = Env.perc() def __init__(self, name): # String name of SynthDef self.name = name # Flag when Synth added to server self.synth_added = False # Initial behaviour such as amplitude / frequency modulation self.base = ["sus = sus * blur;"] self.attr = [] # stores custom attributes # Name of the file to store the SynthDef self.filename = SYNTHDEF_DIR + "/{}.scd".format(self.name) # SynthDef default arguments self.osc = instance("osc") self.freq = instance("freq") self.fmod = instance("fmod") self.output = instance("output") self.sus = instance("sus") self.amp = instance("amp") self.pan = instance("pan") self.rate = instance("rate") self.blur = instance("blur") self.beat_dur = instance("beat_dur") # Envelope self.atk = instance("atk") self.decay = instance("decay") self.rel = instance("rel") self.defaults = { "amp" : 1, "sus" : 1, "pan" : 0, "freq" : 0, "vib" : 0, "fmod" : 0, "rate" : 0, "bus" : 0, "blur" : 1, "beat_dur" : 1, "atk" : 0.01, "decay" : 0.01, "rel" : 0.01, "peak" : 1, "level" : 0.8 } # The amp is multiplied by this before being sent to SC self.balance = 1 # Add to list self.container[self.name] = self self.add_base_class_behaviour() # Context Manager # --------------- def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.add() # String representation # --------------------- def __str__(self): Def = "SynthDef.new(\{},\n".format(self.name) Def += "{}|{}|\n".format("{", format_args(kwargs=self.defaults, delim='=')) Def += "{}\n".format(self.get_base_class_variables()) Def += "{}\n".format(self.get_base_class_behaviour()) Def += "{}".format(self.get_custom_behaviour()) Def += "osc = Mix(osc) * 0.5;\n" Def += "osc = Pan2.ar(osc, pan);\n" Def += "\tReplaceOut.ar(bus, osc)" Def += "}).add;\n" return Def def __repr__(self): return str(self.name) # Combining with other SynthDefs # ------------------------------ def __add__(self, other): if not isinstance(other, SynthDef): raise TypeError("Warning: '{}' is not a SynthDef".format(str(other))) new = copy(self) new.osc = self.osc + other.osc return new # Returning the SynthDefProxy # --------------------------- def __call__(self, degree=None, **kwargs): return SynthDefProxy(self.name, degree, kwargs) # Getter and setter # ----------------- def __getattribute__(self, key): if key.startswith("_"): return object.__getattribute__(self, key) defaults = object.__getattribute__(self, 'defaults') var = object.__getattribute__(self, 'var') synth_added = object.__getattribute__(self, 'synth_added') attr = list(defaults.keys()) + var if synth_added: return object.__getattribute__(self, key) elif key in attr: return instance(key) else: return object.__getattribute__(self, key) raise AttributeError("Attribute '{}' not found".format(key)) def __setattr__(self, key, value): try: if key in self.var + list(self.defaults.keys()): self.attr.append((key, value)) except: pass if key not in self.__dict__ or str(key) != str(value): self.__dict__[key] = value # Defining class behaviour # ------------------------ def add_base_class_behaviour(self): """ Defines the initial setup for every SynthDef """ return def get_base_class_behaviour(self): return "\n".join(self.base) def get_base_class_variables(self): return "var {};".format(", ".join(self.var)) def get_custom_behaviour(self): string = "" for arg, value in self.attr: arg, value = str(arg), str(value) if arg != value: string += (arg + '=' + value + ';\n') return string def get_custom_behaviour2(self): string = "" for arg in list(self.defaults.keys()) + self.var: if arg in self.__dict__: # Don't add redundant lines e.g. sus=sus; if str(arg) != str(self.__dict__[arg]): string += (str(arg) + '=' + str(self.__dict__[arg]) + ';\n') return string def adsr(self, **kwargs): """ Define the envelope """ self.defaults.update(**kwargs) self.env = Env.adsr() return # Adding the SynthDef to the Server # --------------------------------- def write(self): """ Writes the SynthDef to file """ # 1. See if the file exists if os.path.isfile(self.filename): with open(self.filename) as f: contents = f.read() else: contents = "" # 2. If it does, check contents this_string = self.__str__() if contents != this_string: try: with open(self.filename, 'w') as f: f.write(this_string) except IOError: # print("Warning: Unable to update '{}' SynthDef.".format(self.name)) pass # TODO - add python -m --verbose to print warnings? return def has_envelope(self): try: object.__getattribute__(self, 'env') return True except: return False def load(self): """ Load in server""" return SynthDef.server.loadSynthDef(self.filename) def add(self): """ This is required to add the SynthDef to the SuperCollider Server """ if self.has_envelope(): self.osc = self.osc * self.env try: self.synth_added = True # Load to server self.write() self.load() except Exception as e: WarningMsg("{}: SynthDef '{}' could not be added to the server:\n{}".format(e.__class__.__name__, self.name, e)) return None def rename(self, newname): new = copy(self) new.name = str(newname) return new @staticmethod def new_attr_instance(name): return instance(name) def play(self, freq, **kwargs): ''' Plays a single sound ''' message = ["freq", freq] for key, value in kwargs.items(): message += [key, value] self.server.sendNote(self.name, message) return def preprocess_osc(self, osc_message): osc_message['amp'] *= self.balance class SynthDef(SynthDefBaseClass): def __init__(self, *args, **kwargs): SynthDefBaseClass.__init__(self, *args, **kwargs) # add vib depth? def add_base_class_behaviour(self): """ Defines the initial setup for every SynthDef """ SynthDefBaseClass.add_base_class_behaviour(self) self.base.append("freq = In.kr(bus, 1);") self.base.append("freq = [freq, freq+fmod];") return class SampleSynthDef(SynthDefBaseClass): def __init__(self, *args, **kwargs): SynthDefBaseClass.__init__(self, *args, **kwargs) self.buf = self.new_attr_instance("buf") self.pos = self.new_attr_instance("pos") self.defaults['buf'] = 0 self.defaults['pos'] = 0 self.defaults['room'] = 0.1 self.defaults['rate'] = 1.0 self.base.append("rate = In.kr(bus, 1);") # SynthDef from sc file class FileSynthDef(SynthDefBaseClass): def write(self): pass def __str__(self): return open(self.filename, 'rb').read() ''' SynthDefProxy Class ------------------- ''' class SynthDefProxy: def __init__(self, name, degree, kwargs): self.name = name self.degree = degree self.mod = 0 self.kwargs = kwargs self.methods = [] self.vars = vars(self) def __str__(self): return "".format(self.name) def __add__(self, other): self.mod = other return self def __coerce__(self, other): return None def __getattr__(self, name): if name not in self.vars: def func(*args, **kwargs): self.methods.append((name, (args, kwargs))) return self return func else: return getattr(self, name) class CompiledSynthDef(SynthDefBaseClass): def __init__(self, name, filename): super(CompiledSynthDef, self).__init__(name) self.filename = filename def write(self): return def load(self): SynthDef.server.loadCompiled(self.filename) def __str__(self): return repr(self) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/SCLang/_SynthDefs.py0000644000175100001770000005172714611211152021505 0ustar00runnerdockerfrom renardo_lib.SCLang.SCLang import * from renardo_lib.SCLang.SynthDef import SynthDef, SampleSynthDef, FileSynthDef from renardo_lib.Settings import SC3_PLUGINS from renardo_lib.SCLang import Env # Sample Player with SampleSynthDef("play1") as play: play.osc = PlayBuf.ar(1, play.buf, BufRateScale.ir( play.buf) * play.rate, startPos=BufSampleRate.kr(play.buf) * play.pos) play.osc = play.osc * play.amp with SampleSynthDef("play2") as play: play.osc = PlayBuf.ar(2, play.buf, BufRateScale.ir( play.buf) * play.rate, startPos=BufSampleRate.kr(play.buf) * play.pos) play.osc = play.osc * play.amp # Synth Players with SynthDef("audioin") as audioin: audioin.defaults.update(channel=1) audioin.osc = AudioIn.ar(audioin.channel) audioin.env = Env.mask() # with SynthDef("sinepad") as sinepad: # sinepad.amp = sinepad.amp * 1.5 # sinepad.freq = sinepad.freq + [0,2] # sinepad.osc = SinOsc.ar(sinepad.freq, mul=sinepad.amp) # sinepad.osc = HPF.ar(sinepad.osc, 1000); # sinepad.env = Env.perc() # sinepad.env = Env.perc() with SynthDef("noise") as noise: noise.freq = noise.freq * 2 noise.osc = LFNoise0.ar(noise.freq, noise.amp) noise.env = Env.perc() with SynthDef("dab") as synth: a = HPF.ar(Saw.ar(synth.freq / 4, mul=synth.amp / 2), 2000) b = VarSaw.ar(synth.freq / 4, mul=synth.amp, width=Env.perc(synth.sus / 20, synth.sus / 4, 0.5, -5, doneAction=0)) synth.osc = a + b synth.env = Env.env(sus=[Env.sus * 0.25, Env.sus * 1], curve="'lin'") dab = synth del a del b with SynthDef("varsaw") as synth: synth.freq = synth.freq * [1, 1.005] synth.osc = VarSaw.ar(synth.freq, mul=synth.amp / 4, width=synth.rate) synth.env = Env.env() varsaw = synth with SynthDef("lazer") as synth: synth.freq = synth.freq * [1, 1.005] synth.amp = synth.amp * 0.1 synth.osc = VarSaw.ar(synth.freq, width=(synth.rate-1)/4) + LFSaw.ar(LFNoise0.ar( synth.rate * 20, add=synth.freq * Pulse.ar((synth.rate-2) + 0.1, add=1), mul=0.5)) synth.env = Env.perc(0.1) lazer = synth with SynthDef("growl") as growl: growl.sus = growl.sus * 1.5 growl.osc = SinOsc.ar(growl.freq + SinOsc.kr(0.5, add=1, mul=2), mul=growl.amp) * Saw.ar((growl.sus / 1.5) * 32) growl.env = Env.env() with SynthDef("dirt") as dirt: dirt.freq = dirt.freq / 4 dirt.amp = dirt.amp / 2 dirt.osc = LFSaw.ar(dirt.freq, mul=dirt.amp) + VarSaw.ar(dirt.freq + 1, width=0.85, mul=dirt.amp) + SinOscFB.ar(dirt.freq - 1, mul=dirt.amp/2) dirt.env = Env.perc() with SynthDef("crunch") as crunch: crunch.amp = crunch.amp * 0.5 crunch.osc = LFNoise0.ar(Crackle.kr( 1.95) * crunch.freq * 15, mul=crunch.amp) crunch.env = Env.perc(0.01, 0.1, crunch.amp / 4) with SynthDef("rave") as rave: rave.osc = Gendy1.ar(rave.rate-1, mul=rave.amp/2, minfreq=rave.freq, maxfreq=rave.freq*2) rave.env = Env.perc() with SynthDef("scatter") as scatter: scatter.osc = (Saw.ar(scatter.freq, mul=scatter.amp / 8) + VarSaw.ar( scatter.freq + [2, 1], mul=scatter.amp/8)) * LFNoise0.ar(scatter.rate) scatter.env = Env.linen(0.01, scatter.sus/2, scatter.sus/2) with SynthDef("charm") as charm: charm.freq = charm.freq + [0, 2] charm.freq = charm.freq * [1, 2] charm.osc = SinOsc.ar(charm.freq, mul=charm.amp / 4) + \ VarSaw.ar(charm.freq * 8, 10, mul=charm.amp/8) charm.osc = LPF.ar(charm.osc, SinOsc.ar( Line.ar(1, charm.rate*4, charm.sus/8), 0, charm.freq*2, charm.freq*2 + 10)) charm.env = Env.perc() with SynthDef("bell") as bell: bell.defaults.update(verb=0.5, room=0.5, rate=1) bell.amp = bell.amp * 4 bell.osc = Klank.ar([[0.501, 1, 0.7, 2.002, 3, 9.6, 2.49, 11, 2.571, 3.05, 6.242, 12.49, 13, 16, 24], [0.002, 0.1, 0.001, 0.008, 0.02, 0.004, 0.02, 0.04, 0.02, 0.005, 0.05, 0.05, 0.02, 0.03, 0.04], stutter([1.2, 0.9, 0.25, 0.14, 0.07], 3)], Impulse.ar(0.01), bell.freq, 0, 4 * bell.rate) * bell.amp with SynthDef("gong") as gong: gong.amp = gong.amp * 2.5 gong.freq = gong.freq * 2 gong.osc = Klank.ar([[0.501, 1, 0.8, 2.002, 3, 9.6, 2.49, 11, 2.571, 3.05, 6.242, 12.49, 13, 16, 24], [0.002, 0.02, 0.001, 0.008, 0.02, 0.004, 0.02, 0.04, 0.02, 0.005, 0.05, 0.05, 0.02, 0.03, 0.04], [1.2, 1.2, 1.2, 0.9, 0.9, 0.9, 0.25, 0.25, 0.25, 0.14, 0.14, 0.14, 0.07, 0.07, 0.07]], SinOscFB.ar(20, 0, 10), gong.freq, gong.freq * gong.rate, 4) * gong.amp gong.osc = HPF.ar(gong.osc, 440) with SynthDef("soprano") as soprano: soprano.sus = soprano.sus * 1.75 soprano.amp = soprano.amp / 2 soprano.freq = Vibrato.kr(soprano.freq, soprano.rate+4) soprano.osc = SinOsc.ar(soprano.freq * 3, mul=soprano.amp) + \ SinOscFB.ar(soprano.freq * 3, mul=soprano.amp / 2) soprano.env = Env.env() with SynthDef("dub") as dub: dub.freq = dub.freq / 4 dub.amp = dub.amp * 2 dub.osc = LFTri.ar(dub.freq, mul=dub.amp) + \ SinOscFB.ar(dub.freq, mul=dub.amp) dub.env = Env.sine(dur=dub.sus) with SynthDef("scratch") as scratch: scratch.defaults.update(depth=0.5, rate=0.04) scratch.amp = scratch.amp / 4 scratch.freq = scratch.freq * Crackle.ar(1.5) scratch.osc = SinOsc.ar(Vibrato.kr( scratch.freq, 2, 3, rateVariation=scratch.rate, depthVariation=scratch.depth), mul=scratch.amp) scratch.env = Env.env() with SynthDef("klank") as klank: klank.sus = klank.sus * 1.5 klank.osc = Klank.ar([[1, 2, 3, 4], [1, 1, 1, 1], [ 2, 2, 2, 2]], ClipNoise.ar(0.0005).dup, klank.freq) if SC3_PLUGINS: klank.osc = Decimator.ar(klank.osc, bits=klank.rate - 1) klank.env = Env.env(klank.sus*2) with SynthDef("feel") as feel: feel.sus = feel.sus * 1.5 feel.amp = feel.amp / 3 feel.freq = feel.freq * [1, 1.005] feel.osc = Klank.ar([[1, 2, 3, 3 + ((feel.rate-1)/10)], [1, 1, 1, 1], [2, 2, 2, 2]], Impulse.ar(0.0005) * Saw.ar(feel.freq, add=1), feel.freq) feel.env = Env.env(feel.sus*2) with SynthDef("glass") as glass: glass.sus = glass.sus * 1.5 glass.amp = glass.amp * 1.5 glass.freq = glass.freq * [1, (1 + (0.005 * glass.rate))] glass.osc = Klank.ar([[2, 4, 9, 16], [1, 1, 1, 1], [2, 2, 2, 2]], PinkNoise.ar( 0.0005).dup * SinOsc.ar(glass.freq / 4, add=1, mul=0.5), glass.freq) glass.env = Env.env(glass.sus*2) with SynthDef("soft") as soft: soft.freq = soft.freq/2 soft.amp = soft.amp / (200 * (1 + soft.rate)) soft.osc = Klank.ar([[7, 5, 3, 1], [8, 4, 2, 1], [2, 4, 8, 16]], LFNoise0.ar(soft.rate/soft.sus), soft.freq) soft.env = Env.env(soft.sus) with SynthDef("quin") as synth: synth.amp = synth.amp synth.freq = synth.freq * [1, 1.01] synth.osc = Klank.ar([[1, 2, 4, 2], [100, 50, 0, 10], [1, 5, 0, 1]], Impulse.ar( synth.freq).dup, synth.freq) / 5000 synth.osc = synth.osc * LFSaw.ar(synth.freq * (1 + synth.rate)) synth.env = Env.perc(atk=0.01, sus=synth.sus, curve=1) quin = synth with SynthDef("pluck") as pluck: freq = instance('freq') pluck.amp = pluck.amp + 0.00001 pluck.freq = pluck.freq + [0, LFNoise2.ar(50).range(-2, 2)] pluck.osc = SinOsc.ar(freq * 1.002, phase=VarSaw.ar(freq, width=Line.ar(1, 0.2, 2))) * \ 0.3 + SinOsc.ar(freq, phase=VarSaw.ar(freq, width=Line.ar(1, 0.2, 2))) * 0.3 pluck.osc = pluck.osc * \ XLine.kr(pluck.amp, pluck.amp/10000, pluck.sus * 4, doneAction=2) * 0.3 with SynthDef("spark") as synth: freq = instance('freq') synth.amp = synth.amp + 0.00001 synth.freq = synth.freq + [0, LFNoise2.ar(50).range(-2, 2)] synth.osc = LFSaw.ar(freq * 1.002, iphase=Saw.ar(0.1)) * \ 0.3 + LFSaw.ar(freq, iphase=Saw.ar(0.1)) * 0.3 synth.osc = (synth.osc * Line.ar(synth.amp, synth.amp/10000, synth.sus * 1.5) * 0.3) * Line.ar(0.01, 1, synth.sus * 0.033) spark = synth with SynthDef("blip") as synth: freq = instance('freq') synth.amp = synth.amp + 0.00001 synth.freq = freq + [0, LFNoise2.ar(50).range(-2, 2)] synth.freq = synth.freq * 2 synth.osc = (LFCub.ar(freq * 1.002, iphase=1.5) + LFTri.ar(freq, iphase=Line.ar(2, 0, 0, 2)) * 0.3) * Blip.ar(freq / 2, synth.rate) synth.osc = synth.osc * \ XLine.ar(synth.amp, synth.amp/10000, synth.sus * 2) * 0.3 blip = synth del freq with SynthDef("ripple") as ripple: ripple.amp = ripple.amp / 6 ripple.osc = Pulse.ar(ripple.freq/4, 0.2, 0.25) + \ Pulse.ar(ripple.freq+1, 0.5, 0.5) ripple.osc = ripple.osc * SinOsc.ar(ripple.rate/ripple.sus, 0, 0.5, 1) ripple.env = Env.env(sus=[0.55 * ripple.sus, 0.55*ripple.sus]) with SynthDef("creep") as creep: creep.amp = creep.amp / 4 creep.osc = PMOsc.ar(creep.freq, creep.freq * 2, 10) creep.env = Env.reverse() # No context manager SynthDef creation orient = SynthDef("orient") orient.defaults.update(room=10, verb=0.7) orient.osc = LFPulse.ar(orient.freq, 0.5, 0.25, 1/4) + \ LFPulse.ar(orient.freq, 1, 0.1, 1/4) orient.env = Env.perc() orient.add() zap = SynthDef("zap") zap.defaults.update(room=0, verb=0) zap.amp = zap.amp / 10 zap.osc = Saw.ar(zap.freq * [1, 1.01] + LFNoise2.ar(50).range(-2, 2)) + \ VarSaw.ar(zap.freq + LFNoise2.ar(50).range(-2, 2), 1) zap.env = Env.perc(atk=0.025, curve=-10) zap.add() marimba = SynthDef("marimba") marimba.osc = Klank.ar([[1/2, 1, 4, 9], [1/2, 1, 1, 1], [1, 1, 1, 1]], PinkNoise.ar([0.007, 0.007]), marimba.freq, [0, 2]) marimba.sus = 1 marimba.env = Env.perc(atk=0.001, curve=-6) marimba.add() fuzz = SynthDef("fuzz") fuzz.freq = fuzz.freq / 2 fuzz.amp = fuzz.amp / 6 fuzz.osc = LFSaw.ar(LFSaw.kr(fuzz.freq, 0, fuzz.freq, fuzz.freq * 2)) fuzz.env = Env.ramp(amp=[1, 1, 0.01], sus=[fuzz.sus * 0.8, 0.01]) fuzz.add() bug = SynthDef("bug") bug.defaults.update(rate=1) bug.amp = bug.amp / 5 bug.freq = bug.freq * [1, 1.0001] bug.osc = Pulse.ar( bug.freq, width=[0.09, 0.16, 0.25]) * SinOsc.ar(bug.rate * 4) bug.env = Env.perc(bug.sus * 1.5) bug.add() pulse = SynthDef("pulse") pulse.amp = pulse.amp / 8 pulse.osc = Pulse.ar(pulse.freq) pulse.osc = pulse.osc * pulse.amp pulse.env = Env.mask() pulse.add() saw = SynthDef("saw") saw.amp = saw.amp / 8 saw.osc = Saw.ar(saw.freq) saw.osc = saw.osc * saw.amp saw.env = Env.mask() saw.add() snick = SynthDef("snick") snick.osc = LFPar.ar(snick.freq, mul=1) * Blip.ar(((snick.rate+1) * 4)) snick.env = Env.perc() snick.add() twang = SynthDef("twang") twang.freq = twang.freq / 8 twang.freq = twang.freq + [0, 2] twang.osc = LPF.ar(Impulse.ar(twang.freq, 0.1), 4000) twang.osc = Env.perc() * CombL.ar(twang.osc, delaytime=twang.rate / (twang.freq * 8), maxdelaytime=0.25) twang.add() karp = SynthDef("karp") karp.amp = karp.amp * 0.75 karp.osc = LFNoise0.ar(400 + (400 * karp.rate), karp.amp) karp.osc = karp.osc * XLine.ar(1, 0.000001, karp.sus * 0.1) karp.freq = (265 / (karp.freq * 0.666)) * 0.005 karp.osc = CombL.ar(karp.osc, delaytime=karp.freq, maxdelaytime=2) karp.env = Env.ramp() karp.add() arpy = SynthDef("arpy") arpy.freq = arpy.freq / 2 arpy.amp = arpy.amp * 2 arpy.freq = arpy.freq + [0, 0.5] arpy.osc = LPF.ar(Impulse.ar(arpy.freq), 3000) arpy.env = Env.perc(sus=arpy.sus * 0.25) arpy.add() nylon = SynthDef("nylon") nylon.osc = LFPulse.ar(nylon.freq, 0.5, 0.33 * nylon.rate, 0.25) + LFPar.ar(nylon.freq + 0.5, 1, 0.1, 0.25) nylon.env = Env.perc(curve=-4, atk=0.000125, sus=Env.sus * 3) nylon.add() donk = SynthDef("donk") donk.freq = (donk.freq / 2) + [0, 2] donk.amp = donk.amp / 1.25 donk.osc = Ringz.ar(Impulse.ar(0, phase=donk.rate) / (donk.rate+1), donk.freq, donk.sus, donk.amp) donk.add() squish = SynthDef("squish") squish.freq = squish.freq / 4 squish.osc = Ringz.ar(Pulse.ar(4 * squish.rate), squish.freq, squish.sus, squish.amp) squish.osc = squish.osc * XLine.ar(1/2, 0.000001, squish.sus, doneAction=2) squish.osc = squish.osc.cos squish.amp = squish.amp * 4 squish.add() swell = SynthDef("swell") swell.defaults.update(rate=1) swell.amp = swell.amp / 4 swell.freq = swell.freq + [0, 1] swell.freq = swell.freq * [1, 0.5] swell.osc = VarSaw.ar(swell.freq, width=SinOsc.ar( swell.rate / (2 * swell.sus / 1.25), add=0.5, mul=[0.5, 0.5]), mul=[1, 0.5]) swell.env = Env.perc() swell.add() # Credit to Thor Magnusson for brass razz = SynthDef("razz") razz.defaults.update(rate=0.3) razz.freq = razz.freq + [0, 1] razz.rate = Lag.ar(K2A.ar(razz.freq), razz.rate) razz.osc = Saw.ar(razz.rate * [1, 1/2], [1, 1/3]) + \ Saw.ar(razz.rate+LFNoise2.ar(4).range(0.5, 2.5), 1) razz.osc = BPF.ar(razz.osc, razz.freq * 2.5, 0.3) razz.osc = RLPF.ar(razz.osc, 1300, 0.78) razz.env = Env.perc(atk=0.125) razz.add() sitar = SynthDef("sitar") sitar.amp = sitar.amp * 0.75 sitar.sus = sitar.sus * 4 sitar.osc = LFNoise0.ar([8400, 8500], sitar.amp) sitar.osc = sitar.osc * XLine.ar(1, 0.000001, sitar.sus * 0.1) sitar.freq = (265 / (sitar.freq * [0.666, 0.669])) * 0.005 sitar.osc = CombL.ar(sitar.osc, delaytime=sitar.freq, maxdelaytime=2) sitar.env = Env.ramp() sitar.add() with SynthDef("star") as synth: freq = instance('freq') synth.amp = (synth.amp * 2) + 0.00001 synth.freq = synth.freq / 2 synth.osc = LFSaw.ar(freq * 1.002, iphase=VarSaw.kr(freq, width=Line.kr(1, 0.2, synth.sus))) * 0.3 + LFSaw.ar( freq + LFNoise2.ar(50).range(-2, 2) + 2, iphase=VarSaw.kr(freq + 2, width=Line.kr(1, 0.2, synth.sus))) * 0.3 synth.osc = synth.osc * XLine.ar(synth.amp, synth.amp/10000, synth.sus * 3, doneAction=2) * Line.ar(0.01, 0.5, 0.07) star = synth with SynthDef("jbass") as jbass: jbass.freq = jbass.freq / 4 jbass.amp = jbass.amp * 0.8 jbass.osc = LFTri.ar(jbass.freq, mul=jbass.amp) jbass.adsr(atk=0.01, decay=0.01, rel=0.01) # Possible future syntax? # ----------------------- # @SynthDef # def jbass(amp = 0.8): # freq = freq / 4 # return if SC3_PLUGINS: piano = SynthDef("piano") piano.amp = piano.amp * 0.7 piano.osc = MdaPiano.ar( piano.freq[0], vel=40 + (piano.amp * 60), decay=piano.sus / 4) piano.env = Env.ramp() piano.add() # SynthDefs read from file bass = FileSynthDef('bass') bass.add() dirt = FileSynthDef('dirt') dirt.add() sawbass = FileSynthDef('sawbass') sawbass.add() prophet = FileSynthDef('prophet') prophet.add() pads = FileSynthDef('pads') pads.add() pasha = FileSynthDef('pasha') pasha.add() ambi = FileSynthDef("ambi") ambi.add() space = FileSynthDef("space") space.add() keys = FileSynthDef("keys") keys.add() bass = FileSynthDef("bass") bass.add() dbass = FileSynthDef("dbass") dbass.add() sinepad = FileSynthDef("sinepad") sinepad.add() video = FileSynthDef("video") video.add() viola = FileSynthDef("viola") viola.add() hydra = FileSynthDef("hydra") hydra.add() abass = FileSynthDef("abass") abass.add() acidbass = FileSynthDef("acidbass") acidbass.add() alva = FileSynthDef("alva") alva.add() angel = FileSynthDef("angel") angel.add() angst = FileSynthDef("angst") angst.add() bassguitar = FileSynthDef("bassguitar") bassguitar.add() bbass = FileSynthDef("bbass") bbass.add() bchaos = FileSynthDef("bchaos") bchaos.add() bellmod = FileSynthDef("bellmod") bellmod.add() benoit = FileSynthDef("benoit") benoit.add() birdy = FileSynthDef("birdy") birdy.add() blips = FileSynthDef("blips") blips.add() bnoise = FileSynthDef("bnoise") bnoise.add() borgan = FileSynthDef("borgan") borgan.add() bounce = FileSynthDef("bounce") bounce.add() bphase = FileSynthDef("bphase") bphase.add() brass = FileSynthDef("brass") brass.add() brown = FileSynthDef("brown") brown.add() chimebell = FileSynthDef("chimebell") chimebell.add() chipsy = FileSynthDef("chipsy") chipsy.add() click = FileSynthDef("click") click.add() clip = FileSynthDef("clip") clip.add() cluster = FileSynthDef("cluster") cluster.add() combs = FileSynthDef("combs") combs.add() cs80lead = FileSynthDef("cs80lead") cs80lead.add() dafbass = FileSynthDef("dafbass") dafbass.add() dblbass = FileSynthDef("dblbass") dblbass.add() donkysub = FileSynthDef("donkysub") donkysub.add() donorgan = FileSynthDef("donorgan") donorgan.add() dopple = FileSynthDef("dopple") dopple.add() drone = FileSynthDef("drone") drone.add() dustv = FileSynthDef("dustv") dustv.add() ebass = FileSynthDef("ebass") ebass.add() ecello = FileSynthDef("ecello") ecello.add() eeri = FileSynthDef("eeri") eeri.add() eoboe = FileSynthDef("eoboe") eoboe.add() epiano = FileSynthDef("epiano") epiano.add() faim = FileSynthDef("faim") faim.add() faim2 = FileSynthDef("faim2") faim2.add() fbass = FileSynthDef("fbass") fbass.add() filthysaw = FileSynthDef("filthysaw") filthysaw.add() flute = FileSynthDef("flute") flute.add() fm = FileSynthDef("fm") fm.add() fmbass = FileSynthDef("fmbass") fmbass.add() fmrhodes = FileSynthDef("fmrhodes") fmrhodes.add() garfield = FileSynthDef("garfield") garfield.add() # gaze = FileSynthDef("gaze") # gaze.add() glitchbass = FileSynthDef("glitchbass") glitchbass.add() glitcher = FileSynthDef("glitcher") glitcher.add() grat = FileSynthDef("grat") grat.add() gray = FileSynthDef("gray") gray.add() gsynth = FileSynthDef("gsynth") gsynth.add() harp = FileSynthDef("harp") harp.add() hnoise = FileSynthDef("hnoise") hnoise.add() hoover = FileSynthDef("hoover") hoover.add() kalimba = FileSynthDef("kalimba") kalimba.add() ladder = FileSynthDef("ladder") ladder.add() lapin = FileSynthDef("lapin") lapin.add() laserbeam = FileSynthDef("laserbeam") laserbeam.add() latoo = FileSynthDef("latoo") latoo.add() lazer = FileSynthDef("lazer") lazer.add() lfnoise = FileSynthDef("lfnoise") lfnoise.add() linesaw = FileSynthDef("linesaw") linesaw.add() longsaw = FileSynthDef("longsaw") longsaw.add() mhpad = FileSynthDef("mhpad") mhpad.add() mhping = FileSynthDef("mhping") mhping.add() moogbass = FileSynthDef("moogbass") moogbass.add() moogpluck = FileSynthDef("moogpluck") moogpluck.add() moogpluck2 = FileSynthDef("moogpluck2") moogpluck2.add() mpluck = FileSynthDef("mpluck") mpluck.add() noisynth = FileSynthDef("noisynth") noisynth.add() noquarter = FileSynthDef("noquarter") noquarter.add() organ = FileSynthDef("organ") organ.add() organ2 = FileSynthDef("organ2") organ2.add() pbass = FileSynthDef("pbass") pbass.add() phazer = FileSynthDef("phazer") phazer.add() pianovel = FileSynthDef("pianovel") pianovel.add() pink = FileSynthDef("pink") pink.add() pmcrotal = FileSynthDef("pmcrotal") pmcrotal.add() ppad = FileSynthDef("ppad") ppad.add() prayerbell = FileSynthDef("prayerbell") prayerbell.add() prof = FileSynthDef("prof") prof.add() radio = FileSynthDef("radio") radio.add() rhodes = FileSynthDef("rhodes") rhodes.add() rhpiano = FileSynthDef("rhpiano") rhpiano.add() risseto = FileSynthDef("risseto") risseto.add() rissetobell = FileSynthDef("rissetobell") rissetobell.add() rlead = FileSynthDef("rlead") rlead.add() rsaw = FileSynthDef("rsaw") rsaw.add() rsin = FileSynthDef("rsin") rsin.add() scatter = FileSynthDef("scatter") scatter.add() shore = FileSynthDef("shore") shore.add() sillyvoice = FileSynthDef("sillyvoice") sillyvoice.add() sine = FileSynthDef("sine") sine.add() siren = FileSynthDef("siren") siren.add() spacesaw = FileSynthDef("spacesaw") spacesaw.add() sos = FileSynthDef("sos") sos.add() sosbell = FileSynthDef("sosbell") sosbell.add() spick = FileSynthDef("spick") spick.add() sputter = FileSynthDef("sputter") sputter.add() square = FileSynthDef("square") square.add() ssaw = FileSynthDef("ssaw") ssaw.add() # stargazer = FileSynthDef("stargazer") # stargazer.add() steeldrum = FileSynthDef("steeldrum") steeldrum.add() strings = FileSynthDef("strings") strings.add() subbass = FileSynthDef("subbass") subbass.add() subbass2 = FileSynthDef("subbass2") subbass2.add() supersaw = FileSynthDef("supersaw") supersaw.add() tb303 = FileSynthDef("tb303") tb303.add() total = FileSynthDef("total") total.add() tremsynth = FileSynthDef("tremsynth") tremsynth.add() tribell = FileSynthDef("tribell") tribell.add() tritri = FileSynthDef("tritri") tritri.add() triwave = FileSynthDef("triwave") triwave.add() tubularbell = FileSynthDef("tubularbell") tubularbell.add() tworgan = FileSynthDef("tworgan") tworgan.add() tworgan2 = FileSynthDef("tworgan2") tworgan2.add() tworgan3 = FileSynthDef("tworgan3") tworgan3.add() tworgan4 = FileSynthDef("tworgan4") tworgan4.add() varicelle = FileSynthDef("varicelle") varicelle.add() vibass = FileSynthDef("vibass") vibass.add() vinsine = FileSynthDef("vinsine") vinsine.add() virus = FileSynthDef("virus") virus.add() waves = FileSynthDef("waves") waves.add() windmaker = FileSynthDef("windmaker") windmaker.add() wobble = FileSynthDef("wobble") wobble.add() wobblebass = FileSynthDef("wobblebass") wobblebass.add() wsaw = FileSynthDef("wsaw") wsaw.add() wsawbass = FileSynthDef("wsawbass") wsawbass.add() xylophone = FileSynthDef("xylophone") xylophone.add() # Get rid of the variable synth del synth ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/SCLang/__init__.py0000644000175100001770000000027414611211152021165 0ustar00runnerdockerfrom renardo_lib.SCLang.SCLang import * from renardo_lib.SCLang.SynthDef import SynthDefs, SynthDef, SynthDefProxy, SampleSynthDef, CompiledSynthDef # from renardo_lib.SCLang import Env ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Scale.py0000644000175100001770000003557014611211152017355 0ustar00runnerdockerfrom renardo_lib.Patterns import Pattern, PGroup, asStream from renardo_lib.TimeVar import TimeVar from random import choice from copy import copy import math def miditofreq(midinote): """ Converts a midi number to frequency """ return 440 * (2 ** ((midinote - 69.0)/12.0)) def _log2(num): return math.log(num) / math.log(2) def freqtomidi(freq): return 12 * _log2((freq / 440)) + 69 def midi(scale, octave, degree, root=0, stepsPerOctave=12): """ Calculates a midinote from a scale, octave, degree, and root """ # Make sure we force timevars into real values if isinstance(scale, ScalePattern) and isinstance(scale.data, TimeVar): scale = asStream(scale.data.now()) # Force float octave = float(octave) degree = float(degree) root = float(root) # Floor val lo = int(math.floor(degree)) hi = lo + 1 octave = octave + (lo // len(scale)) index = lo % len(scale) # Work out any microtones micro = (degree - lo) if micro > 0: ex_scale = list(scale) + [stepsPerOctave] diff = ex_scale[index + 1] - scale[index] micro = micro * diff midival = stepsPerOctave * octave # Root note of scale midival = midival + root # Adjust for key midival = midival + scale[index] # Add the note midival = midival + micro # And any microtonal return midival def get_freq_and_midi(degree, octave, root, scale): """ Returns the frequency and midinote """ # TODO -- make sure it's always a scale if hasattr(scale, "now"): scale = scale.now() if isinstance(scale, ScaleType): freq, midinote = scale.get_freq(degree, octave, root, get_midi=True) else: midinote = midi(scale, octave, degree, root) freq = miditofreq(midinote) return freq, midinote class ScaleType: pass class TuningType(list): def __init__(self, data): data = list(data) list.__init__(self, data[:-1]) self.steps = int(data[-1]) class Tuning: ET12 = TuningType([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) just = TuningType([0.0, 1.1173128526978, 2.0391000173077, 3.1564128700055, 3.8631371386483, 4.9804499913461, 5.9022371559561, 7.0195500086539, 8.1368628613517, 8.8435871299945, 10.175962878659, 10.882687147302, 12 ]) bohlen_pierce = TuningType([i*12/13*math.log(3, 2) for i in range(14)]) class ScalePattern(ScaleType, Pattern): name = None def __init__(self, semitones, name=None, tuning=Tuning.ET12): self.name = name self.semitones = semitones.data if isinstance(semitones, Pattern) else semitones if not isinstance(tuning, TuningType): self.tuning = TuningType(tuning) else: self.tuning = tuning self.data = self.semitones self.steps = self.tuning.steps if self.steps: self.pentatonic = PentatonicScalePattern(self) def __eq__(self, other): return self.name == other.name if isinstance(other, ScalePattern) else False def __ne__(self, other): return self.name != other.name if isinstance(other, ScalePattern) else True def semitones(self, pitches): """ Returns the semitone values for a series of pitches in this scale """ tones = [] for pitch in asStream(pitches): tones.append( self.note_to_semitone(pitch) ) return Pattern(tones) def get_tuned_note(self, degree): tuning_index = int(self[degree]) % len(self.tuning) # tuning_offset = 0 # if degree < 0: # tuning_offset = (((abs(degree) // len(self.tuning)) + 1) * self.steps) return self.tuning[tuning_index] def get_midi_note(self, degree, octave=5, root=0): """ Calculates a midinote from a scale, octave, degree, and root """ # Make sure we force timevars into real values if isinstance(self.data, TimeVar): scale = asStream(self.data.now()) # Force float octave = float(octave) degree = float(degree) root = float(root) # Floor val lo = int(math.floor(degree)) hi = lo + 1 octave = octave + (lo // len(self)) index = lo % len(self) pitch = self.get_tuned_note(index) # Work out any microtones micro = (degree - lo) if micro > 0: ex_scale = list(self) + [self.steps] diff = ex_scale[index + 1] - self[index] micro = micro * diff midival = self.steps * octave # Root note of scale midival = midival + root # Adjust for key midival = midival + pitch # Add the note midival = midival + micro # And any microtones return midival def get_freq(self, degree, octave=5, root=0, get_midi=False): """ Returns the frequency of a midinote calculated by self.get_midi_note. Returns a tuple containing the freqency and midinote if `get_midi` is set to `True`. """ midinote = self.get_midi_note(degree, octave, root) return (miditofreq(midinote), midinote) if get_midi else miditofreq(midinote) def note_to_semitone(self, pitch): """ Takes a pitch value and returns the semitone value e.g. midinote value not accounting for octaves """ if isinstance(pitch, PGroup): return pitch.__class__([self.note_to_semitone(p) for p in pitch]) else: i = pitch % len(self.data) n = (pitch // len(self.data)) * self.steps return asStream(self.data)[i] + n def getslice(self, start, stop, step=1): """ Called when using __getitem__ with slice notation. Numbers smaller than 0 and greater than the max value are adjusted. """ start = start if start is not None else 0 stop = stop if stop is not None else len(self) step = step if step is not None else 1 if stop < start: stop = (len(self.data) + stop) semitones = [] for i in range(start, stop, step): # Get the semitone tone = self[i] # Negative values if i < 0: sub = (((abs(i) // len(self)) + 1) * self.steps) tone -= sub # Values past the end elif i >= len(self): add = ((i // len(self)) * self.steps) tone += add semitones.append(tone) return ScalePattern(semitones) #def semitone_to_note(self, semitone): # """ Takes a semitone value (midinote) and returns the pitch in this scale """ # return semitone class PentatonicScalePattern(ScalePattern): def __init__(self, scale): self.update(scale) def update(self, scale): self.data = scale self.steps = scale.steps self.semitones = scale.semitones self.tuning = scale.tuning def __len__(self): return 5 @staticmethod def values(scale): shift = ((scale[2]-scale[0]) % 2) * 2 return sorted([scale[(i+shift)%len(scale)] for i in range(0,5*4,4)]) def __str__(self): return str(self.values(self.data)) def __repr__(self): return str(self) def __iter__(self): for note in self.values(self.data): yield note def __getitem__(self, key): return self.values(self.data)[int(key)] class FreqScalePattern(ScalePattern): def __init__(self): ScalePattern.__init__(self, [], name="freq") def get_midi_note(self, freq, *args, **kwargs): return freqtomidi(freq) def get_freq(self, freq, *args, **kwargs): return (freq, freqtomidi(freq)) if kwargs.get("get_midi", False) else freq def __repr__(self): return "[inf]" class _DefaultTuning(TuningType): """ Wrapper for Tuning.default """ def __init__(self, tuning): self.tuning = tuning def __len__(self): return len(self.tuning) class _DefaultScale(ScaleType): """ Wrapper for Scale.default """ def __init__(self, scale): self.scale = copy(scale) self.pentatonic = copy(self.scale.pentatonic) def __len__(self): return len(self.scale) def __repr__(self): return repr(self.scale) def __iter__(self): return self.scale.__iter__() def set(self, new, *args, **kwargs): """ Change the contents of the default scale """ if type(new) == str: self.scale = Scale.get_scale(new) if "tuning" in kwargs: self.scale.tuning = kwargs["tuning"] self.pentatonic.update(self.scale.pentatonic) elif isinstance(new, (list, Pattern, TimeVar)): self.scale = ScalePattern(new, *args, **kwargs) # Store if the user has used a name if self.scale.name is not None and self.scale.name not in Scale.names(): Scale[self.scale.name] = self.scale self.pentatonic.update(self.scale.pentatonic) else: print("Warning: {!r} is not a valid scale".format(new)) return self def __getattribute__(self, attr): if attr not in ("scale", "set", "pentatonic"): return self.scale.__getattribute__(attr) else: return object.__getattribute__(self, attr) # Python2 def __getattr__(self, attr): return self.__getattribute__(attr) # Custom made fibonacci tuing ##fib = [0,1] ##for n in range(2,11): ## fib.append(fib[n-1]+fib[n-2]) ## ##fibonacci = [] ##for n in range(3, len(fib)-1): ## fibonacci.append((n-3) * (fib[n] / float(fib[n-1]))) ## ##fibonacci = Scale("fibonacci", fibonacci) ## ##del n class __scale__: chromatic = ScalePattern([0,1,2,3,4,5,6,7,8,9,10,11], name="chromatic") major = ScalePattern([0,2,4,5,7,9,11], name="major") majorPentatonic = ScalePattern([0,2,4,7,9], name="majorPentatonic" ) minor = ScalePattern([0,2,3,5,7,8,10], name="minor") aeolian = ScalePattern([0,2,3,5,7,8,10], name="aeolian") minorPentatonic = ScalePattern([0,3,5,7,10], name="minorPentatonic") mixolydian = ScalePattern([0,2,4,5,7,9,10], name="mixolydian") melodicMinor = ScalePattern([0,2,3,5,7,9,11], name="melodicMinor") melodicMajor = ScalePattern([0,2,4,5,7,8,11], name="melodicMajor") harmonicMinor = ScalePattern([0,2,3,5,7,8,11], name="harmonicMinor") harmonicMajor = ScalePattern([0,2,4,5,7,8,11], name="harmonicMajor") # Goal: Do normal scales but adjust tuning justMajor = ScalePattern([0,2,4,5,7,9,11], name="justMajor", tuning=Tuning.just) justMinor = ScalePattern([0,2,3,5,7,8,10], name="justMinor", tuning=Tuning.just) dorian = ScalePattern([0,2,3,5,7,9,10], name="dorian") dorian2 = ScalePattern([0,1,3,5,6,8,9,11], name="dorian2") diminished = ScalePattern([0,1,3,4,6,7,9,10], name="diminished") egyptian = ScalePattern([0,2,5,7,10], name="egyptian") yu = ScalePattern([0,3,5,7,10], name="yu") zhi = ScalePattern([0,2,5,7,9], name="zhi") phrygian = ScalePattern([0,1,3,5,7,8,10], name="phrygian") prometheus = ScalePattern([0,2,4,6,11], name="prometheus") indian = ScalePattern([0,4,5,7,10], name="indian") locrian = ScalePattern([0,1,3,5,6,8,10], name="locrian") locrianMajor = ScalePattern([0,2,4,5,6,8,10], name="locrianMajor") lydian = ScalePattern([0,2,4,6,7,9,11], name="lydian") lydianMinor = ScalePattern([0,2,4,6,7,8,10], name="lydianMinor") custom = ScalePattern([0,2,3,5,6,9,10], name="custom") hungarianMinor = ScalePattern([ 0, 2, 3, 6, 7, 8, 11 ], name="hungarianMinor") romanianMinor = ScalePattern([ 0, 2, 3, 6, 7, 9, 10 ], name="romanianMinor") chinese = ScalePattern([ 0, 4, 6, 7, 11 ], name="chinese") wholeTone = ScalePattern([ 0, 2, 4, 6, 8, 10 ], name="wholeTone") # Half-Whole Diminished Scale - halfWhole halfWhole = ScalePattern([ 0, 1, 3, 4, 6, 7, 9, 10 ], name= "halfWhole") # Whole-Half Diminished Scale - wholeHalf wholeHalf = ScalePattern([ 0, 2, 3, 5, 6, 8, 9, 11 ], name= "wholeHalf") ### Bebop Scales ### bebopMaj = ScalePattern([ 0, 2, 4, 5, 7, 8, 9, 11 ], name="bebopMaj") bebopDorian = ScalePattern([ 0, 2, 3, 4, 5, 9, 10 ], name="bebopMin") # aka Bebop Minor bebopDom = ScalePattern([ 0, 2, 4, 5, 7, 9, 10, 11 ], name="bebopDom") # Bebop Dominant/Mixolydian bebopMelMin = ScalePattern([ 0, 2, 3, 5, 7, 8, 9, 11 ], name="bebopMelMin") # Bebop Melodic Minor blues = ScalePattern([ 0, 3, 5, 6, 7, 10 ], name="blues") ### Modes of the Melodic Minor Scale ### # First mode - Min/Maj chord minMaj = ScalePattern([ 0, 2, 3, 5, 7, 9, 11 ], name= "minMaj") # Second mode - (x)susb9 susb9 = ScalePattern([ 0, 1, 3, 5, 7, 9, 10 ], name= "susb9") # Third Mode - Lydian Augmented, (x)Maj7#5 lydianAug = ScalePattern([ 0, 2, 4, 6, 8, 9, 11 ], name= "lydianAug") # Fourth Mode - Lydian Dominant, (x)7#11 lydianDom = ScalePattern([ 0, 2, 4, 6, 7, 9, 10 ], name= "lydianDom") # Fifth Mode - seldom used, but it's IMinMaj/V melMin5th = ScalePattern([ 0, 2, 4, 5, 7, 8, 10 ], name= "melMin5th") # Sixth Mode - half-diminished (aka Locrian #2), (x)half-diminished halfDim = ScalePattern([ 0, 2, 3, 5, 6, 8, 10 ], name= "halfDim") # Seventh Mode - altered (diminished whole-tone), (x)7alt altered = ScalePattern([ 0, 1, 3, 4, 6, 8, 10 ], name= "altered") freq = FreqScalePattern() def __init__(self): self.default = _DefaultScale(self.major) def __setattr__(self, key, value): if key == "default" and key in vars(self): self.default.set(value) else: self.__dict__[key] = value return def __getitem__(self, key): return getattr(self, key) def get_scale(self, name): """ Returns a ScalePattern using a name """ return self.library()[name] def library(self): """ Returns a dictionary with scale names to scale instances """ lib = [] for items in (self.__class__.__dict__.items(), self.__dict__.items()): lib.extend([(key, value) for key, value in items if isinstance(value, ScalePattern)]) return dict(lib) def names(self): """ Returns a list of all the scale names """ return sorted(self.library().keys()) def scales(self): """ Returns a list of all the scales object """ return sorted(self.library().values(), key=lambda scale: scale.name) def choose(self): """ Scale.choose() -> Returns a random scale object """ return choice(self.scales()) Scale = __scale__() # class Chord: # def __init__(self): # self.scale = Scale.default # self.root = Root.default ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/ServerManager/0000755000175100001770000000000014611211157020510 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/ServerManager/__init__.py0000644000175100001770000007624514611211152022632 0ustar00runnerdocker""" Handles OSC messages being sent to SuperCollider. """ import sys if sys.version_info[0] > 2: import queue else: import Queue as queue import json import os.path import subprocess from time import sleep from collections import namedtuple from threading import Thread from renardo_lib.Code import WarningMsg from renardo_lib.Settings import ( OSC_MIDI_ADDRESS, GET_SC_INFO, FOXDOT_INFO_FILE, FOXDOT_RECORD_FILE, RECORDING_DIR, SamplePlayer, LoopPlayer, get_timestamp, SCLANG_EXEC, FOXDOT_STARTUP_FILE, FOXDOT_OSC_FUNC, USER_CWD, FOXDOT_BUFFERS_FILE, GET_SYNTHDEF_FILES, GET_FX_FILES ) from renardo_lib.OSC3 import * # Keep in sync with Info.scd ServerInfo = namedtuple( 'ServerInfo', ('sample_rate', 'actual_sample_rate', 'num_synths', 'num_groups', 'num_audio_bus_channels', 'num_control_bus_channels', 'num_input_bus_channels', 'num_output_bus_channels', 'num_buffers', 'max_nodes', 'max_synth_defs')) class OSCClientWrapper(OSCClient): error_printed = False def send(*args, **kwargs): """ Sends the message given but prints errors instead of raising them """ try: OSCClient.send(*args, **kwargs) except OSCClientError as e: if not OSCClientWrapper.error_printed: print( "Error sending message to SuperCollider server instance: make sure FoxDot quark is running and try again.") OSCClientWrapper.error_printed = True class OSCConnect(OSCClientWrapper): """ An OSCClientWrapper that connects on initialisation """ def __init__(self, address): OSCClientWrapper.__init__(self) self.connect(address) class RequestTimeout(Exception): """ Raised if expecting a response from the server but received none """ class BidirectionalOSCServer(OSCServer): """ This is a combination client/server The UDP server is necessary for receiving responses from the SCLang server when we query it with requests. Note that this is not thread-safe, as the receive() method can discard messages """ def __init__(self, server_address=('localhost', 0), client=None, return_port=0): OSCServer.__init__(self, server_address, client, return_port) self._server_thread = None self.addDefaultHandlers() self.addMsgHandler('default', self._handle_message) self._response_queue = queue.Queue() self._printed_error = False def connect(self, addr): """ Connect to an address and start the server thread """ self.client.connect(addr) self.start() def start(self): """ Start the server thread. """ if self._server_thread is not None: return self._server_thread = threading.Thread(target=self.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() def stop(self): """ Stop the server thread and close the socket. """ if self._server_thread is None: return self.running = False self._server_thread.join() self.server_close() def _handle_message(self, addr, tags, data, client_address): self._response_queue.put((addr, data)) def send(self, *args, **kwargs): try: self.client.send(*args, **kwargs) except OSCClientError as e: if not self._printed_error: print("Error: No connection made to SuperCollider server instance.") self._printed_error = True def receive(self, pattern, timeout=2): """ Retrieve the first message matching the pattern All messages received that do not match will be discarded """ expr = getRegEx(pattern) now = start = time.time() while now - start < timeout: try: addr, data = self._response_queue.get(True, start + timeout - now) except queue.Empty: raise RequestTimeout() if type(addr) is bytes: addr = addr.decode() match = expr.match(addr) if match and (match.end() == len(addr)): return data now = time.time() # Create an abstract base class that could be sub-classed for users who want to send their OSC messages elsewhere class ServerManager(object): def __init__(self, addr, port, osc_address="/s_new"): self.addr = addr self.port = port self.client = OSCClientWrapper() self.client.connect((self.addr, self.port)) self.osc_address = osc_address self.node = 1000 self.num_input_busses = 2 self.num_output_busses = 2 self.bus = self.num_input_busses + self.num_output_busses self.max_busses = 100 self.max_buffers = 1024 @staticmethod def create_osc_msg(dictionary): """ Converts a Python dictionary into an OSC style list """ msg = [] for key, value in dictionary.items(): msg += [key, value] return msg def sendOSC(self, osc_message): self.client.send(osc_message) return def get_bundle(self, *args, **kwargs): bundle = OSCBundle(time=kwargs.get("timestamp", 0)) message = OSCMessage(self.osc_address) for item in args: if type(item) == dict: message.append(self.create_osc_msg(item)) else: message.append(item) bundle.append(message) return bundle def loadSynthDef(self, *args, **kwargs): return def setFx(self, *args, **kwargs): return class SCLangServerManager(ServerManager): fxlist = None synthdefs = None def __init__(self, addr, osc_port, sclang_port): self.addr = addr self.port = osc_port self.SCLang_port = sclang_port self.midi_nudge = 0 self.booted = False self.wait_time = 5 self.count = 0 # Assign a valid OSC Client self.forward = None self.node = 1000 self.num_input_busses = 2 self.num_output_busses = 2 self.bus = self.num_input_busses + self.num_output_busses self.max_busses = 100 self.max_buffers = 1024 self.fx_setup_done = False self.fx_names = {} self.reset() def reset(self): # General SuperCollider OSC connection self.client = OSCClientWrapper() self.client.connect((self.addr, self.port)) # OSC Connection for custom OSCFunc in SuperCollider if GET_SC_INFO: self.sclang = BidirectionalOSCServer() self.sclang.connect((self.addr, self.SCLang_port)) self.loadSynthDef(FOXDOT_INFO_FILE) try: info = self.getInfo() except RequestTimeout: # It's not terrible if we couldn't fetch the info, but we should log it. WarningMsg("Could not fetch info from SCLang server. Using defaults...") else: self.max_buffers = info.num_buffers self.num_input_busses = info.num_input_bus_channels self.num_output_busses = info.num_output_bus_channels self.max_busses = info.num_audio_bus_channels self.bus = self.num_input_busses + self.num_output_busses else: self.sclang = OSCClientWrapper() self.sclang.connect((self.addr, self.SCLang_port)) # Clear SuperCollider nodes if any left over from other session etc self.freeAllNodes() # Load recorder OSCFunc self.loadRecorder() # move to the quark? # Toggle debug in SuperCollider self.dumpOSC(0) def __str__(self): return "FoxDot ServerManager Instance -> {}:{}".format(self.addr, self.port) def __repr__(self): return str(self) def nextnodeID(self): """ Gets the next node ID to use in SuperCollider """ self.node += 1 return self.node def query(self): """ Prints debug status to SuperCollider console """ self.client.send(OSCMessage("/status")) return def nextbusID(self): """ Gets the next SuperCollider bus to use """ self.bus += 2 # Make sure we still have 2 audio channels available if self.bus + 1 >= self.max_busses: self.bus = self.num_input_busses + self.num_output_busses return self.bus def sendOSC(self, osc_message): """ Sends an OSC message to the server. Checks for midi messages """ if osc_message.address == OSC_MIDI_ADDRESS: self.sclang.send(osc_message) else: self.client.send(osc_message) # If we are sending other messages as well if self.forward is not None: self.forward.send(osc_message) return def freeAllNodes(self): """ Triggers a free all message to kill all active nodes (sounds) in SuperCollider """ msg = OSCMessage("/g_freeAll") msg.append([1]) self.client.send(msg) return def setFx(self, fx_list): self.fxlist = fx_list self.fx_names = {name: fx.synthdef for name, fx in fx_list.items()} return def set_midi_nudge(self, value): self.midi_nudge = value return def get_midi_message(self, synthdef, packet, timestamp): """ Prepares an OSC message to trigger midi sent from SuperCollider """ bundle = OSCBundle(time=timestamp) bundle.setAddress(OSC_MIDI_ADDRESS) # these need to be variable names at least msg = OSCMessage(OSC_MIDI_ADDRESS) note = packet.get("midinote", 60) vel = min(127, (packet.get("amp", 1) * 128) - 1) sus = packet.get("sus", 0.5) channel = packet.get("channel", 0) nudge = self.midi_nudge msg.append([synthdef, note, vel, sus, channel, nudge]) bundle.append(msg) return bundle def get_init_node(self, node, bus, group_id, synthdef, packet): msg = OSCMessage("/s_new") # Make sure messages release themselves after 8 * the duration at max (temp) max_sus = float(packet["sus"] * 8) # might be able to get rid of this key = "rate" if synthdef.name in (SamplePlayer, LoopPlayer) else "freq" if key in packet: value = ["rate", packet[key]] else: value = [] osc_packet = ["startSound", node, 0, group_id, 'bus', bus, "sus", max_sus] + value msg.append(osc_packet) return msg, node def get_control_effect_nodes(self, node, bus, group_id, packet): pkg = [] # Go through effects and put together with child attributes for fx in self.fxlist.order[0]: if fx in packet and packet[fx] != 0: # this_effect = effects[fx] # old pre-prepared # prepare each effect here this_effect = self.prepare_effect(fx, packet) # Get next node ID node, last_node = self.nextnodeID(), node msg = OSCMessage("/s_new") osc_packet = [self.fx_names[fx], node, 1, group_id, 'bus', bus] + this_effect msg.append(osc_packet) pkg.append(msg) return pkg, node def get_synth_node(self, node, bus, group_id, synthdef, packet): msg = OSCMessage("/s_new") new_message = {} for key in packet: if key not in ("env", "degree"): # skip some attr try: new_message[key] = float(packet[key]) # is this not already the case? except (TypeError, ValueError) as e: WarningMsg("Could not convert '{}' argument '{}' to float. Set to 0".format(key, packet[key])) new_message[key] = 0.0 # Get next node ID node, last_node = self.nextnodeID(), node osc_packet = [synthdef.name, node, 1, group_id, synthdef.bus_name, bus] \ + self.create_osc_msg(new_message) msg.append(osc_packet) return msg, node def get_pre_env_effect_nodes(self, node, bus, group_id, packet): pkg = [] for fx in self.fxlist.order[1]: if fx in packet and packet[fx] != 0: this_effect = self.prepare_effect(fx, packet) # Get next node ID node, last_node = self.nextnodeID(), node msg = OSCMessage("/s_new") osc_packet = [self.fx_names[fx], node, 1, group_id, 'bus', bus] + this_effect msg.append(osc_packet) pkg.append(msg) return pkg, node def get_synth_envelope(self, node, bus, group_id, synthdef, packet): env_packet = {"sus": packet["sus"], "amp": packet["amp"]} for key in ("atk", "decay", "rel", "legato", "curve", "gain"): # Try and get from the player value = packet.get(key, None) # If it is absent or set to None, get default from Synth if value is None: value = synthdef.get_default_env(key) # Store env_packet[key] = value env = synthdef.get_default_env("env") if packet.get("env", None) is None else packet.get("env", None) try: dest = env.get_env_name() except AttributeError as e: # Set the curve value env_packet["curve"] = env dest = "BasicEnvelope" node, last_node = self.nextnodeID(), node msg = OSCMessage("/s_new") osc_packet = [dest, node, 1, group_id, 'bus', bus] + self.create_osc_msg(env_packet) msg.append(osc_packet) return msg, node def get_post_env_effect_nodes(self, node, bus, group_id, packet): pkg = [] for fx in self.fxlist.order[2]: if fx in packet and packet[fx] != 0: this_effect = self.prepare_effect(fx, packet) # Get next node ID node, last_node = self.nextnodeID(), node msg = OSCMessage("/s_new") osc_packet = [self.fx_names[fx], node, 1, group_id, 'bus', bus] + this_effect msg.append(osc_packet) pkg.append(msg) return pkg, node def prepare_effect(self, name, packet): """ Finds the child attributes in packet and returns an OSC style list """ data = [] effect = self.fxlist[name] for key in effect.args: data.append(key) data.append(float(packet.get(key, effect.defaults[key]))) return data def get_exit_node(self, node, bus, group_id, packet): msg = OSCMessage("/s_new") node, last_node = self.nextnodeID(), node osc_packet = ['makeSound', node, 1, group_id, 'bus', bus, 'sus', float(packet["sus"])] msg.append(osc_packet) return msg, node def get_bundle(self, synthdef, packet, timestamp=0): """ Returns the OSC Bundle for a notew based on a Player's SynthDef, and event and effects dictionaries """ # Create a specific message for midi if synthdef == "MidiOut": # this should be in a dict of synthdef to functions maybe? we need a "nudge to sync" return self.get_midi_message(synthdef, packet, timestamp) # Create a bundle bundle = OSCBundle(time=timestamp) # Get the actual synthdef object synthdef = self.synthdefs[synthdef] # Create a group for the note group_id = self.nextnodeID() msg = OSCMessage("/g_new") msg.append([group_id, 1, 1]) bundle.append(msg) # Get the bus and SynthDef nodes this_bus = self.nextbusID() this_node = self.nextnodeID() # synthdef.preprocess_osc(packet) # so far, just "balance" to multiply amp by 1 # First node of the group (control rate) msg, this_node = self.get_init_node(this_node, this_bus, group_id, synthdef, packet) # Add effects to control rate e.g. vibrato bundle.append(msg) pkg, this_node = self.get_control_effect_nodes(this_node, this_bus, group_id, packet) for msg in pkg: bundle.append(msg) # trigger synth msg, this_node = self.get_synth_node(this_node, this_bus, group_id, synthdef, packet) bundle.append(msg) # ORDER 1 pkg, this_node = self.get_pre_env_effect_nodes(this_node, this_bus, group_id, packet) for msg in pkg: bundle.append(msg) # ENVELOPE # msg, this_node = self.get_synth_envelope(this_node, this_bus, group_id, synthdef, packet) # bundle.append( msg ) # ORDER 2 (AUDIO EFFECTS) pkg, this_node = self.get_post_env_effect_nodes(this_node, this_bus, group_id, packet) for msg in pkg: bundle.append(msg) # OUT msg, _ = self.get_exit_node(this_node, this_bus, group_id, packet) bundle.append(msg) return bundle def send(self, address, message): """ Sends message (a list) to SuperCollider """ msg = OSCMessage(address) msg.append(message) self.client.send(msg) # If we are sending other messages as well if self.forward is not None: self.forward.send(message) return def free_node(self, node): """ Sends a message to SuperCollider to stop a specific node """ message = OSCMessage("/n_free") message.append(node) self.client.send(message) return def bufferRead(self, path, bufnum): """ Sends a message to SuperCollider to read an audio file into a buffer """ message = OSCMessage("/b_allocRead") message.append([bufnum, path]) self.client.send(message) return def bufferFree(self, bufnum): """ Sends a message to SuperCollider to free a buffer """ message = OSCMessage("/b_free") message.append([bufnum]) self.client.send(message) def sendMidi(self, msg, cmd=OSC_MIDI_ADDRESS): """ Sends a message to the FoxDot class in SuperCollider to forward a MIDI message """ msg.setAddress(cmd) self.sclang.send(msg) return def loadSynthDef(self, fn, cmd='/foxdot'): """ Sends a message to the FoxDot class in SuperCollider to load a SynthDef from file """ msg = OSCMessage() msg.setAddress(cmd) msg.append(fn) self.sclang.send(msg) return def loadRecorder(self): """ Loads an OSCFunc that starts/stops recording to a set path """ self.loadSynthDef(FOXDOT_RECORD_FILE) self._is_recording = False return def record(self, fn=None): """ Starts recording audio from SuperCollider """ if self._is_recording is False: if fn is None: fn = "{}.aiff".format(get_timestamp()) path = os.path.join(RECORDING_DIR, fn) msg = OSCMessage('/foxdot-record') msg.append([1, path]) self.sclang.send(msg) self._is_recording = True return def stopRecording(self): """ Stops recording audio from SuperCollider """ if self._is_recording is True: msg = OSCMessage('/foxdot-record') msg.append([0, ""]) # flag to stop recording self.sclang.send(msg) self._is_recording = False return def loadCompiled(self, fn): """ Sends a message to SuperCollider to load a compiled SynthDef file """ msg = OSCMessage() msg.setAddress('/d_load') msg.append(fn) self.client.send(msg) def dumpOSC(self, value=1): """ Debug - Dumps OSC messages SCLang side """ msg = OSCMessage("/dumpOSC") msg.append(value) self.client.send(msg) return def dumpTree(self, group_id=0, flag=0): """ Server will print the node tree """ msg = OSCMessage("/g_dumpTree") msg.append([group_id, flag]) self.client.send(msg) def getInfo(self): """ Fetch info about the SCLang server """ msg = OSCMessage() msg.setAddress('/foxdot/info') self.sclang.send(msg) info = ServerInfo(*self.sclang.receive('/foxdot/info')) return info def start(self): """ Boots SuperCollider using `subprocess`""" if not self.booted: os.chdir(SC_DIRECTORY) print("Booting SuperCollider Server...") self.daemon = subprocess.Popen([SCLANG_EXEC, '-D', FOXDOT_STARTUP_FILE]) os.chdir(USER_CWD) self.booted = True else: print("Warning: SuperCollider already running") return def makeStartupFile(self): ''' Boot SuperCollider and connect over OSC ''' # 1. Compile startup file with open(FOXDOT_STARTUP_FILE, 'w') as startup: startup.write('''Routine.run { s.options.blockSize = 128; s.options.memSize = 131072; s.bootSync();\n''') files = [FOXDOT_OSC_FUNC, FOXDOT_BUFFERS_FILE] files = files + GET_SYNTHDEF_FILES() + GET_FX_FILES() for fn in files: f = open(fn) startup.write(f.read()) startup.write("\n\n") startup.write("};") return def quit(self): if self.booted: self.client.send(OSCMessage("/quit")) sleep(1) self.daemon.terminate() if self._is_recording: self.stopRecording() return def add_forward(self, addr, port): self.forward = OSCClientWrapper() self.forward.connect((addr, port)) try: import socketserver except ImportError: import SocketServer as socketserver class Message: """ Wrapper for JSON messages sent to the server """ def __init__(self, data): self.data = data def __str__(self): """ Prepares the json message to be sent with first 4 digits denoting the length of the message """ packet = str(json.dumps(self.data, separators=(',', ':'))) length = "{:04d}".format(len(packet)) return length + packet def __len__(self): return len(str(self)) def asString(self): return str(self) def read_from_socket(sock): """ Reads data from the socket """ # Get number single int that tells us how many digits to read try: bits = int(sock.recv(4).decode()) except: return None if bits > 0: # Read the remaining data (JSON) data = sock.recv(bits).decode() # Convert back to Python data structure return json.loads(data) def send_to_socket(sock, data): """ Converts Python data structure to JSON message and sends to a connected socket """ msg = Message(data) # Get length and store as string msg_len, msg_str = len(msg), str(msg).encode() # Continually send until we know all of the data has been sent sent = 0 while sent < msg_len: bits = sock.send(msg_str[sent:]) sent += bits return class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): """ Base class """ pass class TempoServer(ThreadedServer): """ Used in TempoClock.py to connect to instances of FoxDot over a network. Sends bpm changes over the network. On initial request this sends the start_time value of the clock """ def __init__(self, clock, port=57999): # tempo clock RequestHandler.metro = self.metro = clock RequestHandler.master = self # Address information self.hostname = str(socket.gethostname()) # Listen on any IP self.ip_addr = "0.0.0.0" self.port = int(port) # Public ip for server is the first IPv4 address we find, else just show the hostname self.ip_pub = self.hostname try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) self.ip_pub = s.getsockname()[0] s.close() except OSError: pass # Instantiate server process self.peers = [] ThreadedServer.__init__(self, (self.ip_addr, self.port), RequestHandler) self.server_thread = Thread(target=self.serve_forever) self.server_thread.daemon = False self.running = False def __str__(self): return "{} on port {}\n".format(self.ip_pub, self.port) def start(self): """ Starts listening on the socket """ self.running = True self.server_thread.start() return def update_tempo(self, source, bpm, bpm_start_beat, bpm_start_time): """ Sends information to all connected peers about changing tempo """ for peer in self.peers: if peer is not source: peer.update_tempo(bpm, bpm_start_beat, bpm_start_time) # Update the master clock tempo if receiving from another peer if source is not None: self.metro.update_tempo_from_connection(bpm, bpm_start_beat, bpm_start_time) return def kill(self): """ Properly terminates the server instance """ self.running = False self.server_thread.join(0) self.shutdown() self.server_close() return class RequestHandler(socketserver.BaseRequestHandler): """ Created whenever a new connection to the server is made: self.request = socket self.server = Server instance self.client_address = (address, port) """ master = None def handle(self): """ Overload """ print("New connection from {}".format(self.client_address)) # First we get latency data = read_from_socket(self.request) # Should be "init" message assert "init" in data send_to_socket(self.request, {"clock_time": time.time()}) # maybe time at a beat? self.master.peers.append(self) while True: data = read_from_socket(self.request) # If a client disconnects, remove and print message if data is None: return self.disconnect() else: # Get the requested data and send to client if "request" in data: send_to_socket(self.request, self.metro.get_sync_info()) # Tell server to update tempo and update clients elif "new_bpm" in data: self.master.update_tempo(self, **data["new_bpm"]) elif "latency": send_to_socket(self.request, ["latency"]) return def disconnect(self): """ Prints a message to the master clock and removes a reference to this client """ print("Client disconnected from {}".format(self.client_address)) self.master.peers.remove(self) return 0 def update_tempo(self, bpm, bpm_start_beat, bpm_start_time): data = { "new_bpm": { "bpm": bpm, "bpm_start_time": bpm_start_time, "bpm_start_beat": bpm_start_beat } } send_to_socket(self.request, data) return class TempoClient: def __init__(self, clock): self.metro = clock self.sync_keys = ("bpm_start_beat", "bpm_start_time", "bpm") self.server_hostname = None self.server_port = None self.server_address = None self.socket = None def connect(self, hostname, port=57890): """ Connects to the server instance """ # Get details of remote self.server_hostname = hostname self.server_port = int(port) self.server_address = (self.server_hostname, self.server_port) # Connect to remote try: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect(self.server_address) except Exception as e: raise (e) raise (ConnectionError("Could not connect to host '{}'".format(self.server_hostname))) # connect to the server and listen for new updates for the tempo-clock self.listening = True self.daemon = Thread(target=self.listen) self.daemon.start() # Send init message self.start_time = None self.stop_time = None self.latency = None self.recording_latency = False send_to_socket(self.socket, ["init"]) self.start_timing() return self def start_timing(self): """ Starts an internal timer for calculating latency """ self.start_time = time.time() def stop_timing(self): """ Stops the internal timer and calculates latency """ self.stop_time = time.time() self.calculate_latency(self.start_time, self.stop_time) def calculate_latency(self, start, end): """ Returns (and stores) the latency using the start and end time to send a message to the master server""" self.latency = (end - start) * 0.5 return self.latency def record_latency(self): self.start_timing() self.recording_latency = True self.send(["latency"]) return def send(self, data): """ Sends data to server """ return send_to_socket(self.socket, data) def listen(self): """ Listens out for data coming from the server and passes it on to the handler. """ # First message is machine clock time time_data = read_from_socket(self.socket) self.stop_timing() # self.metro.calculate_nudge(time_data["clock_time"], self.stop_time, self.latency) self.metro.calculate_nudge(time_data["clock_time"], self.start_time, self.latency) # Enter loop while self.listening: data = read_from_socket(self.socket) # Might be recording latency if self.recording_latency: self.stop_timing() self.recording_latency = False if data is None: break if "sync" in data: for key in self.sync_keys: if key in data["sync"]: object.__setattr__(self.metro, key, data["sync"][key]) self.metro.update_tempo_from_connection(**data["sync"]) self.metro.flag_wait_for_sync(False) elif "new_bpm" in data: self.metro.update_tempo_from_connection(**data["new_bpm"]) return def update_tempo(self, bpm, bpm_start_beat, bpm_start_time): """ Sends data to other connected FoxDot instances to update their tempo """ data = { "new_bpm": { "bpm": bpm, "bpm_start_time": bpm_start_time, "bpm_start_beat": bpm_start_beat } } return self.send(data) def kill(self): """ Properly terminates the connection to the server """ self.listening = False self.socket.close() return if __name__ != "__main__": from renardo_lib.Settings import ADDRESS, PORT, PORT2, FORWARD_PORT, FORWARD_ADDRESS # DefaultServer = SCLangServerManager(ADDRESS, PORT, PORT2) Server = SCLangServerManager(ADDRESS, PORT, PORT2) if FORWARD_PORT and FORWARD_ADDRESS: Server.add_forward(FORWARD_ADDRESS, FORWARD_PORT) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5755405 renardo_lib-0.9.12/renardo_lib/Settings/0000755000175100001770000000000014611211157017547 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Settings/__init__.py0000644000175100001770000001344014611211152021655 0ustar00runnerdockerimport os import sys # Anything that needs to be updated from importlib import reload from renardo_gatherer import get_samples_dir_path # Check for OS -> mac, linux, win SYSTEM = 0 WINDOWS = 0 LINUX = 1 MAC_OS = 2 if sys.platform.startswith('darwin'): SYSTEM = MAC_OS # Attempted fix for some Mac OS users try: import matplotlib matplotlib.use('TkAgg') except ImportError: pass elif sys.platform.startswith('win'): SYSTEM = WINDOWS elif sys.platform.startswith('linux'): SYSTEM = LINUX # Directory informations USER_CWD = os.path.realpath(".") FOXDOT_ROOT = os.path.realpath(__file__ + "/../../") FOXDOT_ICON = os.path.realpath(FOXDOT_ROOT + "/Workspace/img/icon.ico") FOXDOT_ICON_GIF = os.path.realpath(FOXDOT_ROOT + "/Workspace/img/icon.gif") FOXDOT_HELLO = os.path.realpath(FOXDOT_ROOT + "/Workspace/img/hello.txt") FOXDOT_STARTUP_PATH = os.path.realpath(FOXDOT_ROOT + "/Custom/startup.py") # FOXDOT_SND = SAMPLES_FOLDER_PATH / 'foxdot_default' FOXDOT_SND = get_samples_dir_path() # FOXDOT_LOOP = SAMPLES_FOLDER_PATH / 'foxdot_default' / '_loop_' FOXDOT_LOOP = "_loop_" # FOXDOT_LOOP = os.path.realpath(FOXDOT_ROOT + "/../../renardo_samples/_loop_/") SCLANG_EXEC = 'sclang.exe' if SYSTEM == WINDOWS else 'sclang' SYNTHDEF_DIR = os.path.realpath(FOXDOT_ROOT + "/osc/scsyndef/") EFFECTS_DIR = os.path.realpath(FOXDOT_ROOT + "/osc/sceffects/") ENVELOPE_DIR = os.path.realpath(FOXDOT_ROOT + "/osc/scenvelopes/") TUTORIAL_DIR = os.path.realpath(FOXDOT_ROOT + "/demo/") RECORDING_DIR = os.path.realpath(FOXDOT_ROOT + "/rec/") FOXDOT_OSC_FUNC = os.path.realpath(FOXDOT_ROOT + "/osc/OSCFunc.scd") FOXDOT_STARTUP_FILE = os.path.realpath(FOXDOT_ROOT + "/osc/Startup.scd") FOXDOT_BUFFERS_FILE = os.path.realpath(FOXDOT_ROOT + "/osc/Buffers.scd") FOXDOT_EFFECTS_FILE = os.path.realpath(FOXDOT_ROOT + "/osc/Effects.scd") FOXDOT_INFO_FILE = os.path.realpath(FOXDOT_ROOT + "/osc/Info.scd") FOXDOT_RECORD_FILE = os.path.realpath(FOXDOT_ROOT + "/osc/Record.scd") FOXDOT_TEMP_FILE = os.path.realpath(FOXDOT_ROOT + "/Workspace/tmp/tempfile.txt") # If the tempfile doesn't exist, create it if not os.path.isfile(FOXDOT_TEMP_FILE): try: with open(FOXDOT_TEMP_FILE, "w") as f: pass except FileNotFoundError: pass def GET_SYNTHDEF_FILES(): return [os.path.realpath(SYNTHDEF_DIR + "/" + path) for path in os.listdir(SYNTHDEF_DIR)] def GET_FX_FILES(): return [os.path.realpath(EFFECTS_DIR + "/" + path) for path in os.listdir(EFFECTS_DIR)] def GET_TUTORIAL_FILES(): return [os.path.realpath(TUTORIAL_DIR + "/" + path) for path in sorted(os.listdir(TUTORIAL_DIR))] # Set Environment Variables try: reload(conf) # incase of a reload except NameError: from renardo_lib.Settings import conf FOXDOT_CONFIG_FILE = conf.filename ADDRESS = conf.ADDRESS PORT = conf.PORT PORT2 = conf.PORT2 FONT = conf.FONT SC3_PLUGINS = conf.SC3_PLUGINS MAX_CHANNELS = conf.MAX_CHANNELS GET_SC_INFO = conf.GET_SC_INFO USE_ALPHA = conf.USE_ALPHA ALPHA_VALUE = conf.ALPHA_VALUE MENU_ON_STARTUP = conf.MENU_ON_STARTUP TRANSPARENT_ON_STARTUP = conf.TRANSPARENT_ON_STARTUP RECOVER_WORK = conf.RECOVER_WORK CHECK_FOR_UPDATE = conf.CHECK_FOR_UPDATE LINE_NUMBER_MARKER_OFFSET = conf.LINE_NUMBER_MARKER_OFFSET AUTO_COMPLETE_BRACKETS = conf.AUTO_COMPLETE_BRACKETS CPU_USAGE = conf.CPU_USAGE CLOCK_LATENCY = conf.CLOCK_LATENCY FORWARD_ADDRESS = conf.FORWARD_ADDRESS FORWARD_PORT = conf.FORWARD_PORT SAMPLES_PACK_NUMBER = conf.SAMPLES_PACK_NUMBER if conf.SAMPLES_DIR is not None and conf.SAMPLES_DIR != "": FOXDOT_SND = os.path.realpath(conf.SAMPLES_DIR) def get_timestamp(): import time return time.strftime("%Y%m%d-%H%M%S") # Name of SamplePlayer and LoopPlayer SynthDef class _SamplePlayer: names = ('play1', 'play2',) def __eq__(self, other): return other in self.names def __ne__(self, other): return other not in self.names class _LoopPlayer: names = ("loop", "gsynth", 'stretch') def __eq__(self, other): return other in self.names def __ne__(self, other): return other not in self.names class _MidiPlayer: name = "MidiOut" def __eq__(self, other): return other == self.name def __ne__(self, other): return other != self.name SamplePlayer = _SamplePlayer() LoopPlayer = _LoopPlayer() MidiPlayer = _MidiPlayer() # OSC Information OSC_MIDI_ADDRESS = "/foxdot_midi" # Colours class COLOURS: plaintext = conf.plaintext background = conf.background functions = conf.functions key_types = conf.key_types user_defn = conf.user_defn other_kws = conf.other_kws comments = conf.comments numbers = conf.numbers strings = conf.strings dollar = conf.dollar arrow = conf.arrow players = conf.players kick = conf.kick various = conf.various vocal = conf.vocal bell = conf.bell hihat = conf.hihat clap = conf.clap snap = conf.snap shaker = conf.shaker tambourine = conf.tambourine crash = conf.crash cymbal = conf.cymbal soundfx = conf.soundfx tom = conf.tom noise = conf.noise ride = conf.ride perc = conf.perc snare = conf.snare rim = conf.rim loops = conf.loops default = conf.default text1 = conf.text1 text2 = conf.text2 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Settings/conf.py0000644000175100001770000000311014611211152021034 0ustar00runnerdockerimport os.path # Settings # ------------------ ADDRESS='localhost' PORT=57110 PORT2=57120 FONT='Consolas' SUPERCOLLIDER="" BOOT_ON_STARTUP=False CHECK_FOR_UPDATE=True SC3_PLUGINS=False MAX_CHANNELS=2 SAMPLES_DIR="" SAMPLES_PACK_NUMBER=0 GET_SC_INFO=True USE_ALPHA=True ALPHA_VALUE=0.8 MENU_ON_STARTUP=True TRANSPARENT_ON_STARTUP=False RECOVER_WORK=True LINE_NUMBER_MARKER_OFFSET=0 AUTO_COMPLETE_BRACKETS=True CPU_USAGE=2 # 0=low, 1=medium, 2=high CLOCK_LATENCY=0 # 0=low, 1=medium, 2=high FORWARD_ADDRESS='' FORWARD_PORT=0 # Text colours # ------------------ plaintext='#ffffff' background='#1a1a1a' functions='#bf4acc' key_types='#29abe2' user_defn='#29abe2' other_kws='#49db8b' comments='#666666' numbers='#e89c18' strings='#eae02a' dollar='#ec4e20' arrow='#eae02a' players='#ec4e20' # Loading from file # ------------------ filename = os.path.join(os.path.dirname(__file__), "conf.txt") try: with open(filename) as f: contents = f.read() code = compile(contents, "FoxDot", "exec") exec(code, globals()) except FileNotFoundError: pass # Loading from env # ------------------ for key, value in os.environ.items(): if key in globals(): globals()[key] = value # Category colours # ------------------ kick='#780373' various='#ffbf00' vocal='#ffa6a6' bell='#158466' hihat='#81d41a' clap='#729fcf' snap='#729fcf' shaker='#a7074b' tambourine='#a7074b' crash='#bbe33d' cymbal='#bbe33d' soundfx='#3465a4' tom='#ff3838' noise='#6b5e9b' ride='#ffffa6' perc='#ff8000' snare='#ffff38' rim='#ffff38' loops='#1e1e19' default='#b2b2b2' text1='#ffffff' text2='#000000' ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/TempoClock.py0000644000175100001770000010055014611211152020355 0ustar00runnerdocker""" Clock management for scheduling notes and functions. Anything 'callable', such as a function or instance with a `__call__` method, can be scheduled. An instance of `TempoClock` is created when FoxDot started up called `Clock`, which is used by `Player` instances to schedule musical events. The `TempoClock` is also responsible for sending the osc messages to SuperCollider. It contains a queue of event blocks, instances of the `QueueBlock` class, which themselves contain queue items, instances of the `QueueObj` class, which themseles contain the actual object or function to be called. The `TempoClock` is continually running and checks if any queue block should be activated. A queue block has a "beat" value for which its contents should be activated. To make sure that events happen on time, the `TempoClock` will begin processing the contents 0.25 seconds before it is *actually* meant to happen in case there is a large amount to process. When a queue block is activated, a new thread is created to process all of the callable objects it contains. If it calls a `Player` object, the queue block keeps track of the OSC messages generated until all `Player` objects in the block have been called. At this point the thread is told to sleep until the remainder of the 0.25 seconds has passed. This value is stored in `Clock.latency` and is adjustable. If you find that there is a noticeable jitter between events, i.e. irregular beat lengths, you can increase the latency by simply evaluating the following in FoxDot: Clock.latency = 0.5 To stop the clock from scheduling further events, use the `Clock.clear()` method, which is bound to the shortcut key, `Ctrl+.`. You can schedule non-player objects in the clock by using `Clock.schedule(func, beat, args, kwargs)`. By default `beat` is set to the next bar in the clock, but you use `Clock.now() + n` or `Clock.next_bar() + n` to schedule a function in the future at a specific time. To change the tempo of the clock, just set the bpm attribute using `Clock.bpm=val`. The change in tempo will occur at the start of the next bar so be careful if you schedule this action within a function like this: def myFunc(): print("bpm change!") Clock.bpm+=50 This will print the string `"bpm change"` at the next bar and change the bpm value at the start of the *following* bar. The reason for this is to make it easier for calculating currently clock times when using a `TimeVar` instance (See docs on TimeVar.py) as a tempo. You can change the clock's time signature as you would change the tempo by setting the `meter` attribute to a tuple with two values. So for 3/4 time you would use the follwing code: Clock.meter = (3,4) """ from types import MethodType import time from traceback import format_exc as error_stack import sys import threading import inspect from renardo_lib.Players import Player from renardo_lib.Repeat import MethodCall from renardo_lib.Patterns import asStream from renardo_lib.TimeVar import TimeVar from renardo_lib.Midi import MidiIn, MIDIDeviceNotFound from renardo_lib.Utils import modi from renardo_lib.ServerManager import TempoClient, ServerManager, RequestTimeout from renardo_lib.Settings import CPU_USAGE class TempoClock(object): tempo_server = None tempo_client = None waiting_for_sync = False def __init__(self, bpm=120.0, meter=(4,4)): # Flag this when done init self.__setup = False # debug information self.largest_sleep_time = 0 self.last_block_dur = 0.0 # Storing time as a float self.dtype=float self.beat = self.dtype(0) # Beats elapsed self.last_now_call = self.dtype(0) self.ticking = True #?? # Player Objects stored here self.playing = [] # Store history of osc messages and functions in here self.history = History() # All other scheduled items go here self.items = [] # General set up self.bpm = bpm self.meter = meter # Create the queue self.queue = Queue(self) self.current_block = None # Midi Clock In self.midi_clock = None # EspGrid sync self.espgrid = None # Flag for next_bar wrapper self.now_flag = False # Can be configured self.latency_values = [0.25, 0.5, 0.75] self.latency = 0.25 # Time between starting processing osc messages and sending to server self.nudge = 0.0 # If you want to synchronise with something external, adjust the nudge self.hard_nudge = 0.0 self.bpm_start_time = time.time() self.bpm_start_beat = 0 # The duration to sleep while continually looping self.sleep_values = [0.01, 0.001, 0.0001] self.sleep_time = self.sleep_values[CPU_USAGE] self.midi_nudge = 0 # Debug self.debugging = False self.__setup = True # If one object is going to played self.solo = SoloPlayer() self.thread = threading.Thread(target=self.run) def sync_to_espgrid(self, host="localhost", port=5510): """ Connects to an EspGrid instance """ from renardo_lib.EspGrid import EspGrid self.espgrid = EspGrid((host, port)) try: tempo = self.espgrid.get_tempo() except RequestTimeout: err = "Unable to reach EspGrid. Make sure the application is running and try again." raise RequestTimeout(err) self.espgrid.set_clock_mode(2) self.schedule(lambda: self._espgrid_update_tempo(True)) # self._espgrid_update_tempo(True) # could schedule this for next bar? return def _espgrid_update_tempo(self, force=False): """ Retrieves the current tempo from EspGrid and updates internal values """ data = self.espgrid.get_tempo() # If the tempo hasn't been started, start it here and get updated data if data[0] == 0: self.espgrid.start_tempo() data = self.espgrid.get_tempo() if force or (data[1] != self.bpm): self.bpm_start_time = float("{}.{}".format(data[2], data[3])) self.bpm_start_beat = data[4] object.__setattr__(self, "bpm", self._convert_json_bpm(data[1])) # self.schedule(self._espgrid_update_tempo) self.schedule(self._espgrid_update_tempo, int(self.now() + 1)) return def reset(self): """ Deprecated """ self.time = self.dtype(0) self.beat = self.dtype(0) self.start_time = time.time() return @classmethod def set_server(cls, server): """ Sets the destination for OSC messages being compiled (the server is also the class that compiles them) via objects in the clock. Should be an instance of ServerManager - see ServerManager.py for more. """ assert isinstance(server, ServerManager) cls.server = server return @classmethod def add_method(cls, func): setattr(cls, func.__name__, func) def start_tempo_server(self, serv, **kwargs): """ Starts listening for FoxDot clients connecting over a network. This uses a TempoClient instance from ServerManager.py """ self.tempo_server = serv(self, **kwargs) self.tempo_server.start() return def kill_tempo_server(self): """ Kills the tempo server """ if self.tempo_server is not None: self.tempo_server.kill() return def flag_wait_for_sync(self, value): self.waiting_for_sync = bool(value) def connect(self, ip_address, port=57999): try: self.tempo_client = TempoClient(self) self.tempo_client.connect(ip_address, port) self.tempo_client.send(["request"]) self.flag_wait_for_sync(True) except ConnectionRefusedError as e: print(e) pass def kill_tempo_client(self): if self.tempo_client is not None: self.tempo_client.kill() return def __str__(self): return str(self.queue) def __iter__(self): for x in self.queue: yield x def __len__(self): return len(self.queue) def __contains__(self, item): return item in self.items def update_tempo_now(self, bpm): """ emergency override for updating tempo""" self.last_now_call = self.bpm_start_time = time.time() self.bpm_start_beat = self.now() object.__setattr__(self, "bpm", self._convert_json_bpm(bpm)) # self.update_network_tempo(bpm, start_beat, start_time) -- updates at the bar... return def set_tempo(self, bpm, override=False): """ Short-hand for update_tempo and update_tempo_now """ return self.update_tempo_now(bpm) if override else self.update_tempo(bpm) def update_tempo(self, bpm): """ Schedules the bpm change at the next bar, returns the beat and start time of the next change """ try: assert bpm > 0, "Tempo must be a positive number" except AssertionError as err: raise(ValueError(err)) next_bar = self.next_bar() bpm_start_time = self.get_time_at_beat(next_bar) bpm_start_beat = next_bar def func(): if self.espgrid is not None: self.espgrid.set_tempo(bpm) else: object.__setattr__(self, "bpm", self._convert_json_bpm(bpm)) self.last_now_call = self.bpm_start_time = bpm_start_time self.bpm_start_beat = bpm_start_beat # Give next bar value to bpm_start_beat self.schedule(func, next_bar, is_priority=True) return bpm_start_beat, bpm_start_time def update_tempo_from_connection(self, bpm, bpm_start_beat, bpm_start_time, schedule_now=False): """ Sets the bpm externally from another connected instance of FoxDot """ def func(): self.last_now_call = self.bpm_start_time = self.get_time_at_beat(bpm_start_beat) self.bpm_start_beat = bpm_start_beat object.__setattr__(self, "bpm", self._convert_json_bpm(bpm)) # Might be changing immediately if schedule_now: func() else: self.schedule(func, is_priority=True) return def update_network_tempo(self, bpm, start_beat, start_time): """ Updates connected FoxDot instances (client or servers) tempi """ json_value = self._convert_bpm_json(bpm) # If this is a client, send info to server if self.tempo_client is not None: self.tempo_client.update_tempo(json_value, start_beat, start_time) # If this is a server, send info to clients if self.tempo_server is not None: self.tempo_server.update_tempo(None, json_value, start_beat, start_time) return def swing(self, amount=0.1): """ Sets the nudge attribute to var([0, amount * (self.bpm / 120)],1/2)""" self.nudge = TimeVar([0, amount * (self.bpm / 120)], 1/2) if amount != 0 else 0 return def set_cpu_usage(self, value): """ Sets the `sleep_time` attribute to values based on desired high/low/medium cpu usage """ assert 0 <= value <= 2 self.sleep_time = self.sleep_values[value] return def set_latency(self, value): """ Sets the `latency` attribute to values based on desired high/low/medium latency """ assert 0 <= value <= 2 self.latency = self.latency_values[value] return def __setattr__(self, attr, value): if attr == "bpm" and self.__setup: # If connected to EspGrid, just update that # if self.espgrid is not None: # self.espgrid.set_tempo(value) # else: # # Schedule for next bar # start_beat, start_time = self.update_tempo(value) # # Checks if any peers are connected and updates them also # self.update_network_tempo(value, start_beat, start_time) # Schedule for next bar start_beat, start_time = self.update_tempo(value) # Checks if any peers are connected and updates them also self.update_network_tempo(value, start_beat, start_time) elif attr == "midi_nudge" and self.__setup: # Adjust nudge for midi devices self.server.set_midi_nudge(value) object.__setattr__(self, "midi_nudge", value) else: self.__dict__[attr] = value return def bar_length(self): """ Returns the length of a bar in terms of beats """ return (float(self.meter[0]) / self.meter[1]) * 4 def bars(self, n=1): """ Returns the number of beats in 'n' bars """ return self.bar_length() * n def beat_dur(self, n=1): """ Returns the length of n beats in seconds """ return 0 if n == 0 else (60.0 / self.get_bpm()) * n def beats_to_seconds(self, beats): return self.beat_dur(beats) def seconds_to_beats(self, seconds): """ Returns the number of beats that occur in a time period """ return (self.get_bpm() / 60.0) * seconds def get_bpm(self): """ Returns the current beats per minute as a floating point number """ if isinstance(self.bpm, TimeVar): bpm_val = self.bpm.now(self.beat) elif self.midi_clock: bpm_val = self.midi_clock.bpm else: bpm_val = self.bpm return float(bpm_val) def get_latency(self): """ Returns self.latency (which is in seconds) as a fraction of a beat """ return self.seconds_to_beats(self.latency) def get_elapsed_beats_from_last_bpm_change(self): """ Returns the number of beats that *should* have elapsed since the last tempo change """ return float(self.get_elapsed_seconds_from_last_bpm_change() * (self.get_bpm() / 60)) def get_elapsed_seconds_from_last_bpm_change(self): """ Returns the time since the last change in bpm """ return self.get_time() - self.bpm_start_time def get_time(self): """ Returns current machine clock time with nudges values added """ return time.time() + float(self.nudge) + float(self.hard_nudge) def get_time_at_beat(self, beat): """ Returns the time that the local computer's clock will be at 'beat' value """ if isinstance(self.bpm, TimeVar): t = self.get_time() + self.beat_dur(beat - self.now()) else: t = self.bpm_start_time + self.beat_dur(beat - self.bpm_start_beat) return t def sync_to_midi(self, port=0, sync=True): """ If there is an available midi-in device sending MIDI Clock messages, this attempts to follow the tempo of the device. Requies rtmidi """ try: if sync: self.midi_clock = MidiIn(port) elif self.midi_clock: self.midi_clock.close() self.midi_clock = None except MIDIDeviceNotFound as e: print("{}: No MIDI devices found".format(e)) return def debug(self, on=True): """ Toggles debugging information printing to console """ self.debugging = bool(on) return def set_time(self, beat): """ Set the clock time to 'beat' and update players in the clock """ self.start_time = time.time() self.queue.clear() self.beat = beat self.bpm_start_beat = beat self.bpm_start_time = self.start_time # self.time = time() - self.start_time for player in self.playing: player(count=True) return def calculate_nudge(self, time1, time2, latency): """ Approximates the nudge value of this TempoClock based on the machine time.time() value from another machine and the latency between them """ # self.hard_nudge = time2 - (time1 + latency) self.hard_nudge = time1 - time2 - latency return def _convert_bpm_json(self, bpm): if isinstance(bpm, (int, float)): return float(bpm) elif isinstance(bpm, TimeVar): return bpm.json_value() def json_bpm(self): """ Returns the bpm in a data type that can be sent over json""" return self._convert_bpm_json(self.bpm) def get_sync_info(self): """ Returns information for synchronisation across multiple FoxDot instances. To be stored as a JSON object with a "sync" header """ data = { "sync" : { "bpm_start_time" : float(self.bpm_start_time), "bpm_start_beat" : float(self.bpm_start_beat), "bpm" : self.json_bpm(), } } return data def _now(self): """ If the bpm is an int or float, use time since the last bpm change to calculate what the current beat is. If the bpm is a TimeVar, increase the beat counter by time since last call to _now()""" if isinstance(self.bpm, (int, float)): self.beat = self.bpm_start_beat + self.get_elapsed_beats_from_last_bpm_change() else: now = self.get_time() self.beat += (now - self.last_now_call) * (self.get_bpm() / 60) self.last_now_call = now return self.beat def now(self): """ Returns the total elapsed time (in beats as opposed to seconds) """ if self.ticking is False: # Get the time w/o latency if not ticking self.beat = self._now() return float(self.beat) def mod(self, beat, t=0): """ Returns the next time at which `Clock.now() % beat` will equal `t` """ n = self.now() // beat return (n + 1) * beat + t def osc_message_time(self): """ Returns the true time that an osc message should be run i.e. now + latency """ return time.time() + self.latency def start(self): """ Starts the clock thread """ self.thread.daemon = True self.thread.start() return def _adjust_hard_nudge(self): """ Checks for any drift between the current beat value and the value expected based on time elapsed and adjusts the hard_nudge value accordingly """ beats_elapsed = int(self.now()) - self.bpm_start_beat expected_beat = self.get_elapsed_beats_from_last_bpm_change() # Dont adjust nudge on first bar of tempo change if beats_elapsed > 0: # Account for nudge in the drift self.drift = self.beat_dur(expected_beat - beats_elapsed) - self.nudge if abs(self.drift) > 0.001: # value could be reworked / not hard coded self.hard_nudge -= self.drift return self._schedule_adjust_hard_nudge() def _schedule_adjust_hard_nudge(self): """ Start recursive call to adjust hard-nudge values """ return self.schedule(self._adjust_hard_nudge) def __run_block(self, block, beat): """ Private method for calling all the items in the queue block. This means the clock can still 'tick' while a large number of events are activated """ # Set the time to "activate" messages on - adjust in case the block is activated late # `beat` is the actual beat this is happening, `block.beat` is the desired time. Adjust # the osc_message_time accordingly if this is being called late block.time = self.osc_message_time() - self.beat_dur(float(beat) - block.beat) for item in block: # The item might get called by another item in the queue block output = None if item.called is False: try: output = item.__call__() except SystemExit: sys.exit() except: print(error_stack()) # TODO: Get OSC message from the call, and add to list? # Send all the message to supercollider together block.send_osc_messages() # Store the osc messages -- future idea # self.history.add(block.beat, block.osc_messages) return def run(self): """ Main loop """ self.ticking = True self.polled = False while self.ticking: beat = self._now() # get current time if self.queue.after_next_event(beat): self.current_block = self.queue.pop() # Do the work in a thread if len(self.current_block): threading.Thread(target=self.__run_block, args=(self.current_block, beat)).start() # If using a midi-clock, update the values # if self.midi_clock is not None: # self.midi_clock.update() # if using espgrid if self.sleep_time > 0: time.sleep(self.sleep_time) return def schedule(self, obj, beat=None, args=(), kwargs={}, is_priority=False): """ TempoClock.schedule(callable, beat=None) Add a player / event to the queue """ # Make sure the object can actually be called try: assert callable(obj) except AssertionError: raise ScheduleError(obj) # Start the clock ticking if not already if self.ticking == False: self.start() # Default is next bar if beat is None: beat = self.next_bar() # Keep track of objects in the Clock if obj not in self.playing and isinstance(obj, Player): self.playing.append(obj) if obj not in self.items: self.items.append(obj) # Add to the queue self.queue.add(obj, beat, args, kwargs, is_priority) # block.time = self.osc_message_accum return def future(self, dur, obj, args=(), kwargs={}): """ Add a player / event to the queue `dur` beats in the future """ self.schedule(obj, self.now() + dur, args, kwargs) return def next_bar(self): """ Returns the beat value for the start of the next bar """ beat = self.now() return beat + (self.meter[0] - (beat % self.meter[0])) def next_event(self): """ Returns the beat index for the next event to be called """ return self.queue[-1][1] def call(self, obj, dur, args=()): """ Returns a 'schedulable' wrapper for any callable object """ return Wrapper(self, obj, dur, args) def players(self, ex=[]): return [p for p in self.playing if p not in ex] # Every n beats, do... def every(self, n, cmd, args=()): def event(f, n, args): f(*args) self.schedule(event, self.now() + n, (f, n, args)) return self.schedule(event, self.now() + n, args=(cmd, n, args)) return def stop(self): self.ticking = False self.kill_tempo_server() self.kill_tempo_client() self.clear() return def shift(self, n): """ Offset the clock time """ self.beat += n return def clear(self): """ Remove players from clock """ self.items = [] self.queue.clear() self.solo.reset() for player in list(self.playing): player.kill() # for item in self.items: # if hasattr(item, 'stop'): # item.stop() self.playing = [] if self.espgrid is not None: self.schedule(self._espgrid_update_tempo) return ##### class Queue(object): def __init__(self, parent): self.data = [] self.parent = parent def __repr__(self): return "\n".join([str(item) for item in self.data]) if len(self.data) > 0 else "[]" def add(self, item, beat, args=(), kwargs={}, is_priority=False): """ Adds a callable object to the queue at a specified beat, args and kwargs for the callable object must be in a list and dict. """ # item must be callable to be schedule, so check args and kwargs are appropriate for it try: function = inspect.getfullargspec(item) except TypeError: function = inspect.getfullargspec(item.__call__) # If the item can't take arbitrary keywords, check any kwargs are valid if function.varkw is None: for key in list(kwargs.keys()): if key not in function.args: del kwargs[key] # If the new event is before the next scheduled event, # move it to the 'front' of the queue if self.before_next_event(beat): self.data.append(QueueBlock(self, item, beat, args, kwargs, is_priority)) block = self.data[-1] else: # If the event is after the next scheduled event, work # out its position in the queue # need to be careful in case self.data changes size for block in self.data: # If another event is happening at the same time, schedule together if beat == block.beat: block.add(item, args, kwargs, is_priority) break # If the event is later than the next event, schedule it here if beat > block.beat: try: i = self.data.index(block) except ValueError: i = 0 self.data.insert(i, QueueBlock(self, item, beat, args, kwargs, is_priority)) block = self.data[i] break # Tell any players about what queue item they are in if isinstance(item, Player): item.set_queue_block(block) return def clear(self): while len(self.data): del self.data[-1] return def pop(self): return self.data.pop() if len(self.data) > 0 else list() def next(self): if len(self.data) > 0: try: return self.data[-1].beat except IndexError: pass return sys.maxsize def before_next_event(self, beat): try: return beat < self.data[-1].beat except IndexError: return True def after_next_event(self, beat): try: return beat >= self.data[-1].beat except IndexError: return False def get_server(self): """ Returns the `ServerManager` instanced used by this block's parent clock """ return self.parent.server def get_clock(self): return self.parent from types import FunctionType class QueueBlock(object): priority_levels = [ lambda x: type(x) in (FunctionType, MethodType), # Any functions are called first lambda x: isinstance(x, MethodCall), # Then scheduled player methods lambda x: isinstance(x, Player), # Then players themselves lambda x: True # And anything else ] def __init__(self, parent, obj, t, args=(), kwargs={}, is_priority=False): # Why am I forcing an obj? self.events = [ [] for lvl in self.priority_levels ] self.called_events = [] self.called_objects = [] self.items = {} self.osc_messages = [] self.parent = parent self.server = self.parent.get_server() self.metro = self.parent.get_clock() self.beat = t self.time = 0 self.add(obj, args, kwargs, is_priority) @classmethod def set_server(cls, server): cls.server = server # osc server def start_server(self, serv): self.tempo_server = serv(self) return def __repr__(self): return "{}: {}".format(self.beat, self.players()) def add(self, obj, args=(), kwargs={}, is_priority=False): """ Adds a callable object to the QueueBlock """ q_obj = QueueObj(obj, args, kwargs) for i, in_level in enumerate(self.priority_levels): if in_level(obj): # Put at the front if labelled as priority if is_priority: self.events[i].insert(0, q_obj) else: self.events[i].append(q_obj) self.items[q_obj.obj] = q_obj # store the wrapped object as an identifer break return def __call__(self): """ Calls self.osc_messages() """ self.send_osc_messages() def append_osc_message(self, message): """ Adds an OSC bundle if the timetag is not in the past """ if message.timetag > self.metro.get_time(): self.osc_messages.append(message) return def send_osc_messages(self): """ Sends all compiled osc messages to the SuperCollider server """ return list(map(self.server.sendOSC, self.osc_messages)) def players(self): return [item for level in self.events[1:3] for item in level] def all_items(self): return [item for level in self.events for item in level] def __getitem__(self, key): # could this use hashing with Player objects? return self.items[key] def __iter__(self): return (item for level in self.events for item in level) def __len__(self): return sum([len(level) for level in self.events]) def __contains__(self, other): return other in self.items def objects(self): return [item.obj for level in self.events for item in level] class QueueObj(object): """ Class representing each item in a `QueueBlock` instance """ def __init__(self, obj, args=(), kwargs={}): self.obj = obj self.args = args self.kwargs = kwargs self.called = False # flag to True when called by the block def __eq__(self, other): return other == self.obj def __ne__(self, other): return other != self.obj def __repr__(self): return repr(self.obj) def __call__(self): value = self.obj.__call__(*self.args, **self.kwargs) self.called = True return value class History(object): """ Stores osc messages send from the TempoClock so that if the Clock is reveresed we can just send the osc messages already sent """ def __init__(self): self.data = [] def add(self, beat, osc_messages): self.data.append(osc_messages) from renardo_lib import Code class Wrapper(Code.LiveObject): def __init__(self, metro, obj, dur, args=()): self.args = asStream(args) self.obj = obj self.step = dur self.metro = metro self.n = 0 self.s = self.obj.__class__.__name__ def __str__(self): return "" % self.s def __repr__(self): return str(self) def __call__(self): """ Call the wrapped object and re-schedule """ args = modi(self.args, self.n) try: self.obj.__call__(*args) except: self.obj.__call__(args) Code.LiveObject.__call__(self) class SoloPlayer: """ SoloPlayer objects """ def __init__(self): self.data = [] def __repr__(self): if len(self.data) == 0: return "None" if len(self.data) == 1: return repr(self.data[0]) else: return repr(self.data) def add(self, player): if player not in self.data: self.data.append(player) def set(self, player): self.data = [player] def reset(self): self.data = [] def active(self): """ Returns true if self.data is not empty """ return len(self.data) > 0 def __eq__(self, other): """ Returns true if other is in self.data or if self.data is empty """ return (other in self.data) if self.data else True def __ne__(self, other): return (other not in self.data) if self.data else True class ScheduleError(Exception): def __init__(self, item): self.type = str(type(item))[1:-1] def __str__(self): return "Could not schedule object of {}".format(self.type) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/TimeVar.py0000644000175100001770000006251714611211152017676 0ustar00runnerdocker""" Time-Dependent Variables (TimeVar) TODO: using __call__ -> go through getattribute and check instead of already having a __call__ """ from time import time import math from renardo_lib.Patterns import * from renardo_lib.Utils import * from renardo_lib.Patterns.Operations import * from renardo_lib.Constants import inf def fetch(func): """ Function to wrap basic lambda operators for TimeVars """ def eval_now(a, b): if isinstance(a, TimeVar): a = a.now() if isinstance(b, TimeVar): b = b.now() return func(a, b) return eval_now class TimeVar(object): """ Var(values [,durs=[4]]) """ metro = None depth = 128 def __init__(self, values, dur=None, start=0, **kwargs): if dur is None: dur = self.metro.bar_length() self.name = "un-named" self.start_time = float(start) # offset self.values = values self.dur = dur self.bpm = kwargs.get('bpm', None) self.get_seconds = bool(kwargs.get('seconds', False)) # Dynamic method for calculating values self.func = Nil self.evaluate = fetch(Nil) self.dependency = None self.update(values, dur) self.current_value = None self.current_index = 0 self.next_value = None self.next_time = 0 self.prev_time = 0 self.next_index = 0 # Private flags self.__accessed = False self.__inf_index = None self.proportion = 0 # If the clock is not ticking, start it if self.metro.ticking == False: self.metro.start() def json_value(self): """ Returns data about this TimeVar that can be sent over a network as JSON """ ## pickle? return [str(self.__class__.__name__), list(self.values), list(self.dur)] @classmethod def set_clock(cls, tempo_clock): cls.metro = tempo_clock return @classmethod def help(cls): return print(cls.__doc__) @staticmethod def stream(values): return asStream(values) @staticmethod def CreatePvarGenerator(func, *args, **kwargs): return PvarGenerator(func, *args, **kwargs) # Standard dunder methods def __str__(self): return str(self.now()) def __repr__(self): return str(self.now()) def __len__(self): return len(self.now()) def __int__(self): return int(self.now()) def __float__(self): return float(self.now()) def __abs__(self): return abs(self.now()) # For printing the details def info(self): return "<{}({}, {})>".format(self.__class__.__name__, repr(self.get_values()), repr(self.get_durs())) def all_values(self): """ Displays the values and the dependency value - useful for debugging """ return self.value + [self.dependency] # Update methods def new(self, other): """ Returns a new TimeVar object """ # new = TimeVar(other, self.dur, bpm=self.bpm) new = ChildTimeVar(other) new.dependency = self return new def update(self, values, dur=None, **kwargs): """ Updates the TimeVar with new values. """ self.bpm = kwargs.get('bpm', self.bpm) #: Update the durations of each state if dur is not None: self.dur = asStream(dur) self.values = self.stream(values) return self def get_current_index(self, time=None): """ Returns the index of the value currently represented """ # Get the time value if not from the Clock time = self.get_current_time(time) - self.start_time if self.get_inf_index() is not None: return self.get_inf_index() if time >= self.next_time: while True: next_dur = self.dur[self.next_index] self.next_time, self.prev_time = self.next_time + next_dur, self.next_time # If we find an "inf" if self.check_for_inf(next_dur): self.set_inf_index(self.next_index) return self.get_inf_index() self.next_index += 1 if self.next_time >= time: break # Store the % way through this value's time try: self.proportion = float((time - self.prev_time) / (self.next_time - self.prev_time)) except ZeroDivisionError: self.proportion = 1.0 # The current index is the next index minus one self.current_index = self.next_index - 1 # Flag we have accessed the value self.flag_accessed() return self.current_index # Inf def set_inf_index(self, value): self.__inf_index = int(value) return def get_inf_index(self): self.proportion = 0 return self.__inf_index def check_for_inf(self, duration): return (self.__accessed and duration == inf) def flag_accessed(self): self.__accessed = True return # Evaluation methods def calculate(self, val): # maybe rename to resolve """ Returns val as modified by its dependencies """ return self.evaluate(val, self.dependency) def get_current_time(self, beat=None): """ Returns the current beat value """ # Return elapsed time in seconds if get_seconds flag is True if self.get_seconds is True: return float(self.metro.time) # Else return the beat if beat is None: beat = self.metro.now() if self.bpm is not None: beat *= (self.bpm / float(self.metro.bpm)) return float(beat) def now(self, time=None): """ Returns the value currently represented by this TimeVar """ i = self.get_current_index(time) self.current_value = self.calculate(self.values[i]) return self.current_value def copy(self): new = var(self.values, self.dur, bpm=self.bpm) return new def get_durs(self): return self.dur def get_values(self): return self.values # 1. Methods that change the 'var' in place def i_invert(self): lrg = float(max(self.values)) for i, item in enumerate(self.values): self.values[i] = (((item / lrg) * -1) + 1) * lrg return # Method that return an augmented NEW version of the 'var' def invert(self): new = self.new(self.values) lrg = float(max(new.data)) for i, item in enumerate(new.data): new.data[i] = (((item / lrg) * -1) + 1) * lrg return new def lshift(self, duration): time = [self.dur[0]-duration] + list(self.dur[1:]) + [duration] return self.__class__(self.values, time) def rshift(self, duration): time = [duration] + list(self.dur[:-1]) + [self.dur[-1]-duration] data = [self.values[-1]] + list(self.values) return self.__class__(data, time) def extend(self, values, dur=None): data = list(self.values) + list(values) durs = self.dur if not dur else list(self.dur) + list(asStream(dur)) return self.__class__(data, durs) def shuf(self): pass # Mathmetical operators def math_op(self, other, op): """ Performs the mathematical operation between self and other. "op" should be the string name of a dunder method e.g. __mul__ """ if not isinstance(other, (TimeVar, int, float)): if type(other) is tuple: return PGroup([getattr(self, op).__call__(x) for x in other]) elif type(other) is list: return Pattern([getattr(self, op).__call__(x) for x in other]) else: return getattr(other, get_inverse_op(op)).__call__(self) return other def set_eval(self, func): self.evaluate = fetch(func) self.func = func return def __add__(self, other): new = self.math_op(other, "__add__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Add) return new def __radd__(self, other): new = self.math_op(other, "__radd__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(rAdd) return new def __sub__(self, other): new = self.math_op(other, "__sub__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(rSub) return new def __rsub__(self, other): new = self.math_op(other, "__rsub__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Sub) return new def __mul__(self, other): new = self.math_op(other, "__mul__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Mul) return new def __rmul__(self, other): new = self.math_op(other, "__rmul__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Mul) return new def __pow__(self, other): new = self.math_op(other, "__pow__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(rPow) return new def __rpow__(self, other): new = self.math_op(other, "__rpow__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Pow) return new def __floordiv__(self, other): new = self.math_op(other, "__floordiv__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(rFloorDiv) return new def __rfloordiv__(self, other): new = self.math_op(other, "__rfloordiv__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(FloorDiv) return new def __truediv__(self, other): new = self.math_op(other, "__truediv__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(rDiv) return new def __rtruediv__(self, other): new = self.math_op(other, "__rtruediv__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Div) return new # Incremental operators (use in place of var = var + n) def __iadd__(self, other): self.values = self.values + other return self def __isub__(self, other): self.values = self.values - other return self def __imul__(self, other): self.values = self.values * other return self def __idiv__(self, other): self.values = self.values / other return self # Comparisons -- todo: return TimeVars def __gt__(self, other): return float(self.now()) > float(other) def __lt__(self, other): return float(self.now()) < float(other) def __ge__(self, other): return float(self.now()) >= float(other) def __le__(self, other): return float(self.now()) >= float(other) # % def __mod__(self, other): new = self.math_op(other, "__mod__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(rMod) return new def __rmod__(self, other): new = self.math_op(other, "__rmod__") if not isinstance(other, (TimeVar, int, float)): return new new = self.new(other) new.evaluate = fetch(Mod) return new # Comparisons -- todo: return TimeVar def __eq__(self, other): return other == self.now() def __ne__(self, other): return other != self.now() # Storing functions etc # def __call__(self, *args, **kwargs): # """ A TimeVar can store functions and will call the current item with this method """ # if callable(self.now()): # return self.now().__call__(*args, **kwargs) # else: # return self.now() # Emulating container types def __getitem__(self, other): new = self.new(other) new.dependency = self new.evaluate = fetch(rGet) return new def __iter__(self): for item in self.now(): yield item def transform(self, func): """ Returns a new TimeVar based on a func """ new = self.new(0) new.dependency = self new.evaluate = fetch(lambda a, b: func(b)) return new class ChildTimeVar(TimeVar): """ When a new TimeVar is created using a function such as addition, e.g. var([0,2]) + 2, then a ChildTimeVar is created that contains a single value but also creates a new ChildTimeVar when operated upon and behaves just as a TimeVar does.""" def now(self, time=None): self.current_value = self.calculate(self.values[0]) return self.current_value class linvar(TimeVar): def now(self, time=None): """ Returns the value currently represented by this TimeVar """ i = self.get_current_index(time) self.current_value = self.calculate(self.values[i]) self.next_value = self.calculate(self.values[i + 1]) return self.get_timevar_value() def get_timevar_value(self): return (self.current_value * (1-self.proportion)) + (self.next_value * self.proportion) class expvar(linvar): def get_timevar_value(self): self.proportion *= self.proportion return (self.current_value * (1-self.proportion)) + (self.next_value * self.proportion) class sinvar(linvar): def get_timevar_value(self): d = self.current_value > self.next_value x = (self.proportion * 90) + (d * 270) self.proportion = math.sin(math.radians(x)) + int(d) return (self.current_value * (1-self.proportion)) + (self.next_value * self.proportion) PATTERN_METHODS = Pattern.get_methods() class Pvar(TimeVar): """ A TimeVar that represents Patterns that change over time e.g. :: >>> a = Pvar([ [0,1,2,3], [4,5] ], 4) >>> print a # time is 0 P[0, 1, 2, 3] >>> print a # time is 4 P[4, 5] """ stream = PatternContainer def __init__(self, values, dur=None, **kwargs): try: data = [asStream(val) for val in values] except: data = [values] TimeVar.__init__(self, data, dur, **kwargs) def __get_pattern_attr(self, attr): """ Returns a function that transforms the patterns of this Pvar if the attr is a Pattern method, if not it returns the attribute for the current pattern """ pattern_attr = getattr(self.now(), attr) if callable(pattern_attr): def get_new_pvar(*args, **kwargs): # If this is the root Pvar, change the values if self.dependency is None: print(len(self.values)) new_values = [getattr(pat, attr)(*args, **kwargs) for pat in self.values] return Pvar(new_values, dur=self.dur) else: # Get the "parent" Pvar and re-apply the connecting function new_pvar = getattr(self.dependency, attr)(*args, **kwargs) new_item = self.func(new_pvar, self.original_value) return new_item return get_new_pvar else: return pattern_attr def getitem(self, index, *args, **kwargs): """ Returns a TimeVar based on getting the index of this Pattern """ return TimeVar(0).transform(lambda e: self.now().getitem(index)) def __getattr__(self, attr): """ (Python 2 compatability) Override for accessing pattern methods. Returns a new Pvar that has been "transformed" using the method such that then method also applies when values have been updated. """ try: return object.__getattr__(self, attr) except AttributeError: return self.__get_pattern_attr(attr) def __getattribute__(self, attr): """ Override for accessing pattern methods. Returns a new Pvar that has been "transformed" using the method such that then method also applies when values have been updated. """ try: return object.__getattribute__(self, attr) except AttributeError: return self.__get_pattern_attr(attr) def new(self, other): # new = Pvar([other], dur=self.dur) new = ChildPvar(other) new.original_value = other new.dependency = self return new def __getitem__(self, other): """ Return a single timevar when using getitem """ new = ChildTimeVar(other) new.dependency = self new.evaluate = fetch(rGet) return new def set_eval(self, func): self.evaluate = fetch(func) self.func = func return def __add__(self, other): new = self.new(other) new.set_eval(rAdd) return new def __radd__(self, other): new = self.new((other)) new.set_eval(Add) return new def __sub__(self, other): new = self.new((other)) new.set_eval(rSub) return new def __rsub__(self, other): new = self.new((other)) new.set_eval(Sub) return new def __mul__(self, other): new = self.new((other)) new.set_eval(rMul) return new def __rmul__(self, other): new = self.new((other)) new.set_eval(Mul) return new def __div__(self, other): new = self.new((other)) new.set_eval(rDiv) return new def __rdiv__(self, other): new = self.new((other)) new.set_eval(Div) return new def __truediv__(self, other): new = self.new((other)) new.set_eval(rDiv) return new def __rtruediv__(self, other): new = self.new((other)) new.set_eval(Div) return new def __floordiv__(self, other): new = self.new((other)) new.set_eval(rFloorDiv) return new def __rfloordiv__(self, other): new = self.new((other)) new.set_eval(FloorDiv) return new def __pow__(self, other): new = self.new((other)) new.set_eval(rPow) return new def __rpow__(self, other): new = self.new((other)) new.set_eval(Pow) return new def __mod__(self, other): new = self.new((other)) new.set_eval(rMod) return new def __rmod__(self, other): new = self.new((other)) new.set_eval(Mod) return new def __or__(self, other): # Used when piping patterns together new = self.new(PatternContainer(other)) new.set_eval(rOr) return new def __ror__(self, other): # Used when piping patterns together new = self.new(PatternContainer(other)) new.set_eval(Or) return new def transform(self, func): """ Returns a Pvar based on a transformation function, as opposed to a mathematical operation""" new = self.new(self) new.set_eval(lambda a, b: b.transform(func)) return new class ChildPvar(Pvar): def now(self, time=None): self.current_value = self.calculate(self.values[0]) return self.current_value class PvarGenerator(Pvar): """ If a TimeVar is used in a Pattern function e.g. `PDur(var([3,5]), 8)` then a `PvarGenerator` is returned. Each argument is stored as a TimeVar and the function is called whenever the arguments are changed """ def __init__(self, func, *args, **kwargs): self.p_func = func # p_func is the Pattern function e.g. PDur but self.func is created when operating on this PvarGenerator self.args = [] if "pattern" in kwargs: self.args.append(kwargs["pattern"]) self.args.extend( [(arg if isinstance(arg, TimeVar) else TimeVar(arg)) for arg in args] ) self.last_args = [] self.last_data = [] self.evaluate = fetch(Nil) self.dependency = None def info(self): return "<{} {}>".format(self.__class__.__name__, self.func.__name__ + str(tuple(self.args))) def now(self): new_args = [arg.now() if isinstance(arg, TimeVar) else arg for arg in self.args] if new_args != self.last_args: self.last_args = new_args self.last_data = self.p_func(*self.last_args) pat = self.calculate(self.last_data) return pat def new(self, other): # new = Pvar([other]) # TODO -- test this new = self.__class__(lambda x: x, other) new.original_value = other new.dependency = self return new def set_eval(self, func): self.evaluate = fetch(func) self.func = func return def __getattribute__(self, attr): # If it's a method, only return the method if its new, transform, or a dunder if attr in Pattern.get_methods(): if attr not in ("new", "now", "transform") and not attr.startswith("__"): # return a function that transforms the patterns of the root Pvar def get_new_pvar_gen(*args, **kwargs): # If this is the root Pvar, change the values if self.dependency is None: # Create a new function that combines the original *plus* the method def new_func(*old_args, **old_kwargs): return getattr(self.p_func(*old_args, **old_kwargs), attr)(*args, **kwargs) return PvarGenerator(new_func, *self.args) else: # Get the "parent" Pvar and re-apply the connecting function new_pvar_gen = getattr(self.dependency, attr)(*args, **kwargs) return self.func(new_pvar_gen, self.original_value) return get_new_pvar_gen return object.__getattribute__(self, attr) class PvarGeneratorEx(PvarGenerator): """ Un-Documented """ def __init__(self, func, *args): self.func = func self.args = list(args) self.last_args = [] self.last_data = [] self.evaluate = fetch(Nil) self.dependency = 1 class mapvar(Pvar): """ Like a `Pvar`, the `mapvar` returns a whole `Pattern` as opposed to a single value, but instead of using the global clock to find the current value it uses the value in an instance of the `PlayerKey` class or another `TimeVar`. """ def __init__(self, key, mapping, default=0): TimeVar.__init__(self, []) self.key = key self.values = {key: asStream(value) for key, value in mapping.items()} self.default = asStream(default) def get_current_index(self, time=None): self.current_index = self.key.now() return self.current_index def now(self, time=None): """ Returns the value currently represented by this TimeVar """ i = self.get_current_index(time) self.current_value = self.calculate(self.values.get(i, self.default)) return self.current_value # Store and updates TimeVars class _var_dict(object): """ This is the TimeVar generator used in FoxDot. Calling it like `var()` returns a TimeVar but setting an attribute `var.foo = var([1,2],4)` will update the TimeVar that is already in `var.foo`. In short, using `var.name = var([i, j])` means you don't have to delete some of the text and replace it with `var.name.update([k, l])` you can just use `var.name = var([k, l])` and the contents of the var will be updated everywhere else in the program. """ def __init__(self): self.__vars = {} @staticmethod def __call__(*args, **kwargs): return TimeVar(*args, **kwargs) def __setattr__(self, name, value): if name != "__vars" and isinstance(value, TimeVar): if name in self.__vars: if value.__class__ != self.__vars[name].__class__: self.__vars[name].__class__ = value.__class__ self.__vars[name].__dict__ = value.__dict__ else: self.__vars[name] = value return object.__setattr__(self, name, value) def __getattr__(self, name): if name in self.__vars: value = self.__vars[name] else: try: value = object.__getattr__(self, name) except AttributeError: err = NameError("'var.{}' does not exist.".format(name)) raise err return value var = _var_dict() # Give Main.Pattern a reference to TimeVar classes Pattern.TimeVar = TimeVar Pattern.PvarGenerator = PvarGenerator Pattern.Pvar = Pvar ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5795405 renardo_lib-0.9.12/renardo_lib/Utils/0000755000175100001770000000000014611211157017047 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/Utils/__init__.py0000644000175100001770000000774414611211152021167 0ustar00runnerdocker""" Useful functions and classes, mostly relating to the Pattern class but used in multiple sub-packages of FoxDot. """ import sys import json from socket import timeout as socket_timeout from urllib.request import urlopen from urllib.error import URLError def get_pypi_version(): """ Returns the most up-to-date version number on PyPI. Return None on error """ try: addr = "https://pypi.org/pypi/FoxDot/json" page = urlopen(addr, timeout=2.5) data = json.loads(page.read().decode("utf-8")) version = data["info"]["version"] except (URLError, socket_timeout): version = None return version def stdout(*args): """ Forces prints to stdout and not console """ sys.__stdout__.write(" ".join([str(s) for s in args]) + "\n") def sliceToRange(s): start = s.start if s.start is not None else 0 stop = s.stop step = s.step if s.step is not None else 1 try: return list(range(start, stop, step)) except OverflowError: raise TypeError("range() integer end argument expected, got NoneType") def LCM(*args): """ Lowest Common Multiple """ args = [n for n in args if n != 0] # Base case if len(args) == 0: return 1 elif len(args) == 1: return args[0] X = list(args) while any([X[0]!=K for K in X]): i = X.index(min(X)) X[i] += args[i] return X[0] def EuclidsAlgorithm(n, k, lo=0, hi=1): if n == 0: return [n for i in range(k)] data = [[hi if i < n else lo] for i in range(k)] while True: k = k - n if k <= 1: break elif k < n: n, k = k, n for i in range(n): data[i] += data[-1] del data[-1] return [x for y in data for x in y] def PulsesToDurations(data): """ Returns a list of durations based on pulses (1s) and blanks (0s). Data should be a list of [1,0] where 1 is a pulse. """ count, seq = 1, [] for item in data[1:]: if item == 1: seq.append(count) count = 1 else: count += 1 seq.append(count) return seq def get_first_item(array): """ Returns first item from a possibly nested list""" try: return get_first_item(array[0]) except (TypeError, IndexError): return array def modi(array, i, debug=0): """ Returns the modulo index i.e. modi([0,1,2],4) will return 1 """ try: return array[i % len(array)] except(TypeError, AttributeError, ZeroDivisionError): return array def get_expanded_len(data): """ (0,(0,2)) returns 4. int returns 1 """ if type(data) is str and len(data) == 1: return 1 l = [] try: for item in data: try: l.append(get_expanded_len(item)) except(TypeError, AttributeError): l.append(1) return LCM(*l) * len(data) except TypeError: return 1 def max_length(*patterns): """ Returns the largest length pattern """ return max([len(p) for p in patterns]) def get_inverse_op(method): """ Returns the opposite __dunder__ method e.g. get_inverse_op("__add__") -> "__radd__" get_inverse_op("__ror__") -> "__or__" """ if method.startswith("__r"): return method.replace("__r", "__") elif method.startswith("__"): return method.replace("__", "__r", 1) return method def isiterable(obj): """ Returns true if an object is iterable by using `iter(obj)`""" try: iter(obj) return True except: return False def recursive_any(seq): """ Like any but checks lists recursively """ for item in seq: if isiterable(item): if recursive_any(item): return True else: if bool(item): return True else: return False # Classes class dots: """ Class for representing long Patterns in strings """ def __repr__(self): return '...' ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/__init__.py0000644000175100001770000001434214611211152020057 0ustar00runnerdockerimport logging from renardo_lib.Code import * from renardo_gatherer.samples_download import SPackManager FoxDotCode.namespace = globals() spack_manager = SPackManager() from renardo_lib.TempoClock import * from renardo_lib.Buffers import * from renardo_lib.Players import * from renardo_lib.Patterns import * from renardo_lib.Effects import * from renardo_lib.TimeVar import * from renardo_lib.Constants import * from renardo_lib.Midi import * from renardo_lib.Settings import * from renardo_lib.SCLang._SynthDefs import * from renardo_lib.ServerManager import * from renardo_lib.SCLang import SynthDefs, Env, SynthDef, CompiledSynthDef from renardo_lib.Root import Root from renardo_lib.Scale import Scale, Tuning @PatternMethod def __getitem__(self, key): """ Overrides the Pattern.__getitem__ to allow indexing by TimeVar and PlayerKey instances. """ if isinstance(key, PlayerKey): # Create a player key whose calculation is get_item return key.index(self) elif isinstance(key, TimeVar): # Create a TimeVar of a PGroup that can then be indexed by the key item = TimeVar(tuple(self.data)) item.dependency = key item.evaluate = fetch(Get) return item else: return self.getitem(key) def player_method(f): """ Decorator for assigning functions as Player methods. >>> @player_method ... def test(self): ... print(self.degree) >>> p1.test() """ setattr(Player, f.__name__, f) return getattr(Player, f.__name__) PlayerMethod = player_method # Temporary alias def _futureBarDecorator(n, multiplier=1): if callable(n): def switch(*args, **kwargs): Clock.now_flag = True output = n() Clock.now_flag = False return output Clock.schedule(switch, Clock.next_bar()) return switch def wrapper(f): Clock.schedule(f, Clock.next_bar() + (n * multiplier)) return f return wrapper def next_bar(n=0): ''' Schedule functions when you define them with @nextBar Functions will run n beats into the next bar. >>> nextBar(v1.solo) or >>> @nextBar ... def dostuff(): ... v1.solo() ''' return _futureBarDecorator(n) nextBar = next_bar # temporary alias def futureBar(n=0): ''' Schedule functions when you define them with @futureBar Functions will run n bars in the future (0 is the next bar) >>> futureBar(v1.solo) or >>> @futureBar(4) ... def dostuff(): ... v1.solo() ''' return _futureBarDecorator(n, Clock.bar_length()) def update_foxdot_clock(clock): """ Tells the TimeVar, Player, and MidiIn classes to use a new instance of TempoClock. """ assert isinstance(clock, TempoClock) for item in (TimeVar, Player, MidiIn): item.set_clock(clock) clock.add_method(_convert_json_bpm) return def update_foxdot_server(serv): """ Tells the `Effect` and`TempoClock`classes to send OSC messages to a new ServerManager instance. """ assert isinstance(serv, ServerManager) TempoClock.set_server(serv) SynthDefs.set_server(serv) return def instantiate_player_objects(): """ Instantiates all two-character variable Player Objects """ alphabet = list('abcdefghijklmnopqrstuvwxyz') numbers = list('0123456789') for char1 in alphabet: group = [] for char2 in alphabet + numbers: arg = char1 + char2 FoxDotCode.namespace[arg] = EmptyPlayer(arg) group.append(arg) FoxDotCode.namespace[char1 + "_all"] = Group(*[FoxDotCode.namespace[char1+str(n)] for n in range(10)]) return def _reload_synths(): """ Resends all the synth / sample info to SuperCollider. Useful for times when starting FoxDot before running `FoxDot.start` in SuperCollider. """ from renardo_lib import SCLang from renardo_lib import Effects reload(SCLang._SynthDefs) reload(Effects) Samples._reset_buffers() return def foxdot_reload(): Server.reset() SynthDefs.reload() FxList.reload() Samples.reset() return def _convert_json_bpm(clock, data): """ Returns a TimeVar object that has been sent across a network using JSON """ if isinstance(data, list): cls = data[0] val = data[1] dur = data[2] return FoxDotCode.namespace[cls](val, dur) else: return data def Master(): """ Returns a `Group` containing all the players currently active in the Clock """ return Group(*Clock.playing) def Ramp(t=32, ramp_time=4): """ Returns a `linvar` that goes from 0 to 1 over the course of the last `ramp_time` bars of every `t` length cycle. """ return linvar([0,0,1,0],[t-ramp_time, ramp_time, 0, 0]) def allow_connections(valid = True, *args, **kwargs): """ Starts a new instance of ServerManager.TempoServer and connects it with the clock. Default port is 57999 """ if valid: Clock.start_tempo_server(TempoServer, **kwargs) print("Listening for connections on {}".format(Clock.tempo_server)) else: Clock.kill_tempo_server() print("Closed connections") return def Go(): """ Function to be called at the end of Python files with FoxDot code in to keep the TempoClock thread alive. """ try: import time while 1: time.sleep(100) except KeyboardInterrupt: return # Util class class _util: def __repr__(self): return "Renardo ver. 0.9.12" def reload(self): Server.reset() SynthDefs.reload() FxList.reload() Samples.reset() return def reassign_clock(self): FoxDotCode.namespace['Clock'] = _Clock return FoxDot = _util() # Create a clock and define functions _ = None logging.basicConfig(level=logging.ERROR) when.set_namespace(FoxDotCode) # experimental _Clock = Clock = TempoClock() update_foxdot_server(Server) update_foxdot_clock(Clock) instantiate_player_objects() # Create a "now" time variable now = var([0]).transform(lambda a: Clock.now()) nextbar = var([0]).transform(lambda a: Clock.next_bar()) Attributes = Player.get_attributes() PatternMethods = Pattern.get_methods() PatternTypes = functions(Patterns.Sequences) # Start Clock.start() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5795405 renardo_lib-0.9.12/renardo_lib/demo/0000755000175100001770000000000014611211157016673 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/00_intro.py0000644000175100001770000000107014611211152020670 0ustar00runnerdocker# Tutorial 0: Introduction ################ # Executing code # To execute code in FoxDot, make sure your text cursor is in the 'block' of code # (sections of text not separated by blank lines) and press Ctrl+Return # To execute just a single line, even in a block, press Alt+Return # Try it now, move the cursor to the line of code below and press Ctrl+Return print("Hello World") ############## # Help # If you're ever stuck, or want to know more about a function or class # just type help followed by the name of that Python object in brackets: help(object) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/01_playing_notes.py0000644000175100001770000000715014611211152022416 0ustar00runnerdocker# Tutorial 1: Playing Notes # In FoxDot, all two-character variable names are reserved for player objects, such as 'p1' # Creating a Player Object with no arguments will play a single note on middle C, by default, repeatedly until stopped. # Use >> to give one of these to a player object like so: p1 >> pluck() # To stop an individual player object, simply execute p1.stop() # Besides the 2-character variables that are pre-reserved, you can create your # own with your own names foo = Player() foo >> pluck() # The >> in Python is usually reserved for a type of operation, like + or -, but it is not the case in FoxDot. # If a user re-executes the code, FoxDot will update p1 instead of creating a PlayerObject, # which means you can make changes to your music using just one line of code. # If you now give your player object some arguments, you can change the notes being played back. # The first argument should be the degree of the note to be played # (default is the lowest note of octave 5 of the major scale) and does not need to be specified by name. # Python, like most programming languages, using zero-indexing when accessing values in an array, # which means that 0 refers to the first note of the scale. # Give your player object instructions to make music with their Synth. # The first argument is the note of the scale to play. The following code # plays the first three notes of the default scale (major) on repeat. # For a single note p1 >> pluck(0) # Or a list of notes p1 >> pluck([0,1,2]) # But you’ll need to specify whatever else you want to change... # Such as note durations, or the length of each note p1 >> pluck([0,0,0], dur=[1,2,3]) # Or amplitude, the "volume" of each note p1 >> pluck([0,0,0], amp=[1,2,3]) # If the second list, the amp in this example, is too long, then the first list (the degree) just loops, and are matched with the remaining elements from the second list (the amplitude). p1 >> pluck([0,2,4], amp=[1,2,3,1,5]) # More generally, all the lists are traversed regardless of their length. p1 >> pluck([0,2,4], dur=[1,2], amp=[1,2,3,1,5]) # Arguments can be integers, floating points, fractions, lists, # tuples, or a mix p1 >> pluck([0,0,0], dur=2) p1 >> pluck([0,0,0], dur=1.743) p1 >> pluck([0,0,0], dur=[0.25,0.5,0.75]) p1 >> pluck([0,0,0], dur=[1/4,1/2,3/4]) p1 >> pluck([0,0,0], dur=[1/4,0.25,3]) # Lists of values are iterated over as the Player plays notes # The following duration equates to: 1,2,3,1,4,3 # If you don't understand this yet, don't worry, more about patterns in the pattern tutorial p1 >> pluck([0,0,0], dur=[1,[2,4],3]) # Values in tuples are used simultaneously i.e. p1 will play 3 individual notes, then a chord of 3 together at the same time. p1 >> pluck([0,2,4,(0,2,4)]) # You can also assign values to the attributes of player objects directly p1.oct = 5 # To see all the names of player attributes, just execute print(Player.get_attributes()) # More about those later in the player attributes tutorial # You could store several player instances and assign them at different times proxy_1 = pads([0,1,2,3], dur=1/2) proxy_2 = pads([4,5,6,7], dur=1) p1 >> proxy_1 # Assign the first to p1 p1 >> proxy_2 # This replaces the instructions being followed by p1 # To play multiple sequences at once, just do the same things with another # Player object: p1 >> pluck([0, 2, 3, 4], dur=1/2) p2 >> pads([(0, 2, 4), (3, 5, 7)], dur=8) # Play only this player, muting others p1.solo() # default value is 1 (solo on) # And turn the solo off p1.solo(0) # Stop (not just mute) the other players p1.only() # Use Ctrl+. to clear everything for the scheduling clock or run Clock.clear() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/02_algorithmic_manipulation.py0000644000175100001770000000241214611211152024622 0ustar00runnerdocker# Tutorial 2: Algorithmic Manipulation # The code below plays the first four notes of the default scale on repeat: p1 >> pads([0,1,2,3]) # It's possible to manipulate this by adding an array of numbers to the Player object # This raises the 4th note played by 2 degrees p1 >> pads([0,1,2,3]) + [0,0,0,2] # And this raises every third note by 2 p1 >> pads([0,1,2,3]) + [0,0,2] # These values can be laced and grouped together p1 >> pads([0,1,2,3]) + [0,1,[0,(0,2)]] # This behaviour is particularly useful when using the follow method. b1 >> bass([0,4,5,3], dur=2) p1 >> pads().follow(b1) + [2,4,7] # You can schedule players to do things # This will tell p1 to reverse the notes every 4 beats p1 >> pads([0,2,4,6]) p1.every(4, "reverse") # You can "chain" methods together by appending them to the end of # the original line: p1 >> pads([0,2,4,6]).every(4, "reverse") # To stop calling "reverse", use 'never': p1.never("reverse") # Here are a few other methods you can use: # Using "stutter" will play the same note 'n' number of times with different attributes specified p1.every(4, "stutter", 4, oct=4, pan=[-1,1]) # Rotate will move all the values over by 1 in their order p1.every(4, "rotate") # To randomise the order of the notes, use "shuffle" p1.every(4, "shuffle") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/03_playing_samples.py0000644000175100001770000000526414611211152022740 0ustar00runnerdocker# Tutorial 3: Playing Built-In Samples # FoxDot can also be used to sequence and manipulate audio samples. # To do this all you need to do is use the special play SynthDef. # The first argument of the play SynthDef should be a string of characters # instead of a list of numbers as you would do for any other SynthDef. # Each character represents a different audio file, which is stored in a buffer in SuperCollider. # To view which character relates to which audio file, execute print(Samples) # You can play audio samples in the FoxDot/snd/ sub-directories by using the # 'play' Synth and using a string of characters instead of list of notes. bd >> play("x") # A character refers to a sound and whitespace is used for silence, so # you can spread sounds out in time: bd >> play("x x x ") hh >> play(" -") # You can lace patterns using round brackets # Whick plays like: "x o xo " d1 >> play("(x )( x)o ") # The following is the same as "-------=" hh >> play("---(-=)") # Putting characters in square brackets will play them all in the space of one beat # And will be played like one character, not simultaneous, but in quick succession d1 >> play("x-o[-o]") d1 >> play("x-o[---]") d1 >> play("x-o[-----]") d1 >> play("x-o[--------------]") # and can be put in round brackets as if they were one character themselves. d1 >> play("x[--]o(=[-o])") # You can combine the brackets however you like: the following patterns are identical d1 >> play("x-o(-[-o])") d1 >> play("x-o[-(o )]") # Curly braces select a sample sound at random if you want more variety d1 >> play("x-o{-=[--][-o]}") # Angle brackets combine patterns to be play simultaneously d1 >> play("<- ><# >") d1 >> play("< - >< # >< V>") # Each character is mapped to a folder of sound files and you can select different # samples by using the "sample" keyword argument d1 >> play("(x[--])xu[--]") d1 >> play("(x[--])xu[--]", sample=1) d1 >> play("(x[--])xu[--]", sample=2) # Change the sample for each beat d1 >> play("(x[--])xu[--]", sample=[1,2,3]) # You can layer two patterns together - note the "P", look at tutorial 4 for more information. d1 >> play(P["x-o-"] & P[" **"]) # And change effects applied to all the layered patterns at the same time d1 >> play(P["x-o-"] & P[" **"], room=0.5) # Example from the player tutorial, but with samples instead # Conditionals... d1 >> play("x[--]xu[--]x", sample=(d1.degree=="x")) # Or change it to sample bank 2 by multiplying d1 >> play("x[--]xu[--]x", sample=(d1.degree=="x")*2) # Chain multiple conditionals d1 >> play("x[--]xu[--]x", sample=(d1.degree=="x")*2 + (d1.degree=="-")*5) # Which is the same as d1 >> play("x[--]xu[--]x", sample=d1.degree.map({"x":2, "-":5})) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/04_using_patterns.py0000644000175100001770000001073314611211152022614 0ustar00runnerdocker# Tutorial 4: Using Patterns # Player Objects use Python lists, known more commonly as arrays in other languages, # to sequence themselves. You've already used these previously, but they aren't exactly # flexible for manipulation. For example, try multiplying a list by two like so: print([1, 2, 3] * 2) # Is the result what you expected? # FoxDot uses a container type called a 'Pattern' to help solve this problem. # They act like regular lists but any mathematical operation performed on it is done to each item # in the list and done so pair-wise if using a second pattern. A basic pattern is created as # you would with a normal list or tuple, but with a 'P' preceeding it. print(P[1,2,3] * 2) print(P[1,2,3] + 100) # In this operation, the output consists of all the combinations of the two patterns i.e. # [1+3, 2+4, 3+3, 1+4, 2+3, 3+4] print(P[1,2,3] + [3,4]) # You can use Python's slicing syntax to generate a series of numbers print(P[:8]) print(P[0,1,2,3:20]) print(P[2:15:3]) # Try some other mathematical operators and see what results you get. print(P[1,2,3] * (1,2)) # Pattern objects also automatically interlace any nested list. # Compare # Normal list: for n in [0,1,2,[3,4],5]: print(n) # with # Pattern for n in P[0,1,2,[3,4],5]: print(n) # Use PGroups if you want this behavior to be avoided. These can be implicitly # specified as tuples in Patterns: for n in P[0,1,2,(3,4)]: print(n) # This is a PGroup: print(P(0,2,4) + 2) print(type(P(0,2,4) + 2)) # In Python, you can generate a range of integers with the syntax range(start, stop, step). # By default, start is 0 and step is 1. print(list(range(10))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # You can use PRange(start, stop, step) to create a Pattern object with the equivalent values: print(PRange(10)) # P[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # P[0, 2, 2, 6, 4, 10, 6, 14, 8, 18] # [0*1, 1*2, 2*1, 3*2, 4*1, 5*2, 6*1, 7*2, 8*1...] print(PRange(10) * [1, 2]) # Pattern class behaviour # Adding a list (or Pattern) to a Pattern will add the values of the # elements to the other where Python lists would be concatonated. print(PRange(10) + [0,10]) # To concatonate Patterns, use the pipe operator like so: print(PRange(10) | [0,10]) # FoxDot automatically converts any object being piped to a Pattern to the base Pattern class # so you don't have to worry about making sure everything is the right type. # Plays all the values together p1 >> pluck(P(4,6,8)) p1 >> pluck(P[0,1,2,P(4,6,8),7,8]) # Spreads the values across the current "dur" e.g. if the dur is 2 beats then it will play each value 2/3 beats apart p1 >> pluck(P*(0,2,4), dur=1/2) p1 >> pluck(P*(0,2,4), dur=1) p1 >> pluck(P*(0,2,4), dur=2) p1 >> pluck(P[0,1,2,P*(4,6,8),7,8], dur=1) # Is the same as P* but every other time the notes are played they are spread over the dur value. p1 >> pluck(P/(0,2,4), dur=1/2) p1 >> pluck(P/(0,2,4), dur=1) p1 >> pluck(P/(0,2,4), dur=2) p1 >> pluck(P[0,1,2,P/(4,6,8),7,8], dur=1) # Spreads the values across the current "sus" e.g. if the dur is 2 beats and the sus is 3 beats then it will play each value 1 beat apart. p1 >> pluck(P+(0,2,4), dur=2, sus=3) p1 >> pluck(P+(0,2,4), dur=2, sus=1) p1 >> pluck(P[0,1,2,P+(4,6,8),7,8], dur=1, sus=3) # Spreads the first (length - 1) values with a gap of the last value between each # Plays 0,2,4 with a gap of 0.5: p1 >> pluck(P^(0,2,4,0.5), dur=1/2) # Patterns come with several methods for manipulating the contents help(Pattern) # Standard pattern print(P[:8]) # Shuffle pattern by randomizing it print(P[:8].shuffle()) # Append a reversed pattern to the pattern print(P[:8].palindrome()) # Shift the pattern by n (default 1) print(P[:8].rotate()) print(P[:8].rotate(3)) print(P[:8].rotate(-3)) # Takes the pattern and appends it as many times as needed to reach n number of elements in the pattern print(P[:8].stretch(12)) print(P[:8].stretch(20)) # Reverses a pattern print(P[:8].reverse()) # Loops a pattern n number of times print(P[:8].loop(2)) # Add an offset print(P[:8].offadd(5)) # Add a multiplied offset print(P[:8].offmul(5)) # Stutter - Repeat each element n times print(P[:8].stutter(5)) # Amen # Merges and laces the first and last two items such that a # drum pattern "x-o-" would become "(x[xo])-o([-o]-)" and mimics # the rhythm of the famous "amen break" d1 >> play(P["x-o-"].amen()) print(P[:8].amen()) # Bubble # Merges and laces the first and last two items such that a # drum pattern "x-o-" would become "(x[xo])-o([-o]-) d1 >> play(P["x-o-"].bubble()) print(P[:8].bubble()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/05_player_attributes.py0000644000175100001770000000242714611211152023313 0ustar00runnerdocker# Tutorial 5: Referencing Player Attributes # You can set variables outside a player pitches = P[0,1,2,3,4] harmony = pitches + 2 print(pitches) print(harmony) p1 >> pluck(pitches) p2 >> star(harmony) # If you set the duration of the second, it might not have the desired effect p1 >> pluck(pitches) p2 >> star(harmony, dur=1/2) # It is possible for one player object to play exactly what another player is. # To have one player follow another, just use the follow method: p1 >> pluck(pitches) p2 >> star(dur=1/2).follow(p1) + 2 # You can explicitly reference attributes such as pitch or duration too: p2 >> star(p1.pitch) + 2 # this is the same as .follow(p1) # Works for other attributes too p1 >> pluck(pitches) p2 >> star(dur=p1.dur).follow(p1) + 2 # You can reference, and test for the current value # The == returns a 1 if true and a 0 if false print(p1.degree) print(p1.degree == 2) # This allows you to do conditionals like p1 >> pluck([0,1,2,3], amp=(p1.degree==1)) p1 >> pluck([0,1,2,3], amp=(p1.degree>1)) # Or change it to a different amp by multiplying by 4 p1 >> pluck([0,1,2,3], amp=(p1.degree==1)*4) # Chain multiple conditionals p1 >> pluck([0,1,2,3], amp=(p1.degree==1)*4 + (p1.degree==2)*1) # Which is the same as p1 >> pluck([0,1,2,3], amp=p1.degree.map({1:4, 2:1})) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/06_rests.py0000644000175100001770000000063114611211152020705 0ustar00runnerdocker# Tutorial 6: Rests # Rests can be added by using a rest object in the dur array # The rest silences the note that would have been played. # Without a rest, 5 notes (yes, a dur=1 would work, but lets be explicit to counterpoint the next example) p1 >> pads([0,1,2,3,4], dur=[1,1,1,1,1]) # With a rest ... 4 notes and a rest, note "4" is silenced for 4 beats p1 >> pads([0,1,2,3,4], dur=[1,1,1,1,rest(4)]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/07_basic_clock.py0000644000175100001770000000107614611211152022006 0ustar00runnerdocker# Tutorial 7: Clock Basics # To stop all player objects, you can press Ctrl+. (Hold Ctrl and hit the period) # Which is a shortcut for the command: Clock.clear() # Change the tempo (this takes effect at the next bar) Default is 120. Clock.bpm = 144 # To see what is scheduled to be played. print(Clock) # To see what the latency is print(Clock.latency) # Sometimes you want to know when the start of the next X beat cycle. To # do this we use the 'mod' method. For example if we want to see when # the start of the next 32 beat cycle is we can do print(Clock.mod(32))././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/08_scales.py0000644000175100001770000000242514611211152021024 0ustar00runnerdocker# Tutorial 8: Scales # By default, Player Objects use the C Major scale. # These can be changed by using the keyword arguments 'scale' and 'root'. # Scales can be defined as an array of semitones, such that the Major scale is [0,2,4,5,7,9,11] # or one of the predefined scales from the Scale module, e.g. Scale.minor. # Root refers to the tonic of the scale; 0 being C, 1 is C#, 2 is D and so on. # The default scale can be changed such that any Player not using a specific scale will be updated. # This is done using the syntax below (each line is technically equivalent): Scale.default.set("major") Scale.default.set(Scale.major) Scale.default.set([0,2,4,5,7,9,11]) # Or the same thing, but minor: Scale.default.set("minor") Scale.default.set(Scale.minor) Scale.default.set([0,2,3,5,7,10]) # To save some time you can also do Scale.default = "minor" #This is the same for the root: Root.default.set(1) Root.default.set("C#") # Or: Root.default.set(2) Root.default.set("D") # To see a list of all scales, use print(Scale.names()) # You can change the scale used by a player using the 'scale' keyword p1 >> pads([0,1,2], scale=Scale.minor) # Similarly, you can change the root note players using the root keyword # and the Root.default object p1 >> pads([0,1,2], scale=Scale.minor, root=2) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/09_groups.py0000644000175100001770000000321014611211152021063 0ustar00runnerdocker# Tutorial 9: Groups # Attributes of players, such as degree or scale, can also be changed by directly assigning values to it such that p1 >> pads([0,2,4,2], scale=Scale.majorPentatonic) # is equivalent to p1 >> pads() p1.degree = [0,2,4,2] p1.scale = Scale.majorPentatonic # This is useful if you want to assign the same values to multiple Player Object simultaneously, like so: p1 >> pads([0,2,4,2]) p2 >> pads([2,1,0,4]) p3 >> pads([2,3]) p1.dur=p2.dur=p3.dur=[1,1/2,1/4,1/4] p1.stop() p2.stop() p3.stop() # You can reference all the members with similar names p_all.dur = [1/2,1/4] # Run this while p1, p2, etc are playing! # or p_all.amplify = 1 # Or... p_all.stop() # Or... p_all.solo() # To reduce the amount of typing, Player Objects can be grouped together and their attributes modified in a simpler way: p1 >> pads([0,2,4,2]) p2 >> pads([2,1,0,4]) p3 >> pads([2,3]) g1 = Group(p1, p2, p3) g1.dur=[1,1/2,1/4,1/4] # You can group will _all groups g1 = Group(p_all, d_all, b1, b2) # Set the volume on for 4 beats, then off for 4 # This overrides existing amplitudes set in the player object g1.amp=var([1,0],4) g1.stop() # You can use functions to group things together. To execute use CTRL+Return, not ALT+Return. def tune(): b1 >> bass([0,3], dur=4) p1 >> pluck([0,4], dur=1/2) d1 >> play("x--x--x-") tune() # or schedule the clock to call other grouped functions def verse(): b1 >> bass([0,3], dur=4) p1 >> pluck([0,4], dur=1/2) d1 >> play("x--x--x-") Clock.future(16, chorus) def chorus(): b1 >> bass([0,4,5,3], dur=4) p1 >> pluck([0,4,7,9], dur=1/4) d1 >> play("x-o-") Clock.future(16, verse) verse() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/10_using_vars.py0000644000175100001770000001020014611211152021711 0ustar00runnerdocker# Tutorial 10: Using Vars # A TimeVar is an abbreviation of "Time Dependent Variable" and is a key feature of FoxDot. # A TimeVar has a series of values that it changes between after a pre-defined number of beats # and is created using a var object with the syntax var([list_of_values],[list_of_durations]). # Generates the values: 0,0,0,0,3,3,3,3... a = var([0,3],4) # Duration can be single value print(int(Clock.now()), a) # 'a' initally has a value of 0 # >>> 0, 0 # The first value may differ... print(int(Clock.now()), a) # After 4 beats, the value changes to 3 # >>> 4, 3 print(int(Clock.now()), a) # After another 4 beats, the value changes to 0 # >>> 8, 0 # Duration can also be a list a = var([0,3],[4,2]) print(int(Clock.now()), a) # When a TimeVar is used in a mathematical operation, the values it affects also become TimeVars # that change state when the original TimeVar changes state – this can even be used with patterns: a = var([0,3], 4) print(int(Clock.now()), a + 5) # When beat is 0, a is 5 # >>> 5 print(int(Clock.now()), a + 5) # When beat is 4, a is 8 # >>> 8 b = PRange(4) + a print(int(Clock.now()), b) # After 8 beats, the value changes to 0 # >>> P[0, 1, 2, 3] print(int(Clock.now()), b) # After 12 beats, the value changes to 3 # >>> P[3, 4, 5, 6] # Use 'var' with your Player objects to create chord progressions. a = var([0,4,5,3], 4) b1 >> bass(a, dur=PDur(3,8)) p1 >> pads(a + (0,2), dur=PDur(7,16)) # You can add a 'var' to a Player object or a var. b1 >> bass(a, dur=PDur(3,8)) + var([0,1],[3,1]) b = a + var([0,10],8) print(int(Clock.now()), (a, b)) # Updating the values of one 'var' will update it everywhere else a.update([1,4], 8) print(int(Clock.now()), (a, b)) # Vars can be named ... var.chords = var([0,4,5,4],4) # And used later b1 >> pluck(var.chords) # Any players using the named var will be updated var.chords = var([0,1,5,3],4) # You can also use a 'linvar' that changes its values gradually over time # Change the value from 0 to 1 over 16 beats c = linvar([0,1],16) # Run this multiple times to see the changes happening print(int(Clock.now()), c) # Change the amp based off that linvar p1 >> pads(a, amp=c) # a 'Pvar' is a 'var' that can store patterns (as opposed to say, integers) d = Pvar([P[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], P[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]], 8) print(int(Clock.now()), d) p1 >> pads(a, amp=c, dur=1/4) + d # Change the scale every 16 beats Scale.default = Pvar([Scale.major, Scale.minor],16) # You even set the value to last forever once it is reached using a special value called "inf" x = var([0, 1, 2, 3], [4, 4, 4, inf]) print(x) # Keep pressing - it will eventually stop at 3 ###################### # Other types of "var" # There are several sub-classes of "var" that return values between # the numbers specified. For example a "linvar" gradually change # values in a linear fashion: print(linvar([0,1],8)) # keep running to see the value change between 0 and 1 # Example: increase the high-pass filter cutoff over 32 beats p1 >> play("x-o-", hpf=linvar([0,4000],[32,0])) # Other types include "sinvar" and "expvar" print("Linear:", linvar([0, 1], 8)) print("Sinusoidal:", sinvar([0, 1], 8)) print("Exponential:", expvar([0, 1], 8)) ################# # Pattern TimeVar # Sometimes we might want to store whole patterns within a var but # if we try to do so, they are automatically laced: pattern1 = P[0, 1, 2, 3] pattern2 = P[4, 5, 6, 7] print(var([pattern1, pattern2], 4)) # To store whole patterns, you need to use a "Pvar" which does # not lace the values, but stores the patterns instead print(Pvar([pattern1, pattern2], 4)) p1 >> pluck(Pvar([pattern1, pattern2], 4), dur=1/4) ########################### # Offsetting the start time # Another useful trick is offsetting the start time for the var. By # default it is when the Clock time is 0 but you can specify a different # value using the "start" keyword print(linvar([0, 1], 8)) print(linvar([0, 1], 8, start=2)) # This can be combined with Clock.mod() to start a ramp at the start of the# # next 32 beat cycle: d1 >> play("x-o-", hpf=linvar([0,4000],[32,inf], start=Clock.mod(32))) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/11_playing_custom_samples.py0000644000175100001770000000337714611211152024334 0ustar00runnerdocker# Tutorial 11: Playing Custom Samples # You can use your own samples by simply dropping audio files into the existing FoxDot sample directories. # These are found in the 'snd' directory in the root of the FoxDot installation # (e.g., 'C:\Python27\Lib\site-packages\FoxDot\snd'). # You saw earlier how to work with samples using play(). You can also play samples with loop(). s1 >> loop('foxdot') # You may notice that this is just playing the first part of the sample over and over again. # You can tweak the behavior with many of the arguments we've seen thus far for controlling other synths. dur is a good place to start. s1 >> loop('foxdot', dur=4) # If you have a folder full of samples that you would like to use in FoxDot, you can call loop() with the full path to the sample. s1 >> loop('/path/to/samples/quack.wav') # If you give loop the path to a folder, it will play the first sample it finds. You can change which sample it plays with the sample= arg. # Play the first sample in my collection s1 >> loop('/path/to/samples') # Play the second sample in my collection s1 >> loop('/path/to/samples', sample=1) # If you're going to be using a lot of samples from a folder, you can add it to the sample search path. FoxDot will look under all its search paths for a matching sample when you give it a name. Samples.addPath('/path/to/samples') s1 >> loop('quack') # Once you have a search path, you can use pattern matching to search for samples. # Play the 3rd sample under the 'snare' dir s1 >> loop('snare/*', sample=2) # You can use * in directory names too s1 >> loop('*_120bpm/drum*/kick*') # ** means "all recursive subdirectories". This will play the first sample # nested under 'percussion' (e.g. 'percussion/kicks/classic/808.wav') s1 >> loop('percussion/**/*') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/12_synthdefs.py0000644000175100001770000000404514611211152021554 0ustar00runnerdocker# Tutoral 12: SynthDefs # FoxDot creates music by giving player objects a 'digital instrument' # to play, which are called 'SynthDefs'. You can see the list of pre-installed # 'Synths' by executing print(SynthDefs) # Each one of these represents a `SynthDef` *object*. These objects are then # given to Players to play - like giving an instrument to someone in your # orchestra. # Writing your own Synth Definitions # This is a bit more advanced, but if you have already written SynthDefs in # Supercollider then you might feel at home. If not, come back to this section # later. # FoxDot can access any SynthDef stored on the SuperCollider server, # but it needs to know it's there. If you have already written a SynthDef # in SuperCollider and named it \mySynth then you just create a SynthDef # instance using FoxDot like so: mySynth = SynthDef("mySynth") # Using the same variable name in FoxDot as in SuperCollider for your SynthDef # is a good idea to avoid confusion. If you want to write (or edit) your own # SynthDef during run-time in FoxDot you can use a SuperCollider API by # importing the SCLang module. All FoxDot SynthDef objects inherit the # base-class behaviour, such as low- and high-pass filters and vibrato, # but these can be overridden or updated easily. If you want to know more # about digital sound processing and SynthDef creation, check out the # SuperCollider documentation. Below is an example of creating one in FoxDot: # Import module for writing SCLang code from Python from SCLang import * # Create a SynthDef named 'example' (using the same variable name as the SynthDef name is a good idea) example = SynthDef("example") # Create the oscillator (osc) using a sine wave example.osc = SinOsc.ar(ex.freq) # And give it a percussive sound envelope (env) example.env = Env.perc() # Finally, store it! example.add() # How to create a SynthDef with SynthDef("pads") as pads: pads.osc = SinOsc.ar(pads.freq) pads.env = Env.perc() # Equivalent to pads = SynthDef("pads") pads.osc = SinOsc.ar(pads.freq) pads.env = Env.perc() pads.add() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/13_advanced_clock.py0000644000175100001770000000234614611211152022470 0ustar00runnerdocker# Tutorial 13: Advanced Clock # To see what is scheduled to be played. print(Clock) # To see what the latency is print(Clock.latency) # The clock can schedule anything with a __call__ method using # It takes an absolute time clue to schedule a functions # Clock.schedule needs to know the beat to call something on Clock.schedule() # raises TypeError # Schedule an event after a certain durations # Clock.future needs to know how many beats ahead to call something Clock.future() # raises TypeError # These are equivalent Clock.schedule(lambda: print("hello"), Clock.now() + 4) Clock.future(4, lambda: print("hello")) # To schedule something else Clock.schedule(lambda: print("hello ")) # We can call something every n beats Clock.every(4, lambda: print("hello")) # Get the current clock and add 2. Useful for scheduling. print(Clock.now() + 2) # Issue command on the next bar nextBar(Clock.clear) # With a decorator @nextBar def change(): Root.default=4 Scale.default="minor" # etc etc # You can create your own function, and decorate it, to be able # to use it in an .every on a Player object @PlayerMethod def test(self): print(self.degree) p1 >> pluck([0,4]).every(3, "test") # And cancel it with p1.never("test") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/14_player_attributes_reference.py0000644000175100001770000001601614611211152025330 0ustar00runnerdocker# Tutorial 14: Player Attributes Reference # --- TODO: this needs updating # To see all attributes: print(Player.get_attributes()) # You can see what effects are available by evaluating print(FxList) # Let's use the high pass filter for an example. You can see it's described # like so: # "" # Each effect has a "master" argument and then child arguments. Here the # master argument is "hpf" (short for high pass filter) and the child argument # is "hpr" (short for high pass resonance). The effect is only added when the # master argument is non-zero: d1 >> dirt([0,4,2,1], dur=1/2, hpf=4000) # This sets the high pass filter to 4000 Hz so only frequences in the audio # signal *above* that are actually heard. Let's change the resonance value. It's # default value is 1, so let's make it smaller d1 >> dirt([0,4,2,1], dur=1/2, hpf=4000, hpr=0.3) # Notice a difference? We can use patterns / vars in our effects to make them # change over time: d1 >> dirt([0,4,2,1], dur=1/2, hpf=linvar([0,4000],8), hpr=P[1,1,0.3].stretch(8)) #################### # Reference #################### #################### # amp - Amplitude (defaults to 1) # Sets the volume of the note/pattern d1 >> play("*", dur=1/2, amp=1) # Half Volume d1 >> play("*", dur=1/2, amp=.5) # Creating a pattern with amp d1 >> play("*", dur=1/2, amp=[1,0,1,1,0]) #################### # amplify - Changes amp, by multiplying agasint the existing value (instead of overwritting) # Creating a pattern with amp d1 >> play("*", dur=1/2, amp=[1,0,1,1,0]) d1 >> play("*", dur=1/2, amplify=[.5,1,0]) # Set up a "drop" in the music (Plays at full volume for 28, then 0 for 4) p1 >> blip([0,1,2,3], amplify=var([1,0],[28,4])) #################### # bend #################### # benddelay - See bend #################### # bits # The bit depth, in number of bits, that the signal is reduced to; # this is a value between 1 and 24 where other values are ignored. # Use crush to set the amount of reduction to the bitrate (defaults to 8) #################### # bitcrush - See bits #################### # blur #################### # bpf - Band Pass Filter #################### # bpnoise - See bpf #################### # bpr - See bpf #################### # bpm #################### # buf #################### # channel #################### # chop # 'Chops' the signal into chunks using a low frequency pulse wave over the sustain of a note. #################### # coarse #################### # comb delay - See echo #################### # crush #################### # cut # Cuts a duration p1 >> pluck(P[:8], dur=1/2, cut=1/8) p1 >> pluck(P[:8], dur=1/2, cut=1/4) p1 >> pluck(P[:8], dur=1/2, cut=1/2) #################### # cutoff #################### # decay - See echo #################### # degree - The degree of the note, or pitch, can be specified by keyword (also the first positional) p1 >> blip(degree=[0,1,2,3]) # Which is the same as: p1 >> blip([0,1,2,3]) # Only plays the "root" note of the chord b1 >> bass(p1.degree[0]) #################### # delay - A duration of time to wait before sending the information to SuperCollider (defaults to 0) # Delays every 3 note by .1 p1 >> blip([0,1,2,3], delay=[0,0,0.1]) # Delays every 3 note by .5 p1 >> blip([0,1,2,3], delay=[0,0,0.5]) # Plays the note once for each different delays p1 >> blip([0,1,2,3], delay=(0,0.1)) p1 >> blip([0,1,2,3], delay=(0,0.25)) p1 >> blip([0,1,2,3], delay=(0,.1,.2,.3)) #################### # dist #################### # dur - Durations (defaults to 1 and 1/2 for the Sample Player) #################### # echo # Title keyword: echo, Attribute keyword(s): decay # Sets the decay time for any echo effect in beats, works best on Sample Player (defaults to 0) # Multiplied against the sustain value d1 >> play("x-o-", echo=0.1) d1 >> play("x-o-", echo=0.5) p1 >> pluck(P[:8], echo=.25) p1 >> pluck(P[:8], echo=.5) p1 >> pluck(P[:8], echo=.5, decay=.5) #################### # env #################### # fmod #################### # formant #################### # freq #################### # hpf - High Pass Filter # Filters out all the frequencies below given value, removing lower freqencies # 4000 hertz p1 >> pluck(P[:8], dur=1/2, hpf=4000) # HPF is 0 for 4 beats, then 4000 for 4 beats p1 >> pluck(P[:8], dur=1/2, hpf=var([0,4000],[4,4])) # Linear change on hpf from 0 take 4 beats to get to 4000, 4 beats back to 0 p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[4,4])) # Linear change on hpf from 0 take 8 beats to get to 4000, then reset back to 0 p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[8,0])) # With resonance change (default is 1) p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[8,0]), hpr=.5) # With resonance change as a linvar p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[8,0]), hpr=linvar([0.1,1],12)) #################### # hpr - See hpf #################### # lpf - Low Pass Filter # Filters out all the frequencies above given value, removing higher freqencies # 4000 hertz p1 >> pluck(P[:8], dur=1/2, lpf=400) # With resonance change as a linvar p1 >> pluck(P[:8], dur=1/2, lpf=linvar([500,4000],[8,0]), lpr=linvar([0.1,1],12)) #################### # lpr - See lpf #################### # midinote #################### # pan # Panning, where -1 is far left, 1 is far right (defaults to 0) #################### # pitch - See degree #################### # pshift #################### # oct #################### # rate # Variable keyword used for misc. changes to a signal. E.g. Playback rate of the Sample Player (defaults to 1) #################### # room # Title keyword: room, Attribute keyword(s): mix # The room argument specifies the size of the room d1 >> play("x-o-", room=0.5) # Mix is the dry/wet mix of reverb or how much the reverb is mixed with the source. 1 is all reverb, 0 is no reverb at all. (Default 0.1) d1 >> play("x-o-", room=0.5, mix=.5) #################### # Reveb # See Room #################### # sample # Special keyword for Sample Players; selects another audio file from the bank of samples for a sample character. #################### # scale #################### # shape #################### # slide - Slide To # Slides' the frequency value of a signal to freq * (slide+1) over the duration of a note (defaults to 0) p1 >> pluck(P[:8], dur=1/2, slide=1) p1 >> pluck(P[:8], dur=1/2, slide=12) p1 >> pluck(P[:8], dur=1/2, slide=var([0,-1],[12,4])) #################### # slidedelay #################### # slidefrom #################### # slider #################### # spread #################### # spin #################### # striate #################### # stutter #################### # sus - Sustain (defaults to `dur`) #################### # swell #################### # vib - Vibrato # Vibrato - Title keyword: vib, Attribute keyword(s): Vibrato (defaults to 0) p1 >> pluck(P[:8], dur=1/2, vib=12) # With child attribute, vibdepth (default 0.2) p1 >> pluck(P[:8], dur=1/2, vib=12, vibdepth=0.5) #################### # vibdepth - See vib ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/demo/15_pattern_generator_reference.py0000644000175100001770000001046114611211152025310 0ustar00runnerdocker# Tutorial 15: Patterns Generators Reference # There are several other Pattern classes in FoxDot that help you generate arrays of numbers but also behave # in the same way as the base Pattern. To see what Patterns exist and have a go at using them, execute print(classes(Patterns.Sequences)) #################### # PEuclid # PEuclid(n, k) # Returns the Euclidean rhythm which spreads 'n' pulses over 'k' steps as evenly as possible. # 3 pulses over 8 steps print(PEuclid(3, 8)) #################### # PDur # PDur(n, k, start=0, dur=0.25) # Returns the actual durations based on Euclidean rhythms (see PEuclid) where dur is the length of each step. # Spreads 'n' pulses over 'k' steps as evenly as possible print(PDur(3,8)) # P[0.75, 0.75, 0.5] print(PDur(5,8)) # Gives a list of 3 dur, appened with a list of 5 dur print(PDur([3,5],8)) d1 >> play("x", dur=PDur(5,8)) #################### # PIndex # Returns the index being accessed print(PIndex()) print(PIndex()*4) #################### # PSine # PSine(n=16) # Returns values of one cycle of sine wave split into 'n' parts # Split into 5 parts print(PSine(5)) # Split into 10 print(PSine(10)) #################### # PTri # PTri(start, stop=None, step=None) # Returns a Pattern equivalent to `Pattern(range(start, stop, step)) with its reversed form appended. # Think of it like a "Tri"angle. # Up to 5 then down to 1 print(PTri(5)) # Up to 8 then down to 1 print(PTri(8)) # From 3 to 10, then down to 4 print(PTri(3,10)) # From 3 to 30, by 2, then down to 4 print(PTri(3,20,2)) # Up to 4, then down to 1, then up to 8, then down to 1 print(PTri([4,8])) p1 >> pluck(PTri(5), scale=Scale.default.pentatonic) # Same as p1 >> pluck(PRange(5) | PRange(5,0,-1), scale=Scale.default.pentatonic) #################### # PRand # PRand(start, stop=None) # Returns a random integer between start and stop. # Returns a random integer between 0 and start. print(PRand(8)[:5]) # Returns a random integer between start and stop. print(PRand(8,16)[:5]) # If start is a container-type it returns a random item for that container. print(PRand([1,2,3])[:5]) # You can supply a seed print(PRand([1,2,3], seed=5)[:5]) # Keeps generating random tune p1 >> pluck(PRand(8)) # Creates a random list, and iterates over that same list p1 >> pluck(PRand(8)[:3]) #################### # PRhythm # PRhythm takes a list of single durations and tuples that contain values that can be supplied to the `PDur` # The following plays the hi hat with a Euclidean Rhythm of 3 pulses in 8 steps d1 >> play("x-o-", dur=PRhythm([2,(3,8)])) print(PRhythm([2,(3,8)])) #################### # PSum # PSum(n, total) # Returns a Pattern of length 'n' that sums to equal 'total' # Returns a pattern of length 2, with elements summed up to 8 print(PSum(3,8)) # Returns a pattern of length 5, with elements summed up to 4 print(PSum(5,4)) #################### # PStep # PStep(n, value, default=0) # Returns a Pattern that every n-term is 'value' otherwise 'default' # Every 4, make it 1, otherwise default to 0 print(PStep(4,1)) # Every 8, make it 6, otherwise, 4 print(PStep(8,6,4)) # Every 5, make it 2, otherwise, 1 print(PStep(5,2,1)) #################### # PWalk # PWalk(max=7, step=1, start=0) # By default, returns a pattern with each element randomly 1 higher or lower than the previous print(PWalk()[:16]) # Changing step print(PWalk(step=2)[:16]) # With max print(PWalk(max=2)[:16]) # Start at a non-zero number print(PWalk(start=6)[:16]) #################### # PWhite # PWhite(lo=0, hi=1) # Returns random floating point values between 'lo' and 'hi' # Lo defaults to 0, hi defaults to 1 print(PWhite()[:8]) # Returns random numbers between 1 and 5 print(PWhite(1,5)[:8]) #################### # Custom Generator Patterns # Custom generator patterns can be made by subclassing GeneratorPattern # and overriding `GeneratorPattern.func` class CustomGeneratorPattern(GeneratorPattern): def func(self, index): return int(index / 4) print(CustomGeneratorPattern()[:10]) # This can be done more consisely using `GeneratorPattern.from_func`, # passing in a function which takes an index and returns some pattern item. def some_func(index): return int(index / 4) print(GeneratorPattern.from_func(some_func)[:10]) # We can use lambdas too print(GeneratorPattern.from_func(lambda index: int(index / 4))[:10]) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5795405 renardo_lib-0.9.12/renardo_lib/osc/0000755000175100001770000000000014611211157016533 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/Buffers.scd0000644000175100001770000007470114611211152020626 0ustar00runnerdockerBuffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/lower/gb_hihat 0.wav", bufnum:1); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/lower/gb_hihat 1.wav", bufnum:2); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/lower/gb_hihat 3.wav", bufnum:3); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/lower/gb_hihat 4.wav", bufnum:4); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/lower/dot (1).wav", bufnum:5); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/lower/dot (2).wav", bufnum:6); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/lower/dot (3).wav", bufnum:7); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/lower/dot (4).wav", bufnum:8); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/c/lower/voice_1.wav", bufnum:9); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/c/lower/voice_2.wav", bufnum:10); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/c/lower/voice_3.wav", bufnum:11); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/d/lower/alt_rimshot_00.wav", bufnum:12); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/d/lower/rimshot_0.wav", bufnum:13); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/d/lower/rimshot_1.wav", bufnum:14); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/d/lower/rimshot_2.wav", bufnum:15); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/e/lower/cb0.wav", bufnum:16); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/e/lower/cb1.wav", bufnum:17); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/lower/Perc02.wav", bufnum:18); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/lower/Perc03.wav", bufnum:19); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/lower/Perc04.wav", bufnum:20); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/lower/Perc05.wav", bufnum:21); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/lower/Perc11.wav", bufnum:22); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/g/lower/om0.wav", bufnum:23); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/g/lower/om1.wav", bufnum:24); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/g/lower/om2.wav", bufnum:25); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/lower/snap_.wav", bufnum:26); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/lower/snap_0.wav", bufnum:27); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/lower/snap_1.wav", bufnum:28); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/lower/snap_2.wav", bufnum:29); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/lower/snap_4.wav", bufnum:30); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/lower/0_jungle_snare.wav", bufnum:31); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/lower/1_jungle_snare.wav", bufnum:32); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/lower/2_jungle_snare.wav", bufnum:33); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/lower/3_jungle_snare.wav", bufnum:34); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/lower/4_jungle_snare.wav", bufnum:35); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/lower/5_jungle_snare.wav", bufnum:36); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/lower/44.wav", bufnum:37); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/lower/45.wav", bufnum:38); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/lower/46.wav", bufnum:39); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/lower/47.wav", bufnum:40); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/lower/48.wav", bufnum:41); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/lower/misc (1).wav", bufnum:42); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/lower/misc (2).wav", bufnum:43); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/lower/misc (3).wav", bufnum:44); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/lower/misc (4).wav", bufnum:45); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/lower/misc (5).wav", bufnum:46); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/lower/misc (6).wav", bufnum:47); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_0.wav", bufnum:48); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_1.wav", bufnum:49); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_2.wav", bufnum:50); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_3.wav", bufnum:51); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_4.wav", bufnum:52); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_5.wav", bufnum:53); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_6.wav", bufnum:54); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_7.wav", bufnum:55); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/lower/perc_8.wav", bufnum:56); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/lower/0_Tom.wav", bufnum:57); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/lower/1_Tom-Electro.wav", bufnum:58); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/lower/2_Tom-Distort.wav", bufnum:59); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/lower/3_Tom-909.wav", bufnum:60); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/lower/Closedhat02.wav", bufnum:61); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/lower/Closedhat04.wav", bufnum:62); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/lower/Closedhat05.wav", bufnum:63); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/lower/Closedhat06.wav", bufnum:64); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/lower/Closedhat08.wav", bufnum:65); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/lower/Closedhat10.wav", bufnum:66); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/lower/0_snare_drum.wav", bufnum:67); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/lower/1_snare_dru.wav", bufnum:68); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/lower/2_snare_drum.wav", bufnum:69); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/lower/3_snare_drum.wav", bufnum:70); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/lower/9_snare_drum.wav", bufnum:71); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/lower/07-tabla_re.wav", bufnum:72); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/lower/11-tabla_te1.wav", bufnum:73); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/lower/12-tabla_te2.wav", bufnum:74); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/lower/13-tabla_te_m.wav", bufnum:75); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/lower/14-tabla_te_ne.wav", bufnum:76); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/q/lower/113.wav", bufnum:77); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/q/lower/Apex & Motivation Synth 1.wav", bufnum:78); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/lower/00_metal.wav", bufnum:79); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/lower/0_metal.wav", bufnum:80); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/lower/1_metal.wav", bufnum:81); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/lower/2_metal.wav", bufnum:82); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/lower/0_shaker.wav", bufnum:83); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/lower/2_shaker.wav", bufnum:84); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/lower/3_shaker.wav", bufnum:85); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/lower/4_shaker.wav", bufnum:86); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/t/lower/alt_rimshot_0.wav", bufnum:87); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/t/lower/alt_rimshot_1.wav", bufnum:88); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/t/lower/alt_rimshot_2.wav", bufnum:89); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/lower/soft_snare_0.wav", bufnum:90); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/lower/soft_snare_1.wav", bufnum:91); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/lower/soft_snare_2.wav", bufnum:92); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/lower/soft_snare_3.wav", bufnum:93); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/lower/soft_snare_4.wav", bufnum:94); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/lower/0_bass_low.wav", bufnum:95); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/lower/1_bass_drum.wav", bufnum:96); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/lower/1_bass_drum_low.wav", bufnum:97); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/lower/1_bass_low.wav", bufnum:98); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/lower/6_bass_drum_lo.wav", bufnum:99); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/lower/9_bass_drum_lo.wav", bufnum:100); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/w/lower/w1.wav", bufnum:101); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/w/lower/w2.wav", bufnum:102); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/w/lower/w3.wav", bufnum:103); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/w/lower/w4.wav", bufnum:104); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/lower/0_kick_drum.wav", bufnum:105); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/lower/1_kick_drum.wav", bufnum:106); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/lower/2_kick_drum.wav", bufnum:107); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/lower/3_kick_drum.wav", bufnum:108); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/lower/4_kick_drum.wav", bufnum:109); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/lower/5_kick_drum.wav", bufnum:110); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/lower/can_0.wav", bufnum:111); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/lower/can_1.wav", bufnum:112); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/z/lower/0_scratch.wav", bufnum:113); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/z/lower/1_scratch.wav", bufnum:114); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/z/lower/2_scratch.wav", bufnum:115); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/z/lower/rewind-rewind.wav", bufnum:116); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/upper/0_gabba.wav", bufnum:117); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/upper/1_gabba.wav", bufnum:118); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/upper/gb_kick 1.wav", bufnum:119); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/upper/gb_kick 3.wav", bufnum:120); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/a/upper/gb_kick 4.wav", bufnum:121); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/upper/0.wav", bufnum:122); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/upper/56.wav", bufnum:123); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/b/upper/57.wav", bufnum:124); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/c/upper/0_Choral.wav", bufnum:125); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/c/upper/hit074.wav", bufnum:126); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/c/upper/hit085.wav", bufnum:127); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/d/upper/alt_snare_0.wav", bufnum:128); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/e/upper/E1.wav", bufnum:129); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/e/upper/E2.wav", bufnum:130); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/e/upper/E3.wav", bufnum:131); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/upper/Stab 7.wav", bufnum:132); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/upper/brand new.wav", bufnum:133); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/upper/flared funk1.wav", bufnum:134); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/f/upper/horn swipe.wav", bufnum:135); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/g/upper/0_Stab.wav", bufnum:136); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/g/upper/GHOST.wav", bufnum:137); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/upper/clap_0.wav", bufnum:138); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/h/upper/clap_1.wav", bufnum:139); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/upper/0_rock_snare.wav", bufnum:140); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/upper/1_rock_snare.wav", bufnum:141); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/upper/3_rock_snare.wav", bufnum:142); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/i/upper/4_rock_snare.wav", bufnum:143); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/upper/11.wav", bufnum:144); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/upper/145.wav", bufnum:145); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/upper/76.wav", bufnum:146); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/j/upper/81.wav", bufnum:147); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/upper/K1.wav", bufnum:148); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/upper/K2.wav", bufnum:149); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/k/upper/K3.wav", bufnum:150); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/upper/glitch_0.wav", bufnum:151); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/upper/glitch_1.wav", bufnum:152); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/upper/glitch_2.wav", bufnum:153); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/upper/glitch_3.wav", bufnum:154); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/upper/glitch_4.wav", bufnum:155); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/l/upper/glitch_40.wav", bufnum:156); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/upper/11_bass_low.wav", bufnum:157); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/upper/12_bass_low.wav", bufnum:158); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/m/upper/13_bass_low.wav", bufnum:159); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/upper/Openhat01.wav", bufnum:160); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/upper/Openhat03.wav", bufnum:161); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/upper/Openhat08.wav", bufnum:162); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/upper/Openhat09.wav", bufnum:163); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/upper/Openhat10.wav", bufnum:164); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/n/upper/noise_hat_open_0.wav", bufnum:165); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (1).wav", bufnum:166); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (10).wav", bufnum:167); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (2).wav", bufnum:168); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (3).wav", bufnum:169); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (4).wav", bufnum:170); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (5).wav", bufnum:171); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (6).wav", bufnum:172); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (7).wav", bufnum:173); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (8).wav", bufnum:174); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/o/upper/O (9).wav", bufnum:175); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/upper/08-tabla_tas1.wav", bufnum:176); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/upper/09-tabla_tas2.wav", bufnum:177); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/upper/10-tabla_tas3.wav", bufnum:178); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/upper/15-tabla_tun1.wav", bufnum:179); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/upper/16-tabla_tun2.wav", bufnum:180); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/p/upper/17-tabla_tun3.wav", bufnum:181); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/q/upper/G1.wav", bufnum:182); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/q/upper/G2.wav", bufnum:183); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/q/upper/G3.wav", bufnum:184); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/upper/0_metallic.wav", bufnum:185); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/upper/1_metallic.wav", bufnum:186); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/upper/2_metallic.wav", bufnum:187); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/upper/3_metallic.wav", bufnum:188); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/r/upper/4_metallic.wav", bufnum:189); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/upper/0_tamborine.wav", bufnum:190); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/upper/1_tamborine.wav", bufnum:191); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/s/upper/2_tamborine.wav", bufnum:192); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/t/upper/cowbell_0.wav", bufnum:193); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/t/upper/cowbell_1.wav", bufnum:194); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/t/upper/cowbell_2.wav", bufnum:195); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/upper/0_misc.wav", bufnum:196); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/upper/1_misc.wav", bufnum:197); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/upper/2_misc.wav", bufnum:198); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/upper/3_misc.wav", bufnum:199); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/u/upper/4_misc.wav", bufnum:200); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (1).wav", bufnum:201); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (10).wav", bufnum:202); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (11).wav", bufnum:203); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (2).wav", bufnum:204); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (3).wav", bufnum:205); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (4).wav", bufnum:206); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (5).wav", bufnum:207); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (6).wav", bufnum:208); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (7).wav", bufnum:209); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (8).wav", bufnum:210); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/v/upper/V (9).wav", bufnum:211); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/w/upper/0_distortion.wav", bufnum:212); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/w/upper/1_distortion.wav", bufnum:213); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/upper/0_bass_drum.wav", bufnum:214); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/upper/1_kick_drum.wav", bufnum:215); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/x/upper/2_kick_drum_lo.wav", bufnum:216); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/upper/bleep_0.wav", bufnum:217); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/upper/bleep_1.wav", bufnum:218); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/upper/bleep_2.wav", bufnum:219); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/upper/bleep_3.wav", bufnum:220); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/y/upper/bleep_4.wav", bufnum:221); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/z/upper/0_beep.wav", bufnum:222); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/z/upper/1_beep.wav", bufnum:223); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/ampersand/2_triangle.wav", bufnum:224); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/asterix/cp0.wav", bufnum:225); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/asterix/cp1.wav", bufnum:226); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/asterix/cp2.wav", bufnum:227); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/at/gb_noise (1).wav", bufnum:228); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/at/gb_noise (2).wav", bufnum:229); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/at/gb_noise (3).wav", bufnum:230); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/at/gb_noise (4).wav", bufnum:231); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/at/gb_noise (5).wav", bufnum:232); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/at/perc (5).wav", bufnum:233); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/bar/0.wav", bufnum:234); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/caret/0.wav", bufnum:235); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/caret/1.wav", bufnum:236); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/caret/2.wav", bufnum:237); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/caret/3.wav", bufnum:238); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/caret/4.wav", bufnum:239); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/colon/0.wav", bufnum:240); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_0.wav", bufnum:241); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_1.wav", bufnum:242); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_10.wav", bufnum:243); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_11.wav", bufnum:244); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_12.wav", bufnum:245); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_13.wav", bufnum:246); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_14.wav", bufnum:247); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_15.wav", bufnum:248); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_16.wav", bufnum:249); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_17.wav", bufnum:250); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_18.wav", bufnum:251); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_2.wav", bufnum:252); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_3.wav", bufnum:253); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_4.wav", bufnum:254); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_5.wav", bufnum:255); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_6.wav", bufnum:256); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_7.wav", bufnum:257); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/dollar/ikea_9.wav", bufnum:258); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/equals/0_hihat_open.wav", bufnum:259); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/equals/1_hihat_open.wav", bufnum:260); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/equals/3_hihat_open.wav", bufnum:261); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/equals/5_hihat_open.wav", bufnum:262); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/equals/9_hihat_open.wav", bufnum:263); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/exclamation/yeah_0.wav", bufnum:264); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/exclamation/yeah_1.wav", bufnum:265); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/forwardslash/0_cymrev.wav", bufnum:266); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/forwardslash/1_rev.wav", bufnum:267); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/greaterthan/0.wav", bufnum:268); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hash/0_crash.wav", bufnum:269); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hash/1_crash.wav", bufnum:270); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hash/2_crash.wav", bufnum:271); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hyphen/0_hihat_closed.wav", bufnum:272); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hyphen/1_hihat_closed.wav", bufnum:273); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hyphen/2_hihat_closed.wav", bufnum:274); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hyphen/3_hihat_closed.wav", bufnum:275); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hyphen/4_hihat_closed.wav", bufnum:276); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/hyphen/9_hihat_closed.wav", bufnum:277); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/lessthan/0.wav", bufnum:278); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/percent/noise_0.wav", bufnum:279); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/percent/noise_1.wav", bufnum:280); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/percent/noise_2.wav", bufnum:281); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/percent/noise_3.wav", bufnum:282); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/percent/noise_4.wav", bufnum:283); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/plus/beep (1).wav", bufnum:284); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/plus/beep (2).wav", bufnum:285); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/plus/beep (3).wav", bufnum:286); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/plus/beep (4).wav", bufnum:287); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/question/0.wav", bufnum:288); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/tilde/0_ride.wav", bufnum:289); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/tilde/1_ride.wav", bufnum:290); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/backslash/0_lazer.wav", bufnum:291); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/backslash/1_lazer.wav", bufnum:292); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/backslash/2_lazer.wav", bufnum:293); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/1/one1.wav", bufnum:294); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/1/one2.wav", bufnum:295); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/2/two1.wav", bufnum:296); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/2/two2.wav", bufnum:297); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/3/three1.wav", bufnum:298); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/3/three2.wav", bufnum:299); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/4/four1.wav", bufnum:300); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_/4/four2.wav", bufnum:301); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/afro105.wav", bufnum:302); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/break170.wav", bufnum:303); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/cowbells110.wav", bufnum:304); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/dirty120.wav", bufnum:305); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/drums130.wav", bufnum:306); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/foxdot.wav", bufnum:307); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/robot110.wav", bufnum:308); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/techno130.wav", bufnum:309); Buffer.read(s, "C:/Users/Ryan/Documents/GitHub/FoxDot/FoxDot/snd/_loop_/thomas99.wav", bufnum:310); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/Info.scd0000644000175100001770000000112314611211152020111 0ustar00runnerdockerOSCFunc( { arg msg, time, addr, port; addr.sendMsg("/foxdot/info", Server.default.sampleRate, Server.default.actualSampleRate, Server.default.numSynths, Server.default.numGroups, Server.default.options.numAudioBusChannels, Server.default.options.numControlBusChannels, Server.default.options.numInputBusChannels, Server.default.options.numOutputBusChannels, Server.default.options.numBuffers, Server.default.options.maxNodes, Server.default.options.maxSynthDefs, ); }, '/foxdot/info' ); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/OscFunc.scd0000644000175100001770000000044214611211152020561 0ustar00runnerdocker( OSCFunc( { arg msg, time, addr, port; var fn; // Get local filename fn = msg[1].asString; // Print a message to the user ("Loading SynthDef from" + fn).postln; // Add SynthDef to file fn = File(fn, "r"); fn.readAllString.interpret; fn.close; }, 'foxdot' ); )././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/Record.scd0000644000175100001770000000051214611211152020435 0ustar00runnerdocker( OSCFunc( { arg msg, time, addr, port; var flag, path; // Get filename flag = msg[1]; path = msg[2].asString; // Print a message to the user ("Started recording to" + path).postln; // Record or stop / recording if (flag==1, {s.record(path)}, {s.stopRecording()}, ); }, 'foxdot-record' ); ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5915406 renardo_lib-0.9.12/renardo_lib/osc/sceffects/0000755000175100001770000000000014611211157020500 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/DFM1.scd0000644000175100001770000000022114611211152021650 0ustar00runnerdockerSynthDef.new(\DFM1, {|bus, dfm, dfmr, dfmd| var osc; osc = In.ar(bus, 2); osc = DFM1.ar(osc, dfm, dfmr, dfmd,0.0); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/Equalizer.scd0000644000175100001770000000052014611211152023124 0ustar00runnerdockerSynthDef.new(\Equalizer, { |bus, midfreq, mid, midq, lowfreq, low, highfreq, high| var osc; osc = In.ar(bus, 2); osc = BLowShelf.ar(osc, freq: lowfreq, db: low.ampdb); osc = BPeakEQ.ar(osc, freq: midfreq, rq: midq.reciprocal, db: mid.ampdb); osc = BHiShelf.ar(osc, freq: highfreq, db: high.ampdb); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/FrequencyModulationPulse.scd0000644000175100001770000000027514611211152026200 0ustar00runnerdockerSynthDef.new(\FrequencyModulationPulse, { |bus, fm_pulse, fm_pulse_i| var osc; osc = In.kr(bus, 1); osc = osc + (fm_pulse_i * Pulse.kr(osc * fm_pulse)); ReplaceOut.kr(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/FrequencyModulationSaw.scd0000644000175100001770000000026114611211152025635 0ustar00runnerdockerSynthDef.new(\FrequencyModulationSaw, { |bus, fm_saw, fm_saw_i| var osc; osc = In.kr(bus, 1); osc = osc + (fm_saw_i * Saw.kr(osc * fm_saw)); ReplaceOut.kr(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/FrequencyModulationSine.scd0000644000175100001770000000026514611211152026005 0ustar00runnerdockerSynthDef.new(\FrequencyModulationSine, { |bus, fm_sin, fm_sin_i| var osc; osc = In.kr(bus, 1); osc = osc + (fm_sin_i * SinOsc.kr(osc * fm_sin)); ReplaceOut.kr(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/H_Equalizer.scd0000644000175100001770000000026214611211152023376 0ustar00runnerdockerSynthDef.new(\H_Equalizer, { |bus, high, highfreq| var osc; osc = In.ar(bus, 2); osc = BHiShelf.ar(osc, freq: highfreq, db: abs(high).ampdb); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/L_Equalizer.scd0000644000175100001770000000025714611211152023406 0ustar00runnerdockerSynthDef.new(\L_Equalizer, { |bus, low, lowfreq| var osc; osc = In.ar(bus, 2); osc = BLowShelf.ar(osc, freq: lowfreq, db: abs(low).ampdb); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/M_Equalizer.scd0000644000175100001770000000031014611211152023375 0ustar00runnerdockerSynthDef.new(\M_Equalizer, { |bus, mid, midfreq, midq| var osc; osc = In.ar(bus, 2); osc = BPeakEQ.ar(osc, freq: midfreq, rq: midq.reciprocal, db: abs(mid).ampdb); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/MoogFF.scd0000644000175100001770000000020714611211152022302 0ustar00runnerdockerSynthDef.new(\MoogFF, {|bus, mpf, mpr| var osc; osc = In.ar(bus, 2); osc = MoogFF.ar(osc, mpf, mpr,0,1); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/Ringmod.scd0000644000175100001770000000026614611211152022571 0ustar00runnerdockerSynthDef.new(\Ringmod, { |bus, ringzfreq, ringz| var osc; osc = In.ar(bus, 2); osc = Ringz.ar(osc, freq: ringzfreq, decaytime: ringz, mul: 0.05); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/SLPF.scd0000644000175100001770000000032314611211152021730 0ustar00runnerdockerSynthDef.new(\SLPF, {|bus, spf, spr, spfslide, spfend| var osc,spfenv; osc = In.ar(bus, 2); spfenv = EnvGen.ar(Env.new([spf, spfend], [spfslide])); osc = RLPF.ar(osc, spfenv, spr); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/bandPassFilter.scd0000644000175100001770000000044114611211152024066 0ustar00runnerdockerSynthDef.new(\bandPassFilter, {|bus, bpf, bpr, bpnoise, sus| var osc; osc = In.ar(bus, 2); bpnoise = bpnoise / sus; bpf = LFNoise1.kr(bpnoise).exprange(bpf * 0.5, bpf * 2); bpr = LFNoise1.kr(bpnoise).exprange(bpr * 0.5, bpr * 2); osc = BPF.ar(osc, bpf, bpr); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/bitcrush.scd0000644000175100001770000000034414611211152023012 0ustar00runnerdockerSynthDef.new(\bitcrush, { |bus, bits, sus, amp, crush| var osc; osc = In.ar(bus, 2); osc = Decimator.ar(osc, rate: 44100/crush, bits: bits); osc = osc * Line.ar(amp * 0.85, 0.0001, sus * 2); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/chop.scd0000644000175100001770000000065514611211152022125 0ustar00runnerdockerSynthDef.new(\chop, {|bus, chop, sus, chopmix, chopwave, chopi| var osc; osc = In.ar(bus, 2); osc = LinXFade2.ar(osc * SelectX.kr(chopwave, [LFPulse.kr(chop / sus, iphase:chopi, add: 0.01), LFTri.kr(chop / sus, iphase:chopi, add: 0.01), LFSaw.kr(chop / sus, iphase:chopi, add: 0.01), FSinOsc.kr(chop / sus, iphase:chopi, add: 0.01), LFPar.kr(chop / sus, iphase:chopi, add: 0.01)]), osc, 1-chopmix); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/chorus.scd0000644000175100001770000000123114611211152022466 0ustar00runnerdockerSynthDef.new(\chorus, {|bus, chorus, chorusrate| var osc,lfos,numDelays = 4,chrate,maxDelayTime,minDelayTime; osc = In.ar(bus, 2); chrate = Select.kr(chorusrate > 0.5, [LinExp.kr(chorusrate, 0.0, 0.5, 0.025, 0.125),LinExp.kr(chorusrate, 0.5, 1.0, 0.125, 2)]); maxDelayTime = LinLin.kr(chorus, 0.0, 1.0, 0.016, 0.052); minDelayTime = LinLin.kr(chorus, 0.0, 1.0, 0.012, 0.022); osc = osc * numDelays.reciprocal; lfos = Array.fill(numDelays, {|i| LFPar.kr(chrate * {rrand(0.95, 1.05)},0.9 * i,(maxDelayTime - minDelayTime) * 0.5,(maxDelayTime + minDelayTime) * 0.5,)}); osc = DelayC.ar(osc, (maxDelayTime * 2), lfos).sum; osc = Mix(osc); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/coarse.scd0000644000175100001770000000021414611211152022437 0ustar00runnerdockerSynthDef.new(\coarse, {|bus, coarse, sus| var osc; osc = In.kr(bus, 1); osc = osc * LFPulse.ar(coarse / sus); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/combDelay.scd0000644000175100001770000000035114611211152023064 0ustar00runnerdockerSynthDef.new(\combDelay, {|bus, echo, beat_dur, echotime| var osc; osc = In.ar(bus, 2); osc = osc + CombL.ar(osc, delaytime: echo * beat_dur, maxdelaytime: 2 * beat_dur, decaytime: echotime * beat_dur); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/comp.scd0000644000175100001770000000036314611211152022126 0ustar00runnerdockerSynthDef.new(\comp, {|bus, comp, comp_down, comp_up| var osc; osc = In.ar(bus, 2); osc = Compander.ar(osc, osc, thresh: comp, slopeAbove: comp_down, slopeBelow: comp_up, clampTime: 0.01, relaxTime: 0.01, mul: 1); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/dirt_krush.scd0000644000175100001770000000056114611211152023346 0ustar00runnerdockerSynthDef.new(\dirt_krush, { |bus, krush, kutoff| var osc,signal,freq; osc = In.ar(bus, 2); freq = Select.kr(kutoff > 0, [DC.kr(4000), kutoff]); signal = (osc.squared + (krush * osc)) / (osc.squared + (osc.abs * (krush-1.0)) + 1.0); signal = RLPF.ar(signal, clip(freq, 20, 10000), 1); osc = SelectX.ar(krush * 2.0, [osc, signal]); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/disto_mod.scd0000644000175100001770000000033514611211152023150 0ustar00runnerdockerSynthDef.new(\disto_mod, { |bus, disto, smooth, distomix| var osc; osc = In.ar(bus, 2); osc = LinXFade2.ar(CrossoverDistortion.ar(osc, amp:0.5*disto, smooth:smooth), osc, 1-distomix); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/distortion.scd0000644000175100001770000000056614611211152023373 0ustar00runnerdockerSynthDef.new(\distortion, { |bus, dist, tmp| var osc; osc = In.ar(bus, 2); tmp = osc; osc = CrossoverDistortion.ar(osc, amp:0.2, smooth:0.01); osc = osc + (0.1 * dist * DynKlank.ar(`[[60,61,240,3000 + SinOsc.ar(62,mul:100)],nil,[0.1, 0.1, 0.05, 0.01]], osc)); osc = (osc.cubed * 8).softclip * 0.5; osc = SelectX.ar(dist, [tmp, osc]); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/dubdelay.scd0000644000175100001770000000100314611211152022751 0ustar00runnerdockerSynthDef.new(\dubdelay, { |bus, dubd, dublen, dubwidth, dubfeed| var osc,dry; osc = In.ar(bus, 2); dry = osc; osc = osc + Fb({ |feedback| var left, right; var magic = LeakDC.ar(feedback*dubfeed + osc); magic = HPF.ar(magic, 400); magic = LPF.ar(magic, 5000); magic = magic.tanh; #left, right = magic; magic = [DelayC.ar(left, 1, LFNoise2.ar(12).range(0,dubwidth)), DelayC.ar(right, 1, LFNoise2.ar(12).range(dubwidth,0))].reverse; },dublen); osc = SelectX.ar(dubd, [dry, osc]); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/fdist.scd0000644000175100001770000000055714611211152022306 0ustar00runnerdockerSynthDef.new(\fdist, {|bus, fdist, fdistfreq| var osc; osc = In.ar(bus, 2); osc = LPF.ar(osc, fdistfreq); osc = (osc * 1.1 * fdist).tanh; osc = LPF.ar(osc, fdistfreq); osc = (osc * 1.1 * fdist).tanh; osc = LPF.ar(osc, fdistfreq); osc = (osc * 1.4 * fdist).tanh; osc = LPF.ar(osc, fdistfreq); osc = (osc * 2 * fdist).tanh; osc = osc*0.2; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/fdistc.scd0000644000175100001770000000105114611211152022437 0ustar00runnerdockerSynthDef.new(\fdistc, {|bus, fdistc, fdistcfreq1, fdistcfreq2, fdistcfreq3, fdistcfreq4, fdistcm1, fdistcm2, fdistcm3, fdistcm4, fdistcq1, fdistcq2, fdistcq3, fdistcq4| var osc; osc = In.ar(bus, 2); osc = RLPF.ar(osc, fdistcfreq1, fdistcq1); osc = (osc * fdistcm1 * fdistc).tanh; osc = RLPF.ar(osc, fdistcfreq2, fdistcq2); osc = (osc * fdistcm2 * fdistc).tanh; osc = RLPF.ar(osc, fdistcfreq3, fdistcq3); osc = (osc * fdistcm3 * fdistc).tanh; osc = RLPF.ar(osc, fdistcfreq4, fdistcq4); osc = (osc * fdistcm4 * fdistc).tanh; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/feeddelay.scd0000644000175100001770000000035514611211152023113 0ustar00runnerdockerSynthDef.new(\feeddelay, { |bus, feed, feedfreq| var osc,out; osc = In.ar(bus, 2); out = osc + Fb({ arg feedback; osc = CombN.ar(HPF.ar(feedback*feed, feedfreq) + osc, 0.5, 0.25).tanh; },0.5,0.125); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/filterSwell.scd0000644000175100001770000000035314611211152023463 0ustar00runnerdockerSynthDef.new(\filterSwell, {|bus, swell, sus, hpr| var osc,env; osc = In.ar(bus, 2); env = EnvGen.kr(Env([0,1,0], times:[(sus*0.25), (sus*0.25)], curve:\sin)); osc = RHPF.ar(osc, env * swell * 2000, hpr); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/flanger.scd0000644000175100001770000000041114611211152022600 0ustar00runnerdockerSynthDef.new(\flanger, { |bus, flanger, fdecay, flangermix| var osc; osc = In.ar(bus, 2); osc = LinXFade2.ar(CombC.ar(osc, 0.01, SinOsc.ar(flanger, 0, (0.01 * 0.5) - 0.001, (0.01 * 0.5) + 0.001), fdecay, 1), osc, 1-flangermix); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/formantFilter.scd0000644000175100001770000000034414611211152024003 0ustar00runnerdockerSynthDef.new(\formantFilter, {|bus, formant| var osc; osc = In.ar(bus, 2); formant = (formant % 8) + 1; osc = Formlet.ar(osc, formant * 200, ((formant % 5 + 1)) / 1000, (formant * 1.5) / 600).tanh; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/frequencyModulate.scd0000644000175100001770000000021014611211152024653 0ustar00runnerdockerSynthDef.new(\frequencyModulate, { |bus, fmod| var osc; osc = In.kr(bus, 1); osc = [osc, osc+fmod]; ReplaceOut.kr(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/fxout.scd0000644000175100001770000000032214611211152022330 0ustar00runnerdockerSynthDef.new(\fxout, { |bus, fx1, lpfx1, hpfx1| var osc,fxsig; osc = In.ar(bus, 2); fxsig = LPF.ar(osc, lpfx1); fxsig = HPF.ar(fxsig, hpfx1); Out.ar(2, Mix.ar(fxsig*fx1)); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/glissando.scd0000644000175100001770000000032114611211152023145 0ustar00runnerdockerSynthDef.new(\glissando, {|bus, glide, glidedelay, sus| var osc; osc = In.kr(bus, 1); osc = osc * EnvGen.ar(Env([1, 1, (1.059463**glide)], [sus*glidedelay, sus*(1-glidedelay)])); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/highPassFilter.scd0000644000175100001770000000021114611211152024074 0ustar00runnerdockerSynthDef.new(\highPassFilter, {|bus, hpf, hpr| var osc; osc = In.ar(bus, 2); osc = RHPF.ar(osc, hpf, hpr); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/krush.scd0000644000175100001770000000054214611211152022323 0ustar00runnerdockerSynthDef.new(\krush, {|bus, krush, kutoff| var osc,signal,freq; osc = In.ar(bus, 2); freq = Select.kr(kutoff > 0, [DC.kr(4000), kutoff]); signal = (osc.squared + (krush * osc)) / (osc.squared + (osc.abs * (krush-1.0)) + 1.0); signal = RLPF.ar(signal, clip(freq, 20, 10000), 1); osc = SelectX.ar(krush * 2.0, [osc, signal]); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/leg.scd0000644000175100001770000000022414611211152021733 0ustar00runnerdockerSynthDef.new(\leg, {|bus, leg, sus| var osc; osc = In.kr(bus, 1); osc = osc * XLine.ar(Rand(0.5,1.5)*leg,1,0.05*sus); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/lofi.scd0000644000175100001770000000232114611211152022115 0ustar00runnerdockerSynthDef.new(\lofi, {|bus, lofi, lofiwow, lofiamp| var osc,minWowRate,wowRate,maxDepth,maxLfoDepth,depth,depthLfoAmount,wowMul,maxDelay,ratio,threshold,gain; osc = In.ar(bus, 2); osc = HPF.ar(osc, 25); ratio = LinExp.kr(lofiamp, 0, 1, 0.15, 0.01); threshold = LinLin.kr(lofiamp, 0, 1, 0.8, 0.33); gain = 1/(((1.0-threshold) * ratio) + threshold); osc = Limiter.ar(Compander.ar(osc, osc, threshold, 1.0, ratio, 0.1, 1, gain), dur: 0.0008); minWowRate = 0.5; wowRate = LinExp.kr(lofiwow, 0, 1, minWowRate, 4); maxDepth = 35; maxLfoDepth = 5; depth = LinExp.kr(lofiwow, 0, 1, 1, maxDepth - maxLfoDepth); depthLfoAmount = LinLin.kr(lofiwow, 0, 1, 1, maxLfoDepth).floor; depth = LFPar.kr(depthLfoAmount * 0.1, mul: depthLfoAmount, add: depth); wowMul = ((2 ** (depth * 1200.reciprocal)) - 1)/(4 * wowRate); maxDelay = (((2 ** (maxDepth * 1200.reciprocal)) - 1)/(4 * minWowRate)) * 2.5; osc = DelayC.ar(osc, maxDelay, SinOsc.ar(wowRate, 2, wowMul, wowMul + ControlRate.ir.reciprocal)); osc = ((osc * LinExp.kr(lofiamp, 0, 1, 1, 2.5))).tanh; osc = LPF.ar(osc, LinExp.kr(lofi, 0, 1, 2500, 10000)); osc = HPF.ar(osc, LinExp.kr(lofi, 0, 1, 40, 1690)); osc = MoogFF.ar(osc, LinExp.kr(lofi, 0, 1, 1000, 10000), 0); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/lowPassFilter.scd0000644000175100001770000000021014611211152023755 0ustar00runnerdockerSynthDef.new(\lowPassFilter, {|bus, lpf, lpr| var osc; osc = In.ar(bus, 2); osc = RLPF.ar(osc, lpf, lpr); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/makeSound.scd0000644000175100001770000000041014611211152023107 0ustar00runnerdockerSynthDef.new(\makeSound, { arg bus, sus; var osc; osc = In.ar(bus, 2); osc = EnvGen.ar(Env([1,1,0],[sus * 8, 0.1]), doneAction: 14) * osc; DetectSilence.ar(osc, amp:0.0001, time: 0.1, doneAction: 14); OffsetOut.ar(0, osc[0]); OffsetOut.ar(1, osc[1]); }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/octafuz.scd0000644000175100001770000000047414611211152022646 0ustar00runnerdockerSynthDef.new(\octafuz, { |bus, octafuz, octamix| var osc,dis,osc_base; osc = In.ar(bus, 2); osc_base = osc; dis = [1,1.01,2,2.02,4.5,6.01,7.501]; dis = dis ++ (dis*6); osc = ((osc * dis*octafuz).sum.distort); osc = (osc * 1/16)!2; osc = LinXFade2.ar(osc_base, osc, octamix); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/octer.scd0000644000175100001770000000057214611211152022306 0ustar00runnerdockerSynthDef.new(\octer, { |bus, octer, octersub, octersubsub| var osc,oct1,oct2,oct3,sub; osc = In.ar(bus, 2); oct1 = 2.0 * LeakDC.ar(abs(osc)); sub = LPF.ar(osc, 440); oct2 = ToggleFF.ar(sub); oct3 = ToggleFF.ar(oct2); osc = SelectX.ar(octer, [osc, octer*oct1, DC.ar(0)]); osc = osc + (octersub * oct2 * sub) + (octersubsub * oct3 * sub); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/output.scd0000644000175100001770000000017514611211152022531 0ustar00runnerdockerSynthDef.new(\output, { |bus, output| var osc; osc = In.ar(bus, 2); Out.ar(output, osc); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/overdriveDistortion.scd0000644000175100001770000000023614611211152025253 0ustar00runnerdockerSynthDef.new(\overdriveDistortion, {|bus, drive| var osc; osc = In.ar(bus, 2); osc = (osc * (drive * 50)).clip(0,0.2).fold2(2); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/phaser.scd0000644000175100001770000000067314611211152022456 0ustar00runnerdockerSynthDef.new(\phaser, {|bus, phaser, phaserdepth| var osc,delayedSignal; osc = In.ar(bus, 2); delayedSignal = osc; for(1, 4, {|i| delayedSignal = AllpassL.ar(delayedSignal, 0.01 * 4.reciprocal, LFPar.kr(LinExp.kr(phaser, 0, 1, 0.275, 16), i + 0.5.rand, LinExp.kr(phaserdepth*4.reciprocal, 0, 1, 0.0005, 0.01 * 0.5), LinExp.kr(phaserdepth*4.reciprocal, 0, 1, 0.0005, 0.01 * 0.5)), 0)}); osc = osc + delayedSignal; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/pitchBend.scd0000644000175100001770000000034414611211152023067 0ustar00runnerdockerSynthDef.new(\pitchBend, {|bus, bend, sus, benddelay| var osc; osc = In.kr(bus, 1); osc = osc * EnvGen.ar(Env([1, 1, 1 + bend, 1], [sus * benddelay, (sus*(1-benddelay)/2), (sus*(1-benddelay)/2)])); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/pitchShift.scd0000644000175100001770000000020514611211152023270 0ustar00runnerdockerSynthDef.new(\pitchShift, {|bus, pshift| var osc; osc = In.kr(bus, 1); osc = osc * (1.059463**pshift); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/pitchshifter.scd0000644000175100001770000000026114611211152023661 0ustar00runnerdockerSynthDef.new(\pitchshifter, { |bus, shift, shiftsize| var osc; osc = In.ar(bus, 2); osc = PitchShift.ar(osc, shiftsize, shift, 0.02, 0.01); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/position.scd0000644000175100001770000000030114611211152023024 0ustar00runnerdockerSynthDef.new(\position, { |bus, position, sus| var osc; osc = In.ar(bus, 2); osc = osc * EnvGen.ar(Env([0, 0, 1], curve='step', times=[sus * position, 0])); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/resonz.scd0000644000175100001770000000023714611211152022510 0ustar00runnerdockerSynthDef.new(\resonz, { |bus, rfreq, resonz| var osc; osc = In.ar(bus, 2); osc = Resonz.ar(osc, freq: rfreq, bwr: resonz); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/reverb.scd0000644000175100001770000000020714611211152022452 0ustar00runnerdockerSynthDef.new(\reverb, {|bus, room, mix| var osc; osc = In.ar(bus, 2); osc = FreeVerb.ar(osc, mix, room); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/reverb_stereo.scd0000644000175100001770000000054414611211152024037 0ustar00runnerdockerSynthDef.new(\reverb_stereo, {|bus, room2, mix2, damp2, revatk, revsus| var osc,dry; osc = In.ar(bus, 2); dry = osc; osc = HPF.ar(osc, 100); osc = LPF.ar(osc, 10000); osc = FreeVerb2.ar(osc[0], osc[1], 1, room2, damp2); osc = osc * EnvGen.ar(Env([0,1,0], [revatk,revsus], curve: 'welch')); osc = SelectX.ar(mix2, [dry, osc]); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/ring_modulation.scd0000644000175100001770000000033514611211152024361 0ustar00runnerdockerSynthDef.new(\ring_modulation, {|bus, ring, ringl, ringh| var osc,mod; osc = In.kr(bus, 1); mod = ring * SinOsc.ar(Clip.kr(XLine.kr(ringl, ringl + ringh), 20, 20000)); osc = ring1(osc, mod); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/sample_atk.scd0000644000175100001770000000034114611211152023304 0ustar00runnerdockerSynthDef.new(\sample_atk, {|bus, sample_atk, sample_sus| var osc,env; osc = In.ar(bus, 2); env = EnvGen.ar(Env.new(levels: [0,1,0], times:[sample_atk, sample_sus], curve: 'lin')); osc = osc*env; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/sidechain.scd0000644000175100001770000000050614611211152023116 0ustar00runnerdockerSynthDef.new(\sidechain, { |bus, sidechain, sidechain_atk, sidechain_rel, thresh| var osc,schain; osc = In.ar(bus, 2); schain = In.ar(sidechain,1); osc = Compander.ar(osc, schain, thresh: thresh, slopeAbove: 0.1, slopeBelow: 1, clampTime: sidechain_atk, relaxTime: sidechain_rel, mul: 1); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/slideFrom.scd0000644000175100001770000000033514611211152023113 0ustar00runnerdockerSynthDef.new(\slideFrom, {|bus, slidefrom, sus, slidedelay| var osc; osc = In.kr(bus, 1); osc = osc * EnvGen.ar(Env([slidefrom + 1, slidefrom + 1, 1], [sus*slidedelay, sus*(1-slidedelay)])); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/slideTo.scd0000644000175100001770000000030714611211152022571 0ustar00runnerdockerSynthDef.new(\slideTo, {|bus, slide, sus, slidedelay| var osc; osc = In.kr(bus, 1); osc = osc * EnvGen.ar(Env([1, 1, slide + 1], [sus*slidedelay, sus*(1-slidedelay)])); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/spinPan.scd0000644000175100001770000000033514611211152022577 0ustar00runnerdockerSynthDef.new(\spinPan, {|bus, spin, sus| var osc; osc = In.ar(bus, 2); osc = osc * [FSinOsc.ar(spin / 2, iphase: 1, mul: 0.5, add: 0.5), FSinOsc.ar(spin / 2, iphase: 3, mul: 0.5, add: 0.5)]; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/squiz.scd0000644000175100001770000000017314611211152022342 0ustar00runnerdockerSynthDef.new(\squiz, {|bus, squiz| var osc; osc = In.ar(bus, 2); osc = Squiz.ar(osc, squiz); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/startSound.scd0000644000175100001770000000013414611211152023332 0ustar00runnerdockerSynthDef.new(\startSound, { arg bus, rate=1, sus; var osc; ReplaceOut.kr(bus, rate)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/striate.scd0000644000175100001770000000041614611211152022642 0ustar00runnerdockerSynthDef.new(\striate, {|bus, striate, sus, buf, rate| var osc; osc = In.kr(bus, 1); rate = (BufDur.kr(buf) / sus); rate = Select.kr(rate > 1, [1, rate]); osc = osc * LFPulse.ar(striate / sus, width: (BufDur.kr(buf) / rate) / sus) * rate; ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/stutterfx.scd0000644000175100001770000000113614611211152023237 0ustar00runnerdockerSynthDef.new(\stutterfx, { |bus, t_reset, stut, stutrate, stutlen| var osc,dry,reset,wet; osc = In.ar(bus, 2); ~stutter = { |snd, reset, stutlen, maxdelay = 1| var phase, fragment, del; phase = Sweep.ar(reset); fragment = { |ph| (ph - Delay1.ar(ph)) < 0 + Impulse.ar(0) }.value(phase / stutlen % 1); del = Latch.ar(phase, fragment) + ((stutlen - Sweep.ar(fragment)) * (stutrate - 1)); DelayC.ar(snd, maxdelay, del); }; dry = osc; reset = Onsets.kr(FFT(LocalBuf(1024), osc), t_reset); wet = ~stutter.(osc, reset, stutlen); osc = SelectX.ar(stut, [dry, wet], wrap:1); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/tanhDisto.scd0000644000175100001770000000020614611211152023121 0ustar00runnerdockerSynthDef.new(\tanhDisto, {|bus, tanh| var osc; osc = In.ar(bus, 2); osc = osc + (osc*tanh).tanh.sqrt(); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/tek.scd0000644000175100001770000000125614611211152021755 0ustar00runnerdockerSynthDef.new(\tek, { |bus, tek, tekr, tekd| var osc,osc_low,osc_med,osc_high,osc_base,lfo; osc = In.ar(bus, 2); lfo = SinOsc.ar(0.5, phase: 0, mul: 5, add: 1); osc = In.ar(bus, 2); osc_base = osc; osc_low = LPF.ar(osc, lfo) * 1; osc_med = BPF.ar(osc, lfo * 2); osc_med = osc_med + Ringz.ar(CrossoverDistortion.ar(osc_med, 1, 0.1, 0.4),100, decaytime: 0.15, mul:0.1); osc_med = LeakDC.ar(osc_med); osc_high = HPF.ar(osc, 4000 + SinOsc.ar(4, mul: 24)); osc = osc_low + osc_med + osc_high; osc = DFM1.ar(osc, [400, 600], 0.99, tekd, 0) + osc; osc = RHPF.ar(Gammatone.ar(osc, tekr), tekr, mul:2) + osc; osc = LinXFade2.ar(osc_base, osc, tek); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/tremolo.scd0000644000175100001770000000025314611211152022647 0ustar00runnerdockerSynthDef.new(\tremolo, {|bus, tremolo, beat_dur| var osc; osc = In.ar(bus, 2); osc = osc * SinOsc.ar( tremolo / beat_dur, mul:0.5, add:0.5); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/trimLength.scd0000644000175100001770000000030014611211152023274 0ustar00runnerdockerSynthDef.new(\trimLength, {|bus, cut, sus| var osc; osc = In.ar(bus, 2); osc = osc * EnvGen.ar(Env(levels: [1,1,0.01], curve: 'step', times: [sus * cut, 0.01])); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/trimPos.scd0000644000175100001770000000030114611211152022615 0ustar00runnerdockerSynthDef.new(\trimPos, {|bus, position, sus| var osc; osc = In.ar(bus, 2); osc = osc * EnvGen.ar(Env(levels: [0,0,1], curve: 'step', times: [sus * position, 0])); ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/triode.scd0000644000175100001770000000032414611211152022453 0ustar00runnerdockerSynthDef.new(\triode, {|bus, triode| var osc,sc; osc = In.ar(bus, 2); sc = triode * 10 + 1e-3; osc = (osc * (osc > 0)) + (tanh(osc * sc) / sc * (osc < 0)); osc = LeakDC.ar(osc)*1.2; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/vibrato.scd0000644000175100001770000000022614611211152022634 0ustar00runnerdockerSynthDef.new(\vibrato, {|bus, vib, vibdepth| var osc; osc = In.kr(bus, 1); osc = Vibrato.ar(osc, vib, depth: vibdepth); ReplaceOut.kr(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/volume.scd0000644000175100001770000000015714611211152022500 0ustar00runnerdockerSynthDef.new(\volume, {|bus, vol| var osc; osc = In.ar(bus, 2); osc = osc * vol; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/wavefold.scd0000644000175100001770000000077314611211152023004 0ustar00runnerdockerSynthDef.new(\wavefold, { |bus, fold, symetry, smooth| var osc,gain,compensationGain,envFollower,ampgain; osc = In.ar(bus, 2); compensationGain = max(LinLin.kr(fold, 0, 1, 1, 20) * 0.75, 1).reciprocal; envFollower = EnvFollow.ar((osc * 2).softclip, 0.9999); ampgain = (compensationGain * (1 - 0.4)) + (envFollower * 0.4); osc = SmoothFoldS.ar((osc + LinLin.kr(symetry, 0, 1, 1, 0)) * LinLin.kr(fold, 0, 1, 1, 20), smoothAmount: smooth); osc = LeakDC.ar(osc*ampgain); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/waveloss.scd0000644000175100001770000000024614611211152023033 0ustar00runnerdockerSynthDef.new(\waveloss, { |bus, drop, dropof| var osc; osc = In.ar(bus, 2); osc = WaveLoss.ar(osc, drop, outof: dropof, mode: 2); ReplaceOut.ar(bus, osc) }).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/sceffects/wavesShapeDistortion.scd0000644000175100001770000000023714611211152025355 0ustar00runnerdockerSynthDef.new(\wavesShapeDistortion, {|bus, shape| var osc; osc = In.ar(bus, 2); osc = (osc * (shape * 50)).fold2(1).distort / 5; ReplaceOut.ar(bus, osc)}).add;././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.5915406 renardo_lib-0.9.12/renardo_lib/osc/scenvelopes/0000755000175100001770000000000014611211157021061 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scenvelopes/BasicEnvelope.scd0000644000175100001770000000050214611211152024263 0ustar00runnerdockerSynthDef.new(\BasicEnvelope, {|bus, atk, decay, sus, rel, legato, gain, amp, curve=0| var osc; osc = In.ar(bus, 2); sus = sus * legato; osc = osc * EnvGen.kr(Env([0, amp, amp*gain, amp*gain, 0],[atk, decay, sus, rel * sus], curve: curve), levelScale:0.75, timeScale:1, doneAction: 3); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scenvelopes/MaskEnvelope.scd0000644000175100001770000000044414611211152024142 0ustar00runnerdockerSynthDef.new(\MaskEnvelope, {|bus, atk, decay, sus, rel, legato, gain, amp, curve=0| var osc; osc = In.ar(bus, 2); sus = sus * legato; osc = osc * EnvGen.kr(Env([0, amp, amp, 0],[atk, sus, rel], curve: \lin), levelScale:0.75, timeScale:1, doneAction: 3); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scenvelopes/PercussiveEnvelope.scd0000644000175100001770000000045414611211152025400 0ustar00runnerdockerSynthDef.new(\PercussiveEnvelope, {|bus, atk, decay, sus, rel, legato, gain, amp, curve=0| var osc; osc = In.ar(bus, 2); sus = sus * legato; osc = osc * EnvGen.kr(Env([0, amp, amp, 0],[atk, decay, sus], curve: \cub), levelScale:0.75, timeScale:1, doneAction: 3); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scenvelopes/RampEnvelope.scd0000644000175100001770000000043214611211152024143 0ustar00runnerdockerSynthDef.new(\RampEnvelope, {|bus, atk, decay, sus, rel, legato, gain, amp, curve=0| var osc; osc = In.ar(bus, 2); sus = sus * legato; osc = osc * EnvGen.kr(Env([0, amp, 0],[sus, rel], curve: \lin), levelScale:0.75, timeScale:1, doneAction: 3); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scenvelopes/SwellEnvelope.scd0000644000175100001770000000045014611211152024332 0ustar00runnerdockerSynthDef.new(\SwellEnvelope, {|bus, atk, decay, sus, rel, legato, gain, amp, curve=0| var osc; osc = In.ar(bus, 2); sus = sus * legato; osc = osc * EnvGen.kr(Env([0, amp, 0],[atk * sus, rel * sus], curve: curve), levelScale:0.75, timeScale:1, doneAction: 3); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.6235404 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/0000755000175100001770000000000014611211157020351 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/abass.scd0000644000175100001770000000254214611211152022133 0ustar00runnerdockerSynthDef.new(\abass, { |bus=0, amp=1, gate=1, pan=0, spread=0.8, freq=440, atk=0.001, decay=0.01, sus=1,rel=0.01, level=0.8, peak=1, fmod=0, blur=1| var sig, sig1, sig2, sig3, osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = SinOsc.ar(freq*\fmfreq.kr(1).lag(0.3)) * \fmrange.kr(0.5).lag(0.3) * LFNoise1.kr(4).range(0.9,1.1) + 1 * freq; sig = SinOsc.ar(freq.lag(0.1) * [1,8,2,4,1.002]); sig1 = LFPulse.ar(freq * [1,4,1.001,2 * LFNoise1.kr(1/10).range(0.999,1.001),1/2], mul:1.00); sig = sig + sig1; sig = sig.fold2(SinOsc.kr(1/13).range(0.9,1)); sig = sig.wrap2(SinOsc.kr(1/14).range(0.9,1)); sig = LPF.ar(sig, 5500); //sig = sig * 1; sig = HPF.ar(sig, \hpf.kr(80)); sig = sig * EnvGen.ar(\iadsr.kr(Env.adsr(0.01,0.1,0.8,0.1)),\igate.kr(1),doneAction:0); sig = sig * EnvGen.ar(\adsr.kr(Env.adsr(0.005,0.1,0.8,0.1)),gate,doneAction:0); // env=EnvGen.ar(Env.perc(level: amp,releaseTime: sus,attackTime: 0.1,curve: 'lin'), doneAction: 0); //add a ADSR envelope env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); sig = sig.tanh; osc = Mix(sig) * 0.25; osc = Pan2.ar(osc * env , pan); ReplaceOut.ar(bus, osc * amp) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \bass, tags: [] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/acidbass.scd0000644000175100001770000000217314611211152022613 0ustar00runnerdockerSynthDef.new(\acidbass, { |bus = 0, gate = 1, freq = 440, amp = 1, pan = 0, fmod=0, atk = 0.001, dec = 0.4, sus = 1, rel = 0.3, curve = -4, lagtime = 0.12, frange = 6, width = 0.51, rq = 0.4| var ampEnv, filterEnv, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = Lag.kr(freq, lagtime); ampEnv = Env.adsr( attackTime: atk, decayTime: dec, sustainLevel: sus / 20, releaseTime: rel, peakLevel: amp * 0.1, curve: [0, curve, curve, curve] ).kr(gate: gate, doneAction: 0); filterEnv = Env.adsr( attackTime: atk, decayTime: dec * 2, sustainLevel: sus * 1/20, releaseTime: rel, peakLevel: 2.pow(frange), // octaves multiplier curve: [-1 * curve, curve], bias: 1 // env sweeps from 1 to 2.pow(filterRange) and back ).kr(gate: gate, doneAction: 0); osc = LFPulse.ar(freq: freq, width: width).range(-1, 1); osc = RLPF.ar(osc, freq * filterEnv, rq); osc = osc * ampEnv; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "otophilia", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "", category: \bass, tags: [\pitched, \acid, \phat, \subtractive] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/alva.scd0000644000175100001770000000144614611211152021767 0ustar00runnerdockerSynthDef.new(\alva, { |bus=0, amp=1, freq=240, pan=0, gate=1, dur, fmod=0, vib=0, sus=1, blur=1, wide| var osc, env, freqenv, freqenv2, line; freqenv = EnvGen.ar(Env.new([freq, freq, 40], [0.01, 0.4, dur])); freqenv2 = EnvGen.ar(Env.new([freq*1.2, 10, 10], [0.05, 0.25, dur])); sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = SinOsc.ar(freqenv, VarSaw.kr(0), 4) - SinOscFB.ar(freqenv2/0.2, fmod + 1, freq, 2); env=EnvGen.ar(Env(times: [(sus * 0.25), (sus * 1)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * amp * env); //osc = Mix(osc); osc = Limiter.ar(osc); osc = Mix(osc) * 0.13; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \bass, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ambi.scd0000644000175100001770000000120414611211152021744 0ustar00runnerdockerSynthDef.new(\ambi,{ |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0| var osc, env, filter; freq = In.kr(bus, 1); freq = freq + fmod; freq = freq + ( (XLine.kr(freq * rate, freq + LFNoise2.ar(4, mul:1), sus)) * SinOsc.ar(freq + LFNoise2.ar(4, mul:2))); osc=SinOsc.ar(freq + Rand(0.99,1.01), phase:Rand(0,2)); env = EnvGen.ar(Env([0,0.5 * amp, 0.5 * amp,0],[sus/4, sus, sus/4])); filter = BHiPass.ar(osc, 200); osc = osc * env * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/angel.scd0000644000175100001770000000107314611211152022126 0ustar00runnerdockerSynthDef.new(\angel, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, rq=0.5| var osc, env, filter; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 2); freq = freq * [1, 1.01]; osc = Ringz.ar(ClipNoise.ar(0.001).dup / 2, freq * 3); osc = RHPF.ar(osc, freq * 2.5, rq); env = EnvGen.ar(Env([1, 0.8, 0.5, 0],[0.2 * sus, 0.5 * sus, 0.7 * sus])); osc = Mix(osc) * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \bass, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/angst.scd0000644000175100001770000000155114611211152022155 0ustar00runnerdockerSynthDef.new(\angst, { |amp=1, sus=1, gate=1, pan=0, freq=0, vib=0, fmod=0, rate=1, cutoff=18000, rq=0.5, mul=1, bus=0, atk=0.0001, decay=0.01, rel=0.01, level=0.8, peak=1| var osc, pulse, filter,env,clip, z; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; clip = LinLin.kr(rate, 0, 1, 2e-12, 2e-1); z = SinOsc; y = freq; osc = GVerb.ar(z.ar(y+z.kr([freq / 4,freq / 2],0,y*LFDNoise1.kr(0.4,1.4).abs))*0.05+GVerb.ar(PinkNoise.ar(Decay2.kr(Dust.kr(1!2))*0.02))); env=EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = BLowPass4.ar(osc,(cutoff*(env.squared))+200+freq,rq); osc = Mix(osc*env) * 1.6; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \bass, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/arpy.scd0000644000175100001770000000101414611211152022006 0ustar00runnerdockerSynthDef.new(\arpy, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 2); amp=(amp * 2); freq=(freq + [0, 0.5]); osc=LPF.ar(Impulse.ar(freq), 3000); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: (sus * 0.25),level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/audioin.scd0000644000175100001770000000072714611211152022475 0ustar00runnerdockerSynthDef.new(\audioin, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, channel=1| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=AudioIn.ar(channel); env=EnvGen.ar(Env(times: [0.01, (sus - 0.01), 0.01],levels: [0, 1, 1, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bass.scd0000644000175100001770000000140314611211152021765 0ustar00runnerdockerSynthDef.new(\bass, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=8, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 4); amp=(amp * 0.8); osc=((LFTri.ar(freq, mul: amp) + VarSaw.ar(freq, width: (rate / 10), mul: amp)) + SinOscFB.ar(freq, mul: (amp / 2))); env=EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bassguitar.scd0000644000175100001770000000360114611211152023203 0ustar00runnerdockerSynthDef.new(\bassguitar, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.001, decay=0.01, rel=0.01, pick=0.414, rq = 0.5, cutoff = 250| var exciter, freqArray, ampArray, decArray, constant, mute, osc, openFreq, pickupPos, pickupWidth, decayCoef, dampCoef; openFreq = 82.5; pickupPos = 17*decay; pickupWidth = 0.75; decayCoef = 0.125; dampCoef = 0.0002; sus = sus*blur; freq = In.kr(bus, 1); freq = freq/4; freq = [freq, freq+fmod]; constant = pickupWidth/25.5; constant = constant * pi/2; constant = constant/82.5; freqArray = Array.fill(10, {arg i; (i + 1) * sqrt(1 + ((i + 1).pow(2) * 0.00001))}); freqArray = freqArray/freqArray[0]; decArray = Array.fill(10, {arg i; exp((-1 * i)/((1/decayCoef) + ((dampCoef/10) * freq.pow(2)) + (dampCoef * freqArray[i].pow(2))))}); decArray = decArray/decArray[0]; freqArray = freqArray * freq; ampArray = Array.fill(10, {arg i; ((1 - ((freqArray[i] - 19000)/1000).tanh)/2) * sin(((i + 1) * pi) * pick) * ( sin(pi * pickupPos * freqArray[i]/openFreq) * ( ( sin(constant * freqArray[i])/ (constant * freqArray[i]) ) - cos(constant * freqArray[i]) ) )/(freqArray[i].pow(2)) }); ampArray = ampArray * 2/(constant.pow(2)); exciter = Impulse.ar(0) * 1; osc = Klank.ar(specificationsArrayRef: Ref.new([freqArray, ampArray, decArray]), input: exciter, decayscale: sus*2 + rel); osc = Mix.ar(osc); osc = RLPF.ar(in: osc, freq: cutoff, rq: rq); osc = LPF.ar(in: osc, freq: 250); mute = Env.new(levels: [1, 1, 0, 0], times: [rel+sus, 0.05, 0.01]).ar(doneAction: 2); osc = LPF.ar(in: osc, freq: LinExp.ar(in: mute, srclo: 0, srchi: 1, dstlo: 20, dsthi: 20000)); osc = osc * amp; osc = osc.tanh; osc = LeakDC.ar(osc); osc = Limiter.ar(osc); ReplaceOut.ar(bus, Pan2.ar(osc, pan)); }, metadata: ( credit: "by Josh Mitchell", category: \guitar, tags: [\pitched, \modal] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bbass.scd0000644000175100001770000000160014611211152022126 0ustar00runnerdockerSynthDef.new(\bbass, { |bus=0, freq = 0, amp = 1, pan=0, fmod=0, atk=0.07, sus=1, blur=1| var env, oscfreq, osc, envout, lfo; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus = sus * blur; oscfreq = {freq * LFNoise2.kr(Rand(0.0001, 0.5)).range(0.98, 1.02)}!5; lfo = { SinOsc.kr({ 1/Rand(2, 52) }!5) }; env = Env.adsr(atk, 1, sus, 0.1).kr(doneAction:0); osc = LFSaw.ar(oscfreq, mul: lfo.value.range(0,1)); osc = RLPF.ar(osc,(env*freq) + 1*freq * lfo.value.range(10/freq,5/freq), lfo.value.range(0.1,1)); osc = Splay.ar(osc, lfo.value.range(0,1)); envout = EnvGen.ar(Env.perc(level: amp, releaseTime: sus, attackTime: 0.02, curve: 'lin'), doneAction: 0); osc = Mix(osc) * 0.02 * envout * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc); }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bchaos.scd0000644000175100001770000000331014611211152022273 0ustar00runnerdockerSynthDef.new(\bchaos, { |bus = 0, pan = 0, freq = 0, amp = 1, gate = 1, fmod=0, atk = 0.01, sus = 1, rel = 1.5, curve = \lin, chaosUpStart = 0, chaosUpEnd = 0.5, chaosUpTime = 1, chaosDownStart = 0, chaosDownEnd = 0, chaosDownTime = 1, cutoff = 20000, reHashesPerCycle = 1, hashRate = 1, nyquist = 5000| var env, chaosRise, chaosFall, noisefunction, noise, switcha, switchb, shapea, shapeb, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(attackTime: atk, sustainTime: sus, releaseTime: rel, level: amp, curve: curve).kr; chaosRise = Line.kr(start: chaosUpStart, end: chaosUpEnd, dur: chaosUpTime ); chaosFall = Line.kr(start: chaosDownStart, end: chaosDownEnd, dur: chaosDownTime); switcha = LFPulse.ar(freq: freq, iphase: 0 ); switchb = LFPulse.ar(freq: freq, iphase: 0.5); noisefunction = Impulse.ar(freq: freq * reHashesPerCycle, mul: 1, add: -1); noisefunction = Sweep.ar(trig: noisefunction); noise = Hasher.ar(in: noisefunction); noise = LPF.ar(in: noise, freq: nyquist); noise = Latch.ar(noise, Impulse.ar(nyquist * 2)); noise = LPF.ar(in: noise, freq: nyquist); noise = noise * LFTri.ar(freq: freq, iphase: 0); shapea = noise * switcha * chaosRise; shapeb = noise * switchb * chaosFall; shapea = Saw.ar(freq: freq, mul: switcha/2, add: shapea); shapeb = LFCub.ar(freq: freq, iphase: 1, mul: -1 * switchb, add: shapeb); osc = Mix.ar(shapea/2 + shapeb/2) * amp *0.1; osc = LeakDC.ar(osc); osc = LPF.ar(in: osc, freq: cutoff, mul: env); DetectSilence.ar(in: osc, doneAction: 0); osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", decription: "", category: \misc, tags: [\pitched, \noisy] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bell.scd0000644000175100001770000000124114611211152021753 0ustar00runnerdockerSynthDef.new(\bell, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, verb=0.5, room=0.5| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 4); osc=(Klank.ar(`[[0.501, 1, 0.7, 2.002, 3, 9.6, 2.49, 11, 2.571, 3.05, 6.242, 12.49, 13, 16, 24], [0.002, 0.1, 0.001, 0.008, 0.02, 0.004, 0.02, 0.04, 0.02, 0.005, 0.05, 0.05, 0.02, 0.03, 0.04], [1.2, 1.2, 1.2, 0.9, 0.9, 0.9, 0.25, 0.25, 0.25, 0.14, 0.14, 0.14, 0.07, 0.07, 0.07]], Impulse.ar(0.01), freq, 0, (4 * rate)) * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bellmod.scd0000644000175100001770000000270714611211152022463 0ustar00runnerdockerSynthDef.new(\bellmod, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, lag = 10, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, wide=0.0, input, s1=1, s2=0, s3=0| var osc, env, sig1, sig2, sig3; env=EnvGen.ar(Env.perc(attackTime: atk,releaseTime: sus,level: amp,curve: 'lin'), doneAction: 0); sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sig1=(Klank.ar(`[[0.501, 1, 0.7, 2.002, 3, 9.6, 2.49, 11, 2.571, 3.05, 6.242, 12.49, 13, 16, 24], [0.002, 0.1, 0.001, 0.008, 0.02, 0.004, 0.02, 0.04, 0.02, 0.005, 0.05, 0.05, 0.02, 0.03, 0.04], [1.2, 1.2, 1.2, 0.9, 0.9, 0.9, 0.25, 0.25, 0.25, 0.14, 0.14, 0.14, 0.07, 0.07, 0.07]], Impulse.ar(0.01), freq, 0, (4 * rate)) * amp); sig1 = Mix(sig1 * env) * 4; sig2=(Klank.ar(`[ [1, 2, 2.803, 3.871, 5.074, 7.81, 10.948, 14.421], [1, 0.044, 0.891, 0.0891, 0.794, 0.1, 0.281, 0.079], [1, 0.205, 1, 0.196, 0.339, 0.047, 0.058, 0.047] ], Impulse.ar(0.01), freq, 0, (4 * rate)) * amp); sig2 = Mix(sig2 * env) * 0.8; sig3=(Klank.ar(`[ [1.013, 1.512, 2.113, 2.525, 3.35, 4.57, 6.48], [1, 0.78, 0.89, 0.63, 0.31, 0.56, 0.25], [1, 0.9, 0.8, 0.65, 0.45, 0.3, 0.1] ], Impulse.ar(0.01), freq, 0, (4 * rate)) * amp); sig3 = Mix(sig3 * env) * 0.6; osc = (sig1 * s1) +(sig2 * s2) + (sig3 * s3); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \bass, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/benoit.scd0000644000175100001770000000154614611211152022325 0ustar00runnerdockerSynthDef.new(\benoit, { |bus=0, amp=1, freq=440, fmod=0, semione=12, semitwo=24, trackmul=2, width=0.17, gate=1, sus=1, rel=1, pan = 0| var env, osc, osc1, osc2, osc3, osc4, ringmod, tracking; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc1 = Pulse.ar(freq, width); osc2 = Pulse.ar((freq.cpsmidi - semione).midicps, width); osc3 = Pulse.ar((freq.cpsmidi + semitwo).midicps, width); osc4 = LFTri.ar((freq.cpsmidi - semitwo).midicps); env = EnvGen.ar(Env.linen(0,sus,rel), gate, doneAction:0); tracking = ((freq * 1.01) + freq) * trackmul; osc = (osc1 + osc2 + osc3 + (osc4 * 2))/2; osc = RLPF.ar(osc, tracking, 1, 0.33); osc = osc.tanh; osc = osc * env * amp * 0.2; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/birdy.scd0000644000175100001770000000216014611211152022147 0ustar00runnerdockerSynthDef(\birdy,{ |bus=0, amp=1, sus=1, fmod=0, pan=0.0, atk=0.01, rel=0.09, freq=440, range=0, noiserate=10| var osc, osc2, freqenv, convIn, env, trig, rand; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; rand = LFNoise1.ar(noiserate); freq = Latch.kr(rand.range(0, 1).round(0.1), rand) * freq; freq = LFCub.ar(LFCub.ar(rand)*rand.range(0, 10)).range(freq, freq*2); rand = LFNoise1.ar(noiserate); convIn = LinCongN.ar(noiserate); env = EnvGen.ar(Env.perc(atk, sus, rel, -2), doneAction: 0); freqenv = EnvGen.ar(Env([Rand(1000,3000), Rand(3000, 6000), Rand(1000, 2000), Rand(2000, 5000)], [0.1, 0.01, 0.1]);, 1); osc = SinOsc.ar(freq + freqenv, phase: 1.0, mul: 1); osc2 = LFCub.ar(Convolution.ar(convIn, convIn)); osc2 = Formlet.ar(osc2, freq, convIn.abs*0.1, rand.abs); osc2 = Normalizer.ar(osc2, 0.9, 0.1) * convIn.abs * LFPulse.kr(LFPulse.kr(rand.abs), 0, rand.abs); osc = Mix([osc/2, osc2]); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Unknown", modified_by: "Jens Meisner", decription: "Bird singer", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/blip.scd0000644000175100001770000000111214611211152021760 0ustar00runnerdockerSynthDef.new(\blip, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp + 1e-05); freq=(freq + [0, LFNoise2.ar(50).range(-2, 2)]); freq=(freq * 2); osc=((LFCub.ar((freq * 1.002), iphase: 1.5) + (LFTri.ar(freq, iphase: Line.ar(2, 0, 0, 2)) * 0.3)) * Blip.ar((freq / 2), rate)); osc=((osc * XLine.ar(amp, (amp / 10000), (sus * 2))) * 0.3); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/blips.scd0000644000175100001770000000102414611211152022145 0ustar00runnerdockerSynthDef.new(\blips, { |bus = 0, freq = 0, nharm = 20, fmod=0, atk = 0.1, rel = 1, sus=1, amp = 1, pan = 0, offnote = 1.001| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.perc(atk, rel * sus * 20, amp).kr(doneAction: 0); osc = LeakDC.ar(Mix(Blip.ar([freq, freq * offnote], nharm))); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bnoise.scd0000644000175100001770000000213114611211152022313 0ustar00runnerdockerSynthDef.new(\bnoise, { |bus=0, amp=0.1, freq=10, blur=1, fmod=0, dur=1, gate=1, freq1=1000, freq2=2000, pan=0, sus=1| var sig0, sig1, sig2, sig3, osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env(times: [sus, sus],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); sig1 = BPF.ar(BrownNoise.ar(mul: SinOsc.ar(freq, phase: Rand (0, pi), mul: Rand (0.1, 2))), 3 * Rand(0, freq1)); sig2 = BPF.ar(PinkNoise.ar(mul: SinOsc.ar(freq * 1.1, phase: Rand (0, pi), mul: Rand (0.1, 1))), 2 * Rand(0, freq2)); sig3 = ({ Mix.fill(5,{Pan2.ar(SinOsc.ar(Gendy4.ar(6.rand,6.rand,SinOsc.kr(0.1,0,0.49,0.51),SinOsc.kr(0.13,0,0.49,0.51),freq ,freq, SinOsc.kr(0.17,0,0.49,0.51), SinOsc.kr(0.19,0,0.49,0.51), 12, 12, 200, 400), 0, 0.1), 1.0.rand2)})}); sig0 = (((sig1 + sig2 + sig3)) * 8).tanh ; osc = sig0 * amp; osc = (osc * env); osc = HPF.ar(osc, 40); osc = LPF.ar(osc, 8000); osc = Mix(osc) * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/borgan.scd0000644000175100001770000000173214611211152022312 0ustar00runnerdockerSynthDef.new(\borgan, { |bus=0, amp=1, gate=1, atk=0.02, pan=0, spread=0.8, freq=0, sus=1, fmod=0, blur=1, lagtime=0.1| var osc1, osc2, osc3, osc, env; freq = In.kr(bus, 1); sus = sus * blur; freq = [freq, freq+fmod]; freq = SinOsc.ar(freq*\fmfreq.kr(1).lag(0.3)) * \fmrange.kr(0.5).lag(0.3) * LFNoise1.kr(4).range(0.9,1.1) + 1 * freq; env = EnvGen.ar(Env.linen(attackTime: atk,sustainTime: sus,curve: 'sin'), doneAction: 0); osc1 = SinOsc.ar(freq.lag(lagtime) * [1,8,2,4,1.002]); osc2 = LFPulse.ar(freq * [1,4,1.001,2 * LFNoise1.kr(1/20).range(0.999,1.001),1/2], mul:1.2); osc = (osc1 + osc2); osc = osc.fold2(SinOsc.kr(1/13).range(0.7,1)); osc = osc.wrap2(SinOsc.kr(1/14).range(0.7,1)); osc = HPF.ar(osc, \hpf.kr(80)); osc = osc.tanh; osc = Mix(osc); osc = osc * env * amp * 0.02; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bounce.scd0000644000175100001770000000112114611211152022305 0ustar00runnerdockerSynthDef.new(\bounce, { |bus=0, gate=1, atk=0.1, sus=1, rel=0.09, amp=1, pan=0, freq=0, fmod=0, para1=2, para2=2.5, nharm=3| var env, osc; freq = In.kr(bus, 1); freq = [freq,freq+fmod]; osc = CombN.ar(Decay2.ar(Impulse.ar([[para1,para2], 1]), 0.08, sus), delaytime:0) * Blip.ar(freq, nharm); env = Env.linen(atk,sus,rel, curve:\lin).kr(doneAction:0); osc = Mix(osc) * 0.1; osc = osc * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bphase.scd0000644000175100001770000000121214611211152022275 0ustar00runnerdockerSynthDef.new(\bphase, { |bus = 0, freq = 0, fmod=0, atk = 0.02, amp=1, sus = 1, rel = 0.3, pan = 0, pmindex=2| var osc, env, osc1, osc2; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc1 = PMOsc; osc2 = SinOsc; env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \lin), doneAction:0); osc = osc1.ar(osc2.kr(0.1,freq), freq/2 + osc2.kr(freq * 0.6, pi), pmindex, osc1.ar(4,2,1,0,osc1.kr(freq*0.02, 2, 1)), osc2.kr(0.1)); osc = Mix.ar(osc * env) * amp * 0.1; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/brass.scd0000644000175100001770000000267514611211152022163 0ustar00runnerdocker<<<<<<< HEAD:renardo_lib/renardo_lib/osc/scsyndef/brass.scd SynthDef.new(\brass, {|vib=0, rate=0.3, sus=1, fmod=0, bus=0, amp=1, freq=0, pan=0| var osc, env; freq = In.kr(bus, 1); freq = freq + fmod; rate=Lag.ar(freq, rate); osc=(Saw.ar(rate, 0.4) + Saw.ar((rate + LFNoise2.ar(1).range(0.5, 1.1)), 0.4)); osc=(osc + Resonz.ar(osc, (freq * XLine.ar(1, 5, 0.13)), 1)); osc=BPF.ar(osc, (freq * 2.5), 0.3); osc=RLPF.ar(osc, 1300, 0.78); env=EnvGen.ar(Env.perc(level: amp,curve: 0,attackTime: 0.01,releaseTime: sus), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ======= SynthDef.new(\brass, { |vib=0, rate=0.3, sus=1, fmod=0, bus=0, atk = 0.01, amp=1, freq=0, pan=0| var osc, env, lagrate; freq = In.kr(bus, 1); freq = [freq, freq + fmod]; rate = Lag.kr(freq, rate); osc = (Saw.ar(rate, 0.4) + Saw.ar((rate + LFNoise2.ar(1).range(0.5, 1.1)), 0.4)); osc = (osc + Resonz.ar(osc, (freq * XLine.ar(1, 5, 0.13)), 1)); osc = BPF.ar(osc, (freq * 2.5), 0.3); osc = RLPF.ar(osc, 1300, 0.78); env = EnvGen.ar(Env.perc(level: amp, curve: 0, attackTime: atk,releaseTime: sus), doneAction: 0); osc = (osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \category, tags: [\tag] ) ).add; >>>>>>> 03b34654 (Fixed bugs in synths, Added most CrashServer synths):FoxDot/osc/scsyndef/brass.scd ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/brown.scd0000644000175100001770000000070614611211152022171 0ustar00runnerdockerSynthDef.new(\brown, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = BrownNoise.ar(); env = EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction:1); osc = (osc * env); osc = Mix(osc) * 0.1; osc = Pan2.ar(osc * amp, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/bug.scd0000644000175100001770000000104014611211152021607 0ustar00runnerdockerSynthDef.new(\bug, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 5); freq=(freq * [1, 1.0001]); osc=(Pulse.ar(freq, width: [0.09, 0.16, 0.25]) * SinOsc.ar((rate * 4))); env=EnvGen.ar(Env.perc(attackTime: (sus * 1.5),releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/charm.scd0000644000175100001770000000121014611211152022123 0ustar00runnerdockerSynthDef.new(\charm, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq + [0, 2]); freq=(freq * [1, 2]); osc=(SinOsc.ar(freq, mul: (amp / 4)) + VarSaw.ar((freq * 8), 10, mul: (amp / 8))); osc=LPF.ar(osc, SinOsc.ar(Line.ar(1, (rate * 4), (sus / 8)), 0, (freq * 2), ((freq * 2) + 10))); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/chimebell.scd0000644000175100001770000000152214611211152022763 0ustar00runnerdockerSynthDef.new(\chimebell, { |bus=0, atk=0.01, rel=0.02, freq=0, t60=8, offnote=1.001, fmod=0, amp=1, pan=0| var osc, env, exciter; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.perc(atk, rel, curve:\sin).kr(doneAction:0); exciter = WhiteNoise.ar() * env; osc = DynKlank.ar( `[ [1, 2, 2.803, 3.871, 5.074, 7.81, 10.948, 14.421], // freqs [1, 0.044, 0.891, 0.0891, 0.794, 0.1, 0.281, 0.079], // amplitudes [1, 0.205, 1, 0.196, 0.339, 0.047, 0.058, 0.047] * t60 // ring times ], exciter,freqscale: freq, freqoffset: offnote); DetectSilence.ar(osc, 0.001, 0.75, doneAction:0); osc = Mix(osc) * 0.0001 * amp; osc = Pan2.ar(osc,pan,amp); Out.ar(bus,osc); }, metadata: ( credit: "http://sccode.org/1-5aD", modified_by: "Jens Meisner", decription: "Description", category: \bells, tags: [\pitched, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/chipsy.scd0000644000175100001770000000104514611211152022336 0ustar00runnerdockerSynthDef.new(\chipsy, { |bus = 0, freq = 0, amp = 1, fmod=0, atk = 0.001, sus=1, rel=0.009, offnote=0.75, pan = 0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(atk, sus, rel, curve:\lin).kr(doneAction: 0); osc = Mix(LFPulse.ar(freq: freq * [1, offnote], iphase: 0.003, width: 0.5, mul:0.04)).tanh; osc = osc * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/click.scd0000644000175100001770000000122314611211152022122 0ustar00runnerdockerSynthDef.new(\click, { |amp = 1, freq = 0, bus=0, fmod=0, sus=1, pan = 0, vib=1, mult=4, ptime=0.2| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = BLowPass.ar(Impulse.ar(vib, 0, vib+4), mult, 0.5); osc = osc + LFPar.ar( Env.perc(0, ptime).ar.linexp(0, 1, freq, freq * 2) * LFDNoise3.kr(4).exprange(fmod.midiratio, 0.1.midiratio), -1); env = Env([1, 0], sus, -4).kr(2); osc = osc * env; osc = Mix(osc) * 0.1; osc = Pan2.ar(osc, pan); osc = Splay.ar(osc * amp); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/clip.scd0000644000175100001770000000067714611211152022000 0ustar00runnerdockerSynthDef.new(\clip, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = ClipNoise.ar(); env = EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction:1); osc = osc * env * amp; osc = Mix(osc) * 0.1; osc = Pan2.ar(osc , pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \noise, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/cluster.scd0000644000175100001770000000131614611211152022521 0ustar00runnerdockerSynthDef.new(\cluster, { |bus=0, gate=1, amp=1, dur=1, pan=0, freq=0, atk=0.01, sus=1, rel=0.009, blur=1, fmod=0, para1=7, mult=4, pstep=0.75| var env, osc; freq = In.kr(bus,1); freq = [freq, freq+fmod]; sus = sus * blur; env = Env.linen(attackTime:atk,sustainTime:sus,releaseTime:rel,curve:\lin).kr(doneAction:0); osc = Splay.ar(LeakDC.ar(CombN.ar(SinOsc.ar(1/para1,Spring.ar(LFPulse.ar(pstep), 4 / para1, [[0.5e-1, 1.4e-3]]) * LFTri.ar(freq, 0, 2pi, mult * pi), mul: 0.05), 2, 0, 2))).tanh; osc = Mix(osc * env) * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/combs.scd0000644000175100001770000000227714611211152022152 0ustar00runnerdockerSynthDef.new(\combs, { |bus=0, pan=0, amp=1, freq=440, gate=1, fmod=0, atk=0.01, sus=1, rel=0.3, vibrate=2, depth=0.8, regen= -3, sweep=8, rq=0.9, nharm=2| var max, min, vibrato, osc, env, filterenv; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; //Setting some values for the filters: min = ((1 + depth) / freq); max = (1 / (freq * (1 + depth))); vibrato = LFNoise1.ar(vibrate).range(min, max); //Amplitude and filter cutoff envelopes env = Env.asr(atk, sus, rel, curve: \sin).kr(gate: gate, doneAction: 0); filterenv = Env.perc(atk, sus + rel).kr; filterenv = ((filterenv * sweep) + 1) * freq; //The core noise: osc = Mix.ar([BrownNoise.ar(1) * 1/4, freq]); osc = CombL.ar(osc, max, vibrato, regen); osc = CombN.ar(osc, nharm / freq, nharm / freq, regen, env); //More filters and output stuff: osc = RHPF.ar(osc, freq * 2, rq); osc = RLPF.ar(osc, filterenv, rq, amp); osc = Limiter.ar(osc, amp); osc = Mix(osc) * 0.02; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "Modification of combs bass synth led to ambient sound shape", category: \misc, tags: [\metallic, \bass, \ambient, \pitched] ) ).add././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/creep.scd0000644000175100001770000000073214611211152022137 0ustar00runnerdockerSynthDef.new(\creep, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 4); osc=PMOsc.ar(freq, (freq * 2), 10); env=EnvGen.ar(Env(times: [sus, 0.001],levels: [0.0001, amp, 0],curve: 'exp'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/crunch.scd0000644000175100001770000000077514611211152022332 0ustar00runnerdockerSynthDef.new(\crunch, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 0.5); osc=LFNoise0.ar(((Crackle.kr(1.95) * freq) * 15), mul: amp); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: 0.1,level: (amp / 4),curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/cs80lead.scd0000644000175100001770000000250614611211152022445 0ustar00runnerdockerSynthDef.new(\cs80lead, { |bus = 0, freq = 440, amp = 1, gate = 1.0, pan = 0, fmod = 0, atk = 0.3, sus = 0.8, rel = 1.0, dec = 0.8, fatk = 0.75, fdec = 0.5, fsus = 0.8, frel = 1.0, cutoff = 200, dtune = 0.002, vibspeed = 4, vibdepth = 0.015, ratio = 0.8, glide = 0.15| var env, fenv, vib, ffreq, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; //Envelopes for amplitude and frequency: env = Env.linen(atk, sus, rel, curve: \sin).kr(gate: gate, doneAction: 0); fenv = Env.adsr(fatk, fdec, fsus, frel, curve: 2).kr(gate: gate, doneAction: 0); //Giving the input freq vibrato: vib = SinOsc.kr(vibspeed).range(1 / (1 + vibdepth), (1 + vibdepth)); freq = Line.kr(start: freq * ratio, end: freq, dur: glide); freq = freq * vib; //See beatings.scd for help with dtune osc = Saw.ar([freq, freq * (1 + dtune)], mul: env * amp * 0.05); osc = Mix.ar(osc); //Sending it through an LPF: (Keep ffreq below nyquist!!) ffreq = max(fenv * freq * 12, cutoff) + 100; osc = LPF.ar(osc, ffreq); osc = Mix(osc); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Mike Hairston", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "Vangelis/Blade Runner lead sound, based on tutorial by meastempo ", category: \keyboards, tags: [\lead, \modulation, \analog, \cs80, \vangelis, \bladerunner] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dab.scd0000644000175100001770000000116614611211152021571 0ustar00runnerdockerSynthDef.new(\dab, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=(HPF.ar(Saw.ar((freq / 4), mul: (amp / 2)), 2000) + VarSaw.ar((freq / 4), mul: amp, width: EnvGen.ar(Env.perc(attackTime: (sus / 20),releaseTime: (sus / 4),level: 0.5,curve: -5), doneAction: 0))); env=EnvGen.ar(Env(times: [(sus * 0.25), (sus * 1)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dafbass.scd0000644000175100001770000000154514611211152022447 0ustar00runnerdockerSynthDef.new(\dafbass, { |amp=1 pan=0, freq=0, vib=0, fmod=0, ffmod=1, rate=0, bus=0, atk=0.01, dec=0.1, sus=1, rel=0.09, level=0.8, peak=1, offnote=1.01| var osc, env, harm; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; //freq = [freq, freq] * Line.ar(Rand(0.5, 1.5), 1, 0.02); freq = (freq / 4); harm = [1, offnote, 2, offnote * 2]; harm = harm++(harm*ffmod); amp = amp / (ffmod / 0.5); osc = (SinOsc.ar(freq*harm).sum.distort * 2) + LFPulse.kr(freq + harm, 0, [0.5, 0.99]).sum.distort; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, dec, max((atk + dec + rel), sus - (atk + dec + rel)), rel], curve:\sin), doneAction: 0); osc = Mix(osc) * env * amp * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dbass.scd0000644000175100001770000000126414611211152022136 0ustar00runnerdockerSynthDef.new(\dbass, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, atk=0.02, decay=0.01, rel=0.01| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod] * Line.ar(Rand(0.5, 1.5), 1, 0.02); freq = (freq / 4); osc = ( VarSaw.ar(freq, width: LFTri.ar((0.5 * rate) / sus, iphase:0.9, add:0.8, mul: 0.2), mul: amp * 0.08)); env = EnvGen.ar(Env([0, 1, 0.8, 0.8, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel]), doneAction: 0); osc = Mix(osc * env); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dblbass.scd0000644000175100001770000000234314611211152022453 0ustar00runnerdockerSynthDef.new(\dblbass, { |bus = 0, amp = 1, freq = 440, fmod=0, atk = 0.01, sus=0, rel = 1.0, crv = \lin, vel = 1.0, // Other Controls freqdev = 4, op1mul = 0.1, op2mul = 0.1, op3mul = 0.1, spread = 0.5, subAmp = 0.1, pan=0| var env, op1, op2, op3, op4, osc, sub; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = (freq / 4); env = Env.linen(attackTime: atk, sustainTime: sus, releaseTime: rel, curve: crv).kr(doneAction: 0); op1 = SinOsc.ar(freq: freq * 4, mul: vel / 2 + op1mul); op2 = SinOsc.ar(freq: freq * 3, phase: op1, mul: vel / 2 + op2mul); op3 = SinOsc.ar(freq: freq * 2, phase: op2, mul: vel / 2 + op3mul); op4 = SinOsc.ar(freq: freq + NRand(-1 * freqdev, freqdev, 3), phase: op3, mul: amp * 0.5); osc = {DelayN.ar(in: op4, maxdelaytime: 0.06, delaytime: Rand(0.03, 0.06))} !8; osc = LeakDC.ar(osc); osc = Splay.ar(inArray: osc, spread: spread, level: 0.6, center: pan); sub = SinOsc.ar(freq: freq/2, mul: env * subAmp); sub = Pan2.ar(sub, pan); osc = osc + sub * env; osc = Limiter.ar(osc); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Matias Monteagudo", modified_by: "Suhel Keswani, Josh Mitchell, Jens Meisner", description: "", category: \bass, tags: [\pitched, \bass] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dirt.scd0000644000175100001770000000110214611211152021773 0ustar00runnerdockerSynthDef.new(\dirt, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 4); amp=(amp / 2); osc=((LFSaw.ar(freq, mul: amp) + VarSaw.ar((freq + 1), width: 0.85, mul: amp)) + SinOscFB.ar((freq - 1), mul: (amp / 2))); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/donk.scd0000644000175100001770000000065614611211152022001 0ustar00runnerdockerSynthDef.new(\donk, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=((freq / 2) + [0, 2]); amp=(amp / 1.25); osc=Ringz.ar((Impulse.ar(0, phase: rate) / (rate + 1)), freq, sus, amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/donk1.scd0000644000175100001770000000065614611211152022062 0ustar00runnerdockerSynthDef.new(\donk1, {|vib=0, bus=0, slide=0, rate=1, sus=1, slidefrom=1, fmod=0, amp=1, freq=0, bits=0, pan=0| var osc, env; freq = freq + fmod; freq = Line.ar(freq * slidefrom, freq * (1 + slide), sus); freq = Vibrato.kr(freq, rate: vib); amp=(amp * 9); freq=(freq / 4); osc=Ringz.ar(Impulse.ar(0), [freq, (freq + 2)], sus, amp); osc=osc.tanh; osc = osc * [min(1, (1-pan)/2), min(1, (pan+1)/2)]; ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/donk2.scd0000644000175100001770000000064014611211152022054 0ustar00runnerdockerSynthDef.new(\donk2, {|vib=0, bus=0, slide=0, rate=1, sus=1, slidefrom=1, fmod=0, amp=1, freq=0, bits=0, pan=0| var osc, env; freq = freq + fmod; freq = Line.ar(freq * slidefrom, freq * (1 + slide), sus); freq = Vibrato.kr(freq, rate: vib); amp=(amp * 9); freq=(freq / 4); osc=Ringz.ar(Impulse.ar(0), [freq, (freq + 2)], sus, amp); osc = osc * [min(1, (1-pan)/2), min(1, (pan+1)/2)]; ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/donkysub.scd0000644000175100001770000000120314611211152022671 0ustar00runnerdockerSynthDef.new(\donkysub, { |vib=4, bus=0, slide=0, rate=1, atk=0.08, sus=1, rel=0.9, slidefrom=1, fmod=0, amp=1, freq=0, bits=0, pan=0, frate=2| var osc, env; freq = freq + fmod; freq = Line.ar(freq * slidefrom, freq * (1 + slide), sus); freq = Vibrato.kr(freq, rate: vib); amp = (amp * 6); freq = (freq / (frate + 0.1)); osc = Ringz.ar(Impulse.ar(0), [freq, (freq + 2)], sus, amp); env = EnvGen.ar(Env.asr(atk, sus, rel, curve: \sin), doneAction:0); osc = osc * env * amp * 0.1; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \bass, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/donorgan.scd0000644000175100001770000000147014611211152022650 0ustar00runnerdockerSynthDef.new(\donorgan,{ |bus=0, pan=0, freq=440, amp=1, gate=1, fmod=0, atk=0.01, dec=0.5, sus=1, rel=0.5, lforate=9, lfowidth=0.01, cutoff=220, rq=0.5| var vibrato, filter, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; vibrato = SinOsc.kr(lforate, Rand(0, 2.0)); freq = freq * [1, 1.9953843530485, 3.0139733629359]; freq = freq * (1.0 + (lfowidth * vibrato)); env = EnvGen.ar(Env.linen(atk, sus, rel), gate, doneAction: 0); osc = VarSaw.ar(freq, iphase: 1, width: Rand(0.3, 0.5) ! 2, mul: 0.2); filter = RLPF.ar(osc, cutoff, rq); osc = Mix(osc * env ) * amp * 0.1; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Mitchell Sigman, Nick Collins", modified_by: "Bruno Ruviaro, Jens Meisner", decription: "Description", category: \organ, tags: [\keys, \pulsesynth] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dopple.scd0000644000175100001770000000171714611211152022330 0ustar00runnerdockerSynthDef.new(\dopple, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, bus=0, blur=1, gate=1, rate=1| var osc, env, osc1, osc2, osc3, ffreq, sig1; var buf = LocalBuf(2*s.sampleRate, 2); var choosetrig; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; ffreq = Sweep.kr(Impulse.kr(1/rate), 1/rate) * 10000; osc1 = LFSaw.ar(freq * 1 + (0.04 * [1,-1])); osc2 = LFSaw.ar(freq * 0.99); osc3 = LFSaw.ar(freq * 1 ); env = EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0], curve: 'lin'), doneAction: 0); osc = osc1 + osc2 + osc3; osc = (osc*50).tanh; osc = osc *env; sig1 = RLPF.ar(osc, ffreq, 0.5); RecordBuf.ar(sig1, buf, loop:1, trigger:0); rate = EnvGen.kr(Env([1,1,1],[0,1], -3), 0); osc = sig1; osc = Limiter.ar(osc).softclip; osc = Mix(osc) * 1/16; osc = Pan2.ar(osc * amp, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \noise, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/drone.scd0000644000175100001770000000135714611211152022154 0ustar00runnerdockerSynthDef.new(\drone, { |bus = 0, amp = 1, atk=0.01, pan=0, sus = 1, dur = 1, freq=0, gate=1, hpf2=40, fmod=0, speed = 2, lfnoise=80| var osc, sig, env; freq = In.kr(bus, 1); freq = (freq / 2); sig = LFNoise1; env = EnvGen.ar(Env.linen(atk, sus, 0.5, 0.1, curve:\lin), gate, doneAction:0); osc = HPF.ar( FreeVerb2.ar(*XFade2.ar( SinOscFB.ar([freq, freq], sig.ar(speed) + 0.5), SinOscFB.ar([freq, freq + fmod], sig.ar(speed * 2)), sig.ar(lfnoise))) , hpf2); osc = LeakDC.ar(osc, 0.995); osc = Limiter.ar(osc, 0.8); osc = Mix(osc * env) * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dub.scd0000644000175100001770000000074214611211152021614 0ustar00runnerdockerSynthDef.new(\dub, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 4); amp=(amp * 2); osc=(LFTri.ar(freq, mul: amp) + SinOscFB.ar(freq, mul: amp)); env=EnvGen.ar(Env.sine(dur: sus,level: amp), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dust.scd0000644000175100001770000000076214611211152022023 0ustar00runnerdockerSynthDef.new(\dust, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, rate=1, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq + fmod]; osc = Dust.ar(freq + rate); env = EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 0.25; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Modifier", decription: "Dust noise via random impulses", category: \noise, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/dustv.scd0000644000175100001770000000136614611211152022212 0ustar00runnerdockerSynthDef.new(\dustv, { |amp=1, sus=1, pan=0, freq=440, vib=0, atk=0.01, rel=0.09, fmod=0, reverbtime=3, roomdepth=8, rate=0, room=0, bus=0| var osc, env, random; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; random = Dwhite(0.0, 1.0, inf); osc = GVerb.ar(CombC.ar(Dust.ar(rate+5) / Blip.ar(freq, Line.kr(5, 120, 200), 0.2), Dust.ar(random), 0.01, 0.02), roomdepth, reverbtime, mul: 0.001); //env = EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction: 0); env = EnvGen.ar(Env.linen(atk, sus, rel, curve:\lin), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \noise, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ebass.scd0000644000175100001770000000443314611211152022140 0ustar00runnerdockerSynthDef(\ebass, { // Standard values |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.001, decay=0.01, rel=0.01, pick=0.414, rq = 0.5, cutoff = 250| var exciter, freqArray, ampArray, decArray, constant, mute, osc, openFreq, pickupPos, pickupWidth, decayCoef, dampCoef; openFreq = 82.5; pickupPos = 17*decay; pickupWidth = 0.75; decayCoef = 0.125; dampCoef = 0.0002; sus = sus*blur; freq = In.kr(bus, 1); freq = freq / 4; freq = [freq, freq+fmod]; // Make a Constant from pickupWidth for ampArray constant = pickupWidth/25.5; // The scale length is set to 25.5 inches constant = constant * pi/2; constant = constant/82.5; // Stiff String Model for Frequencies freqArray = Array.fill(10, {arg i; (i + 1) * sqrt(1 + ((i + 1).pow(2) * 0.00001)) }); freqArray = freqArray/freqArray[0]; // Decay Times decArray = Array.fill(10, {arg i; exp((-1 * i)/((1/decayCoef) + ((dampCoef/10) * freq.pow(2)) + (dampCoef * freqArray[i].pow(2))))}); decArray = decArray/decArray[0]; // Rescale freqArray for ampArray and Klank freqArray = freqArray * freq; // Effects of Pick Position and Pickup Placement ampArray = Array.fill(10, {arg i; ((1 - ((freqArray[i] - 19000)/1000).tanh)/2) * sin(((i + 1) * pi) * pick) * ( sin(pi * pickupPos * freqArray[i]/openFreq) * ( ( sin(constant * freqArray[i])/ (constant * freqArray[i]) ) - cos(constant * freqArray[i]) ) )/(freqArray[i].pow(2))}); ampArray = ampArray * 2/(constant.pow(2)); // The Pick exciter = Impulse.ar(0) * 1; // The String osc = Klank.ar(specificationsArrayRef: Ref.new([freqArray, ampArray, decArray]), input: exciter, decayscale: sus*2 + rel); osc = Mix.ar(osc); // The Pickup osc = RLPF.ar(in: osc, freq: cutoff, rq: rq); osc = LPF.ar(in: osc,freq: 250); // An Envelope for Muting the String mute = Env.new(levels: [1, 1, 0, 0], times: [rel+sus, 0.05, 0.01]).ar(doneAction: 2); // Mute the String osc = LPF.ar(in: osc, freq: LinExp.ar(in: mute, srclo: 0, srchi: 1, dstlo: 20, dsthi: 20000)); // Output Stuff osc = osc * amp; osc = osc.tanh; osc = LeakDC.ar(osc); osc = Limiter.ar(osc); //DetectSilence.ar(in: osc, doneAction:0); ReplaceOut.ar(bus, Pan2.ar(osc, pan)); }, metadata: ( credit: "by Josh Mitchell", category: \guitar, tags: [\pitched, \modal] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ecello.scd0000755000175100001770000000165314611211152022312 0ustar00runnerdockerSynthDef(\ecello,{ |bus=0, amp=1, sus=1, dur=1, fmod=0, pan=0.0, atk=0.3, rel=0.09, rq=0.9, freq=440, range=0, vibrate=6, width=1, decimate=22040, decibits=4, offnote=1.005| var osc, osc2, env, w; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 4; env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \lin), doneAction: 0); w = LFNoise2.kr(width).range(0.001, 0.8); osc = VarSaw.ar([freq, freq * offnote] + SinOsc.ar(vibrate, mul: Line.kr(0.0, 1, dur, mul: 1, doneAction: 0)), width: w, mul: 1); osc = RLPF.ar(osc, freq, rq); osc2 = SyncSaw.ar(freq + SinOsc.ar(vibrate, mul: 1), mul: 1/2); osc2 = RLPF.ar(osc2, freq, rq); osc = Mix.ar([osc, osc2]); osc = Decimator.ar(osc, decimate, decibits); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Unknown", modified_by: "Jens Meisner", decription: "Bird singer", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/eeri.scd0000644000175100001770000000160414611211152021764 0ustar00runnerdockerSynthDef.new(\eeri, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, cutoff=400, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus = (sus * 1.75); amp = (amp * 2); freq=Vibrato.kr(freq, (rate + 4)); osc = RLPF.ar(SinOsc.ar(Saw.ar([1, 2]).range(1, 104)) * SyncSaw.ar(SinOsc.ar(0.01).range(1, 100), SinOsc.ar(0.01).range(freq, freq*2)), Line.ar(cutoff, freq, 1)); osc = GVerb.ar(osc + CombL.ar(osc, 0.3, 1, 1), 10); env = EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc = (osc * env); // osc = DWGReverb3Band.ar(osc, 10); osc = Mix(osc) * 1/16; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \noise, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/eoboe.scd0000644000175100001770000000174714611211152022141 0ustar00runnerdockerSynthDef(\eoboe,{ |bus=0, amp=1, sus=1, dur=1, fmod=0, pan=0.0, atk=0.3, rel=0.4, rq=0.3, freq=440, range=0, vibrate=6, width=1, decimate=22040, decibits=2, offnote=1.005| var osc, osc2, env, wid; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = [freq / 2, freq / 2 * offnote]; env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \sin), doneAction:0); wid = LFNoise2.kr(width).range(0.001, width); osc = VarSaw.ar(freq + SinOsc.ar(vibrate, mul: Line.kr(0.0, 1, dur, mul:1, doneAction: 0)), width: wid, mul:1/2); osc = RLPF.ar(osc, freq, rq); osc2 = SinOsc.ar(freq + SinOsc.ar(vibrate, mul: Line.kr(0.0, 1, dur, mul:1, doneAction: 0)), mul:2/3); osc2 = RLPF.ar(osc2, freq*2, rq); osc = Mix([osc, osc2]); osc = Decimator.ar(osc, decimate, decibits); osc = osc * env * amp * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Unknown", modified_by: "Jens Meisner", decription: "Distorted mock on oboe", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/epiano.scd0000644000175100001770000000232314611211152022312 0ustar00runnerdockerSynthDef(\epiano, { |bus = 0, freq = 440, amp = 1, fmod = 0, atk = 0.1, sus = 1, rel = 0.3, pan = 0, tone = 0.5, hollowness = 0.02| var hammer, osc, delay, tonefreq, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.perc(atk, sus + rel, amp, -1).ar(doneAction: 0); // Delay line times: freq, freq - 4 cents, freq + 3 cents. In the original this was done by converting freq to midi. delay = (1 / (freq * [2.pow(-0.04/12), 1, 2.pow(0.03/12)])); tonefreq = tone.linlin(0, 1, 1000, 5000); hammer = Decay2.ar(in: Impulse.ar(0.001), attackTime: 0.008, decayTime: 0.04, mul: LFNoise2.ar(freq: amp.linlin(0, 1, tonefreq, 2 * tonefreq), mul: 0.25)); //Try LFNoise1, LFNoise0, or even LFClipNoise above for a slightly grainier sound. osc = CombL.ar(hammer, delay, delay, 50 * amp); osc = HPF.ar(osc, hollowness.linlin(0, 1, 50, 1000)); osc = osc * env; osc = Limiter.ar(osc); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Jeff & James", modified_by: "Josh Mithell, Bruno Ruviaro, Jens Meisner", description: "based on something posted 2008-06-17 by jeff, based on an old example by james mcc", category: \keyboards, tags: [\casio, \piano, \pitched] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/faim.scd0000644000175100001770000000342714611211152021761 0ustar00runnerdockerSynthDef.new(\faim, { |bus=0, amp=1, atk=0.001, decay=0.01, sus=1, rel=0.01, level=0.8, peak=1, gate=1, pan=0, freq=0, fmod=0, vib=0, rate=1, blur=1, beat_dur=1, vibr=0| var osc, sig1, sig2, sig3, sig4, sig5, sig6, sig7, sig8, env, env1, env2, env3, env4, env5, env6, env7, env8; sus = sus*blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq * ((0..1)/1 - 0.5 * 0.0007 + 1); env1 = EnvGen.kr(Env([0, 1, 0.051, 0], [0.001, 0.01, 0.8], [4, -8]), 1); env2 = EnvGen.kr(Env([0,1,0.051,0],[0.005,0.5,1.5], [0,-8], releaseNode:2), 1); env3 = EnvGen.kr(Env([0,1,1,0],[0.01,0.01,0.2], [0,0,-4], releaseNode:2), gate); env4 = EnvGen.kr(Env([0,1,0],[0.002,2.8], [0,-4]), 1); env5 = EnvGen.kr(Env([0,1,1,0],[0.001,0.1,0.8], [4,0,-4], releaseNode:2), gate); env6 = EnvGen.kr(Env([0,1,0],[0.001,3.0], [0,-4]), 1); sig1 = SinOsc.ar(freq * 11 + 0) * env1 + (SinOsc.ar(vibr) * env1); sig2 = SinOsc.ar(freq * 6 * ( sig1 * 2.5 + 1 )) * env2; sig3 = SinOsc.ar(freq * 2 * 1 + 0) * env3; sig4 = SinOsc.ar(freq * 1 * ( sig3 * 2.5 + 1 ) + 0) * env4; sig5 = SinOsc.ar(freq * 1 * ( sig2 * 2.5 + 1 ) * (sig4 * 2.5 + 1)) * env5; sig6 = SinOsc.ar(freq * 2) * env6; osc = [sig1, sig2, sig3, sig4, sig5, sig6] * DC.ar([0.0, 0.0, 0.0, 0.0, 0.5, 0.5]); osc = osc / 2; osc = osc.flop.sum; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = osc * env; osc = BLowShelf.ar(osc, 40, 1.0, -12); osc = osc * AmpComp.kr(freq); osc = Limiter.ar(osc); osc = osc.tanh; osc = Mix(osc) * amp * 0.05; osc = Pan2.ar(osc, pan + [ 0, 0, 0, 0, 0, 0]).sum; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/faim2.scd0000644000175100001770000000336114611211152022040 0ustar00runnerdockerSynthDef.new(\faim2, { |bus=0, amp=0.1, atk=0.001, decay=0.01, sus=1, rel=0.01, level=0.8, peak=1, gate=1, pan=0, freq=0, fmod=0, vib=0, beef=0, rate=1, blur=1, beat_dur=1| var osc, osc1, osc2, osc3, osc4, osc5, osc6, osc7, osc8; var env, env1, env2, env3, env4, env5, env6, env7, env8; sus = sus*blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 2; freq = freq * ((0..1)/1 - 0.5 * 0.0007 + 1); env1 = EnvGen.kr(Env([0,1,0.051,0],[0.001,0.01,0.8], [4,-8]), 1); env2 = EnvGen.kr(Env([0,1,0.051,0],[0.005,0.5,1.5], [0,-8], releaseNode:2), 1); env3 = EnvGen.kr(Env([0,1,1,0],[0.01,0.01,0.2], [0,0,-4], releaseNode:2), gate); env4 = EnvGen.kr(Env([0,1,0],[0.002,2.8], [0,-4]), 1); env5 = EnvGen.kr(Env([0,1,1,0],[0.001,0.1,0.8], [4,0,-4], releaseNode:2), gate); env6 = EnvGen.kr(Env([0,1,0],[0.001,3.0], [0,-4]), 1); osc1 = SinOsc.ar(freq * 11) * env1 + (SinOsc.ar(vib) * env1); osc2 = SinOsc.ar(freq * 8 * ( osc1 * 2.5 + 1 )) * env2; osc3 = SinOsc.ar(freq * 2) * env3; osc4 = SinOsc.ar(freq * 1 * ( osc3 * 2.5 + 1 ) + 0) * env4; osc5 = SinOsc.ar(freq * (1+beef) * ( osc2 * 2.5 + 1 ) * (osc4 * 2.5 + 1)) * env5; osc6 = SinOsc.ar(freq * 1) * env6; env = EnvGen.ar(Env.asr(atk, sus, rel, curve:\sin), gate, doneAction: 0); osc = [osc1, osc2, osc3, osc4, osc5, osc6] * DC.ar([0.0, 0.0, (1+beef) / 4, 0.0, 0.5, 1]); osc = osc / ( 2 + beef); osc = osc.flop.sum; // Cutting very low freq osc = BLowShelf.ar(osc, 40, 1, -12); osc = osc * AmpComp.kr(freq) * 0.65; osc = Limiter.ar(osc); osc = osc.tanh; osc = osc * env * amp; osc = Mix(osc) * 0.3; osc = Pan2.ar(osc, pan).sum; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/fbass.scd0000644000175100001770000000204314611211152022134 0ustar00runnerdockerSynthDef.new(\fbass, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.001, decay=1, rel=0.2, cutoff = 250, rq = 0.35| var total, exciter, osc, env, sub; sus = sus*blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 4; total = (atk + sus + decay + rel) * freq; exciter = Env.new(levels: [0, 1, 1, 0, 0], times: [atk, decay, sus, rel]/total).ar; env = EnvGen.ar(Env([0,1,0.8,0.8,0], [0.002, 0.01, sus, sus]), doneAction: 0); // Delay line osc = CombN.ar(in: exciter, maxdelaytime: 0.06, delaytime: 1/freq, decaytime: sus); // LPF osc = RLPF.ar(in: osc, freq: LinExp.ar(Amplitude.ar(in: osc), 0, 1, cutoff, 18000), rq: rq); // Compressor for fun osc = CompanderD.ar(in: osc, thresh: 0.4, slopeBelow: 1, slopeAbove: 1/2.5); osc = Mix.ar(osc.tanh); osc = LeakDC.ar(osc); osc = osc * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc); }, metadata: ( credit: "Josh Mitchell, CrashServer", modified_by: "", description: "", category: \bass, tags: [\pitched, \bass] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/feel.scd0000644000175100001770000000113414611211152021751 0ustar00runnerdockerSynthDef.new(\feel, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus=(sus * 1.5); amp=(amp / 3); freq=(freq * [1, 1.005]); osc=Klank.ar(`[[1, 2, 3, (3 + ((rate - 1) / 10))], [1, 1, 1, 1], [2, 2, 2, 2]], (Impulse.ar(0.0005) * Saw.ar(freq, add: 1)), freq); env=EnvGen.ar(Env(times: (sus * 2),levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/filthysaw.scd0000644000175100001770000000172514611211152023056 0ustar00runnerdockerSynthDef.new(\filthysaw, { |bus=0, freq=0, amp=1, gate=1, fmod=0, atk=0.001, sus=1, decay=0.01, cf=100, vib=0, t_bd=0, t_sd=0, pw=0.4, pan=0| var base, env, osc, sd, bd; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; base = Splay.ar(RLPF.ar(Pulse.ar(freq * [0.99, 0.5, 1.01], pw), cf.lag(0.05), 0.8).madd(SinOsc.ar(vib).range(0.5, 4)).sin); env = EnvGen.ar(Env.linen(atk, sus, decay), gate, doneAction:0); osc = Mix([base/2, (LFSaw.ar(freq)/20)]); bd = tanh(Ringz.ar(LPF.ar(Trig.ar(t_bd,SampleDur.ir), 2000), freq, 0.5, 5).sin*2); sd = tanh(Ringz.ar(LPF.ar(Trig.ar(t_sd,SampleDur.ir), 2000), freq, 0.75, PinkNoise.ar(2!2)).sin*2); sd = HPF.ar(sd, 60); osc = tanh(GVerb.ar(HPF.ar(base * env, 30), 70, 11, 0.15)*0.5 + osc + bd + sd); osc = osc * env * amp * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/flute.scd0000644000175100001770000000322614611211152022161 0ustar00runnerdockerSynthDef(\flute, { |bus=0, scl = 0.4, freq = 440, fmod=0, atk=0.1, dur=1, sus=1, ipress = 0.9, ibreath = 0.09, ifeedbk1 = 0.4, ifeedbk2 = 0.4, gate = 1, pan = 0, amp = 1| var kenv1, kenv2, kenvibr, kvibr, sr, cr, block, poly, osc, ifqc, fdbckArray; var aflow1, asum1, asum2, afqc, atemp1, ax, apoly, asum3, avalue, atemp2, aflute1; sr = SampleRate.ir; cr = ControlRate.ir; block = cr.reciprocal; freq = In.kr(bus, 1); ifqc = freq; // noise envelope kenv1 = EnvGen.kr(Env.linen(atk, sus*2/3, sus*1/3, 1.0, \lin), doneAction: 0); // overall envelope kenv2 = EnvGen.kr(Env.linen(atk, sus*2/3, sus*1/3, 1.0, \sin), doneAction: 0); // vibrato envelope kenvibr = EnvGen.kr(Env.linen(atk, sus*2/3, sus*1/3, 1.0, \sin), doneAction:0); // create air flow and vibrato aflow1 = LFClipNoise.ar(sr, kenv1); kvibr = SinOsc.ar(5, 0, 0.1 * kenvibr); asum1 = (ibreath * aflow1) + kenv1 + kvibr; afqc = ifqc.reciprocal - (asum1/20000) - (9/sr) + (ifqc/12000000) - block; fdbckArray = LocalIn.ar(1); aflute1 = fdbckArray; asum2 = asum1 + (aflute1 * ifeedbk1); //ax = DelayL.ar( asum2, ifqc.reciprocal * 0.5, afqc * 0.5 ); ax = DelayC.ar(asum2, ifqc.reciprocal - block, afqc * 0.5 - (asum1/ifqc/cr) + 0.001); apoly = ax - (ax.cubed); asum3 = apoly + (aflute1 * ifeedbk2); avalue = LPF.ar(asum3, 2100); aflute1 = DelayC.ar(avalue, ifqc.reciprocal - block * 4, afqc); fdbckArray = [aflute1]; LocalOut.ar(fdbckArray); osc = avalue * 1/2; osc = osc * kenv2 * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc); }, metadata: ( credit: "John E. Bower", modified_by: "Jens Meisner", description: "", category: \flute, tags: [\slideflute, \wind, \bassflute] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/fm.scd0000644000175100001770000000125614611211152021445 0ustar00runnerdockerSynthDef.new(\fm, { |bus = 0, freq = 440, index = 3, amp=1, pan=0, sus=1, level=1, atk=0.5, rel=0.09, gate=1, fmod=0| var mod, car, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod] * Line.ar(Rand(0.5,1.5),1,0.02); mod = SinOsc.ar(freq * 1,0,freq * index); osc = SinOsc.ar((freq * 2) + mod, 4); osc = osc + (Mix.arFill(7, { CombL.ar(osc, 0.005, 0.15, 0.15) })/2); env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \sin), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 1/32; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/fmbass.scd0000644000175100001770000000254514611211152022320 0ustar00runnerdockerSynthDef.new(\fmbass, { |bus = 0, pan = 0, amp = 0.1, freq = 440, fmod = 0, atk = 0.1, sus=1, rel = 1, crv = -4, atkfract = 0.05, relfract = 0.7, modindex = 80, modratio = 1.51, subamp = 0.99, modfb = 1| var scale, mAtk, mRel, modulatorEnv, modulator, carrierEnv, carrier, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; // Scale the att/rel for the Modulator scale = (atkfract + relfract); scale = Select.kr(which: InRange.kr(in: scale, lo: 1, hi: inf), array: [ DC.kr([atkfract, relfract]), DC.kr([atkfract/scale, relfract/scale]) ]); scale = scale * (atk + sus + rel); mAtk = scale[0]; mRel = scale[1]; // Modulator modulatorEnv = Env.perc(attackTime: mAtk, releaseTime: mRel, level: modindex, curve: crv).ar; modulator = SinOscFB.ar(freq: freq * modratio, feedback: modfb, mul: modulatorEnv); // Carrier carrierEnv = Env.perc(attackTime: atk, releaseTime: sus + rel, curve: crv).ar(doneAction: 0); carrier = SinOsc.ar(freq: freq + modulator, mul: carrierEnv); // Add a Sub osc = carrier + SinOsc.ar(freq: freq/2, mul: carrierEnv * subamp); // Output Stuff osc = Limiter.ar(osc); osc = Mix(osc) * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "FM-based SynthDef mostly from Eli Fieldsteel", category: \bass, tags: [\pitched, \fm] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/fmrhodes.scd0000644000175100001770000000242314611211152022647 0ustar00runnerdockerSynthDef.new(\fmrhodes, { |bus = 0, freq = 0, gate = 1, pan = 0, amp = 1, fmod=0, vel = 0.8, modindex = 0.2, oscmix = 0.1, lfospeed = 0.4, lfodepth = 0.1| var env1, env2, env3, env4, osc1, osc2, osc3, osc4, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; lfospeed = lfospeed * 12; env1 = EnvGen.ar(Env.adsr(0.001, 1.25, 0.0, 0.04, curve: \lin)); env2 = EnvGen.ar(Env.adsr(0.001, 1.00, 0.0, 0.04, curve: \lin)); env3 = EnvGen.ar(Env.adsr(0.001, 1.50, 0.0, 0.04, curve: \lin)); env4 = EnvGen.ar(Env.adsr(0.001, 1.50, 0.0, 0.04, curve: \lin)); osc4 = SinOsc.ar(freq * 0.5) * 2pi * 2 * 0.535887 * modindex * env4 * vel; osc3 = SinOsc.ar(freq, osc4) * env3 * vel; osc2 = SinOsc.ar(freq * 9) * 2pi * 0.108819 * env2 * vel; osc1 = SinOsc.ar(freq, osc2) * env1 * vel; osc = Mix((osc3 * (1 - oscmix)) + (osc1 * oscmix)) * 0.08; osc = osc * (SinOsc.ar(lfospeed) * lfodepth + 1); env = EnvGen.ar(Env.asr(0, 1, 0.1), gate, doneAction: 0); osc = osc * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "unknown", modified_by: "Josh Mitchell, Bruno Ruviaro, Jens Meisner", decription: "FM Rhodes Synthesizer. Native SuperCollider port of STK's Rhodey", category: \keyboards, tags: [\fmSynth, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/four.scd0000644000175100001770000000140514611211152022012 0ustar00runnerdockerSynthDef.new(\four, { |amp=1, sus=1, atk=0.01, rel=0.008, dec=0.8, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = SinOsc.ar([1, 2, 4, 8], mul:0.5) * LFSaw.ar([freq, freq*1.02, freq*(fmod + 0.99), freq*1.01]); osc = OnePole.ar(osc, SinOsc.ar(0.1).range(-0.9,0.9)); osc = LPF.ar(osc,SinOsc.kr(rate).range(110,8100)); osc = AllpassN.ar(osc,0.133, 0.133, 1); osc = FreeVerb.ar(osc, 0.133, 1); env = EnvGen.ar(Env([0,1,0.8,0.8,0], [0.02, 0.01,sus,sus]), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/fuzz.scd0000644000175100001770000000102514611211152022033 0ustar00runnerdockerSynthDef.new(\fuzz, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 2); amp=(amp / 6); osc=LFSaw.ar(LFSaw.kr(freq, 0, freq, (freq * 2))); env=EnvGen.ar(Env(times: [(sus * 0.8), 0.01],levels: [(amp * 1), (amp * 1), (amp * 0.01)],curve: 'step'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/garfield.scd0000644000175100001770000000144114611211152022614 0ustar00runnerdockerSynthDef.new(\garfield, { |bus=0, freq=440, amp=1, pan=0, gate=1, fmod=0, atk=0.01, sus=1, phase=0, smooth=0.5, mult=3, vibrato=1, rq=1| var env, osc, del; freq = In.kr(bus,1); freq = [freq, freq+fmod]; env = Env.linen(atk, sus, 0.1, curve:\sin).kr(doneAction:0); del = SinOsc.ar(1/8, phase, mult); osc = SinOscFB.ar(freq, 0.3, add: SinOsc.ar(vibrato)); osc = CrossoverDistortion.ar(osc, 0.8, smooth); osc = RLPF.ar(osc, 2800, rq) + osc; osc = CombN.ar(osc, 0.03, 0.085); osc = Splay.ar(osc); osc = Mix(osc); osc = LeakDC.ar(Limiter.ar(osc * 0.08, 1)); osc = osc * env * amp * 0.2; osc = osc.tanh; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc); }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/gaze.scd0000644000175100001770000000327314611211152021772 0ustar00runnerdockerSynthDef.new(\gaze, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.0001, decay=0.01, rel=0.01, peak=1, level=0.8, wave=0, freq1=880, freq2=880, res1=0.0, res2=0.0, rate1=10, rate2 = 10, rate3 = 10, depth1=1, depth2=1, depth3=1, lfo1=0, lfo2=0, lfo3 = 0| var sig, env, detuned, pitch, lfo1wave, lfo2wave, lfo3wave, filter1; ~wt = Array.fill(90, { var numSegs = rrand (90, 20); Env( (({rrand(0.0, 1.0)}!(numSegs-1))*[1, -1]).scramble, {rrand(1, 20)}!numSegs, 'sine' // {rrand(-20,20)}!numSegs ).asSignal(1024).asWavetable; }); ~vbuf = Buffer.allocConsecutive(90, s, 2048); ~vbuf.do({ arg buf, i; buf.loadCollection(~wt[i]); }); sus = sus * blur; freq = In.kr(bus, 1); lfo1wave=Select.kr(lfo1, [LFTri.kr(rate1), LFSaw.kr(rate1), LFPulse.kr(rate1)]); lfo2wave=Select.kr(lfo2, [LFTri.kr(rate2), LFSaw.kr(rate2), LFPulse.kr(rate2)]); lfo3wave=Select.kr(lfo3, [LFTri.kr(rate3), LFSaw.kr(rate3), LFPulse.kr(rate3)]); detuned = VOsc.ar(wave, freq+fmod); wave = ~vbuf[0].bufnum + wave; env=EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); sig = VOsc.ar(wave, freq); sig = XFade2.ar(sig, detuned, 0.5); sig = MoogLadder.ar(sig, freq1*lfo1.range(1, depth1), res1); //sig = Decimator.ar(filter1, alias, redux); sig = MoogLadder.ar(sig, freq2*lfo2.range(1, depth2), res2); sig = Splay.ar(sig); sig = LeakDC.ar(sig); sig=sig*amp*env*lfo3.range(1, depth3); sig = Limiter.ar(sig, 0.9); ReplaceOut.ar(bus, sig) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \organ, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/glass.scd0000644000175100001770000000116214611211152022150 0ustar00runnerdockerSynthDef.new(\glass, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus=(sus * 1.5); amp=(amp * 1.5); freq=(freq * [1, (1 + (0.005 * rate))]); osc=Klank.ar(`[[2, 4, 9, 16], [1, 1, 1, 1], [2, 2, 2, 2]], (PinkNoise.ar(0.0005).dup * SinOsc.ar((freq / 4), add: 1, mul: 0.5)), freq); env=EnvGen.ar(Env(times: (sus * 2),levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/glitchbass.scd0000644000175100001770000000207314611211152023164 0ustar00runnerdockerSynthDef.new(\glitchbass, { |amp=1, sus=1, gate=1, pan=0, modfreq=5 freq=0, vib=0, fmod=0, rate=1, phase=0.5, cutoff=2000, rq=0.5, mul=1, bus=0, atk=0.0001, decay=0.01, rel=0.01, level=0.8, peak=1| var osc, pulse, filter, env, clip; freq = In.kr(bus, 1); freq = freq/2; amp = amp*0.5; clip = LinLin.kr(vib, 0, 1, 2e-12, 2e-1); osc = AllpassC.ar(SinOsc.ar(freq).tanh, 1, TExpRand.ar(2e-4,clip, Impulse.ar(fmod)).round([4e-3, 4e-1]), 2); osc = AllpassN.ar(osc, 0.01, XLine.kr(0.0001, 0.01, 20), 0.2); osc = osc/2 + GVerb.ar(osc); osc = LPF.ar(osc, 4400); osc = LPF.ar(osc, 4400); osc = LPF.ar(osc, 4400); osc = HPF.ar(osc, 80); env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = BLowPass4.ar(osc,(cutoff*(env.squared))+200+freq,rq); osc = osc * env * amp; osc = Mix(osc) * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/glitcher.scd0000644000175100001770000000273514611211152022647 0ustar00runnerdockerSynthDef(\glitcher, { |bus=0, pan=0, amp=1, fmod=0, len =20, sus=1, henA=2, rate=1, henB=0.4, t=1, gate = 1| var osc, env, mainEnv, speed, freq, pulse, a, bass, tone1, tone2, tone3, noise, impulse; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env(times: [(sus * 0.25), (sus * 1)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); mainEnv = EnvGen.kr(Env.triangle(len,1), gate, doneAction: 0); speed = Array.geom(8, t, [0.75, 1.25].choose); freq = Array.geom(2, freq*4, 1); pulse = {|rat1,rat2|LFPulse.ar(rate, [0,0.5,1].choose)*LFPulse.ar(rat2)}; a = Lag.ar(HenonN.ar(speed.choose*(mainEnv*500000.rand), henA, henB), 0.01); bass = SinOsc.ar(freq!2*(a*rate.rand), 1, Lag.ar(pulse.(t, speed.choose), 0.001)); tone1 = SinOsc.ar([(freq+Rand(0,5))*a,(freq+Rand(0,5))*a], 0, 0.01*pulse.(speed.choose, speed.choose)); tone2 = Pan2.ar(SinOsc.ar(freq.choose*a, 0, 0.1*pulse.(speed.choose, t)), a); tone3 = SinOsc.ar([freq.choose,freq.choose*a], 0, 0.05*pulse.(speed.choose, t))*mainEnv.round(0.25); noise = Pan2.ar(PinkNoise.ar(a*4*pulse.(t,t)), a); impulse = RLPF.ar(Impulse.ar(pulse.(t, speed.choose), a), freq.choose+(a*rate), 1, 0.1).tanh; osc = (bass+tone1+tone2+tone3+noise+impulse).tanh; osc = DelayN.ar(osc, 0.2, 0.1); osc = HPF.ar(osc, 200); osc = osc * amp * env; osc = Mix(osc) * 0.8; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/gong.scd0000644000175100001770000000130014611211152021763 0ustar00runnerdockerSynthDef.new(\gong, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 2.5); freq=(freq * 2); osc=(Klank.ar(`[[0.501, 1, 0.8, 2.002, 3, 9.6, 2.49, 11, 2.571, 3.05, 6.242, 12.49, 13, 16, 24], [0.002, 0.02, 0.001, 0.008, 0.02, 0.004, 0.02, 0.04, 0.02, 0.005, 0.05, 0.05, 0.02, 0.03, 0.04], [1.2, 1.2, 1.2, 0.9, 0.9, 0.9, 0.25, 0.25, 0.25, 0.14, 0.14, 0.14, 0.07, 0.07, 0.07]], SinOscFB.ar(20, 0, 10), freq, (freq * rate), 4) * amp); osc=HPF.ar(osc, 440); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/grat.scd0000644000175100001770000000212214611211152021771 0ustar00runnerdockerSynthDef.new(\grat, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, bus=0, blur=1, gate=1, rate=1, rlpf=4000| var osc, env, minfreqs, freqs, dry, osc2, osc3; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freqs = (freq +[0,7,12,15,19,24].midicps) /4; minfreqs = freqs*0.5; freqs = freqs*MouseButton.kr(1,0.75,4); env = EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc = LocalIn.ar(2) + WhiteNoise.ar(0.001!2); osc = DelayN.ar(osc,1/10-ControlDur.ir,1/20-ControlDur.ir); osc = CombN.ar(osc!6,1/minfreqs,1/freqs,8).mean; osc = LPF.ar(osc, 8000); osc = HPF.ar(osc * 5 + WhiteNoise.ar(2),80); osc = RLPFD.ar(osc, rlpf + WhiteNoise.kr(mul:4)*[1,1.1],0.1,0.5); osc = osc + osc.mean; osc2 = LocalOut.ar(osc); dry = osc; 5.do { d = 0.2.rand; osc3 = AllpassN.ar(osc,d,d,5); }; osc = (dry + osc) * 0.125; osc = osc * env * amp * 1/2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/gray.scd0000644000175100001770000000067714611211152022013 0ustar00runnerdockerSynthDef.new(\gray, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = GrayNoise.ar(); env=EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction:1); osc=(osc * env * amp); osc = Mix(osc) * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/growl.scd0000644000175100001770000000103614611211152022171 0ustar00runnerdockerSynthDef.new(\growl, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus=(sus * 1.5); osc=(SinOsc.ar((freq + SinOsc.kr(0.5, add: 1, mul: 2)), mul: amp) * Saw.ar(((sus / 1.5) * 32))); env=EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/gsynth.scd0000644000175100001770000000123014611211152022347 0ustar00runnerdockerSynthDef.new(\gsynth, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1.0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, buf=0, pos=0, room=0.1, sample=0| var osc, env; sus = sus * blur; rate = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = PlayBuf.ar(2, buf, BufRateScale.kr(buf) * rate, startPos: BufSampleRate.kr(buf) * pos); osc = osc * EnvGen.ar(Env([0,1,1,0],[0.05, sus-0.05, 0.05])); osc=(osc * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/harp.scd0000644000175100001770000000211314611211152021766 0ustar00runnerdockerSynthDef.new(\harp,{ |bus=0, amp=1, freq=0, pan=0, fmod=0, atk=0.01, sus=1, trig=1, decaytime=7, coef=0.04, blend=0.7| var osc, env, exciter, root, octave; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(attackTime: atk, sustainTime: decaytime, releaseTime: sus).kr(doneAction: 0); exciter = PinkNoise.ar(amp); //fundamental root = Pluck.ar(in: exciter, trig: trig, maxdelaytime: 0.02, //only change this if freq goes below 20hz delaytime: 1 / freq, decaytime: decaytime, coef: coef, mul: blend); //octave up octave = Pluck.ar(in: exciter, trig: trig, maxdelaytime: 0.02, //only change this if freq goes below 20hz delaytime: 1/(2*freq), decaytime: decaytime, coef: coef, mul: (1 - blend)); osc = Mix.ar(root + octave); osc = osc * env * amp * 0.5; DetectSilence.ar(in: osc, doneAction: 0); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Zé Craum", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", decription: "Harpsichord based on Pluck Ugen", category: \keyboards, tags: [\pitched, \harpsichord] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/hnoise.scd0000644000175100001770000000236114611211152022326 0ustar00runnerdockerSynthDef(\hnoise, { |bus=0, freq=800, gate=1, amp=1, atk=0.01 sus=1, fmod=0, pan=0, rel=0.9, room=0.5, rate=1| var env, osc, osc2, cenv; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; cenv = EnvGen.ar(Env.perc(0, 0.02), Dust.kr(SinOsc.kr(0.01).range(1, 10))); env = EnvGen.ar(Env.asr(atk, sus, rel), gate, doneAction: 0); osc = Henon2DN.ar(freq, freq*2, LFNoise2.kr(1, 0.2, 1.2), LFNoise2.kr(1, 0.15, 0.15) * 12); osc = Pan2.ar(osc * cenv); osc = PitchShift.ar(osc,0.2,TRand.kr(4, 2, Dust.kr(0.5))); osc = CombC.ar(osc, 1, LFNoise1.kr(0.1).range(0.1, 0.3), 4); osc2 = RLPFD.ar(LFSaw.ar([osc.range(100, 10000).round(50),osc.range(100, 10000).round(50)], 0, 0.8),1000, 0.8, 0.6, 10); osc2 = Decimator.ar(CombC.ar(osc2, 0.1, 0.5, 10), 2020, 3) * 0.0125; osc = Mix([osc, osc2 * 1]); osc = LeakDC.ar(CombC.ar(Mix.ar([osc,(osc2*LFNoise1.kr(0.01, 0.02).abs)]), 1, LFNoise1.kr(0.1).range(0.01, 0.6), 7, 1)); osc = LeakDC.ar(CombC.ar(osc, 1, SinOsc.kr(TRand.kr(0, 10)).range(0.0001, 2), 80)); osc = osc * env * amp; //osc = Decimator.ar(osc); osc = Normalizer.ar(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \noise, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/hoover.scd0000644000175100001770000000123014611211152022335 0ustar00runnerdockerSynthDef.new(\hoover, { |bus=0, freq=0, amp=1, pan=0, fmod=0, atk=0.01, sus=1, rel=0.09, offnote=0.5| var osc, bw, delay, decay, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; bw = 1.035; osc = { DelayN.ar(Saw.ar(freq * ExpRand(bw, 1 / bw)) + Saw.ar(freq * offnote * ExpRand(bw, 1 / bw)), 0.01, Rand(0, 0.01)) }.dup(18); osc = (Splay.ar(osc)).atan; env = Env.linen(atk, sus, rel, curve: \lin).kr(doneAction: 0); osc = Mix(osc * env) * amp * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/hydra.scd0000644000175100001770000000127314611211152022151 0ustar00runnerdockerSynthDef.new(\video, { arg amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, brightness=0, contrast=0, color=0, colorama=0, invert=0, luma=0, posterize=0, saturate=0, shift=0, thresh=0, kaleid=0, pixelate=0, repeat=0, repeatX=0, repeatY=0, rotate=0, zoom=0, scrollX=0, scrollY=0, modulate=0, modulateHue=0, modulateKaleid=0, modulatePixelate=0, modulateRepeat=0, modulateRepeatX=0, modulateRepeatY=0, modulateRotate=0, modulateScale=0, modulateScrollX=0, modulateScrollY=0, add=0, blend=0, diff=0, layer=0, mask=0, mult=0; var osc, env; freq = In.kr(bus, 1); osc = Mix(osc) * 0.5; ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/jbass.scd0000644000175100001770000000103414611211152022137 0ustar00runnerdockerSynthDef.new(\jbass, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 4); amp=(amp * 0.8); osc=LFTri.ar(freq, mul: amp); env=EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/kalimba.scd0000644000175100001770000000160014611211152022434 0ustar00runnerdockerSynthDef.new(\kalimba, { |bus=0, freq=0, amp=1, pan=0, atk=0.01, sus=1, fmod=0, rel=0.7, oscmix=0.4, relMin=2.5, relMax=3.5| var osc, env1, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; rel = Rand(relMin, relMax); osc = SinOsc.ar(freq); env1 = EnvGen.ar(Env.perc(atk, rel,curve:-4), doneAction: 0); osc = osc * env1 * 1/2; osc = (osc * (1 - oscmix)) + (DynKlank.ar(`[ [240*ExpRand(0.9, 1.1), 2020*ExpRand(0.9, 1.1), 3151*ExpRand(0.9, 1.1)], [-7, 0, 3].dbamp, [0.8, 0.05, 0.07]], PinkNoise.ar * EnvGen.ar(Env.perc(atk, 0.01))) * oscmix); env = Env.linen(atk, sus, rel, curve:\sin).kr(doneAction:0); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Nathan Ho aka Snappizz", modified_by: "Josh Mitchell, Bruno Ruviaro, Jens Meisner", description: "", category: \percussion, tags: [\pitched, \kalimba] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/karp.scd0000644000175100001770000000115514611211152021776 0ustar00runnerdockerSynthDef.new(\karp, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 0.75); osc=LFNoise0.ar((400 + (400 * rate)), amp); osc=(osc * XLine.ar(1, 1e-06, (sus * 0.1))); freq=((265 / (freq * 0.666)) * 0.005); osc=CombL.ar(osc, delaytime: freq, maxdelaytime: 2); env=EnvGen.ar(Env(times: [sus],levels: [(amp * 1), (amp * 1)],curve: 'step'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/keys.scd0000644000175100001770000000120114611211152022004 0ustar00runnerdockerSynthDef.new(\keys, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, cutoff=400| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq * [1, 1.005]; amp = amp / 4; osc = SinOsc.ar(freq + (rate * 100) * XFade2.ar(LFPar.ar(freq * (1/2)), LFTri.ar(freq * 1)), phase: 0.2, mul: 0.8); osc = RHPF.ar(osc, 400, 3); env = EnvGen.ar(Env([0, 1, 0.9, 0.5, 0],[0.01, 0, 0.5 * sus, 1 * sus])); osc = Mix(osc) * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/klank.scd0000644000175100001770000000101314611211152022132 0ustar00runnerdockerSynthDef.new(\klank, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus=(sus * 1.5); osc=Klank.ar(`[[1, 2, 3, 4], [1, 1, 1, 1], [2, 2, 2, 2]], ClipNoise.ar(0.0005).dup, freq); env=EnvGen.ar(Env(times: (sus * 2),levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ladder.scd0000644000175100001770000000120514611211152022270 0ustar00runnerdockerSynthDef.new(\ladder, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = MoogLadder.ar(LFSaw.ar(freq), LinExp.kr(LFCub.kr(rate, 1*pi), -1, 1, 180, 8500), 0.75); env = EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction:1); // env=EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 1; osc = Pan2.ar(osc * amp, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/lapin.scd0000644000175100001770000000264414611211152022150 0ustar00runnerdockerSynthDef(\lapin, { |bus=0, amp=1, atk=0.001, decay=0.01, sus=1,rel=0.01, level=0.8, peak=1, gate=1, pan=0, freq=0, fmod=0, vib=0, rate=1, blur=1, beat_dur=1| var osc, env, string; sus = sus*blur; string = { |freq| var delay; delay = freq.reciprocal; Pluck.ar(SinOsc.ar(Line.ar(1000, 50, 0.01)) * Env.perc(0.001, 0.01).ar, Impulse.ar(0), delay, delay, 5*rate, 0.5)}; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = string.(freq) + string.(freq) + string.(freq * 0.5); osc = osc + (HPF.ar(LocalIn.ar(2), 3000) * -50.dbamp); osc = osc + HPF.ar(osc, 3000); osc = (osc * 32.dbamp).tanh; // osc = RLPF.ar(osc, 3000, 0.5); osc = (osc * 32.dbamp).tanh; osc = RLPF.ar(osc, 300, 0.5); osc = (osc * 32.dbamp).tanh; osc = CombN.ar(osc!4,4/(freq/24),4/freq,1) + osc; osc = BHiShelf.ar(osc, 3200, 1, -3.0); osc = LeakDC.ar(osc); osc = DelayC.ar(osc, 0.1, SinOsc.kr(0.1, [0, 1pi]).range(0, 1e-4)); osc = HPF.ar(osc,60); osc = RLPFD.ar(osc,6400*[1,1.1],0.1,0.5); 5.do { d = 0.2.rand; osc = AllpassN.ar(osc,d,d,5); }; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); //osc = osc * amp * 0.35; osc = osc * env * amp; osc = Mix(osc) * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/laserbeam.scd0000644000175100001770000000111214611211152022765 0ustar00runnerdockerSynthDef.new(\laserbeam, { |bus = 0, pan = 0.0, freq = 0, amp = 1, fmod=0, atk = 0.01, sus = 1| var osc, freqenv, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freqenv = EnvGen.ar(Env([4, 0.5, 1, 1], [atk, 0.01, 1.0])); env = EnvGen.ar(Env([atk, sus, 0.0], [atk, sus, 0.1]),levelScale: amp, doneAction: 0); osc = LFTri.ar(freq: freq * freqenv); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Mitchell Sigman", modified_by: "Jens Meisner", description: "", category: \keys, tags: [\synthesizer, \misc] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/latoo.scd0000644000175100001770000000113514611211152022155 0ustar00runnerdockerSynthDef.new(\latoo, { |amp=1, sus=1, pan=0, freq=440, vib=0, atk=0.01, rel=0.9, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = Latoocarfian2DN.ar(SampleRate.ir / 4, SampleRate.ir, LFNoise2.kr(2.dup, 1, 1), d: LFNoise2.kr(2.dup, 0.5, 1), mul:0.2); env = EnvGen.ar(Env.asr(atk, sus, rel, curve: \lin), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc * amp, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \ambient, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/lazer.scd0000644000175100001770000000114514611211152022155 0ustar00runnerdockerSynthDef.new(\lazer, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq * [1, 1.005]); amp=(amp * 0.1); osc=(VarSaw.ar(freq, width: ((rate - 1) / 4)) + LFSaw.ar(LFNoise0.ar((rate * 20), add: (freq * Pulse.ar(((rate - 2) + 0.1), add: 1)), mul: 0.5))); env=EnvGen.ar(Env.perc(attackTime: 0.1,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/lfnoise.scd0000644000175100001770000000155114611211152022500 0ustar00runnerdockerSynthDef.new(\lfnoise, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env, bitRate; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp = amp * 2; osc = (Dust2.ar(LinLin.kr(rate, 0, 1, 1, 5), 1) + Crackle.ar(1.95, 0.1) + SinOsc.ar((PinkNoise.ar(0.5) * 7500) + 40, 0, 0.006)); bitRate = 48000 * LinLin.kr(rate, 0, 1, 0, 3).ceil.reciprocal; osc = (Decimator.ar(osc, bitRate, LinExp.kr(rate, 0, 1, 24, 6)) * 0.3) + (osc * 0.7); env = EnvGen.ar(Env(times: [(sus / 2), (sus*2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc = (osc * env * 4); osc = Mix(osc); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/linesaw.scd0000644000175100001770000000402214611211152022477 0ustar00runnerdockerSynthDef.new(\linesaw, { // Standard values |bus = 0, freq = 1000, pan = 0, amp = 0.1, fmod=0, atk = 0.001, sus = 1, rel = 1.3, crv = -2, lforate1 = 5, lfodepth1 = 0.25, phasecenter1 = 0.35, lforate2 = 2.7, lfodepth2 = 0.5, phasecenter2 = 0.5, pswitch = 0, fdelay1 = 0.00025, fdelay2 = 0.00015| var input, lfoA, lfoB, phaseShiftA, phaseShiftB, env, saw, polarity, phaseA, phaseB, phase, osc; // Makes three lines with a slope of 1/second freq = In.kr(bus, 1); freq = [freq, freq+fmod]; input = Line.ar(start: 0, end: atk + sus + rel, dur: atk + sus + rel, doneAction: 0); input = input - [0, fdelay1, fdelay2]; // Make two sine LFOs with freq "lfoRate" and amplitude "lfoDepth" lfoA = sin(2pi * (lforate1 * input).mod(1)) * lfodepth1; lfoB = sin(2pi * (lforate2 * input).mod(1)) * lfodepth2; // Use the LFOs to determine a phase parameter from 0 to 1 cycles phaseShiftA = (phasecenter1 + lfoA).wrap(0, 1); phaseShiftB = (phasecenter2 + lfoB).wrap(0, 1); // Make an asr envelope with a fixed sustain time env = (input/atk).clip(0, 1); env = env - ((input - (atk + sus))/rel).clip(0, 1); env = env.pow(exp(-1 * crv)); // Make a sawtooth wave with freq "freq" saw = (input * freq).mod(1); polarity = 1 - (2 * pswitch); // Make a pulse wave from the sawtooth wave phaseA = sign(sign(phaseShiftA - saw) + 0.5); phaseA = (phaseA - 1)/2 - phaseShiftA + 0.5; // Add it to the saw to get a phase-shifted saw phaseA = saw + phaseA; // Rinse and repeat phaseB = sign(sign(phaseShiftB - saw) + 0.5); phaseB = (phaseB - 1)/2 - phaseShiftB + 0.5; phaseB = saw + phaseB; // Add it all together osc = ((polarity * (saw - 0.5)) + phaseA + phaseB)/2; // Filter the sound a tiny bit osc = (osc[0] + osc[1] + osc[2])/3 * amp; // Output Stuff osc = osc.softclip; osc = [osc * cos((pan + 1) * pi/4), osc * sin((pan + 1) * pi/4)]; osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "by Josh Mitchell", modified_by: "Jens Meisner", description: "", category: \pads, tags: [\pitched] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/longsaw.scd0000644000175100001770000000101714611211152022510 0ustar00runnerdockerSynthDef.new(\longsaw, { |amp=1, atk=0.01, sus=1, rel=0.8, pan=0, freq=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp = (amp / 10); env = EnvGen.ar(Env.linen(atk, sus, rel), doneAction: 0); osc = Saw.ar(freq,Line.kr(1, 2, 4), mul: 1); osc = (osc * env * amp); osc = Mix(osc) * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/loop.scd0000644000175100001770000000114614611211152022012 0ustar00runnerdockerSynthDef.new(\loop, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1.0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, buf=0, pos=0, room=0.1, sample=0, spack=0, beat_stretch=0| var osc, env; sus = sus * blur; rate = In.kr(bus, 1); rate = (rate * (1-(beat_stretch>0))) + ((BufDur.kr(buf) / sus) * (beat_stretch>0)); osc = PlayBuf.ar(2, buf, BufRateScale.kr(buf) * rate, startPos: BufSampleRate.kr(buf) * pos, loop: 1.0); osc = osc * EnvGen.ar(Env([0,1,1,0],[0.05, sus-0.05, 0.05])); osc=(osc * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/marimba.scd0000644000175100001770000000103614611211152022447 0ustar00runnerdockerSynthDef.new(\marimba, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=Klank.ar(`[[0.5, 1, 4, 9], [0.5, 1, 1, 1], [1, 1, 1, 1]], PinkNoise.ar([0.007, 0.007]), freq, [0, 2]); sus=1; env=EnvGen.ar(Env.perc(attackTime: 0.001,releaseTime: sus,level: amp,curve: -6), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/mhpad.scd0000644000175100001770000000161014611211152022126 0ustar00runnerdockerSynthDef(\mhpad, { //Standard Values: |bus = 0, pan = 0, freq = 440, amp = 1, fmod=0, atk = 0.1, dec = 0.05, sus = 1, rel = 0.09, gate = 1, vibrate = 4, vibdepth = 0.08, trem=2, tremdepth = 0.2| var env, osc, vibrato, mod2, mod3; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; vibrato = SinOsc.kr(vibrate).range(freq * (1 - vibdepth), freq * (1 + vibdepth)); trem = LFNoise2.kr(1).range(0.2, 2) * SinOsc.kr(trem).range((1 - tremdepth), 1); osc = SinOsc.ar(freq: [freq, vibrato], mul: 1.0).distort; env = Env.asr(atk, sus / 2, rel, curve: \sin).kr(gate: gate, doneAction: 0); osc = osc * env * amp * 0.15; DetectSilence.ar(osc, 0.0001, 0.2, doneAction: 0); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata:( credit: "Mike Hairston", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "", category: \category, tags: [\pad, \vibrato, \sustained] ) ).add././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/mhping.scd0000644000175100001770000000131614611211152022322 0ustar00runnerdockerSynthDef.new(\mhping, { |bus=0, freq = 0, amp = 1, fmod=0, atk=0.001, sus=1, rel=0.3, curve= -4, pan=0, rate=9, depth=0.02| var osc, lfo, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; lfo = LFNoise2.ar(rate).range(1/(1 + depth),(1 + depth)); env = Env.linen(attackTime: atk, sustainTime: sus, releaseTime: rel, curve: curve).kr(doneAction:0); osc = SinOsc.ar(freq: [freq, freq * lfo], mul: env); osc = osc * env * amp * 0.1; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "unknown", modified_by: "Bruno Ruviaro, Josh Mitchell", decription: "Your basic percussive synth instrument, a good default sound for testing patterns", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/moogbass.scd0000644000175100001770000000156314611211152022656 0ustar00runnerdockerSynthDef.new(\moogbass, { |bus = 0, pan = 0, freq = 440, amp = 1, atk = 0.1, sus = 1, rel = 0.08, fmod=0, gate = 1, cutoff = 1200, gain = 0.9, lagamount = 0.01, width=0.6| var filter, env, filterenv, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 4; osc = Mix(VarSaw.ar(freq.lag(lagamount) * [1.0, 1.001, 2.0], iphase: 0.5, width: width, mul: 0.2)); filterenv = EnvGen.ar(envelope: Env.asr(atk, sus, rel), gate: gate); filter = MoogFF.ar(in: osc, freq: cutoff * (1.0 + (0.8 * filterenv)), gain: gain); env = EnvGen.ar(Env.asr(atk, sus, rel), gate: gate, doneAction: 0); osc = (0.9 * filter + (0.3 * filter.distort)); osc = osc * env * amp * 0.4; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Nick Collins", modified_by: "Bruno Ruviaro, Jens Meisner", description: "", category: \bass, tags: [\pitched, \bass] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/moogpluck.scd0000644000175100001770000000160614611211152023042 0ustar00runnerdockerSynthDef.new(\moogpluck, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.001, decay=0.01, rel=0.01, peak=1, level=0.8, pluckfilter=4, pluckcoef=0.8, pluckmix=0.8| var pluck, moog, osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; pluck = Pluck.ar(SinOsc.ar(freq * PinkNoise.ar()), 1, freq.reciprocal, freq.reciprocal, sus, coef:pluckcoef.clip(-0.5,0.99)); pluck = pluck * EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); moog = MoogFF.ar(pluck, (freq*pluckfilter), 2); osc = SelectX.ar(pluckmix,[LPF.ar(pluck, 4300), moog]); osc = osc * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/moogpluck2.scd0000644000175100001770000000152214611211152023121 0ustar00runnerdockerSynthDef.new(\moogpluck2, { |amp=1, sus=1, pan=0, freq=0, dur=1, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, legato=1, para1=0.5| var osc, osc_pluck, osc_moog, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus = sus * blur; amp = (amp + 1e-05); freq = (freq + [0, LFNoise2.ar(50).range(-2, 2)]); osc_pluck = Pluck.ar(PinkNoise.ar, 1, 0.2, freq.reciprocal, dur*legato, 1-para1); osc_moog = MoogFF.ar(osc_pluck, (freq*3), 2); osc = SelectX.ar(0.5, [LPF.ar(osc_pluck,2500),osc_moog]); osc = ((osc * XLine.kr(amp, (amp / 1000), (sus * 4), doneAction: 0)) * 1); osc = Mix(osc) * amp * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/mpluck.scd0000644000175100001770000000167314611211152022341 0ustar00runnerdockerSynthDef(\mpluck, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, filter=3, dur=2| var osc, osc_pluck, osc_moog,env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp + 1e-05); freq=(freq + [0, LFNoise2.ar(50).range(-2, 2)]); osc_pluck = Pluck.ar(PinkNoise.ar,1,0.2,freq.reciprocal,dur*sus,0.5); osc_moog = MoogFF.ar(osc_pluck, (freq*filter),2); osc = SelectX.ar(0.5,[LPF.ar(osc_pluck,2500),osc_moog]); env=EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc=((osc * XLine.kr(amp, (amp / 10000), (sus * 4), doneAction: 0)) * 1); osc = Mix(osc) * 4; osc = Pan2.ar(osc * env, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \pluck, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/mySynth.scd0000644000175100001770000000055314611211152022515 0ustar00runnerdockerSynthDef.new(\mySynth, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/noise.scd0000644000175100001770000000072514611211152022160 0ustar00runnerdockerSynthDef.new(\noise, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq * 2); osc=LFNoise0.ar(freq, amp); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/noisynth.scd0000644000175100001770000000121414611211152022710 0ustar00runnerdockerSynthDef.new(\noisynth, { |freq = 0, amp = 1, fmod=0, atk = 0.07, sus = 1, pan = 0, bus = 0| var env, osc, lfo; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = {freq * LFNoise2.kr(Rand(0.0001,0.5)).range(0.98, 1.02)}!12; lfo = { SinOsc.kr({ 1/Rand(2,52) }!2) }; env = Env.linen(atk, sus, 0.9, 0.2, curve:\sin).kr(doneAction:0); osc = LFSaw.ar(osc, mul: lfo.value.range(0, 1)); osc = Splay.ar(osc, lfo.value.range(0, 1)); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/noquarter.scd0000644000175100001770000000354514611211152023066 0ustar00runnerdockerSynthDef.new(\noquarter, { // Standard Arguments |bus = 0, freq = 440, amp = 1, pan = 0, fmod=0, atk = 0.1, sus=1, rel = 1, curve = -1| var subfreq, env, pluck, tri, sin, sub, click, osc, subenv; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; subfreq = freq / 2; // Envelopes subenv = Env.linen(attackTime: atk, sustainTime: sus, releaseTime: rel, level: amp, curve: curve).kr(doneAction: 0); env = Env.linen(atk, sus, rel, amp, curve).kr(doneAction: 0); // Component synthesis pluck = Pluck.ar(in: PinkNoise.ar, trig: 1, maxdelaytime: 0.8, delaytime: subfreq.reciprocal) * subenv * 2; tri = VarSaw.ar(freq) * env; sin = SinOsc.ar(freq) * env; sub = (SinOsc.ar([subfreq, subfreq - 4, subfreq + 4]).sum / subenv).tanh; click = RLPF.ar(in: Impulse.ar(0), freq: [900, 2000], rq: 0.5).sum * 1000; // Initial signal osc = pluck + tri + sub + click; // Resonant LPFs //osc = RLPF.ar(in: osc, freq: XLine.ar(freq * 90, freq * 20, 0.05)); osc = osc + (MoogFF.ar(in: osc, freq: freq * 100, gain: 2.5) * 0.3); // EQ resulting signal osc = BPeakEQ.ar(osc, 400, 0.5, -9); osc = BPeakEQ.ar(osc, 2000, 0.5, 6); osc = BHiShelf.ar(osc, 8000, 1, 3); osc = BPeakEQ.ar(osc, 200, 1, 3); // Apply another envelope to dampen a bit more osc = osc * XLine.kr(1, 0.6, 0.1); // Tanh distortion / limiting osc = (osc * 1).tanh; // Another round of signal coloring, using another RLPF // and sine components osc = osc + RLPF.ar(in: osc, freq: XLine.ar(freq * 100, freq * 10, 0.15)) + sin + sub; // Another round of tanh distortion / limiting osc = (osc / 2.3).tanh; // Another resonant LPF osc = MoogFF.ar(in: osc, freq: XLine.ar(freq*150, freq*30, 0.1), gain: 0.1); osc = Pan2.ar(osc, pan) * amp * 0.15; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Eric Sluyter", modified_by: "Jens Meisner", description: "", category: \bass, tags: [\pitched, \bass, \karplus] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/nylon.scd0000644000175100001770000000101414611211152022172 0ustar00runnerdockerSynthDef.new(\nylon, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=(LFPulse.ar(freq, 0.5, (0.33 * rate), 0.25) + LFPar.ar((freq + 0.5), 1, 0.1, 0.25)); env=EnvGen.ar(Env.perc(attackTime: 0.000125,releaseTime: (sus * 3),level: amp,curve: -4), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/organ.scd0000644000175100001770000000620114611211152022144 0ustar00runnerdocker<<<<<<< HEAD:renardo_lib/renardo_lib/osc/scsyndef/organ.scd ( SynthDef(\organ, {|f=440, width = 0.5, pan = 0.0, bus = 0, amp = 1, sus=1, freq=440, fmod=0,rate = 0.5| var signal, tapPhase, tap, tapPhaseL, tapPhaseR, tapL, tapR; var timeMod, eqMod, bufferL, bufferR; var osc; var env=EnvGen.ar(Env(times: [(sus * 0.25), (sus * 1)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); var input = Vibrato.ar(VarSaw.ar(freq, 0, LFNoise2.kr(1)), 5, 0.1, 0, 0.2, 0.1, 0.7); var theSine = SinOsc.ar(freq); var oscs = 6; var scaler = 1/oscs; var lfo1 = LFTri.ar(fmod*1.51); var lfo2 = LFTri.ar(fmod*1.11); var lfo3 = LFTri.ar(fmod*1.31); var lfo4 = LFTri.ar(fmod*0.71); var lfo5 = LFTri.ar(fmod*0.61); var lfo6 = LFTri.ar(fmod*0.51); var comp1 = input > lfo1; var comp2 = input > lfo2; var comp3 = input > lfo3; var comp4 = input > lfo4; var comp5 = input > lfo5; var comp6 = input > lfo6; var output = scaler*(comp1+comp2+comp3+comp4+comp5+comp6); output = output+0.001*theSine; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; output = 0.01*LeakDC.ar(output, 0.9995); output = MoogFF.ar(output.tanh*20.0, (f*12)+LFNoise2.ar(1, 400, 1), LFNoise2.ar(0,3.5, 0)); ======= SynthDef.new(\organ, { |f=440, width = 0.5, pan = 0.0, bus = 0, amp = 1, sus=1, freq=440, fmod=0, rate = 0.5| var signal, tapPhase, tap, tapPhaseL, tapPhaseR, tapL, tapR, comp1, comp2, comp3, comp4, comp5, comp6, output; var timeMod, eqMod, bufferL, bufferR, osc, env, input, theSine, oscs, scaler, lfo1, lfo2, lfo3, lfo4, lfo5, lfo6; env = EnvGen.ar(Env(times: [(sus * 0.25), (sus * 1)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); input = Vibrato.ar(VarSaw.ar(freq, 0, LFNoise2.kr(1)), 5, 0.1, 0, 0.2, 0.1, 0.7); theSine = SinOsc.ar(freq); oscs = 6; scaler = 1/oscs; lfo1 = LFTri.ar(fmod*1.51); lfo2 = LFTri.ar(fmod*1.11); lfo3 = LFTri.ar(fmod*1.31); lfo4 = LFTri.ar(fmod*0.71); lfo5 = LFTri.ar(fmod*0.61); lfo6 = LFTri.ar(fmod*0.51); comp1 = input > lfo1; comp2 = input > lfo2; comp3 = input > lfo3; comp4 = input > lfo4; comp5 = input > lfo5; comp6 = input > lfo6; output = scaler*(comp1+comp2+comp3+comp4+comp5+comp6); output = output+0.001*theSine; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; output = 0.01 * LeakDC.ar(output, 0.9995); output = MoogFF.ar(output.tanh*20.0, (f*12 ) + LFNoise2.ar(1, 400, 1), LFNoise2.ar(0,3.5, 0)); >>>>>>> badc8940 (Add meta-data block and filled in known information, add new synths, rename and fix old synths):FoxDot/osc/scsyndef/organ.scd output = MoogFF.ar(output*4, f*LFNoise2.kr(0.2, 6, 4), 0.5); timeMod = LFDNoise3.ar(rate, 0.0005); eqMod = LFDNoise3.kr(1, 400); osc = 2*env*output.tanh; osc = Mix(osc) * 0.5; osc = HPF.ar(osc, 40); osc = LPF.ar(osc, 14000); osc = Splay.ar(osc * amp, pan); <<<<<<< HEAD:renardo_lib/renardo_lib/osc/scsyndef/organ.scd ReplaceOut.ar(bus, osc)}).add; ) ======= ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Jens Meisner", decription: "Description", category: \organ, tags: [\keys, \tag] )).add; >>>>>>> badc8940 (Add meta-data block and filled in known information, add new synths, rename and fix old synths):FoxDot/osc/scsyndef/organ.scd ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/organ2.scd0000644000175100001770000000105114611211152022224 0ustar00runnerdockerSynthDef.new(\organ2, { |bus = 0, freq = 0, fmod=0, pan = 0, sus = 1, amp = 1, gate = 1| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = Splay.ar(SinOsc.ar(freq*Array.geom(4,1,2), mul:1/8)); osc = osc + SinOsc.ar(freq/2, mul:0.2)!2; env = EnvGen.ar(Env.linen(0.001,sus,0.01), gate, doneAction:0); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/orient.scd0000644000175100001770000000100614611211152022334 0ustar00runnerdockerSynthDef.new(\orient, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, room=10, verb=0.7| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=(LFPulse.ar(freq, 0.5, 0.25, 0.25) + LFPulse.ar(freq, 1, 0.1, 0.25)); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pads.scd0000644000175100001770000000142614611211152021771 0ustar00runnerdockerSynthDef.new(\pads, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, atk=0.1, decay=0.5, rel=0.7| var osc, env, filter; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 2); freq = freq * [1, 1.01]; osc = SinOsc.ar(Line.kr(freq * 4, freq, 0.01) + (Line.kr(10, (freq * 2), sus) * Pulse.ar(freq * rate, width: SinOsc.kr(0.225/sus))), mul:decay); env = EnvGen.ar(Env([0, atk, decay, 0],[atk, decay * sus, rel * sus])); osc = RHPF.ar(osc, [Line.kr(400, 1000, sus), Line.kr(4000,900,sus)], decay); osc = osc * env * amp * Line.ar(0.001,1,sus * 0.05); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pasha.scd0000644000175100001770000000107014611211152022131 0ustar00runnerdockerSynthDef.new(\pasha, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, cutoff=8000| var osc, env, lfo; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; lfo = LFPar.kr([1,1.04], mul:0.5); osc = Pulse.ar(freq, lfo); env = EnvGen.ar(Env([0,1,0.5,0.2,0], [0, 0.01, sus / 1.5, sus / 1.5], curve:'cub'), doneAction:3); osc = osc * env * amp; osc = Mix(osc) * 0.25; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pbass.scd0000644000175100001770000000267314611211152022157 0ustar00runnerdockerSynthDef.new(\pbass, { |bus=0, amp=1, atk=0.001, decay=0.01, sus=1, rel=0.01, level=0.8, peak=1, gate=1, pan=0, freq=0, fmod=0, vib=0, rate=1, blur=1, beat_dur=1| var subfreq, subenv, env, pluck, tri, sin, sub, click, sig, osc; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; subfreq = freq / 2; subenv = Env.linen(0,sustainTime:sus/2,curve:\lin).kr(doneAction:0); env = Env.linen(0,sustainTime:sus/2,curve:\lin).kr(doneAction: 0); pluck = Pluck.ar(PinkNoise.ar, 1, 0.2, subfreq.reciprocal) * subenv * 2; tri = VarSaw.ar(freq); sin = SinOsc.ar(freq); sub = (SinOsc.ar([subfreq, subfreq - 2, subfreq + 2]).sum * subenv).tanh; click = RLPF.ar(Impulse.ar(0), [2000, 8000], 1).sum * 1000; osc = pluck + tri + sub + click; osc = RLPF.ar(osc, XLine.ar(freq * 100, freq * 10, sus * 0.8).clip(0,20000)); osc = osc + (MoogFF.ar(osc, freq * 10, 2.5).clip(0,20000) * 0.1); osc = BPeakEQ.ar(osc, 400, 0.5, -9); osc = BPeakEQ.ar(osc, 2000, 0.5, 6); osc = BHiShelf.ar(osc, 8000, 1, 3); osc = BPeakEQ.ar(osc, 200, 1, 3); osc = osc * XLine.kr(1, 0.6, 0.1); osc = (osc * 1).tanh; osc = osc + RLPF.ar(osc, XLine.ar(freq * 20,freq * 10,sus).clip(0,20000)) + sin + sub; osc = (osc / 2.3).tanh; osc = MoogFF.ar(osc,10000,0.1); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/phazer.scd0000644000175100001770000000151514611211152022332 0ustar00runnerdockerSynthDef.new(\phazer, { |bus = 0, pan = 0, freq = 0, amp = 1, gate = 1, fmod=0, atk = 1, sus = 1, rel = 1.5, crv = -4, rq = 0.2, rate = 3, minfreq = 100, maxfreq = 4000, drylevel = 1.2, fmdepth = 0.8| var env, lfo, osc, fmfreq; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; fmfreq = freq - 8; env = Env.linen(attackTime: atk,sustainTime: sus, releaseTime: rel,curve: crv).kr(doneAction: 0); lfo = LinExp.ar(LFTri.ar(rate), -1, 1, minfreq, maxfreq/8); osc = LFSaw.ar(freq: SinOsc.ar(fmfreq).range(1, fmdepth) * freq); osc = BAllPass.ar(osc, [1, 2, 4, 8] * lfo, rq); osc = Mix.ar(osc); osc = osc + (osc * -1 * drylevel) * 0.3; osc = osc * env * amp; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", category: \misc, tags: [\pitched, \effects] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/piano.scd0000644000175100001770000000101314611211152022140 0ustar00runnerdockerSynthDef.new(\piano, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 0.7); osc=MdaPiano.ar((freq[0]), vel: (40 + (amp * 60)), decay: (sus / 4)); env=EnvGen.ar(Env(times: [sus],levels: [(amp * 1), (amp * 1)],curve: 'step'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pianovel.scd0000644000175100001770000000135314611211152022656 0ustar00runnerdockerSynthDef.new(\pianovel, { |bus=0, freq=0, gate=1, amp=1, fmod=0, velocity=80, hard=0.8, sus=1, blur=1, velhard=0.6, pan=0, vib=0| var env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = MdaPiano.ar([freq + fmod], gate, release: 0.9, stereo: 0.8, sustain: sus * blur, vel: velocity, hard: hard, velhard: velhard); osc = TwoPole.ar(osc, 200,0.5, mul:0.5) + osc/2; env = EnvGen.ar(Env(times: [sus],levels: [(amp * 0.5), (amp * 0.5)],curve: 'step'), doneAction: 0); DetectSilence.ar(osc, 0.01, doneAction:2); osc = Mix(osc) * env * amp * 0.5; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc); }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pink.scd0000644000175100001770000000101414611211152021774 0ustar00runnerdockerSynthDef.new(\pink, { |amp=1, sus=1, pan=0, freq=440, vib=0, fmod=0, rate=0, bus=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; //osc = PinkNoise.ar() + PulseDPW(freq, freq, mul: 0.2); osc = PinkNoise.ar(); env = EnvGen.ar(Env.new([1, 1], [1, 1]), doneAction: 0); osc = (osc * env * amp); osc = Mix(osc) * 0.25; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/play1.scd0000644000175100001770000000065114611211152022067 0ustar00runnerdockerSynthDef.new(\play1, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1.0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, buf=0, pos=0, room=0.1| var osc, env; sus = sus * blur; rate = In.kr(bus, 1); osc=PlayBuf.ar(1, buf, (BufRateScale.ir(buf) * rate), startPos: (BufSampleRate.kr(buf) * pos)); osc=(osc * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/play2.scd0000644000175100001770000000065114611211152022070 0ustar00runnerdockerSynthDef.new(\play2, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1.0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, buf=0, pos=0, room=0.1| var osc, env; sus = sus * blur; rate = In.kr(bus, 1); osc=PlayBuf.ar(2, buf, (BufRateScale.ir(buf) * rate), startPos: (BufSampleRate.kr(buf) * pos)); osc=(osc * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pluck.scd0000644000175100001770000000116114611211152022154 0ustar00runnerdockerSynthDef.new(\pluck, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp + 1e-05); freq=(freq + [0, LFNoise2.ar(50).range(-2, 2)]); osc=((SinOsc.ar((freq * 1.002), phase: VarSaw.ar(freq, width: Line.ar(1, 0.2, 2))) * 0.3) + (SinOsc.ar(freq, phase: VarSaw.ar(freq, width: Line.ar(1, 0.2, 2))) * 0.3)); osc=((osc * XLine.kr(amp, (amp / 10000), (sus * 4), doneAction: 2)) * 0.3); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pmcrotal.scd0000644000175100001770000000130514611211152022657 0ustar00runnerdockerSynthDef.new(\pmcrotal, { |bus=0, freq=440, fmod=0, atk=0, sus=1, rel=0.9, curve= -7, amp=1, pan=0, mod=5, atone=2, btone=4| var env, osc1, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(atk, sus, rel, curve: curve).kr(doneAction:0); osc = PMOsc.ar(freq/2, mod * freq / 2, pmindex: atone, mul: 0.5); osc1 = PMOsc.ar(freq/4, freq, pmindex: btone, mul: 0.5); osc = HPF.ar(osc, freq, mul: 0.4); osc = Mix.ar([osc, osc1]) * 0.2; osc = osc * env * amp * 0.4; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "unknown", modified_by: "Bruno Ruviarol, Josh Mitchell, Jens Meisner", description: "", category: \percussion, tags: [\pitched, \bell] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ppad.scd0000644000175100001770000000140514611211152021763 0ustar00runnerdockerSynthDef.new(\ppad, { |amp=1, freq=0, gate=1, sus=1, pan=0, vib=0, fmod=0, rate=0, bus=0, blur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, osc1, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = SinOsc.ar(freq); osc1 = SinOsc.ar(freq + LFNoise0.ar([400,160]).range(2,24).round(2)); osc = Mix.ar([osc,osc1]).tanh / 3; osc = osc + BPF.ar(PinkNoise.ar([0.4,0.8]),freq,0.1); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/prayerbell.scd0000644000175100001770000000446714611211152023213 0ustar00runnerdockerSynthDef.new(\prayerbell, { |bus=0, freq = 0, amp = 1, fmod=0, decayscale=0.6, singswitch=0, lag=3, pan=0| var osc, input, first, freqscale, mallet, sing; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freqscale = freq / 2434; freqscale = Lag3.kr(freqscale, lag); decayscale = Lag3.kr(decayscale, lag); mallet = LPF.ar(in: Impulse.ar(0)!2,freq: 8000 * freqscale); sing = LPF.ar(in: {PinkNoise.ar * Integrator.kr(singswitch * 0.001, 0.999).linexp(0, 1, 0.01, 1)}!2 * amp, freq:2434 * freqscale); sing = sing + Dust.ar(0.15); sing = LPF.ar(sing, 10000 * freqscale); sing = sing * LFNoise1.kr(0.5).range(-45, -30).dbamp; input = mallet/2 + (singswitch.clip(0, 1) * sing); osc = DynKlank.ar( specificationsArrayRef: `[ // Array of filter frequencies [ (first = LFNoise1.kr(0.5).range(2424, 2444)) + Line.kr(20, 0, 0.5), first + LFNoise1.kr(0.5).range(1,3), LFNoise1.kr(1.5).range(5435, 5440) - Line.kr(35, 0, 1), LFNoise1.kr(1.5).range(5480, 5485) - Line.kr(10, 0, 0.5), LFNoise1.kr(2).range(8435, 8445) + Line.kr(15, 0, 0.05), LFNoise1.kr(2).range(8665, 8670), LFNoise1.kr(2).range(8704, 8709), LFNoise1.kr(2).range(8807, 8817), LFNoise1.kr(2).range(9570, 9607), LFNoise1.kr(2).range(10567, 10572) - Line.kr(20, 0, 0.05), LFNoise1.kr(2).range(10627, 10636) + Line.kr(35, 0, 0.05), LFNoise1.kr(2).range(14689, 14697) - Line.kr(10, 0, 0.05) ], // Array of filter amplitudes [ LFNoise1.kr(1).range(-10, -5).dbamp, LFNoise1.kr(1).range(-20, -10).dbamp, LFNoise1.kr(1).range(-12, -6).dbamp, LFNoise1.kr(1).range(-12, -6).dbamp, -20.dbamp, -20.dbamp, -20.dbamp, -25.dbamp, -10.dbamp, -20.dbamp, -20.dbamp, -25.dbamp ], // Array of filter decay times [ 20 * freqscale.pow(0.2), 20 * freqscale.pow(0.2), 5, 5, 0.6, 0.5, 0.3, 0.25, 0.4, 0.5, 0.4, 0.6 ] * freqscale.reciprocal.pow(0.5) ], input: input, freqscale: freqscale, freqoffset: 0, decayscale: decayscale ); osc = osc * amp * 0.4; DetectSilence.ar(osc,doneAction: 0); osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Wondersluyter", modified_by: "Bruno Ruviaro, Jens Meisner", decription: "Tibetan prayer bell", category: \bells, tags: [\percussion, \bell, \prayer, \tibetan] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/prof.scd0000644000175100001770000000161414611211152022007 0ustar00runnerdockerSynthDef(\prof, { |amp=0.3, pan=0, freq=0, vib=0, fmod=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, sus=1, rel=0.01, peak=1, level=0.8, gate = 1, rate = 0.1, phase = 0.5, cutoff = 900, rq = 0.5| var lfo, osc, filter, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; lfo = LFTri.kr(rate * [1, 1.01], Rand(0, 2.0) ! 2, 1); osc = Pulse.ar(freq * [1, 1.01], lfo * phase + 0.5); filter = RLPF.ar(osc, cutoff, rq); //env = EnvGen.ar(envelope: Env.adsr(atk, decay, sus, rel, amp),gate: gate,doneAction: 2); env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = Mix(osc * filter * env); osc = osc * amp * 0.8; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \category, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/prophet.scd0000644000175100001770000000134214611211152022520 0ustar00runnerdockerSynthDef(\prophet, { |bus=0 freq=440 amp=1.0 gate=1 lforate=1 lfowidth=0.5 cutoff=6000 rq=0.4 pan=0.0, sus=0.1, fmod=0| var lfo, pulse, filter, env; // Amp is way too much for foxdot amp = amp * 0.1; freq = In.kr(bus) + [0, fmod]; lfo = LFTri.kr(lforate * [1, 1.01], Rand(0, 2.0)!2); pulse = Pulse.ar(freq * [1, 1.01], lfo * lfowidth + 0.5); filter = RLPF.ar(pulse, cutoff, rq); filter = BHiPass.ar(filter, 200); env = EnvGen.ar(Env([0,1,0.8,0.8,0], [0.01, 0, sus, sus]), doneAction:3); ReplaceOut.ar(bus, Pan2.ar(Mix(filter) * env * amp * 0.5, pan)) }, metadata: ( credit: "Mitchell Sigman", modified_by: "Bruno Ruviaro, Jens Meisner", description: "", category: \keys, tags: [\polyphonic, \analog, \Synthesizer] ) ).add././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/pulse.scd0000644000175100001770000000074514611211152022175 0ustar00runnerdockerSynthDef.new(\pulse, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 8); osc=Pulse.ar(freq); osc=(osc * amp); env=EnvGen.ar(Env(times: [0.01, (sus - 0.01), 0.01],levels: [0, 1, 1, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/quin.scd0000644000175100001770000000111714611211152022013 0ustar00runnerdockerSynthDef.new(\quin, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq * [1, 1.01]); osc=(Klank.ar(`[[1, 2, 4, 2], [100, 50, 0, 10], [1, 5, 0, 1]], Impulse.ar(freq).dup, freq) / 5000); osc=(osc * LFSaw.ar((freq * (1 + rate)))); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 1), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/radio.scd0000644000175100001770000000116514611211152022140 0ustar00runnerdockerSynthDef.new(\radio, { |bus=0, freq=800, gate=1, amp=0.5, pan=0, fmod=0, rel=3, rate=1| var env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env.asr(0, 1, rel), gate, doneAction: 0); osc = Pan2.ar(CombN.ar(Resonz.ar(Gendy5.ar(1, 40, minfreq: 0.2, maxfreq: freq, durscale: 0.1, initCPs: 10), freq * rate,0.1),0.1,0.5,0.6)); //sig = FreeVerb.ar(sig, 0.1, 0.5); osc = Mix(osc) * 0.4; osc = Limiter.ar(osc*env); osc = Splay.ar(osc*amp, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \ambient, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rave.scd0000644000175100001770000000076614611211152022005 0ustar00runnerdockerSynthDef.new(\rave, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=Gendy1.ar((rate - 1), mul: (amp / 2), minfreq: freq, maxfreq: (freq * 2)); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/razz.scd0000644000175100001770000000122214611211152022022 0ustar00runnerdockerSynthDef.new(\razz, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0.3, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq + [0, 1]); rate=Lag.ar(K2A.ar(freq), rate); osc=(Saw.ar((rate * [1, 0.5]), [1, 0.3333333333333333]) + Saw.ar((rate + LFNoise2.ar(4).range(0.5, 2.5)), 1)); osc=BPF.ar(osc, (freq * 2.5), 0.3); osc=RLPF.ar(osc, 1300, 0.78); env=EnvGen.ar(Env.perc(attackTime: 0.125,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rhodes.scd0000644000175100001770000000140514611211152022323 0ustar00runnerdockerSynthDef.new(\rhodes, { |amp=1, sus=1, gate=1, pan=0, freq=0, vib=0, fmod=0, rate=4.85, phase=0.5, cutoff=2000, rq=0.5, mul=1, bus=0, atk=0.0001, decay=0.01, rel=0.01, level=0.8, peak=1| var osc, pulse, filter,env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = Pulse.ar(freq*[1,33.5.midiratio],[0.2,0.1],[0.7,0.3]); env=EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = BLowPass4.ar(osc,(cutoff*(env.squared))+200+freq,rq); osc = Mix(osc*env*amp) * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "unknown", modified_by: "Jens Meisner", description: "", category: \piano, tags: [\pitched, \keyboard, \mda_piano] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rhpiano.scd0000644000175100001770000000224614611211152022503 0ustar00runnerdockerSynthDef.new(\rhpiano, { |bus=0, freq=0, pan=0, amp=1, fmod=0, atk=0.001, sus=1, vel=0.8, modindex=0.2, mix=0.2, lfospeed=0.4, lfodepth=0.1| var env1, env2, env3, env4, osc1, osc2, osc3, osc4, osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; lfospeed = lfospeed * 12; env = Env.linen(atk, sus, 0.04, curve: -4).kr(doneAction: 0); env1 = EnvGen.ar(Env.adsr(0.001, 1.25, 0.0, 0.04, curve: \lin)); env2 = EnvGen.ar(Env.adsr(0.001, 1.00, 0.0, 0.04, curve: \lin)); env3 = EnvGen.ar(Env.adsr(0.001, 1.50, 0.0, 0.04, curve: \lin)); env4 = EnvGen.ar(Env.adsr(0.001, 1.50, 0.0, 0.04, curve: \lin)); osc4 = SinOsc.ar(freq * 0.5) * 2pi * 2 * 0.535887 * modindex * env4 * vel; osc3 = SinOsc.ar(freq, osc4) * env3 * vel; osc2 = SinOsc.ar(freq * 15) * 2pi * 0.108819 * env2 * vel; osc1 = SinOsc.ar(freq, osc2) * env1 * vel; osc = Mix((osc3 * (1 - mix)) + (osc1 * mix)) * 0.3; osc = osc * (SinOsc.ar(lfospeed) * lfodepth + 1); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ripple.scd0000644000175100001770000000107214611211152022332 0ustar00runnerdockerSynthDef.new(\ripple, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 6); osc=(Pulse.ar((freq / 4), 0.2, 0.25) + Pulse.ar((freq + 1), 0.5, 0.5)); osc=(osc * SinOsc.ar((rate / sus), 0, 0.5, 1)); env=EnvGen.ar(Env(times: [(0.55 * sus), (0.55 * sus)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/risseto.scd0000644000175100001770000000226314611211152022532 0ustar00runnerdockerSynthDef.new(\risseto, { |bus=0, freq = 440, fmod=0, atk = 0.1, sus=1, rel = 1, amp = 1, pan = 0| var partials, durs, amps, osc, env, pulsefreq; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; pulsefreq = (freq / 100).trunc(1) ; partials = [246.4, 247.4, 404.8, 406.5, 523.6, 748, 880, 1206, 1320, 1654, 1791]; // original freqs partials = partials / freq * 0.5; // consider 440 the 'root' durs = [11, 10, 7, 6, 4, 3.4, 3, 2.2, 2, 1.1, 1] / 11; amps = durs.linlin(1, 11, 0.2, 1); env = Env.linen(attackTime: atk, sustainTime: sus, releaseTime: durs * rel, level: amps).kr(doneAction: 0); osc = Pulse.ar(Mix.ar([freq, partials])) * env * amp / 13; osc = RLPF.ar(in: osc, freq: freq * LFPulse.ar(pulsefreq).range(2, 4), rq: SinOsc.ar(LFNoise2.kr(1).range(4, 9)).range(0.1, 0.3)); osc = LPF.ar(osc, 12000); osc = Limiter.ar(Mix.ar(osc)); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "by Bruno Tucunduva Ruviaro, based on Jean-Claude Risset's bell", modified_by: "Jens Meisner", description: "Pulse synth after Risset bell + the higher the pitch, the higher the frequency of pulse", category: \pads, tags: [\pulsesynth, \bell, \harmonic, \pitched] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rissetobell.scd0000644000175100001770000000206414611211152023370 0ustar00runnerdockerSynthDef.new(\rissetobell, { |bus = 0, pan = 0, freq = 440, amp = 0.1, fmod = 0, atk = 0.1, sus=1, rel = 0.9, gate = 1| var amps, durs, frqs, dets, doneActionEnv, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq * 2; amps = #[1, 0.67, 1, 1.8, 2.67, 1.67, 1.46, 1.33, 1.33, 1, 1.33]; durs = #[1, 0.9, 0.65, 0.55, 0.325, 0.35, 0.25, 0.2, 0.15, 0.1, 0.075]; frqs = #[0.56, 0.56, 0.92, 0.92, 1.19, 1.7, 2, 2.74, 3, 3.76, 4.07]; dets = #[0, 1, 0, 1.7, 0, 0, 0, 0, 0, 0, 0]; doneActionEnv = Env.linen(atk, sus, rel, curve: \sin).ar(gate: gate, doneAction: 0); osc = Mix.fill(11, {arg i; env = Env.perc(attackTime: atk, releaseTime: sus + rel * durs[i], level: amps[i], curve: atk.explin(0.005, 4, -4.5, 0)).ar(gate: gate); SinOsc.ar(freq: freq * frqs[i] + dets[i], mul: env * amp); }); osc = osc * doneActionEnv * amp * 0.05; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Jean-Claude Risset's bell", modified_by: "Jens Meisner", description: "", category: \bells, tags: [\percussion, \bell, \inharmonic] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rlead.scd0000644000175100001770000000130714611211152022127 0ustar00runnerdockerSynthDef.new(\rlead, { |bus = 0, freq=0, amp=1, fmod=0, gate=1, atk=0.01, sus=1, bps=2, seqnote1=3, seqnote2=1, seqnote3=2, pan = 0| var osc, env, seq; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; seq = Demand.kr(Impulse.kr(bps*4), 0, Dseq(freq*[seqnote1,seqnote2,seqnote3], inf)).lag(0.02); osc = LFSaw.ar(freq*{rrand(0.995, 1.005)}!2); osc = Splay.ar(osc, 2, center:pan); osc = MoogFF.ar(osc, seq, 2); env = Env.linen(atk, sus, 0.01, curve:-4).kr(doneAction:0); osc = osc * env * amp * 0.4; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rsaw.scd0000644000175100001770000000125714611211152022020 0ustar00runnerdockerSynthDef.new(\rsaw, { |bus = 0, freq = 0, amp = 1, fmod=0, atk = 0.1, rel = 1.2, sus = 1, pan = 0, lofreq = 800, hifreq = 4000| var env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(attackTime: atk,sustainTime: sus, releaseTime: rel, level: amp, curve:\sin).kr(doneAction: 0); osc = Saw.ar(freq: freq * [0.99, 1, 1.001, 1.008], mul: env); osc = LPF.ar(in: osc,freq: LFNoise0.kr(1).range(lofreq, hifreq)); osc = osc * env * amp * 0.3; osc = Splay.ar(osc); osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/rsin.scd0000644000175100001770000000150614611211152022014 0ustar00runnerdockerSynthDef.new(\rsin, { |bus=0, amp=1, gate=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, blur=1, beat_dur=0.5, atk=0.01, decay=0.01, rel=0.01, peak=0.9, level=0.7| var osc, env, osc1, osc2; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc1 = VarSaw; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sqr), doneAction: 0); osc = FreeVerb2.ar(*XFade2.ar(SinOscFB.ar([60,4],osc1.kr(rate)+1/2),SinOscFB.ar([freq*2,freq],526/2),osc1.kr(0.1))); osc = Mix(osc); osc = BLowShelf.ar(osc,80,2.0,-24); osc = osc * env * 4; osc = LeakDC.ar(Limiter.ar(osc,1),mul:amp); osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/saw.scd0000644000175100001770000000074114611211152021633 0ustar00runnerdockerSynthDef.new(\saw, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 8); osc=Saw.ar(freq); osc=(osc * amp); env=EnvGen.ar(Env(times: [0.01, (sus - 0.01), 0.01],levels: [0, 1, 1, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sawbass.scd0000644000175100001770000000165314611211152022507 0ustar00runnerdockerSynthDef(\sawbass, { |amp=1, sus=0.2, pan=0, bus=0, freq=440, cutoff=1000, rq=0.5, fmod=0| var osc1, osc2, filter, filter2, env, filterenv, ab; amp = amp * 0.2; freq = (In.kr(bus) / 4) + fmod; osc1 = Saw.ar(freq); osc2 = Mix(Saw.ar(freq * [0.25,1,1.5], [0.5,0.4,0.1])); filterenv = EnvGen.ar(Env.adsr(0.0, 0.5, 0.2, sus), 1, doneAction: 0); filter = RLPF.ar(osc1 + osc2, cutoff * filterenv + 100, rq); ab = abs(filter); filter2 = (filter * (ab + 2) / (filter ** 2 + 1 * ab + 1)); filter2 = BLowShelf.ar(filter2, 300, 1.0, -12); filter2 = BPeakEQ.ar(filter2, 1600, 1.0, -6); //env = EnvGen.ar(Env.adsr(0.01, 0.0, sus / 2, 0.05), 1, doneAction:3); env = EnvGen.ar(Env([0,1,0.8,0.8,0], [0.01, 0, sus, 0.05]), doneAction:0); ReplaceOut.ar(bus,Pan2.ar((filter + filter2) * env * amp, pan)) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/scatter.scd0000644000175100001770000000103614611211152022504 0ustar00runnerdockerSynthDef.new(\scatter, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=((Saw.ar(freq, mul: (amp / 8)) + VarSaw.ar((freq + [2, 1]), mul: (amp / 8))) * LFNoise0.ar(rate)); env=EnvGen.ar(Env.linen(attackTime: 0.01,releaseTime: (sus / 2),level: (sus / 2),curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/scrap.scd0000644000175100001770000000111014611211152022140 0ustar00runnerdockerSynthDef.new(\scrap, { |vib=0, bus=0, slide=0, rate=1, atk=0.01, sus=1, slidefrom=1, fmod=0, amp=1, freq=0, bits=0, pan=0| var osc, env, vibr; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = Line.ar(freq * slidefrom, freq * (1 + slide), sus); vibr = Vibrato.kr(osc, rate: vib); env = Env.linen(atk, sus, 0.04, curve: -4).kr(doneAction: 0); osc = osc * vibr; osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/scratch.scd0000644000175100001770000000110714611211152022465 0ustar00runnerdockerSynthDef.new(\scratch, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0.04, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, depth=0.5| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 4); freq=(freq * Crackle.ar(1.5)); osc=SinOsc.ar(Vibrato.kr(freq, 2, 3, rateVariation: rate, depthVariation: depth), mul: amp); env=EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/shore.scd0000644000175100001770000000107314611211152022160 0ustar00runnerdockerSynthDef.new(\shore, { |bus=0, dur=1, amp=1, fmod=0, freq=0, pan=0, noiselevel=0.1, density=100| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGate.new(doneAction: 0, curve: \sin); osc = OnePole.ar(WhiteNoise.ar(noiselevel) + Dust.ar(density, 0.5), 0.7); osc = osc + Splay.ar(FreqShift.ar(osc, 1/(4..9))); osc = osc * env * amp; osc = Mix(osc) * 0.1; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sillyvoice.scd0000644000175100001770000000353114611211152023223 0ustar00runnerdockerSynthDef.new(\sillyvoice, { |freq=0, amp=1, vibro=6, vibdepth=4, curve= -4, vowel=0, fmod=0, atk=0.01, sus=1, rel=0.1, lag=1, gate=1, pan=0, bus=0| var in, vibrato, env, va, ve, vi, vo, vu, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; vibrato = SinOsc.kr(freq:vibro, mul: vibdepth); in = Saw.ar(Lag.kr(freq, lag) + vibrato); env = Env.linen(atk, sus, rel, curve: -4).kr(doneAction: 0); va = BBandPass.ar(in: in,freq: [ 600, 1040, 2250, 2450, 2750 ], bw: [ 0.1, 0.067307692307692, 0.048888888888889, 0.048979591836735, 0.047272727272727 ], mul: [ 1, 0.44668359215096, 0.35481338923358, 0.35481338923358, 0.1 ]); ve = BBandPass.ar(in: in,freq: [ 400, 1620, 2400, 2800, 3100 ] , bw: [ 0.1, 0.049382716049383, 0.041666666666667, 0.042857142857143, 0.038709677419355 ], mul: [ 1, 0.25118864315096, 0.35481338923358, 0.25118864315096, 0.12589254117942 ]); vi = BBandPass.ar(in: in,freq: [ 250, 1750, 2600, 3050, 3340 ] , bw: [ 0.24, 0.051428571428571, 0.038461538461538, 0.039344262295082, 0.035928143712575 ], mul: [ 1, 0.031622776601684, 0.15848931924611, 0.079432823472428, 0.03981071705535 ] ); vo = BBandPass.ar(in: in,freq:[ 400, 750, 2400, 2600, 2900 ] , bw: [ 0.1, 0.10666666666667, 0.041666666666667, 0.046153846153846, 0.041379310344828 ], mul: [ 1, 0.28183829312645, 0.089125093813375, 0.1, 0.01 ]); vu = BBandPass.ar(in: in,freq: [ 350, 600, 2400, 2675, 2950 ], bw: [ 0.11428571428571, 0.13333333333333, 0.041666666666667, 0.044859813084112, 0.040677966101695 ], mul: [ 1, 0.1, 0.025118864315096, 0.03981071705535, 0.015848931924611 ]); osc = SelectX.ar(Lag.kr(vowel,lag),[va, ve, vi, vo, vu]); osc = Mix.new(osc) * 2; osc = osc * env * amp; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Bruno Ruviaro", modified_by: "Jens Meisner", description: "", category: \choir, tags: [\voice, \bass] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sine.scd0000644000175100001770000000106714611211152022001 0ustar00runnerdockerSynthDef.new(\sine, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, rel=0.01, peak=1, level=0.5, sinefb=0.2| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = SinOscFB.ar(freq, sinefb)*0.1; env = Env.linen(atk,sus,rel,curve:'lin').kr(doneAction: 0); osc = osc * env * amp; osc = Mix(osc); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sinepad.scd0000644000175100001770000000114514611211152022463 0ustar00runnerdockerSynthDef.new(\sinepad, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 1.5); freq=(freq + [0, 2]); osc=SinOsc.ar(freq, mul: amp); osc=HPF.ar(osc, 1000); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/siren.scd0000644000175100001770000000144114611211152022157 0ustar00runnerdockerSynthDef.new(\siren, { |bus=0, slide=0, rate=1, slidefrom=1, atk=0.01, sus=1, fmod=0, amp=1, freq=0, bits=0, pan=0, vib=0, offnote=1.005| var osc, osc2, env; freq = [freq, freq + fmod]; freq = Line.ar(freq * slidefrom, freq * (1 + slide), sus); freq = Vibrato.kr(freq, rate: vib); osc = VarSaw.ar([freq, (freq * offnote)], width: ((rate - 1) / 4)); osc2 = LFSaw.ar(freq + LFNoise0.ar((rate * 20), mul: 0.5, add: (freq * Pulse.ar(((rate - 2) + 0.1), add: 1)))); env = EnvGen.ar(Env.perc(attackTime: 0.1, releaseTime: sus, level: amp, curve: \sin), doneAction: 0); osc = Mix(osc, osc2) * env * amp * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sitar.scd0000644000175100001770000000117614611211152022166 0ustar00runnerdockerSynthDef.new(\sitar, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 0.75); sus=(sus * 4); osc=LFNoise0.ar([8400, 8500], amp); osc=(osc * XLine.ar(1, 1e-06, (sus * 0.1))); freq=((265 / (freq * [0.666, 0.669])) * 0.005); osc=CombL.ar(osc, delaytime: freq, maxdelaytime: 2); env=EnvGen.ar(Env(times: [sus],levels: [(amp * 1), (amp * 1)],curve: 'step'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/snick.scd0000644000175100001770000000074214611211152022151 0ustar00runnerdockerSynthDef.new(\snick, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc=(LFPar.ar(freq, mul: 1) * Blip.ar(((rate + 1) * 4))); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/soft.scd0000644000175100001770000000104614611211152022013 0ustar00runnerdockerSynthDef.new(\soft, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 2); amp=(amp / (200 * (1 + rate))); osc=Klank.ar(`[[7, 5, 3, 1], [8, 4, 2, 1], [2, 4, 8, 16]], LFNoise0.ar((rate / sus)), freq); env=EnvGen.ar(Env(times: sus,levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/soprano.scd0000644000175100001770000000110314611211152022513 0ustar00runnerdockerSynthDef.new(\soprano, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus=(sus * 1.75); amp=(amp / 2); freq=Vibrato.kr(freq, (rate + 4)); osc=(SinOsc.ar((freq * 3), mul: amp) + SinOscFB.ar((freq * 3), mul: (amp / 2))); env=EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sos.scd0000644000175100001770000000162114611211152021643 0ustar00runnerdockerSynthDef(\sos, { |amp=1, gate=1, rel=1,dur=8, bus=0, freq=200, freqs=240,pan=0, fmod=0, sus=1, vib=0| var osc1, env, osc, osc2; osc1 = VarSaw; freqs = (Rand(60, 40)).midicps + SinOsc.ar(Rand(0, 8)); env = EnvGen.ar(Env(curve: 'lin',levels: [0, amp, 0],times: (sus * 1.2)), doneAction: 0); osc = FreeVerb2.ar(*XFade2.ar( SinOscFB.ar([Rand(1, 240),Rand(1, 240)], osc1.kr(Rand(1, 400))), SinOscFB.ar([freqs * 1.2,freqs], osc1.kr(vib+1)+Rand(2, 2000)/2), osc1.kr(0.1))); osc2 = SinOscFB; osc2 = RLPF.ar(BrownNoise.ar(1), Rand(200, 1600), 0.015,1) * 1; osc = (osc + (osc2 * Rand(0, 0.01))) * env; // sig = Mix(sig) * 1; // sig = LPF.ar(sig, 5000); osc = BLowShelf.ar(osc, 60); osc = osc * amp * 0.4; osc = Pan2.ar(osc, pan).tanh; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \ambient, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sosbell.scd0000644000175100001770000000272714611211152022512 0ustar00runnerdockerSynthDef.new(\sosbell, { //Standard Values |freq=440, bus=0, amp=1, fmod=0, pan=0, rel=2, curve=\lin, ringamp=1, ringrel=0.9, wobbledepth=0.9, wobblemin=0.3, wobblemax=3.8, strikeamp=1, strikedec=0.05, strikerel=0.09, strikedepth=0.058, strikeharm=4, humamp=0.7, atk=0.1, sus=1| var osc, ring, ringEnv, ringFreqs, strike, strikeEnv, strikeMod, hum, humEnv; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; ringFreqs = [2, 3, 4.1, 5.43, 6.8, 8.21]; ringEnv = Env.new(levels: [1, 0.3, 0.2, 0], times: [1/3, 1/3, 1/3] * ringrel * rel, curve: curve).kr; ring = SinOsc.ar(freq: ringFreqs * freq, mul: Array.series(6, 1, -0.1) * ringEnv); ring = ring * LFTri.ar(freq: {Rand(wobblemin, wobblemax)}.dup(6)).range((1 - wobbledepth), 1); strikeEnv = Env.new(levels: [1, 0.1, 0], times: [strikedec, strikerel * rel], curve: curve).kr; strikeMod = LFNoise1.ar(freq * 36).range(1/ (strikedepth + 1), strikedepth + 1); strike = SinOsc.ar(freq: freq * strikeharm * strikeMod, mul: strikeEnv); humEnv = Env.new(levels: [0, 1, 0.8, 0], times: [atk, sus, rel*2], curve: curve).kr; hum = SinOsc.ar(freq: freq * [1.01, 0.47], mul: humEnv); osc = Mix.ar((ring * ringamp) + (strike * strikeamp) + (hum * humamp)) * amp * 0.03; DetectSilence.ar(in: osc, doneAction: 0); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Dan Stowell", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", category: \bells, tags: [\bell, \percussion, \pitched, \additive, \sos] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/space.scd0000644000175100001770000000116614611211152022136 0ustar00runnerdockerSynthDef.new(\space, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, rq=0.5| var osc, env, filter; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp * 2); freq = freq * [1, 1.01]; osc = Ringz.ar(ClipNoise.ar(0.001).dup / 2 + Impulse.ar(0.01, mul:0.02 * rate,), freq * 3); osc = RHPF.ar(osc, freq * 2.5, rq); env = EnvGen.ar(Env([1, 0.8, 0.5, 0],[0.2 * sus, 0.5 * sus, 0.7 * sus])); osc = Mix(osc) * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/spacesaw.scd0000644000175100001770000000317714611211152022655 0ustar00runnerdockerSynthDef.new(\spacesaw, { // Standard Values |bus=0, amp=1, gate=1, freq=100, fmod=0, pan=0, atk=0.25, sus=1, rel=0.3, crv= -4, filterlow=100, filterhigh=2000, rq=0.3, sidepreamp=2, midpreamp=1, lfofreq=0.1, lfodepth=0.015, balance=0.5, monoswitch=0| var env, lfo, leftIn, rightIn, mid, side, leftOut, rightOut, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; // Envelope and LFO env = EnvGen.ar(Env.linen(atk, sus, rel, (sus / 2),curve: crv), doneAction: 0); lfo = SinOsc.ar(freq: lfofreq, phase: [0, pi]); lfo = lfo.range(1 - lfodepth, 1 + lfodepth); //Stereo signal with beatings leftIn = LFSaw.ar(freq: freq * lfo[0]); rightIn = LFSaw.ar(freq: freq * lfo[1]); // L/R to M/S conversion mid = (leftIn + rightIn)/2; side = (leftIn - rightIn)/2; // FX on the M/S signal mid = RLPF.ar(in: mid, freq: LinExp.ar( in: env, srclo: 0, srchi: 1, dstlo: filterlow, dsthi: filterhigh), rq: rq, mul: midpreamp); mid = mid.softclip/midpreamp.softclip; mid = mid * (1 - balance).clip(0, 1) * env; side = RLPF.ar(in: side, freq: LinExp.ar(in: env, srclo: 0, srchi: 1, dstlo: filterhigh, dsthi: filterlow), rq: rq, mul: sidepreamp); side = side.softclip/sidepreamp.softclip; side = side * balance.clip(0, 1) * env; // Output Stuff and Converting Back to L/R leftOut = mid + side; rightOut = mid - side; osc = Select.ar(which: monoswitch, array: [[leftOut, rightOut], Pan2.ar(leftOut, pan)]); osc = osc * amp * 0.15; osc = Limiter.ar(osc); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "", category: \pads, tags: [\pitched, \midsidesaw] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/spark.scd0000644000175100001770000000111114611211152022151 0ustar00runnerdockerSynthDef.new(\spark, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp + 1e-05); freq=(freq + [0, LFNoise2.ar(50).range(-2, 2)]); osc=((LFSaw.ar((freq * 1.002), iphase: Saw.ar(0.1)) * 0.3) + (LFSaw.ar(freq, iphase: Saw.ar(0.1)) * 0.3)); osc=(((osc * Line.ar(amp, (amp / 10000), (sus * 1.5))) * 0.3) * Line.ar(0.01, 1, (sus * 0.033))); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/spick.scd0000644000175100001770000000130014611211152022142 0ustar00runnerdockerSynthDef.new(\spick, { |vib=0, bus=0, slide=0, rate=1, atk=0.1, sus=1, slidefrom=1, fmod=0, amp=1, freq=0, bits=0, pan=0| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = Line.ar(freq * slidefrom, freq * (1 + slide), sus); freq = Vibrato.kr(freq, rate: vib); sus = (sus * 1.25); osc = (LFPulse.ar(freq).distort + Impulse.ar((freq + 1)).tan); env = EnvGen.ar(Env.perc(attackTime: atk, releaseTime: sus, level: 1, curve: 0), doneAction: 0); osc = osc * env * amp; osc = Mix(osc) * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/sputter.scd0000644000175100001770000000452714611211152022555 0ustar00runnerdockerSynthDef.new(\sputter, { //Standard Values // Modulation Controls // Resonator controls // Other Controls (all go from 0 to 1, except for method from 0 to 4) |bus = 0, pan = 0, amp = 1, freq = 440, fmod = 0, atk = 0.1, sus = 1, rel = 2.5, crv = -6, pw = 0.5, noisedepth = 0.05, pwmrate = 12, pwmdepth = 0.15, rstartf = 2000, rlf = 500, rrf = 5000, ratk = 0.5, method = 0, gateSwitch = 1, gateThresh = 0.5, stereoWidth = 0.75| var env, envNoise, resControl, pwm, osc, res; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; // Make an Envelope env = Env.perc(attackTime: atk, releaseTime: sus + rel, curve: crv).ar; // Add a Little Noise to the Envelope envNoise = [LFClipNoise.ar(freq: freq).range(0, noisedepth), LFClipNoise.ar(freq: freq).range(0, noisedepth)]; envNoise = Schmidt.ar(in: env, lo: 0.0001, hi: 0.0001) * envNoise; env = env + envNoise; // Make an LFO for the Pulse Width pwm = LFTri.ar(freq: pwmrate, mul: pwmdepth); pwm = (pwm + pw).clip(0, 1); // Make a Square Wave osc = LFPulse.ar(freq: freq, width: pwm, mul: env); // Make a Noise Gate osc = osc * Schmidt.ar(in: osc, lo: gateThresh * gateSwitch, hi: gateThresh); //Make a Resonator for the Square resControl = Line.ar(start: rstartf, end: [rlf, rrf], dur: ratk); res = DelayC.ar(in: osc, maxdelaytime: [(1/rstartf).max(1/rlf), (1/rstartf).max(1/rrf)], delaytime: 1/resControl); // Choose how to Combine the Square and Resonator osc = Select.ar( which: method.clip(0, 4).round(1), array: [(osc + res).clip(0, 1), // kinda like "snd or res" (osc + res).wrap(0, 1), // kinda like "snd or res" osc * res, // kinda like "snd and res" (1 - osc) * res, // kinda like "not-snd and res" ((1 - osc) * res) + ((1 - res) * osc) // like "snd xor res" ]); osc = LeakDC.ar(osc); // Set the Stereo Width osc = XFade2.ar( inA: [osc[1], osc[0]], inB: [osc[0], osc[1]], pan: stereoWidth ); // Output Stuff osc = HPF.ar(in: osc, freq: freq/2); osc = osc * amp; osc = Limiter.ar(osc); DetectSilence.ar(in: Mix.ar(osc), doneAction: 0); // Stereo Version of Pan2.ar osc = Balance2.ar(left: osc[0], right: osc[1], pos: pan); osc = Mix(osc) * 0.05; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "", category: \keyboards, tags: [\pitched, \lead, \stereo] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/square.scd0000644000175100001770000000121614611211152022337 0ustar00runnerdockerSynthDef.new(\square, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, phase=0.5, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sus = sus * blur; osc = PulseDPW.ar(freq, phase); env = EnvGen.ar(Env(times: [0.01, (sus - 0.01), 0.01],levels: [0, 1, 1, 0],curve: 'lin'), doneAction: 0); osc = osc * env * (amp/8); osc = Mix(osc) * 0.3; osc = osc * env * amp; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/squish.scd0000644000175100001770000000072014611211152022352 0ustar00runnerdockerSynthDef.new(\squish, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 4); osc=Ringz.ar(Pulse.ar((4 * rate)), freq, sus, amp); osc=(osc * XLine.ar(0.5, 1e-06, sus, doneAction: 2)); osc=osc.cos; amp=(amp * 4); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/ssaw.scd0000644000175100001770000000326214611211152022017 0ustar00runnerdockerSynthDef.new(\ssaw, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, sawmix=0.75, sawtune=0.75, sawtype=0| var osc, osc1, osc2, osc3, env, detuneCurve, centerGain, sideGain, center, freqs, side; freq = In.kr(bus, 1); freq = [freq, freq+fmod] * Line.ar(Rand(0.5,1.5),1,0.02); freq=(freq / 2); amp=(amp * 0.4); detuneCurve = { |x| (10028.7312891634*x.pow(11)) - (50818.8652045924*x.pow(10)) + (111363.4808729368*x.pow(9)) - (138150.6761080548*x.pow(8)) + (106649.6679158292*x.pow(7)) - (53046.9642751875*x.pow(6)) + (17019.9518580080*x.pow(5)) - (3425.0836591318*x.pow(4)) + (404.2703938388*x.pow(3)) - (24.1878824391*x.pow(2)) + (0.6717417634*x) + 0.0030115596 }; centerGain = { |x| (-0.55366 * x) + 0.99785 }; sideGain = { |x| (-0.73764 * x.pow(2)) + (1.2841 * x) + 0.044372 }; center = LFSaw.ar(freq, Rand()); freqs = [ (freq - (freq*(detuneCurve.(sawtune))*0.11002313)), (freq - (freq*(detuneCurve.(sawtune))*0.06288439)), (freq - (freq*(detuneCurve.(sawtune))*0.01952356)), (freq + (freq*(detuneCurve.(sawtune))*0.01991221)), (freq + (freq*(detuneCurve.(sawtune))*0.06216538)), (freq + (freq*(detuneCurve.(sawtune))*0.10745242)) ]; side = Mix.fill(6, { |n| SelectX.ar(sawtype, [VarSaw.ar(freqs[n], Rand(0, 2)),LFSaw.ar(freqs[n], Rand(0, 2))], 1); }); osc = (center * centerGain.(sawmix)) + (side * sideGain.(sawmix)); osc = HPF.ar(osc, freq); env=EnvGen.ar(Env([0,1,0.8,0.8,0], [0.02, 0.01, sus/2, sus/2]), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 1/4; osc = Pan2.ar(osc * amp, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \category, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/star.scd0000644000175100001770000000123414611211152022010 0ustar00runnerdockerSynthDef.new(\star, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=((amp * 2) + 1e-05); freq=(freq / 2); osc=((LFSaw.ar((freq * 1.002), iphase: VarSaw.kr(freq, width: Line.kr(1, 0.2, sus))) * 0.3) + (LFSaw.ar(((freq + LFNoise2.ar(50).range(-2, 2)) + 2), iphase: VarSaw.kr((freq + 2), width: Line.kr(1, 0.2, sus))) * 0.3)); osc=((osc * XLine.ar(amp, (amp / 10000), (sus * 3), doneAction: 2)) * Line.ar(0.01, 0.5, 0.07)); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/stargazer.scd0000644000175100001770000000354114611211152023044 0ustar00runnerdockerSynthDef.new(\stargazer, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.0001, decay=0.01, rel=0.01, peak=1, level=0.8, wave=0, sub=0, detune=1, mix=(-1.0), freq1=880, freq2=880, res1=0.0, res2=0.0, rate1 = 10, rate2 = 10, rate3 = 10, depth1 = 1, depth2 = 1, depth3 = 1, alias=44100, redux=24, lfo1type1 = 0, lfo1type2 = 0, lfo1type3 = 0| var osc, env, detuned, pitch, lfo1, lfo2, lfo3, filter1, filter2; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; ~wt = Array.fill(90, { var numSegs = rrand (90, 20); Env( (({rrand(0.0, 1.0)}!(numSegs-1))*[1, -1]).scramble, {rrand(1, 20)}!numSegs, 'sine' // {rrand(-20,20)}!numSegs ).asSignal(1024).asWavetable; }); ~vbuf = Buffer.allocConsecutive(90, s, 2048); ~vbuf.do({ arg buf, i; buf.loadCollection(~wt[i]); }); lfo1=Select.kr(lfo1type1, [LFTri.kr(rate1), LFSaw.kr(rate1), LFPulse.kr(rate1)]); lfo2=Select.kr(lfo1type2, [LFTri.kr(rate2), LFSaw.kr(rate2), LFPulse.kr(rate2)]); lfo3=Select.kr(lfo1type3, [LFTri.kr(rate3), LFSaw.kr(rate3), LFPulse.kr(rate3)]); detuned = Select.ar(sub, [VOsc.ar(wave, freq*detune.midiratio), VOsc.ar(wave, (freq*0.5)*detune.midiratio)]); wave = ~vbuf[0].bufnum + wave; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = VOsc.ar(wave, freq); osc = XFade2.ar(osc, detuned, mix); filter1 = MoogLadder.ar(osc, freq1*lfo1.range(1, depth1), res1); osc = Decimator.ar(filter1, alias, redux); filter2 = MoogLadder.ar(osc, freq2*lfo2.range(1, depth2), res2); osc = Splay.ar(filter2); osc = LeakDC.ar(osc); osc = osc * amp * env * lfo3.range(1, depth3); osc = Limiter.ar(osc, 0.1); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \organ, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/steeldrum.scd0000644000175100001770000000252214611211152023044 0ustar00runnerdockerSynthDef.new(\steeldrum, { |bus=0, freq=440, amp=1, pan=0, fmod=0, atk=0.01, sus=1, curve = -6, fharm=6, offnote=2.015| var osc, resFreqArray, resAmpArray, resDecArray, enva, envb, envc, osca, oscb, oscc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; resFreqArray = [2, 2.98, 4.75, 6.21, 9, 9.15, 11.87]; resAmpArray = [0.35, 0.23, 0.10, 0.06, 0.07, 0.05, 0.01]; resDecArray = [0.86, 0.72, 0.37, 0.55, 0.32, 0.21, 0.16]; enva = Env.pairs([[0, 0], [atk, 1], [(atk + sus), 0]], curve).kr; envb = Env.pairs([[0, 0], [(atk * 5), 0.25], [(atk * 6), 0.75], [((atk * 6) + (sus)), 0]], curve).kr; envc = Env.pairs([[0, 0], [(atk * 5), 0.1], [(atk * 8), 0.5], [((atk * 8) + (sus*1.2)), 0]], curve).kr; osca = SinOsc.ar(freq: freq, mul: enva); oscb = SinOsc.ar(freq: freq * offnote, mul: envb); oscc = DynKlank.ar(specificationsArrayRef:Ref.new([resFreqArray * freq, resAmpArray, resDecArray * sus ]),input:LPF.ar(HPF.ar(CombN.ar(PinkNoise.ar(1), 1/freq, 1/freq, -1, envc), freq * 2), freq * fharm)); osc = Mix.ar([osca, oscb, oscc]) * amp * 0.1; osc = Limiter.ar(osc, amp); DetectSilence.ar(in: osc, amp: 0.0001, time: 0.5, doneAction: 0); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "", category: \percussion, tags: [\pitched, \steelDrum, \steelPan] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/stretch.scd0000644000175100001770000000074114611211152022515 0ustar00runnerdockerSynthDef.new(\stretch, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1.0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, buf=0, pos=0, room=0.1| var osc, env; sus = sus * blur; rate = In.kr(bus, 1); osc = Warp1.ar(2, buf, Line.kr(0,1,sus), rate, windowSize: 0.2, overlaps: 4, interp:2); osc = osc * EnvGen.ar(Env([0,1,1,0],[0.05, sus-0.05, 0.05])); osc=(osc * amp); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/strings.scd0000644000175100001770000000203214611211152022525 0ustar00runnerdockerSynthDef.new(\strings, { //Standard Definitions |bus = 0, freq = 440, amp = 1, gate = 1, pan = 0, fmod=0, atk = 0.1, sus = 1, rel = 0.2, freqlag = 0.9, rq = 0.012, combharm = 4, sawharm = 1.5, mix = 0.33| var env, osc, combFreq; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; combFreq = 1 / (Lag.kr(in: freq, lagTime: freqlag / 2) * combharm); env = Env.linen(atk, sus, rel, curve: \sin).kr(gate: gate, doneAction: 0); osc = SyncSaw.ar(syncFreq: freq * WhiteNoise.kr().range(1/1.025, 1.025), sawFreq: freq * sawharm, mul: 8); osc = (osc * (1 - mix)) + PinkNoise.ar(180 * mix); osc = CombL.ar(osc, combFreq, combFreq, -1); //Try positive 1 for decay time as well. osc = Resonz.ar(osc, Lag.kr(in: freq, lagTime: freqlag), rq).abs; osc = Mix.ar(osc) * env * amp; osc = Limiter.ar(osc, amp * 0.1); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Original from Julian Rohrhuber, 2007", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "", category: \strings, tags: [\pitched] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/subbass.scd0000644000175100001770000000270314611211152022503 0ustar00runnerdockerSynthDef.new(\subbass, { //Blend goes from 0 to 1 |bus=0, amp=1, pan=0, freq = 440, fmod=0, atk = 0.01, sus=1, rel = 0.15, curve = -12, blend = 0.5, plpf=2400, plpr=1.0| var env, in, ina, synca, octa, inb, syncb, syncc, octb, octave, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 3; amp = amp * 2; //A slightly rounded percussive envelope env = Env.linen(atk, sus, rel, amp, [curve, -1 * curve]).kr(doneAction: 0); //Input wave - To use SinOsc.ar, replace "iphase: 2" with "phase: 3pi/2" in = LFPar.ar(freq: freq , iphase: 0.5); //Mirroring the wave around the x-axis ina = in.range(-1, 1); inb = ina; //Two square waves exactly out of phase and an octave below the input wave synca = LPF.ar(LFSaw.ar(freq: freq / 1, iphase: 0.5, mul: 0.2) + SinOscFB.ar(freq, mul: 1), plpf, plpr); syncb = LPF.ar(LFTri.ar(freq: freq / 2, iphase: 0.5, mul: 1.0) + SinOscFB.ar(freq, mul: 1), plpf, plpr) ; //This smoothly swaps between outputting the input wave and its mirror octa = ina * synca; octb = ina * syncb; octave = Mix.ar([octa, octb]); //Mixer stage, volume adjustments, envelope, and output osc = Mix.ar([octave * blend * 0.4, in * (1 - blend)]); osc = LeakDC.ar(osc); osc = Limiter.ar(in: osc, level: 1); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "", category: \bass, tags: [\pitched, \sub] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/subbass2.scd0000644000175100001770000000305014611211152022561 0ustar00runnerdockerSynthDef.new(\subbass2, { //Blend goes from 0 to 1 |bus=0, amp=1, pan=0, freq=440, fmod=0, atk=0.01, sus=1, rel=0.9, curve= \sqr, blend=0.1, plpf=800, plpr=1.0| var env, in, ina, synca, octa, inb, syncb, octb, octave, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 2; //A slightly rounded percussive envelope env = Env.linen(atk, sus, rel, amp, [curve, -1 * curve]).kr(doneAction: 0); /* Input wave +/- 90 degrees - To use SinOsc.ar, replace: -"iphase: 0" with "phase: pi/2" -"iphase: 1" with "phase: 0" -"iphase: -1" with "phase: pi" */ in = LFPar.ar(freq: freq, iphase: pi/2); ina = LFPar.ar(freq: freq, iphase: 0); inb = LFPar.ar(freq: freq, iphase: pi); //Two square waves exactly out of phase and an octave below the input wave synca = LPF.ar(LFPulse.ar(freq: freq / 2, iphase: 0, mul: 0.4) + LFCub.ar(freq: freq, iphase: 0), plpf, plpr); syncb = LPF.ar(LFPulse.ar(freq: freq / 2, iphase: 0, mul: 0.4) + LFCub.ar(freq: freq, iphase: 0.5), plpf, plpr); //This smoothly swaps between outputting the +90 degree wave and -90 degree wave octa = ina * synca; octb = inb * syncb; octave = Mix.ar([octa, octb]); //Mixer stage, volume adjustments, envelope, and output osc = Mix.ar([octave * blend, in * (blend - 1)]); osc = LeakDC.ar(osc); osc = Limiter.ar(in: osc, level: 1); osc = osc * env * amp * 0.8; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Josh Mitchell", modified_by: "Jens Meisner", description: "", category: \bass, tags: [\pitched, \sub] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/supersaw.scd0000644000175100001770000000122714611211152022712 0ustar00runnerdockerSynthDef.new(\supersaw, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, rel=0.01, peak=1, level=0.8, phase=0, noiserate=0.5| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = {freq * LFNoise2.kr(noiserate).range(0.98, 1.02)}!20; amp = (amp / 20); osc = LFSaw.ar(freq, phase); env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \lin), doneAction: 0); osc = Mix(osc); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "unknown", modified_by: "Jens Meisner", description: "", category: \pads, tags: [\pitched] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/swell.scd0000644000175100001770000000112314611211152022162 0ustar00runnerdockerSynthDef.new(\swell, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 4); freq=(freq + [0, 1]); freq=(freq * [1, 0.5]); osc=VarSaw.ar(freq, width: SinOsc.ar((rate / ((2 * sus) / 1.25)), add: 0.5, mul: [0.5, 0.5]), mul: [1, 0.5]); env=EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tb303.scd0000644000175100001770000000261014611211152021671 0ustar00runnerdocker<<<<<<< HEAD:renardo_lib/renardo_lib/osc/scsyndef/tb303.scd ( SynthDef (\tb303, {| bus=0, freq=440, atk=0.1, wave=0, ctf=100, res=0.2, pan=0, sus=1, dec=1.0, top=1000, gate=0, amp=1| var filEnv, volEnv, waves, osc; ======= SynthDef.new(\tb303, { |bus=0, freq=440, atk=0.1,fmod=0, pan=0, sus=1, dec=1.0, gate=0, amp=1, wave=0, ctf=100, res=0.2, top=1000| var filEnv, volEnv, waves, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; >>>>>>> badc8940 (Add meta-data block and filled in known information, add new synths, rename and fix old synths):FoxDot/osc/scsyndef/tb303.scd volEnv = EnvGen .ar( Env .new([10e-10, 1, 1, 10e-10], [0.01, sus, dec], 'exp' )); filEnv = EnvGen .ar( Env .new([10e-10, 1, 10e-10], [0.01, dec], 'exp' )); waves = [ Saw .ar(freq, volEnv), Pulse .ar(freq, 0.5, volEnv)]; osc = RLPF .ar( Select .ar(wave, waves), ctf + (filEnv * top), res).dup * amp; osc = Mix(osc) * 0.5; osc = HPF.ar(osc, 20); osc = LPF.ar(osc, 14000); osc = Splay.ar(osc * amp, pan); <<<<<<< HEAD:renardo_lib/renardo_lib/osc/scsyndef/tb303.scd ReplaceOut.ar(bus, osc)}).add; ) ======= ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; >>>>>>> badc8940 (Add meta-data block and filled in known information, add new synths, rename and fix old synths):FoxDot/osc/scsyndef/tb303.scd ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/total.scd0000644000175100001770000000135714611211152022170 0ustar00runnerdockerSynthDef.new(\total, { |bus = 0, amp = 0.5, fmod=0, sus=1, blur=1, rate=0, freq = 220, atk=0.25, rel = 0.2, gate=1, pan = 0| var sig , sig1, sig2, sig3, env, osc; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; sig1 = SinOscFB; sig2 = mean(FreqShift.ar(c=sig1.ar(sig1.ar(sig1.ar(freq/b=(1..8),1),fmod/b)+b*[fmod, 99, freq],1),1/b)+c); sig = sig2 ; sig = sig * LinSelectX.kr(rate,[1, SinOsc.ar(4, 0, 1)]); env=EnvGen.ar(Env(times: [atk, (sus * 1)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(sig * env); osc = Mix(osc) * 0.4; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \organ, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tremsynth.scd0000644000175100001770000000107214611211152023074 0ustar00runnerdockerSynthDef.new(\tremsynth, { |bus=0, freq=0, amp=1, pan=0, fmod=0, atk=0.01, sus=1, rel=0.1, pos=0, modfreq=3| var osc, mod, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; mod = SinOsc.kr(freq: modfreq, mul: 1).range(0,1); osc = LFTri.ar(freq: freq, mul: mod); env = Env.linen(atk, sus, rel, curve: \lin).kr(doneAction: 0); osc = Mix(osc); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tribell.scd0000644000175100001770000000151414611211152022475 0ustar00runnerdockerSynthDef.new(\tribell,{ |bus = 0, pan = 0.0, freq = 440, amp = 1.0, gate = 1, fmod = 0, atk = 0.1, sus = 1, rel = 3, lforate = 8, lfowidth = 0.02, cutoff = 80, rq = 0.05| var osc1, osc2, vibrato, filter, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; vibrato = SinOsc.ar(lforate, Rand(0, 2.0)); osc1 = Saw.ar(freq * (1.0 + (lfowidth * vibrato)), 0.65); osc2 = Mix(LFTri.ar((freq.cpsmidi + [11.9, 12.1]).midicps)); filter = RHPF.ar((osc1 + (osc2 * 0.8)) * 0.4, cutoff, rq); env = EnvGen.ar(envelope: Env.perc(atk, sus + rel, amp), gate: gate, doneAction: 0); osc = Mix(osc); osc = filter * env * amp * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Mitchell Sigman", modified_by: "Bruno Ruviaro, Jens Meisner", decription: "Description", category: \pads, tags: [\pitched, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tritri.scd0000644000175100001770000000142714611211152022360 0ustar00runnerdockerSynthDef.new(\tritri, { |amp=1, sus=1, gate=1, pan=0, modfreq=5 freq=0, vib=0, fmod=0, rate=4.85, phase=0.5, cutoff=2000, rq=0.5, mul=1, bus=0, atk=0.0001, decay=0.01, rel=0.01, level=0.8, peak=1| var osc, pulse, filter,env, modulator; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; modulator = SinOsc.ar(modfreq).range(0, 1); osc = LFTri.ar(freq: freq, mul: modulator); env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); osc = BLowPass4.ar(osc,(cutoff*(env.squared))+200+freq,rq); osc = Mix(osc*env) * amp * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "", description: "", category: \organ, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/triwave.scd0000644000175100001770000000135114611211152022520 0ustar00runnerdockerSynthDef.new(\triwave,{ |bus=0, pan=0.0, freq=0, fmod=0, amp=1.0, atk=0.01, sus=1, rel=0.1, lforate=3, lfowidth=0.0, cutoff=400, rq=0.7| var osc1, osc2, vibrato, filter, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; vibrato = SinOsc.ar(lforate, Rand(0, 3.0)); env = Env.linen(atk, sus, rel, curve:\sin).kr(doneAction: 0); osc1 = Saw.ar(freq * (1.0 + (lfowidth * vibrato)), 0.5); osc2 = Mix.ar(LFTri.ar((freq.cpsmidi + [11.9, 12.1]).midicps)); osc = RHPF.ar(((osc1 * 0.2) + (osc2 * 0.4))); osc = Mix(osc); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc,pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tubularbell.scd0000644000175100001770000000172014611211152023354 0ustar00runnerdockerSynthDef.new(\tubularbell, { |freq=440, amp=1, pan=0, bus=0, fmod=0, atk=0.1, sus=1, rel=9, exciterRel=0.05| var env, osc, exciter; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp = amp / 10; env = Env.perc(atk, exciterRel, 0.05).kr; exciter = GrayNoise.ar(env); osc = DynKlank.ar( specificationsArrayRef: Ref.new([ [1.013, 1.512, 2.113, 2.525, 3.35, 4.57, 6.48], // harmonics [1, 0.78, 0.89, 0.63, 0.31, 0.56, 0.25], // amplitudes [1, 0.9, 0.8, 0.65, 0.45, 0.3, 0.1] // ring times ]), input: exciter, freqscale: freq, decayscale: sus + rel ); osc = Mix.ar(osc); osc = osc * amp * 0.4; DetectSilence.ar(in: osc, amp: 0.001, time: 0.5, doneAction: 0); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "nicolaariutti, Zé Craum", modified_by: "Josh Mitchell, Bruno Ruviaro, Jens Meisner", description: "", category: \bells, tags: [\pitched, \tubular, \bell] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/twang.scd0000644000175100001770000000105514611211152022160 0ustar00runnerdockerSynthDef.new(\twang, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq / 8); freq=(freq + [0, 2]); osc=LPF.ar(Impulse.ar(freq, 0.1), 4000); osc=(EnvGen.ar(Env.perc(attackTime: 0.01,releaseTime: sus,level: amp,curve: 0), doneAction: 0) * CombL.ar(osc, delaytime: (rate / (freq * 8)), maxdelaytime: 0.25)); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tworgan.scd0000644000175100001770000000213014611211152022514 0ustar00runnerdockerSynthDef.new(\tworgan, { |bus=0, freq=0, amp=1, fmod=0, atk=0.001, sus=1, rel=0.01, pan=0, curve= -4, gate=1, bass=1, qnt=1, fndmtl=1, nazard=1, oct=5, bflute=1, trc=1, lrigot=1, sflute=1, vrate=3, vdepth=0.008, vdelay=0.1, vonset=0, vratevar=0.1, vdepthvar=0.1| var osc, env, vibrato; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp = amp / 4; vibrato = Vibrato.kr(freq: freq,rate: vrate,depth: vdepth,delay: vdelay, onset: vonset, rateVariation: vratevar,depthVariation: vdepthvar,); env = Env.linen(attackTime: atk, sustainTime: sus, releaseTime: rel, curve: curve).kr(gate: gate, doneAction: 0); osc = DynKlang.ar(specificationsArrayRef: Ref.new([ [1/12, 1/7, 1, 12, 19, 24, 28, 31, 36].midiratio, [bass, qnt, fndmtl, oct, nazard, bflute, trc, lrigot, sflute].normalizeSum,nil]), freqscale: vibrato); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Zé Craum", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", decription: "Tonewheel organ ", category: \organ, tags: [\tonewheelorgan, \pitched] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tworgan2.scd0000644000175100001770000000163014611211152022602 0ustar00runnerdockerSynthDef.new(\tworgan2, { //Standard Values |bus=0, pan=0, freq=440, amp=1, fmod=0, atk=0.001, sus=1, rel=0.1, gate=1, vibrate=6.0, vibharm=1.017, fharm=5.04, rq=1, blend=0.83| var osc, env, vibrato; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(atk, sus, rel, curve: \sin).kr(gate: gate, doneAction: 0); vibrato = SinOsc.ar(freq: vibrate).range(freq, freq * vibharm); osc = LFPulse.ar(freq: freq, width: 0.5, mul: 1 - blend) + LFPulse.ar(freq: freq + vibrato, width: 0.18, mul: blend); osc = RLPF.ar(in: osc, freq: fharm * freq, rq: rq, mul: env); osc = osc * amp * 0.15; osc = LeakDC.ar(osc); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Zé Craum", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "Subtractive tonewheel organ with cheep CPU usage", category: \organ, tags: [\tonewheelorgan, \pitched, \substractive] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tworgan3.scd0000644000175100001770000000202114611211152022576 0ustar00runnerdockerSynthDef.new(\tworgan3, { |bus=0, pan=0, freq=440, amp=1, fmod=0, atk=0.1, sus=1, rel=0.1, gate=1, vrate=6, vdepth=0.02, vdelay=0.1, vonset=0, vratevar=0.1, vdepthvar=0.1, fharm=5.04, rq=1, blend=0.83| var osc, env, vibrato; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(atk, sus, rel).kr(gate: gate, doneAction: 0); vibrato = Vibrato.kr(freq: freq, rate: vrate, depth: vdepth, delay: vdelay, onset: vonset, rateVariation: vratevar, depthVariation: vdepthvar); osc = LFPulse.ar(freq: freq, width: 0.5, mul: 1 - blend) + LFPulse.ar(freq: freq + vibrato, width: 0.18, mul: blend); osc = BLowPass4.ar(in: osc, freq: fharm * freq, rq: rq, mul: env); osc = LeakDC.ar(osc); osc = Mix(osc); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Zé Craum", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "Subtractive tonewheel organ with cheap CPU usage", category: \organ, tags: [\tonewheelorgan, \pitched, \substractive] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/tworgan4.scd0000644000175100001770000000202414611211152022602 0ustar00runnerdockerSynthDef.new(\tworgan4, { //Standard Values |bus=0, pan=0, freq=440, amp=1, gate=1, fmod=0, atk=0.1, sus=1, rel=0.3, lforate=4.85, lfodepth=0.006, cutoff=5000, rq=0.5, parfreq=400, parrq=1, pardb=3, blend=0.6| var lfo, pulse, filter, fenv, env, osc; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp = amp / 2; lfo = LFTri.kr(freq: lforate * [1, 1.01], iphase: Rand(0, 2.0) ! 2).range(1 / (1 + lfodepth), (1 + lfodepth)); pulse = Pulse.ar(freq: freq * [1, 3] * lfo, width: [0.5, 0.51], mul: [(1 - blend), blend]); env = Env.linen(atk, sus, rel, curve:\sin).kr(doneAction: 0); filter = BLowPass4.ar(in: pulse, freq: cutoff, rq: rq); filter = BPeakEQ.ar(in: filter, freq: parfreq, rq: parrq, db: pardb); osc = Mix.ar([filter]); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Nick Collins", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "Subtractive tonewheel organ from Steal this Sound example", category: \organ, tags: [\pitched] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/varcell.scd0000644000175100001770000000203614611211152022470 0ustar00runnerdockerSynthDef.new(\varicelle, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, blur=1, beat_dur=1, atk=0.03, decay=0.03, rel=0.09, peak=1, level=0.8, cutoff=4800, noisemix=0.5, noiserate=12, xvib=2| var osc, oscl, oscr, sigA, sigB, sigC, env, modul; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); modul = fmod * SinOsc.kr(rate, add: amp) * Line.kr(0, 1, 7); sigA = Pulse.ar(freq + modul, LFNoise2.kr(1).range(0.2, 0.8) ); sigB = VarSaw.ar(freq + modul); sigC = LPF.ar(WhiteNoise.ar(noisemix) * 0.15, freq * noiserate); sigA = sigA + sigC; sigB = sigB + sigC; osc = SelectX.ar(LFDNoise3.kr(xvib, 0.5).range(0, 1), [sigA, sigB]); osc = Mix(osc); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/varicelle.scd0000644000175100001770000000203614611211152023006 0ustar00runnerdockerSynthDef.new(\varicelle, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=1, bus=0, blur=1, beat_dur=1, atk=0.03, decay=0.03, rel=0.09, peak=1, level=0.8, cutoff=4800, noisemix=0.5, noiserate=12, xvib=2| var osc, oscl, oscr, sigA, sigB, sigC, env, modul; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0); modul = fmod * SinOsc.kr(rate, add: amp) * Line.kr(0, 1, 7); sigA = Pulse.ar(freq + modul, LFNoise2.kr(1).range(0.2, 0.8) ); sigB = VarSaw.ar(freq + modul); sigC = LPF.ar(WhiteNoise.ar(noisemix) * 0.15, freq * noiserate); sigA = sigA + sigC; sigB = sigB + sigC; osc = SelectX.ar(LFDNoise3.kr(xvib, 0.5).range(0, 1), [sigA, sigB]); osc = Mix(osc); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/varsaw.scd0000644000175100001770000000077114611211152022347 0ustar00runnerdockerSynthDef.new(\varsaw, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq=(freq * [1, 1.005]); osc=VarSaw.ar(freq, mul: (amp / 4), width: rate); env=EnvGen.ar(Env(times: [(sus / 2), (sus / 2)],levels: [0, amp, 0],curve: 'lin'), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/vibass.scd0000644000175100001770000000115114611211152022324 0ustar00runnerdockerSynthDef.new(\vibass, { |freq=0, amp=1, bus=0, pan=0, fmod=0, atk=0.01, sus=1, dur=1, rel=0.3, curve = -9, vibrate=9| var env, osc, osc1, osc2; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 2; env = Env.linen(atk, sus, rel, curve:curve).kr(doneAction: 0); osc1 = SinOsc.ar(freq); osc2 = SinOsc.ar(Line.kr(freq + vibrate, freq, dur, doneAction:0)); osc = Mix([osc1, osc2]); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/video.scd0000644000175100001770000000051214611211152022143 0ustar00runnerdockerSynthDef.new(\video, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, fx1=0, fx2=0, fx3=0| var osc, env; freq = In.kr(bus, 1); osc = Mix(osc) * 0.5; ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/vinsine.scd0000644000175100001770000000206214611211152022512 0ustar00runnerdockerSynthDef.new(\vinsine, { |bus=0, amp=1, freq=440, pan=0, fmod=0, atk=0.001, sus=1, rel=0.5, gate=1, noiseamp=0.02, mainsdepth=0.35, mainshz = 50, vrate = 2, vdepth = 0.005, sineclip = 0.825| var noise, env, osc, vibrato; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = Env.linen(atk, sus , rel, curve: \lin).kr(gate: gate, doneAction: 0); noise = PinkNoise.ar(noiseamp * LFPar.ar(mainshz * 2).range((1 - mainsdepth), 1)); noise = noise + LFPar.ar(freq: mainshz, mul: noiseamp*0.1); vibrato = freq * LFNoise2.ar(vrate).range(1/(1 + vdepth), (1 + vdepth)); osc = Clip.ar(LFTri.ar(vibrato), -1 * sineclip, sineclip).softclip; osc = osc + noise; osc = Mix(osc); osc = osc * env * amp * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Zé Craum", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "Crude simulation of old sinusoidal generators - with random vibrato and a high noise floor, 50hz mains hum emulation and slightly distorted sine", category: \keyboards, tags: [\vintage, \pitched] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/viola.scd0000644000175100001770000000131114611211152022145 0ustar00runnerdockerSynthDef.new(\viola, { |amp=1, sus=1, pan=0, freq=0, vib=6, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.25, decay=0.01, rel=0.75, peak=1, level=0.8, verb=0.33, curve=0| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 2); osc=PMOsc.ar(freq, Vibrato.kr(freq, rate: vib, depth: 0.008, delay: (sus * 0.25)), 10, mul: (amp / 2)); env=EnvGen.ar(Env.perc(attackTime: (atk * sus),releaseTime: (rel * sus),level: amp,curve: curve), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "", modified_by: "", decription: "Description", category: \strings, tags: [\violin, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/virus.scd0000644000175100001770000000274214611211152022214 0ustar00runnerdockerSynthDef(\virus, { |len = 2, freq = 420, fmod = 0.1, vib = 0.25, rate = 1, atk=0.01, sus=1, rel=0.09, prate1=1, prate2=2, gate = 1, bus=0, amp=1, pan=0| var mainEnv, speed, freqs, pulse, a, bass, tone1, tone2, tone3, noise, impulse, osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; mainEnv = EnvGen.kr(Env.triangle(len,1), gate, doneAction:0); speed = Array.geom(4, rate, [1.75, 1.25].choose); freqs = Array.geom(8, freq/2, 1.5); pulse = {|prate1, prate2|LFPulse.ar(prate1, [0,0.5,1].choose)*LFPulse.ar(prate2)}; a = Lag.ar(HenonN.ar(speed.choose*(mainEnv*10000.rand), fmod, vib), 0.01); bass = SinOsc.ar(freqs!2*(a*1.0.rand), 0, Lag.ar(pulse.(rate, speed.choose), 0.001)); tone1 = SinOsc.ar([(freqs+Rand(0,5))*a,(freqs+Rand(0,5))*a], 0, 0.01*pulse.(speed.choose, speed.choose)); tone2 = Pan2.ar(SinOsc.ar(freqs.choose*a, 0, 0.1*pulse.(speed.choose, rate)), a); tone3 = SinOsc.ar([freqs.choose,freqs.choose*a], 0, 0.05 * pulse.(speed.choose, rate))*mainEnv.round(0.25); noise = Pan2.ar(PinkNoise.ar(a*0.1*pulse.(rate,rate)), a); impulse = RLPF.ar(Impulse.ar(pulse.(rate, speed.choose), a), freqs.choose+(a*10), 0.01, 0.1).tanh; osc = (bass+tone1+tone2+tone3+noise+impulse).tanh; env = EnvGen.ar(Env.asr(atk, sus, rel, curve:\lin), doneAction: 0); osc = Mix.ar(osc); osc = osc * amp * env * 0.8; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc); }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \noise, tags: [\tag] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/vrender.scd0000644000175100001770000000070514611211152022506 0ustar00runnerdockerSynthDef.new(\vrender, { |amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/waves.scd0000644000175100001770000000202214611211152022160 0ustar00runnerdockerSynthDef(\waves, { |amp=0.5, pan=0, bus=0, freq=220, atk=0.01, rel=0.09, rate=4, gate=1, sus=1, fmod=0, blur=1| var env, osc2, osc; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; env = EnvGen.ar(Env.asr(atk, sus, rel, curve: 'lin'), doneAction: 0); osc = SinOsc.ar(freq * (fmod + 1), 0, freq * (rate + 4) * LFNoise1.kr(10.reciprocal).abs); osc2 = SinOsc.ar((freq * fmod) + osc, 0, 0.5); osc = SinOscFB.ar(osc2, Gendy5.ar(0.1, 0.4, 0.1, mul: 0.1)) + osc2; osc = DelayN.ar(osc2, 0.048, 0.048); osc = Mix.arFill(4, { CombN.ar(osc, 0.1, LFNoise1.ar(Rand(0, 0.1), 0.04, 0.05), 15) }); osc = AllpassN.ar(osc, 0.050, [Rand(0, 0.05), Rand(0,0.05)], 1)!2; osc = FreqShift.ar(osc, (freq / 2) * (-1)); //osc = LPF.ar(osc, 4200); osc = HPF.ar(HPF.ar(osc, 50)); osc = Limiter.ar(osc).tanh; osc = (osc * amp) * env; osc = Mix(osc) * 0.1; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "CrashServer", modified_by: "Jens Meisner", description: "", category: \noise, tags: [\tag] ) ).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/windmaker.scd0000644000175100001770000000126614611211152023025 0ustar00runnerdockerSynthDef.new(\windmaker, { |bus=0, pan=0.0, freq=440, amp=1, fmod=0, gate=1, atk=0.01, sus=1, rel=1, delay=0.3, cutoff=100, rq=0.1| var source, filter, env, osc, delayEnv; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; source = WhiteNoise.ar; filter = BLowPass4.ar(source, freq, rq) * 0.3; env = EnvGen.ar(Env.linen(atk, sus, rel, amp), gate: gate, doneAction: 0); osc = (0.7 * filter + (0.3 * filter.distort)); osc = Mix(osc); osc = osc * env * amp * 0.3; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Mitchell Sigman", modified_by: "Bruno Ruviaro, Jens Meisner", decription: "Description", category: \misc, tags: [\ambient, \wind, \storm] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/wobble.scd0000644000175100001770000000125014611211152022307 0ustar00runnerdockerSynthDef.new(\wobble, { |bus=0, amp=1, sus=1, fmod=0, pan=0.0, atk=0.01, rel=0.09, freq=440, modfreq=4, width=0.4| var osc, osc1, osc2, mod, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; mod = SinOsc.kr(modfreq).range(0, 1); osc1 = LFPulse.ar(freq, width: width, mul: mod); osc2 = LFTri.ar(freq, mul: mod); env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \sin), doneAction: 0); osc = Mix([osc1, osc2]); osc = osc * env * amp * 0.15; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "gacastillo", modified_by: "Jens Meisner", decription: "Simple modified Low Filter Triangle Oscillator", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/wobblebass.scd0000644000175100001770000000157014611211152023165 0ustar00runnerdockerSynthDef.new(\wobblebass, { |bus=0, amp=1, sus=1, fmod=0, pan=0.0, atk=0.01, rel=0.09, freq=440, modfreqlo=1, modfreqhi=6, gate=1, wfmax=8500, reso=0.4, iphase=0.0, offnote1=0.98, offnote2=1.025| var osc, mod, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 2; osc = MoogVCF.ar(in: (Pulse.ar([freq * offnote1, freq], mul:0.5) + PinkNoise.ar(LFNoise0.ar(2).range(0, 1.0)) + Saw.ar([freq, freq * offnote2], mul: 2)).clip2(1), fco: LFCub.kr(freq: LFPulse.kr(0.5, iphase, width: 0.25).range(modfreqlo, modfreqhi)).exprange(40, wfmax), res: reso, mul: 1); env = EnvGen.ar(Env.linen(atk, sus, rel, curve: \sin), doneAction: 0); osc = Mix(osc); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "Luka P.", modified_by: "Jens Meisner", decription: "Description", category: \category, tags: [\tag, \tag] )).add;././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/wsaw.scd0000644000175100001770000000160614611211152022023 0ustar00runnerdockerSynthDef.new(\wsaw, { |bus=0, amp=1, gate=1, pan=0, fmod=0, spread=0.8, freq=0, atk = 0.01, sus = 1, rel = 0.3, iphase1=0.4, iphase2=0.5, iphase3=0.0, offnote1=1, offnote2=0.99, offnote3=1.005| var osc, env, osc1, osc2, osc3; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp = amp / 10; env = Env.linen(atk, sus, rel, curve: \sin).kr(doneAction: 0); osc1 = LFSaw.ar(freq * offnote1 + (0.04 * [1,-1]), iphase: iphase1, mul: 1/8); osc2 = LFSaw.ar(freq * offnote2, iphase: iphase2, mul: 1/8); osc3 = LFSaw.ar(freq * offnote3, iphase: iphase3, mul: 1/8); osc = (osc1 + osc2 + osc3); osc = (osc * 20).tanh; osc = Mix(osc); osc = Splay.ar(osc, spread:spread, center:pan); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Credit", modified_by: "Modifier", decription: "Description", category: \category, tags: [\tag, \tag] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/wsawbass.scd0000644000175100001770000000136514611211152022676 0ustar00runnerdockerSynthDef.new(\wsawbass, { |bus = 0, freq = 0, amp = 1, pan = 0, fmod=0, atk = 0.01, sus = 1, rel = 0.3, slidetime = 0.08, cutoff = 1100, width = 0.15, detune = 1.002, preamp = 4| var osc, env; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; freq = freq / 2; env = Env.linen(atk, sus, rel, curve:\sin).kr(doneAction: 0); freq = Lag.kr(freq, slidetime); osc = VarSaw.ar(freq: [freq, freq * detune], width: width, mul: preamp); osc = Mix(osc, 0.7).distort; osc = LPF.ar(osc, cutoff, amp); osc = osc * env * amp * 0.2; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus,osc) }, metadata: ( credit: "James Harkins", modified_by: "Bruno Ruviaro, Josh Mitchell, Jens Meisner", description: "", category: \bass, tags: [\bass, \synth, \pitched] ) ).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/xylophone.scd0000644000175100001770000000141414611211152023064 0ustar00runnerdockerSynthDef.new(\xylophone, { |bus=0, freq=0, fmod=0, amp=1, gate=1, pan=0, t60=2| var osc, exciter; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; exciter = WhiteNoise.ar() * Env.perc(0.001, 0.07).kr(doneAction: 0) * 0.02; osc = DynKlank.ar( `[ [1,2,2.803,3.871,5.074,7.81,10.948,14.421], // freqs [1,0.044,0.891,0.0891,0.794,0.1,0.281,0.079], // amplitudes [1,0.205,1,0.196,0.339,0.047,0.058,0.047] * t60 // ring times ], exciter, freq); osc = Mix(osc); osc = osc * amp * 0.15; DetectSilence.ar(osc, 0.001, 0.65, doneAction: 0); osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc) }, metadata: ( credit: "Nicola Ariutti", modified_by: "Zé Craum, Jens Meisner", description: "", category: \bells, tags: [\xylophone, \pitched, \glockenspiel] )).add; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/renardo_lib/osc/scsyndef/zap.scd0000644000175100001770000000110214611211152021623 0ustar00runnerdockerSynthDef.new(\zap, {|amp=1, sus=1, pan=0, freq=0, vib=0, fmod=0, rate=0, bus=0, blur=1, beat_dur=1, atk=0.01, decay=0.01, rel=0.01, peak=1, level=0.8, room=0, verb=0| var osc, env; sus = sus * blur; freq = In.kr(bus, 1); freq = [freq, freq+fmod]; amp=(amp / 10); osc=(Saw.ar(((freq * [1, 1.01]) + LFNoise2.ar(50).range(-2, 2))) + VarSaw.ar((freq + LFNoise2.ar(50).range(-2, 2)), 1)); env=EnvGen.ar(Env.perc(attackTime: 0.025,releaseTime: sus,level: amp,curve: -10), doneAction: 0); osc=(osc * env); osc = Mix(osc) * 0.5; osc = Pan2.ar(osc, pan); ReplaceOut.ar(bus, osc)}).add; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.6235404 renardo_lib-0.9.12/renardo_lib.egg-info/0000755000175100001770000000000014611211157017441 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705582.0 renardo_lib-0.9.12/renardo_lib.egg-info/PKG-INFO0000644000175100001770000003057014611211156020542 0ustar00runnerdockerMetadata-Version: 2.1 Name: renardo_lib Version: 0.9.12 Summary: Python livecoding environment - New fork of FoxDot Home-page: http://renardo.org/ Author: Elie Gavoty Author-email: eliegavoty@free.fr License: cc-by-sa-4.0 Description-Content-Type: text/markdown License-File: LICENSE Requires-Dist: renardo_gatherer==0.1.3 Requires-Dist: midiutil Renardo v0.9 - FoxDot fork =========================== Renardo/FoxDot is a Python programming environment that provides a fast and user-friendly abstraction to SuperCollider. It also comes with its own IDE, which means it can be used straight out of the box; all you need is Python and SuperCollider and you're ready to go! ## Important If you are having trouble installing using `pip install FoxDot`, try updating Python's `setuptools` and `wheel` libraries using the following code and trying again. ``` pip install -U setuptools pip install -U wheel ``` ### v0.8 Updates - Added `stretch` synth for timestretching samples, similar to `loop` but better and only plays the whole file. Stretches the audio's duration to the `sus` attribute without affecting pitch and does not require the tempo to be known. ```python # Stretches the audio to 4 beats without affecting pitch p1 >> stretch("Basic_Rock_135", dur=4) ``` --- ## Installation and startup #### Prerequisites - [Python 2 or 3](https://www.python.org/) - add Python to your path and install "pip" when prompted during the install. - [SuperCollider 3.8 and above](http://supercollider.github.io/download) - [Tkinter](https://tkdocs.com/tutorial/install.html) - Usually packaged with Python but Linux and MacOS users may need to install using: ```bash $ sudo apt-get install python3-tk (Linux) $ sudo port install py-tkinter (MacOS) ``` #### Recommended - [sc3 plugins](http://sc3-plugins.sourceforge.net/) #### Installing FoxDot - Open up a command prompt and type `pip install --user FoxDot`. This will download and install the latest stable version of FoxDot from the Python Package Index if you have properly configured Python. - You can update FoxDot to the latest version if it's already installed by adding `-U` or `--upgrade` flag to this command. - Alternatively, you can build from source from directly from this repository: ``` bash $ git clone https://github.com/Qirky/FoxDot.git $ cd FoxDot $ python setup.py install ``` - Open SuperCollder and install the FoxDot Quark and its dependencies (this allows FoxDot to communicate with SuperCollider) by entering the following and pressing `Ctrl+Return` (Note: this requires [Git to be installed](http://git-scm.com/) on your machine if it is not already): ```supercollider Quarks.install("FoxDot") ``` - Recompile the SuperCollider class library by going to `Language -> Recompile Class Library` or pressing `Ctrl+Shift+L` #### Startup 1. Open SuperCollider and type in `FoxDot.start` and evaluate this line. SuperCollider is now listening for messages from FoxDot. 2. Start FoxDot by entering `FoxDot` at the command line. If that doesn't work, try `python -m FoxDot`. 3. If you have installed the SC3 Plugins, use the "Code" drop-down menu to select "Use SC3 Plugins". Restart FoxDot and you'll have access to classes found in the SC3 Plugins. 4. Keep up to date with the latest verion of FoxDot by running `pip install FoxDot --upgrade` every few weeks. 5. Check out the [YouTube tutorials](https://www.youtube.com/channel/UCRyrNX07lFcfRSymZEWwl6w) for some in-depth tutorial videos on getting to grips with FoxDot #### Installing with SuperCollider 3.7 or earlier If you are having trouble installing the FoxDot Quark in SuperCollider, it is usually because the version of SuperCollider you are installing doesn’t have the functionality for installing Quarks or it doesn’t work properly. If this is the case, you can download the contents of the following SuperCollider script: [foxdot.scd](http://foxdot.org/wp-content/uploads/foxdot.scd). Once downloaded, open the file in SuperCollider and press Ctrl+Return to run it. This will make SuperCollider start listening for messages from FoxDot. #### Frequently Asked Questions You can find answers to many frequently asked questions on the [FAQ post on the FoxDot discussion forum](http://foxdot.org/forum/?view=thread&id=1). ## Basics ### Executing Code A 'block' of code in FoxDot is made up of consecutive lines of code with no empty lines. Pressing `Ctrl+Return` (or `Cmd+Return` on a Mac) will execute the block of code that the cursor is currently in. Try `print(1 + 1)` to see what happens! ### Player Objects Python supports many different programming paradigms, including procedural and functional, but FoxDot implements a traditional object orientated approach with a little bit of cheating to make it easier to live code. A player object is what FoxDot uses to make music by assigning it a synth (the 'instrument' it will play) and some instructions, such as note pitches. All one and two character variable names are reserved for player objects at startup so, by default, the variables `a`, `bd`, and `p1` are 'empty' player objects. If you use one of these variables to store something else but want to use it as a player object again, or you want to use a variable with more than two characters, you just have to reserve it by creating a `Player` and assigning it like so: ``` python p1 = Player("p1") # The string name is optional ``` To stop a Player, use the `stop` method e.g. `p1.stop()`. If you want to stop all players, you can use the command `Clock.clear()` or the keyboard short-cut `Ctrl+.`, which executes this command. Assigning synths and instructions to a player object is done using the double-arrow operator `>>`. So if you wanted to assign a synth to `p1` called 'pads' (execute `print(SynthDefs)` to see all available synths) you would use the following code: ``` python p1 >> pads([0,1,2,3]) ``` The empty player object, `p1` is now assigned a the 'pads' synth and some playback instructions. `p1` will play the first four notes of the default scale using a SuperCollider `SynthDef` with the name `\pads`. By default, each note lasts for 1 beat at 120 bpm. These defaults can be changed by specifying keyword arguments: ```python p1 >> pads([0,1,2,3], dur=[1/4,3/4], sus=1, vib=4, scale=Scale.minor) ``` The keyword arguments `dur`, `oct`, and `scale` apply to all player objects - any others, such as `vib` in the above example, refer to keyword arguments in the corresponding `SynthDef`. The first argument, `degree`, does not have to be stated explicitly. Notes can be grouped together so that they are played simultaneously using round brackets, `()`. The sequence `[(0,2,4),1,2,3]` will play the the the first harmonic triad of the default scale followed by the next three notes. ### 'Sample Player' Objects In FoxDot, sound files can be played through using a specific SynthDef called `play`. A player object that uses this SynthDef is referred to as a Sample Player object. Instead of specifying a list of numbers to generate notes, the Sample Player takes a string of characters (known as a "PlayString") as its first argument. To see a list of what samples are associated to what characters, use `print(Samples)`. To create a basic drum beat, you can execute the following line of code: ``` python d1 >> play("x-o-") ``` To have samples play simultaneously, you can create a new 'Sample Player' object for some more complex patterns. ``` python bd >> play("x( x) ") hh >> play("---[--]") sn >> play(" o ") ``` Alternatively, you can do this in one line using `<>` arrows to separate patterns you want to play together like so: ```python d1 >> play("<---[--]>< o >") ``` Or you can use `PZip`, the `zip` method, or the `&` sign to create one pattern that does this. This can be useful if you want to perform some function on individual layers later on: ``` python d1 >> play(P["x( x) "].palindrome().zip("---[--]").zip(P[" o "].amen())) # The first item must be a P[] pattern, not a string. d1 >> play(P["x( x) "].palindrome() & "---[--]" & P[" o "].amen()) ``` Grouping characters in round brackets laces the pattern so that on each play through of the sequence of samples, the next character in the group's sample is played. The sequence `(xo)---` would be played back as if it were entered `x---o---`. Using square brackets will force the enclosed samples to played in the same time span as a single character e.g. `--[--]` will play two hi-hat hits at a half beat then two at a quarter beat. You can play a random sample from a selection by using curly braces in your Play String like so: ``` python d1 >> play("x-o{-[--]o[-o]}") ``` There is now the functionality to specify the sample number for an individual sample when using the `play` SynthDef. This can be done from the play string itself by using the bar character in the form `||`. These can also be patterns created using brackets: ```python # Plays the kick drum with sample 2 but the rest with sample 0 p1 >> play("|x2|-o-") # You can use square brackets to play multiple samples p1 >> play("|x[12]| o ") # Round brackets alternate which sample is used on each loop through the sequence p1 >> play("|x(12)| o ") # Curly braces will pick a sample at random p1 >> play("|x{0123}| o ") ``` ## Scheduling Player methods You can perform actions like shuffle, mirror, and rotate on Player Objects just by calling the appropriate method. ```python bd >> play("x o xo ") # Shuffle the contents of bd bd.shuffle() ``` You can schedule these methods by calling the `every` method, which takes a list of durations (in beats), the name of the method as a string, and any other arguments. The following syntax mirrors the string of sample characters after 6 beats, then again 2 beats later and also shuffles it every 8 beats. ```python bd >> play("x-o-[xx]-o(-[oo])").every([6,2], 'mirror').every(8, 'shuffle') ``` ## Documentation [Link to documentation website](https://foxdot.org/docs/) (still in progress) ## Using alternative editors FoxDot comes pre-packaged with its own basic editor so that you don't have to tinker with config files or download any other tools but if you want to use an existing editor you can. [Koltes](https://github.com/KoltesDigital) has written a plugin for the popular Atom editor. You can install it by going to Settings -> Install -> Searching "foxdot" and pressing install on the plug in. Press Ctrl+Alt+f or go to menu -> Packages -> FoxDot -> Toggle to start FoxDot running. ## Running Python files with FoxDot code You can import `FoxDot` into your own Python programs as you would any other module. If you are not writing an interactive program, i.e. only containing FoxDot code, then you need to call a function `Go()` at the end of your program to get playback otherwise the program will terminate immediately. For example your program, `my_file.py`, should look something like this: ```python from FoxDot import * p1 >> pads([0, 1, 2, 3]) d1 >> play("x-o-") Go() ``` Then just run like any other Python program: `python my_file.py` ## Thanks - The SuperCollider development community and, of course, James McCartney, its original developer - PyOSC, Artem Baguinski et al - Members of the Live Coding community who have contributed to the project in one way or another including, but not limited to, Alex McLean, Sean Cotterill, and Dan Hett. - Big thanks to those who have used, tested, and submitted bugs, which have all helped improve FoxDot - Thank you to those who have found solutions for SuperCollider related issues, such as DavidS48 ### Samples FoxDot's audio files have been obtained from a number of sources but I've lost record of which files are attributed to which original author. Here's a list of thanks for the unknowing creators of FoxDot's sample archive. - [Legowelt Sample Kits](https://awolfe.home.xs4all.nl/samples.html) - [Game Boy Drum Kit](http://bedroomproducersblog.com/2015/04/08/game-boy-drum-kit/) - A number of sounds courtesy of Mike Hodnick's live coded album, [Expedition](https://github.com/kindohm/expedition) - Many samples have been obtained from http://freesound.org and have been placed in the public domain via the Creative Commons 0 License: http://creativecommons.org/publicdomain/zero/1.0/ - thank you to the original creators - Other samples have come from the [Dirt Sample Engine](https://github.com/tidalcycles/Dirt-Samples/tree/c2db9a0dc4ffb911febc613cdb9726cae5175223) which is part of the TidalCycles live coding language created by Yaxu - another huge amount of thanks. If you feel I've used a sample where I shouldn't have, please get in touch! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705582.0 renardo_lib-0.9.12/renardo_lib.egg-info/SOURCES.txt0000644000175100001770000003121714611211156021330 0ustar00runnerdockerLICENSE README.md setup.py renardo_lib/Bang.py renardo_lib/Buffers.py renardo_lib/Chords.py renardo_lib/Constants.py renardo_lib/Key.py renardo_lib/Logging.py renardo_lib/Midi.py renardo_lib/OSC3.py renardo_lib/Players.py renardo_lib/Repeat.py renardo_lib/Root.py renardo_lib/Scale.py renardo_lib/TempoClock.py renardo_lib/TimeVar.py renardo_lib/__init__.py renardo_lib.egg-info/PKG-INFO renardo_lib.egg-info/SOURCES.txt renardo_lib.egg-info/dependency_links.txt renardo_lib.egg-info/requires.txt renardo_lib.egg-info/top_level.txt renardo_lib/Code/__init__.py renardo_lib/Code/foxdot_func_cmp.py renardo_lib/Code/foxdot_live_function.py renardo_lib/Code/foxdot_tokenize.py renardo_lib/Code/foxdot_when_statement.py renardo_lib/Code/main_lib.py renardo_lib/Custom/__init__.py renardo_lib/Custom/startup.py renardo_lib/Effects/NewEffects.py renardo_lib/Effects/Util.py renardo_lib/Effects/__init__.py renardo_lib/EspGrid/EspGridHelper.py renardo_lib/EspGrid/__init__.py renardo_lib/Extensions/PArp.py renardo_lib/Extensions/__init__.py renardo_lib/Extensions/SonicPi/__init__.py renardo_lib/Extensions/SonicPi/generate_sonic_pi.py renardo_lib/Extensions/VRender/Composer.py renardo_lib/Extensions/VRender/MidiFactory.py renardo_lib/Extensions/VRender/Sinsy.py renardo_lib/Extensions/VRender/VRender.py renardo_lib/Extensions/VRender/VoiceSpecificator.py renardo_lib/Extensions/VRender/__init__.py renardo_lib/Patterns/Generators.py renardo_lib/Patterns/Main.py renardo_lib/Patterns/Operations.py renardo_lib/Patterns/PGroups.py renardo_lib/Patterns/Parse.py renardo_lib/Patterns/PlayString.py renardo_lib/Patterns/Sequences.py renardo_lib/Patterns/Utils.py renardo_lib/Patterns/__init__.py renardo_lib/SCLang/Env.py renardo_lib/SCLang/SCLang.py renardo_lib/SCLang/SynthDef.py renardo_lib/SCLang/_SynthDefs.py renardo_lib/SCLang/__init__.py renardo_lib/ServerManager/__init__.py renardo_lib/Settings/__init__.py renardo_lib/Settings/conf.py renardo_lib/Utils/__init__.py renardo_lib/demo/00_intro.py renardo_lib/demo/01_playing_notes.py renardo_lib/demo/02_algorithmic_manipulation.py renardo_lib/demo/03_playing_samples.py renardo_lib/demo/04_using_patterns.py renardo_lib/demo/05_player_attributes.py renardo_lib/demo/06_rests.py renardo_lib/demo/07_basic_clock.py renardo_lib/demo/08_scales.py renardo_lib/demo/09_groups.py renardo_lib/demo/10_using_vars.py renardo_lib/demo/11_playing_custom_samples.py renardo_lib/demo/12_synthdefs.py renardo_lib/demo/13_advanced_clock.py renardo_lib/demo/14_player_attributes_reference.py renardo_lib/demo/15_pattern_generator_reference.py renardo_lib/osc/Buffers.scd renardo_lib/osc/Info.scd renardo_lib/osc/OscFunc.scd renardo_lib/osc/Record.scd renardo_lib/osc/sceffects/DFM1.scd renardo_lib/osc/sceffects/Equalizer.scd renardo_lib/osc/sceffects/FrequencyModulationPulse.scd renardo_lib/osc/sceffects/FrequencyModulationSaw.scd renardo_lib/osc/sceffects/FrequencyModulationSine.scd renardo_lib/osc/sceffects/H_Equalizer.scd renardo_lib/osc/sceffects/L_Equalizer.scd renardo_lib/osc/sceffects/M_Equalizer.scd renardo_lib/osc/sceffects/MoogFF.scd renardo_lib/osc/sceffects/Ringmod.scd renardo_lib/osc/sceffects/SLPF.scd renardo_lib/osc/sceffects/bandPassFilter.scd renardo_lib/osc/sceffects/bitcrush.scd renardo_lib/osc/sceffects/chop.scd renardo_lib/osc/sceffects/chorus.scd renardo_lib/osc/sceffects/coarse.scd renardo_lib/osc/sceffects/combDelay.scd renardo_lib/osc/sceffects/comp.scd renardo_lib/osc/sceffects/dirt_krush.scd renardo_lib/osc/sceffects/disto_mod.scd renardo_lib/osc/sceffects/distortion.scd renardo_lib/osc/sceffects/dubdelay.scd renardo_lib/osc/sceffects/fdist.scd renardo_lib/osc/sceffects/fdistc.scd renardo_lib/osc/sceffects/feeddelay.scd renardo_lib/osc/sceffects/filterSwell.scd renardo_lib/osc/sceffects/flanger.scd renardo_lib/osc/sceffects/formantFilter.scd renardo_lib/osc/sceffects/frequencyModulate.scd renardo_lib/osc/sceffects/fxout.scd renardo_lib/osc/sceffects/glissando.scd renardo_lib/osc/sceffects/highPassFilter.scd renardo_lib/osc/sceffects/krush.scd renardo_lib/osc/sceffects/leg.scd renardo_lib/osc/sceffects/lofi.scd renardo_lib/osc/sceffects/lowPassFilter.scd renardo_lib/osc/sceffects/makeSound.scd renardo_lib/osc/sceffects/octafuz.scd renardo_lib/osc/sceffects/octer.scd renardo_lib/osc/sceffects/output.scd renardo_lib/osc/sceffects/overdriveDistortion.scd renardo_lib/osc/sceffects/phaser.scd renardo_lib/osc/sceffects/pitchBend.scd renardo_lib/osc/sceffects/pitchShift.scd renardo_lib/osc/sceffects/pitchshifter.scd renardo_lib/osc/sceffects/position.scd renardo_lib/osc/sceffects/resonz.scd renardo_lib/osc/sceffects/reverb.scd renardo_lib/osc/sceffects/reverb_stereo.scd renardo_lib/osc/sceffects/ring_modulation.scd renardo_lib/osc/sceffects/sample_atk.scd renardo_lib/osc/sceffects/sidechain.scd renardo_lib/osc/sceffects/slideFrom.scd renardo_lib/osc/sceffects/slideTo.scd renardo_lib/osc/sceffects/spinPan.scd renardo_lib/osc/sceffects/squiz.scd renardo_lib/osc/sceffects/startSound.scd renardo_lib/osc/sceffects/striate.scd renardo_lib/osc/sceffects/stutterfx.scd renardo_lib/osc/sceffects/tanhDisto.scd renardo_lib/osc/sceffects/tek.scd renardo_lib/osc/sceffects/tremolo.scd renardo_lib/osc/sceffects/trimLength.scd renardo_lib/osc/sceffects/trimPos.scd renardo_lib/osc/sceffects/triode.scd renardo_lib/osc/sceffects/vibrato.scd renardo_lib/osc/sceffects/volume.scd renardo_lib/osc/sceffects/wavefold.scd renardo_lib/osc/sceffects/waveloss.scd renardo_lib/osc/sceffects/wavesShapeDistortion.scd renardo_lib/osc/scenvelopes/BasicEnvelope.scd renardo_lib/osc/scenvelopes/MaskEnvelope.scd renardo_lib/osc/scenvelopes/PercussiveEnvelope.scd renardo_lib/osc/scenvelopes/RampEnvelope.scd renardo_lib/osc/scenvelopes/SwellEnvelope.scd renardo_lib/osc/scsyndef/abass.scd renardo_lib/osc/scsyndef/acidbass.scd renardo_lib/osc/scsyndef/alva.scd renardo_lib/osc/scsyndef/ambi.scd renardo_lib/osc/scsyndef/angel.scd renardo_lib/osc/scsyndef/angst.scd renardo_lib/osc/scsyndef/arpy.scd renardo_lib/osc/scsyndef/audioin.scd renardo_lib/osc/scsyndef/bass.scd renardo_lib/osc/scsyndef/bassguitar.scd renardo_lib/osc/scsyndef/bbass.scd renardo_lib/osc/scsyndef/bchaos.scd renardo_lib/osc/scsyndef/bell.scd renardo_lib/osc/scsyndef/bellmod.scd renardo_lib/osc/scsyndef/benoit.scd renardo_lib/osc/scsyndef/birdy.scd renardo_lib/osc/scsyndef/blip.scd renardo_lib/osc/scsyndef/blips.scd renardo_lib/osc/scsyndef/bnoise.scd renardo_lib/osc/scsyndef/borgan.scd renardo_lib/osc/scsyndef/bounce.scd renardo_lib/osc/scsyndef/bphase.scd renardo_lib/osc/scsyndef/brass.scd renardo_lib/osc/scsyndef/brown.scd renardo_lib/osc/scsyndef/bug.scd renardo_lib/osc/scsyndef/charm.scd renardo_lib/osc/scsyndef/chimebell.scd renardo_lib/osc/scsyndef/chipsy.scd renardo_lib/osc/scsyndef/click.scd renardo_lib/osc/scsyndef/clip.scd renardo_lib/osc/scsyndef/cluster.scd renardo_lib/osc/scsyndef/combs.scd renardo_lib/osc/scsyndef/creep.scd renardo_lib/osc/scsyndef/crunch.scd renardo_lib/osc/scsyndef/cs80lead.scd renardo_lib/osc/scsyndef/dab.scd renardo_lib/osc/scsyndef/dafbass.scd renardo_lib/osc/scsyndef/dbass.scd renardo_lib/osc/scsyndef/dblbass.scd renardo_lib/osc/scsyndef/dirt.scd renardo_lib/osc/scsyndef/donk.scd renardo_lib/osc/scsyndef/donk1.scd renardo_lib/osc/scsyndef/donk2.scd renardo_lib/osc/scsyndef/donkysub.scd renardo_lib/osc/scsyndef/donorgan.scd renardo_lib/osc/scsyndef/dopple.scd renardo_lib/osc/scsyndef/drone.scd renardo_lib/osc/scsyndef/dub.scd renardo_lib/osc/scsyndef/dust.scd renardo_lib/osc/scsyndef/dustv.scd renardo_lib/osc/scsyndef/ebass.scd renardo_lib/osc/scsyndef/ecello.scd renardo_lib/osc/scsyndef/eeri.scd renardo_lib/osc/scsyndef/eoboe.scd renardo_lib/osc/scsyndef/epiano.scd renardo_lib/osc/scsyndef/faim.scd renardo_lib/osc/scsyndef/faim2.scd renardo_lib/osc/scsyndef/fbass.scd renardo_lib/osc/scsyndef/feel.scd renardo_lib/osc/scsyndef/filthysaw.scd renardo_lib/osc/scsyndef/flute.scd renardo_lib/osc/scsyndef/fm.scd renardo_lib/osc/scsyndef/fmbass.scd renardo_lib/osc/scsyndef/fmrhodes.scd renardo_lib/osc/scsyndef/four.scd renardo_lib/osc/scsyndef/fuzz.scd renardo_lib/osc/scsyndef/garfield.scd renardo_lib/osc/scsyndef/gaze.scd renardo_lib/osc/scsyndef/glass.scd renardo_lib/osc/scsyndef/glitchbass.scd renardo_lib/osc/scsyndef/glitcher.scd renardo_lib/osc/scsyndef/gong.scd renardo_lib/osc/scsyndef/grat.scd renardo_lib/osc/scsyndef/gray.scd renardo_lib/osc/scsyndef/growl.scd renardo_lib/osc/scsyndef/gsynth.scd renardo_lib/osc/scsyndef/harp.scd renardo_lib/osc/scsyndef/hnoise.scd renardo_lib/osc/scsyndef/hoover.scd renardo_lib/osc/scsyndef/hydra.scd renardo_lib/osc/scsyndef/jbass.scd renardo_lib/osc/scsyndef/kalimba.scd renardo_lib/osc/scsyndef/karp.scd renardo_lib/osc/scsyndef/keys.scd renardo_lib/osc/scsyndef/klank.scd renardo_lib/osc/scsyndef/ladder.scd renardo_lib/osc/scsyndef/lapin.scd renardo_lib/osc/scsyndef/laserbeam.scd renardo_lib/osc/scsyndef/latoo.scd renardo_lib/osc/scsyndef/lazer.scd renardo_lib/osc/scsyndef/lfnoise.scd renardo_lib/osc/scsyndef/linesaw.scd renardo_lib/osc/scsyndef/longsaw.scd renardo_lib/osc/scsyndef/loop.scd renardo_lib/osc/scsyndef/marimba.scd renardo_lib/osc/scsyndef/mhpad.scd renardo_lib/osc/scsyndef/mhping.scd renardo_lib/osc/scsyndef/moogbass.scd renardo_lib/osc/scsyndef/moogpluck.scd renardo_lib/osc/scsyndef/moogpluck2.scd renardo_lib/osc/scsyndef/mpluck.scd renardo_lib/osc/scsyndef/mySynth.scd renardo_lib/osc/scsyndef/noise.scd renardo_lib/osc/scsyndef/noisynth.scd renardo_lib/osc/scsyndef/noquarter.scd renardo_lib/osc/scsyndef/nylon.scd renardo_lib/osc/scsyndef/organ.scd renardo_lib/osc/scsyndef/organ2.scd renardo_lib/osc/scsyndef/orient.scd renardo_lib/osc/scsyndef/pads.scd renardo_lib/osc/scsyndef/pasha.scd renardo_lib/osc/scsyndef/pbass.scd renardo_lib/osc/scsyndef/phazer.scd renardo_lib/osc/scsyndef/piano.scd renardo_lib/osc/scsyndef/pianovel.scd renardo_lib/osc/scsyndef/pink.scd renardo_lib/osc/scsyndef/play1.scd renardo_lib/osc/scsyndef/play2.scd renardo_lib/osc/scsyndef/pluck.scd renardo_lib/osc/scsyndef/pmcrotal.scd renardo_lib/osc/scsyndef/ppad.scd renardo_lib/osc/scsyndef/prayerbell.scd renardo_lib/osc/scsyndef/prof.scd renardo_lib/osc/scsyndef/prophet.scd renardo_lib/osc/scsyndef/pulse.scd renardo_lib/osc/scsyndef/quin.scd renardo_lib/osc/scsyndef/radio.scd renardo_lib/osc/scsyndef/rave.scd renardo_lib/osc/scsyndef/razz.scd renardo_lib/osc/scsyndef/rhodes.scd renardo_lib/osc/scsyndef/rhpiano.scd renardo_lib/osc/scsyndef/ripple.scd renardo_lib/osc/scsyndef/risseto.scd renardo_lib/osc/scsyndef/rissetobell.scd renardo_lib/osc/scsyndef/rlead.scd renardo_lib/osc/scsyndef/rsaw.scd renardo_lib/osc/scsyndef/rsin.scd renardo_lib/osc/scsyndef/saw.scd renardo_lib/osc/scsyndef/sawbass.scd renardo_lib/osc/scsyndef/scatter.scd renardo_lib/osc/scsyndef/scrap.scd renardo_lib/osc/scsyndef/scratch.scd renardo_lib/osc/scsyndef/shore.scd renardo_lib/osc/scsyndef/sillyvoice.scd renardo_lib/osc/scsyndef/sine.scd renardo_lib/osc/scsyndef/sinepad.scd renardo_lib/osc/scsyndef/siren.scd renardo_lib/osc/scsyndef/sitar.scd renardo_lib/osc/scsyndef/snick.scd renardo_lib/osc/scsyndef/soft.scd renardo_lib/osc/scsyndef/soprano.scd renardo_lib/osc/scsyndef/sos.scd renardo_lib/osc/scsyndef/sosbell.scd renardo_lib/osc/scsyndef/space.scd renardo_lib/osc/scsyndef/spacesaw.scd renardo_lib/osc/scsyndef/spark.scd renardo_lib/osc/scsyndef/spick.scd renardo_lib/osc/scsyndef/sputter.scd renardo_lib/osc/scsyndef/square.scd renardo_lib/osc/scsyndef/squish.scd renardo_lib/osc/scsyndef/ssaw.scd renardo_lib/osc/scsyndef/star.scd renardo_lib/osc/scsyndef/stargazer.scd renardo_lib/osc/scsyndef/steeldrum.scd renardo_lib/osc/scsyndef/stretch.scd renardo_lib/osc/scsyndef/strings.scd renardo_lib/osc/scsyndef/subbass.scd renardo_lib/osc/scsyndef/subbass2.scd renardo_lib/osc/scsyndef/supersaw.scd renardo_lib/osc/scsyndef/swell.scd renardo_lib/osc/scsyndef/tb303.scd renardo_lib/osc/scsyndef/total.scd renardo_lib/osc/scsyndef/tremsynth.scd renardo_lib/osc/scsyndef/tribell.scd renardo_lib/osc/scsyndef/tritri.scd renardo_lib/osc/scsyndef/triwave.scd renardo_lib/osc/scsyndef/tubularbell.scd renardo_lib/osc/scsyndef/twang.scd renardo_lib/osc/scsyndef/tworgan.scd renardo_lib/osc/scsyndef/tworgan2.scd renardo_lib/osc/scsyndef/tworgan3.scd renardo_lib/osc/scsyndef/tworgan4.scd renardo_lib/osc/scsyndef/varcell.scd renardo_lib/osc/scsyndef/varicelle.scd renardo_lib/osc/scsyndef/varsaw.scd renardo_lib/osc/scsyndef/vibass.scd renardo_lib/osc/scsyndef/video.scd renardo_lib/osc/scsyndef/vinsine.scd renardo_lib/osc/scsyndef/viola.scd renardo_lib/osc/scsyndef/virus.scd renardo_lib/osc/scsyndef/vrender.scd renardo_lib/osc/scsyndef/waves.scd renardo_lib/osc/scsyndef/windmaker.scd renardo_lib/osc/scsyndef/wobble.scd renardo_lib/osc/scsyndef/wobblebass.scd renardo_lib/osc/scsyndef/wsaw.scd renardo_lib/osc/scsyndef/wsawbass.scd renardo_lib/osc/scsyndef/xylophone.scd renardo_lib/osc/scsyndef/zap.scd tests/test_buffers.py tests/test_generator_pattern.py tests/test_patterns.py././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705582.0 renardo_lib-0.9.12/renardo_lib.egg-info/dependency_links.txt0000644000175100001770000000000114611211156023506 0ustar00runnerdocker ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705582.0 renardo_lib-0.9.12/renardo_lib.egg-info/requires.txt0000644000175100001770000000004114611211156022033 0ustar00runnerdockerrenardo_gatherer==0.1.3 midiutil ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705582.0 renardo_lib-0.9.12/renardo_lib.egg-info/top_level.txt0000644000175100001770000000001414611211156022165 0ustar00runnerdockerrenardo_lib ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.6235404 renardo_lib-0.9.12/setup.cfg0000644000175100001770000000004614611211157015310 0ustar00runnerdocker[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/setup.py0000644000175100001770000000223114611211152015172 0ustar00runnerdocker#!/usr/bin/env python from setuptools import setup with open("README.md", "r") as f: long_description=f.read() setup( name='renardo_lib', version="0.9.12", description='Python livecoding environment - New fork of FoxDot', author='Elie Gavoty', author_email='eliegavoty@free.fr', license='cc-by-sa-4.0', url='http://renardo.org/', packages=[ 'renardo_lib', 'renardo_lib.Code', 'renardo_lib.Custom', 'renardo_lib.Extensions', 'renardo_lib.Extensions.VRender', 'renardo_lib.Extensions.SonicPi', 'renardo_lib.EspGrid', 'renardo_lib.Effects', 'renardo_lib.Patterns', 'renardo_lib.SCLang', 'renardo_lib.Settings', 'renardo_lib.Utils', 'renardo_lib.ServerManager', ], long_description=long_description, long_description_content_type="text/markdown", # entry_points={'gui_scripts' : ['FoxDotEditor = FoxDotEditor.__init__:main']}, # data_files=[('', 'LICENSE')], package_data = {'renardo_lib': ['README.md','demo/**', 'osc/**'],}, install_requires=[ 'renardo_gatherer==0.1.3', 'midiutil', ], ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1713705582.6235404 renardo_lib-0.9.12/tests/0000755000175100001770000000000014611211157014631 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/tests/test_buffers.py0000644000175100001770000000713014611211152017672 0ustar00runnerdocker""" Tests for BufferManager """ import os import shutil import tempfile import unittest from os.path import join from renardo_lib.Buffers import BufferManager class TestSampleSearch(unittest.TestCase): """ Test search functionality for sample files """ def setUp(self): super(TestSampleSearch, self).setUp() def mkdir(dirname): os.mkdir(join(self.wd, dirname)) def touch(filename): fullpath = join(self.wd, filename) open(fullpath, 'w').close() return fullpath self.wd = tempfile.mkdtemp() self.bm = BufferManager() self.bm._paths = [self.wd] self._yeah = touch('yeah.wav') mkdir('snares') self._snare1 = touch('snares/snare1.wav') self._snare2 = touch('snares/snare2.wav') mkdir('kicks') self._808 = touch('kicks/808.wav') self._kick = touch('kicks/kick.wav') mkdir('kicks/house') self._housekick = touch('kicks/house/house_bass.wav') def tearDown(self): super(TestSampleSearch, self).tearDown() shutil.rmtree(self.wd) def test_abspath(self): """ Sample file as absolute path """ sample = join(self.wd, 'yeah.wav') found = self.bm._findSample(sample) self.assertEqual(found, sample) def test_abspath_no_ext(self): """ Sample file as absolute path with no extension """ sample = join(self.wd, 'yeah') found = self.bm._findSample(sample) self.assertEqual(found, self._yeah) def test_relpath(self): """ Sample file as relative path """ sample = 'yeah.wav' found = self.bm._findSample(sample) self.assertEqual(found, self._yeah) def test_relpath_no_ext(self): """ Sample file as relative path with no extension """ sample = 'yeah' found = self.bm._findSample(sample) self.assertEqual(found, self._yeah) def test_dir_first(self): """ Sample directory load first sample """ sample = 'snares' found = self.bm._findSample(sample) self.assertEqual(found, self._snare1) def test_dir_nth(self): """ Sample directory load nth sample """ sample = 'snares' found = self.bm._findSample(sample, 1) self.assertEqual(found, self._snare2) def test_dir_nth_overflow(self): """ Sample directory load nth sample (exceeds count) """ sample = 'snares' found = self.bm._findSample(sample, 2) self.assertEqual(found, self._snare1) def test_nested_filename(self): """ Sample filename loaded from nested dir """ sample = 'snare1.wav' found = self.bm._findSample(sample) self.assertEqual(found, self._snare1) def test_nested_filename_no_ext(self): """ Sample filename with no extension loaded from nested dir """ sample = 'snare1' found = self.bm._findSample(sample) self.assertEqual(found, self._snare1) def test_pathpattern(self): """ Sample specified as pattern with path elements """ sample = 'k?c*/*' found = self.bm._findSample(sample) self.assertEqual(found, self._808) def test_pathpattern_doublestar(self): """ Sample specified as pattern containing /**/ """ sample = '**/snare*' found = self.bm._findSample(sample) self.assertEqual(found, self._snare1) def test_doublestar_deep_path(self): """ Sample specified as pattern containing /**/path """ sample = '**/house/*' found = self.bm._findSample(sample) self.assertEqual(found, self._housekick) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/tests/test_generator_pattern.py0000644000175100001770000000104314611211152021756 0ustar00runnerdockerimport unittest from renardo_lib.Patterns import GeneratorPattern from renardo_lib.Patterns import P class TestPatternMethods(unittest.TestCase): def test_from_func(self): def some_generation_func(index): if index == 3: return 2 else: return 1 pattern = GeneratorPattern.from_func(some_generation_func) self.assertTrue(isinstance(pattern, GeneratorPattern)) self.assertEqual(pattern[:4], P[1, 1, 1, 2]) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1713705578.0 renardo_lib-0.9.12/tests/test_patterns.py0000644000175100001770000000023114611211152020071 0ustar00runnerdockerimport unittest from renardo_lib import Patterns class TestPatternMethods(unittest.TestCase): pass if __name__ == "__main__": unittest.main()