Repository: tmhglnd/mercury Branch: master Commit: b61aabcfba9c Files: 239 Total size: 7.2 MB Directory structure: gitextract_ao7h6v4s/ ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── docs/ │ └── deprecated-docs/ │ ├── 00-general.md │ ├── 01-global.md │ ├── 02-instrument.md │ ├── 03-emitter.md │ ├── 04-fx.md │ ├── 05-ring.md │ ├── 06-shortkeys.md │ ├── 07-environment.md │ ├── 08-troubleshooting.md │ ├── 09-visuals.md │ ├── 10-includes.md │ ├── README.md │ ├── _config.yml │ ├── collaborate.md │ ├── linux-guide.md │ ├── quick-start.md │ ├── reference.md │ ├── table-of-content.md │ └── tutorial.md ├── examples/ │ ├── 00_sample-and-time.txt │ ├── 01_offset-in-time.txt │ ├── 02_linear-beat.txt │ ├── 03_sample-scrubbing.txt │ ├── 04_possibility-rhythm.txt │ ├── 05_synth-and-note.txt │ ├── 06_generative-melody.txt │ └── 07_granular-playback.txt ├── examples-basic/ │ ├── 01-sample.txt │ ├── 02-tempo.txt │ ├── 03-time.txt │ ├── 04-offset.txt │ ├── 05-rhythm-ring.txt │ ├── 06-probability.txt │ ├── 07-synth.txt │ ├── 08-two-notes.txt │ ├── 09-melody-ring.txt │ ├── 10-scale.txt │ ├── 11-shape.txt │ └── 12-fx.txt ├── grammar/ │ ├── .gitignore │ ├── README.md │ ├── data/ │ │ ├── bind-functions.json │ │ ├── bind-instruments.json │ │ ├── function-parse.js │ │ ├── instrument-methods.json │ │ ├── mini-functions.json │ │ └── objects.js │ ├── grammar.js │ ├── mercury.ne │ ├── mercuryIR.js │ ├── package.json │ ├── parser.js │ ├── src/ │ │ └── dict.js │ ├── test/ │ │ ├── grammar-example.txt │ │ ├── mercuryAST.json │ │ ├── mercuryIR.json │ │ ├── ring-test.txt │ │ └── synth-test.txt │ └── totalSerialismIR.js └── mercury_ide/ ├── .vscode/ │ └── settings.json ├── _deprecated/ │ ├── argBindings.txt │ ├── arr2dTo1d.maxpat │ ├── beatSyncSystem.maxpat │ ├── bind-functions.txt │ ├── codeParser.js │ ├── dspLib.genexpr │ ├── ease.mxe64 │ ├── ease.mxo/ │ │ └── Contents/ │ │ ├── Info.plist │ │ ├── MacOS/ │ │ │ └── ease │ │ └── PkgInfo │ ├── editor.maxpat │ ├── fb-delay.gendsp │ ├── ladder~.maxpat │ ├── listLib.js │ ├── moogLadderFilter.genexpr │ ├── noise.genjit │ ├── phasorRate.gendsp │ ├── recursiveFolder.js │ ├── samples.json │ ├── soundObjectShapeJitter.maxpat │ ├── textScale.maxpat │ ├── textToMtx.js │ └── tokens.txt ├── code/ │ ├── dictionary.js │ ├── editor.js │ ├── editorGL.js │ ├── lexer.js │ ├── mercury.js │ ├── package.json │ ├── parser.js │ └── preferences.js ├── data/ │ ├── bind-functions.gen.json │ ├── bind-functions.json │ ├── binding-instruments.json │ ├── initials.json │ ├── mini-functions.json │ ├── scales.txt │ └── tonics.txt ├── dev/ │ ├── fx-dev.txt │ ├── grammar-dev.txt │ ├── kick-dev.txt │ ├── midi-dev.txt │ ├── new-list-functions.txt │ ├── osc-dev-code.txt │ ├── osc-digilog.txt │ ├── osc-receive.maxpat │ ├── osc-receive.txt │ ├── osc-receiver.maxpat │ ├── ring-dev-scale-map.txt │ ├── ring-dev.txt │ ├── sample-dev.txt │ ├── sample-test.txt │ ├── solo-instruments.maxpat │ ├── string-dev.txt │ ├── synth-dev.txt │ ├── synth-test.txt │ ├── util-dev.txt │ └── visual-dev.txt ├── external/ │ ├── aka.speech.mxo/ │ │ └── Contents/ │ │ ├── Info.plist │ │ ├── MacOS/ │ │ │ └── aka.speech │ │ ├── PkgInfo │ │ ├── Resources/ │ │ │ └── maxmspsdk.xcconfig │ │ └── _CodeSignature/ │ │ └── CodeResources │ ├── clockwarp.gendsp │ ├── cv.jit.resize.mxe64 │ ├── cv.jit.resize.mxo/ │ │ └── Contents/ │ │ ├── Info.plist │ │ ├── MacOS/ │ │ │ └── cv.jit.resize │ │ └── PkgInfo │ ├── dyn-range-comp.genexpr │ ├── hidecursor.maxpat │ ├── jit.gl.spoutreceiver.mxe64 │ ├── jit.gl.spoutsender.mxe64 │ ├── moogLadderFilter.genexpr │ ├── shortkeys.json │ ├── th.clockwarp~.maxpat │ ├── th.comp~.maxpat │ ├── th.gl.editor.js │ ├── th.gl.texteditor.maxpat │ └── th.yafr~.maxpat ├── fonts/ │ ├── IBM_Plex_Mono/ │ │ └── OFL.txt │ ├── Roboto_Mono/ │ │ └── LICENSE.txt │ ├── Source_Code_Pro/ │ │ └── OFL.txt │ ├── Space_Mono/ │ │ └── OFL.txt │ ├── Ubuntu_Mono/ │ │ └── UFL.txt │ └── VT323/ │ └── OFL.txt ├── icon/ │ ├── README.md │ ├── icon.icns │ └── mercury_icon.psd ├── media/ │ ├── README.md │ └── images/ │ └── planet_colors.jit ├── mercury_ide.maxproj └── patchers/ ├── _mercury_main.maxpat ├── _mercury_visuals.maxpat ├── analyseDisplay.maxpat ├── argGetList.maxpat ├── argListLookup.maxpat ├── calcExpr.maxpat ├── consoleLog.maxpat ├── divToMs.maxpat ├── drywet~.maxpat ├── emptyScene.maxpat ├── envelopeGen.maxpat ├── eventSequencer.maxpat ├── fftCatch~.maxpat ├── fftCross~.maxpat ├── fftFreeze~.maxpat ├── fxChorus.maxpat ├── fxComb.maxpat ├── fxCompress.maxpat ├── fxDegrade.maxpat ├── fxDelay.maxpat ├── fxDrive.maxpat ├── fxEnvelopeFilter.maxpat ├── fxFilter.maxpat ├── fxFreeze.maxpat ├── fxFuzz.maxpat ├── fxKink.maxpat ├── fxLFO.maxpat ├── fxLadderFilter.maxpat ├── fxLoopDelay.maxpat ├── fxMorph.maxpat ├── fxPitchShift.maxpat ├── fxRetune.maxpat ├── fxReverb.maxpat ├── fxRing.maxpat ├── fxSquash.maxpat ├── fxStutter.maxpat ├── fxTriggerFilter.maxpat ├── fxVibrato.maxpat ├── fxVocoder.maxpat ├── fxVocoderBand.maxpat ├── fxVowel.maxpat ├── getVariables.maxpat ├── gtep.maxpat ├── keyPressed.maxpat ├── mcy.buffers~.maxpat ├── midiToOSC.maxpat ├── modulatorObject~.maxpat ├── newInstance.maxpat ├── noteToMidi.maxpat ├── planetaryMotion.maxpat ├── probList.maxpat ├── probTrig.maxpat ├── setupAudio.maxpat ├── setupEditor.maxpat ├── setupShortkeys.maxpat ├── setupVisuals.maxpat ├── soundObject.maxpat ├── srcExtension.maxpat ├── srcFmSynth.maxpat ├── srcInput.maxpat ├── srcKarplus.maxpat ├── srcKick.maxpat ├── srcNoise.maxpat ├── srcPolySample.maxpat ├── srcSample.maxpat ├── srcSampleRack.maxpat ├── srcSynth.maxpat ├── srcWavetable.maxpat ├── srcWrapper.maxpat ├── strange-attractor.maxpat ├── syncToScale.maxpat ├── synthPoly.maxpat ├── visual/ │ ├── circling.maxpat │ ├── cubes.maxpat │ ├── mesh.maxpat │ ├── meshes.maxpat │ ├── meshwave.maxpat │ ├── pillars.maxpat │ ├── plane.maxpat │ ├── shape.maxpat │ ├── syphon.maxpat │ └── template.maxpat ├── visualObject.maxpat └── wavetablePlayer.maxpat ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # ignore DS_Store .DS_Store # ignore the mercury.ini file, this is autogenerated mercury_ide/mercury.ini ================================================ FILE: .gitmodules ================================================ [submodule "mercury-docs"] path = docs/mercury-docs url = https://github.com/tmhglnd/mercury-docs [submodule "docs/mercury-docs"] path = docs/mercury-docs url = https://github.com/tmhglnd/mercury-docs ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.md ================================================ # 🌕 Mercury Live Coding Environment **Welcome to Mercury! ✌️ ☮️ Make Music, Not War!** ☮️ ✌️ **Mercury is a free/open-source, beginner-friendly, minimal and human-readable language for the live coding of algorithmic electronic music performances** Mercury currently has 2 versions: * Original version running in Max8 (Windows/Mac only) (you're in the right place) * Web version running in the browser (Windows/Mac/Linux) [go to this repo](https://github.com/tmhglnd/mercury-playground) **🚀 Start coding with the latest version:** `git clone https://github.com/tmhglnd/mercury.git` [**👾 Start coding directly in the playground!** (recommended for beginners)](https://mercury.timohoogland.com/) [**🙏 Support Mercury by buying me a coffee ko-fi**](https://ko-fi.com/tmhglnd) [**💬 Join the Discord Community!**](https://discord.gg/vt59NYU) ![Livecoding Performance with Mercury (photo: Zuzanna Zgierska)](media/mercury-live.png) ## 📋 Table of Contents - 📟 [Mercury?](#-about) - 🎮 [What can I do with Mercury?](#-features-overview) - 👩‍💻 [Code together with others!](#-collaborative-coding) - 🚀 [Let's get started!](#-install) - [Quick Start](#-install) - [Tutorial](https://tmhglnd.github.io/mercury/docs/usage/coding) - [External Editor](#️-external-editor) - [Documentation](https://tmhglnd.github.io/mercury/docs/) - [Troubleshooting](#-troubleshooting) - [Sounds in Mercury](#-sounds) - 🔎 [Read more](#-further-reading) - 👾 [Hear what others made](#-made-with-mercury) - 🤓 [I like to help](#-contribute) - 🔋 [Powered By](#-powered-by) - 🙏 [Thanks](#-thanks) - ✨ [Inspiration](#-inspiration) - 📄 [Licenses](#-licenses) ## 📟 About **Mercury is a free/open-source, beginner-friendly, minimal and human-readable language for the live coding of algorithmic electronic music** All elements of the language are designed around making code more accessible and less obfuscating for the audience. This motivation stretches down to the coding style itself which uses clear descriptive names for functions and a clear syntax. Furthermore the editor is restricted to 30 lines of code, keeping all code always visible. Mercury provides the performer with an extensive library of algorithms to generate or transform numbersequences that can modulate parameters, such as melody and rhythm, over time. The environment produces sound in conjunction with visuals. Besides looking at the code, the audience is also looking at the visuals that are reactive to the sound or generated by the sound. It is named after te planet Mercury. Mercury rules the creation and expression of our mental processes. The planet implores us to express ourselves. Mercury is about a quick wit, quick thinking. It lets us move from one thing to the next. ![Screenshot of the Mercury environment](media/mercury-screenshot2.png) ## 🎮 Features Overview Quick access to playback of samples and change timing and tempo of samples or synthesizers ```java set tempo 89 new sample kick_909 time(1/4) new sample hat_909 time(3/16) ``` Make rhythmic patterns with sequences of numbers and probabilities ```java list loBeat [1 0 0 1 0.5] list hiBeat [0 1 0.2 0] new sample tabla_lo time(1/8) play(loBeat) new sample tabla_hi time(1/8) play(hiBeat) ``` Generate psuedorandom melodic content for a synthesizer in a range and set a scale ```java set scale minor d set randomSeed 31415 list melody random(16 0 24) new synth saw note(melody) time(1/16) shape(4 100) ``` Design sounds with various effects ```java new sample chimes time(2) speed(-0.25) fx(reverb 0.3 15) fx(drive 10) fx(lfo 1/8 sine) ``` Easily give multiple instruments the same effects ```java new sample chimes time(2) new sample harp_down time(3) new sample gong_lo time(5) set all fx(lfo 1/16) fx(delay) fx(reverb 0.5 11) ``` Generate sequences algorithmically to compose complex structures and choose from an extensive library of algorithms to work with ```java set scale minor a list rhythm euclidean(32 13) list melody spread(5 0 24) list melody palinedrome(melody) list melody clone(melody 0 5 7 3) list melody lace(melody melody) new synth triangle note(melody 1) shape(1 80) play(rhythm) ``` Control external midi devices or send midi to other applications and use clock sync ```java set midi getPorts //=> prints the available devices to the console new midi "Your Awesome Midi Device" time(1/4) note(7 1) length(100) sync(on) ``` Control other environments via OSC-messages ```java list params [0.25 0.5 0.75] new emitter osc address(yourDevice) theParam(params) time(1/4) // emits => /yourDevice/theParam 0.25 // /yourDevice/theParam 0.5 // /yourDevice/theParam 0.75 // /yourDevice/theParam 0.25 // etc... ``` Easily control parameters in Mercury via external OSC-messages ```java new synth triangle fx(reverb '/extOSC/verbAmount') fx(filter low '/extOSC/cutoff' 0.4) time(1) shape(1 1000) ``` **AND MANY MORE (TO COME...)** ⭐️ *watch and star this repo to keep up-to-date with the latest changes whenever they're made* ## 👩‍💻👨‍💻 Collaborative Coding You can code together in Mercury by using the amazing [**Flok**](https://flok.cc/) live coding environment for the browser developed by Damián Silvani (a.k.a. Munshkr). Flok is a web-based P2P collaborative editor for live coding music and graphics. Similar to Etherpad, but focused on code evaluation for livecoding. - [Start coding together here](https://tmhglnd.github.io/mercury/docs/collaborate) ## 💻 Install - 📖 [I need some help installing](https://tmhglnd.github.io/mercury/docs/getting-started#-mercury4max) - 🚀 [I'm an experienced computer user](https://tmhglnd.github.io/mercury/docs/getting-started#-mercury4max) - 💻 [Is my computer powerful enough?](https://tmhglnd.github.io/mercury/docs/getting-started#-system-requirements) OR - 🤓 I'll just download and figure it out myself ``` $ cd ~/Documents/Max\ 8/Projects $ git clone http://github.com/tmhglnd/mercury $ cd mercury $ open mercury_ide/mercury_ide.maxproj ``` ### ⚠ Troubleshooting It could be that you are having issues with Mercury. Please follow the steps below: - [Open the Troubleshooting](https://tmhglnd.github.io/mercury/docs/usage/troubleshooting) ### ⌨️ External Editor Instead of using the editor built in the Max Mercury version you can also load an external textfile or use a plugin for Pulsar (previously Atom). - [Follow the instructions here for the Pulsar Plugin](https://tmhglnd.github.io/mercury/docs/usage/editors) - [Follow the instructions here for other editors](https://tmhglnd.github.io/mercury/docs/usage/editors) ### 📖 Documentation Full documentation of everything you can do in Mercury: - [Open the documentation](https://tmhglnd.github.io/mercury/docs) ### 🎵 Sounds Most of the sounds in Mercury are from [freesound.org](http://www.freesound.org) and are licensed with Creative Commons Attribution or Creative Commons 0 licenses. If not downloaded from freesound it is made sure that the license allows you to redistribute the sounds via the Mercury environment and that you can use them in your projects. All the sounds are listed below with their original source, license and credits. - [List of sounds and credits](https://tmhglnd.github.io/mercury/docs/usage/sounds) ## 🔍 Further reading [A list of other reading material and inspiration](https://tmhglnd.github.io/mercury/docs/about/inspiration#-further-reading) ## 👾 Made with Mercury *Made something with Mercury? Please add a URL here and send a pull request!* 😎 [**See the full list here**](https://tmhglnd.github.io/mercury/docs/about/inspiration) ### Small selection - [iTypeMusic - Electronic Music Stream with Live Coding](https://www.youtube.com/watch?v=x77RP20uWxA&ab_channel=itypemusic) - [LXT @levoxtrip (at Solstice Stream December 2023)](https://www.youtube.com/watch?v=TzM-koWkRow&ab_channel=Eulerroom) - [Linalab(Mercury) + Turbulente(p5Live) - Live at Algorave Lisbon](https://youtu.be/WSPNDC0a2X4) - [T.mo - Liber Abaci (Mercury Coding Sessions)](https://youtu.be/syUL76qCV6w) - [Roald van Dillewijn - Smashing Temparateness (Mercury Coding Sessions)](https://youtu.be/KJ4OpJ3-Ik0) - [Guillem Góngora Moral - Transcription #1 (Mercury Coding Sessions)](https://youtu.be/wRVQHlghitM) - [Anne Veinberg - CodeKlavier meets Mercury (Mercury Coding Sessions)](https://youtu.be/e4sPKOlaYS8) - [Nick Levantis - Wake Up](https://youtu.be/UsfKF0ggn7k) ## 📝 Contribute Contributions to the Mercury environment are much appreciated in whatever form they come! You can contribute in any many ways! [Please follow the steps here](https://tmhglnd.github.io/mercury/docs/contribute) ## 🔋 Powered By - Mercury has been granted funding from [**Creative Industries Fund NL**](https://stimuleringsfonds.nl/en/) - Mercury has been granted in-kind funding from [**Creative Coding Utrecht**](https://creativecodingutrecht.nl/) ## 🙏 Thanks - [Lina Bautista](https://axolot.cat/about/lina-bautista/) for working together on developing functionalities in Mercury to control modular synths via cv - [SEMA/MIMIC project](https://mimicproject.com/about) team (Thor Magnusson, Chris Kiefer and Francisco Bernardo) for their awesome full week workshop at Sussex University in Brighton on designing a live coding language in the browser combined with machine learning - [Roald van Dillewijn](https://roaldvandillewijn.nl/) for working together on osc and midi functionalities combined with his [Digilog modified guitar-pedals](https://roaldvandillewijn.nl/projects/digilog) - [Guillem Gongora Moral](https://www.guillemgongora.com/) for using Mercury as a composition tool and sharing valuable feedback in the process - [Anne Veinberg](https://anneveinberg.com/) for working with Mercury and a Mercury extensions for the [CodeKlavier](https://codeklavier.space/) project - [Rafaele Maria Andrade](https://www.rafaele-andrade.com/) for collaboration on [networked performance](https://www.youtube.com/watch?v=7UWywv_DPHI&t=4s) between Mercury and Knurl - Live performance image by Zuzanna Zgierska ## ✨ Inspiration During the development of Mercury (both the playground and the full version) I've found inspiration in many other live coding environments, practices and platforms. Some of these are: - [Hydra](https://hydra.ojack.xyz/) - Live coding visual synthesizer by Olivia Jack - [Sema](https://sema.codes/about) - Live coding language design platform combined with Machine Learning - [MIMIC Project](https://mimicproject.com/about) - a web platform for the artistic exploration of musical machine learning and machine listening. - [Tidal](https://tidalcycles.org/index.php/Welcome) - Live coding of patterns - [Sonic Pi](https://sonic-pi.net/) - The live coding synth for everyone - [Tone.js](https://tonejs.github.io/) - Webaudio framework for programming synths and sequencers - [Nearley](https://nearley.js.org/) - Parsing toolkit ## 📄 Licenses - Main Source - [The GNU GPL v.3 License](https://choosealicense.com/licenses/gpl-3.0/) (c) Timo Hoogland 2019-2024 - Sound Files - Individually licensed, listed under [Sounds in Mercury](https://tmhglnd.github.io/mercury/docs/usage/sounds#sample-credits) - Documentation - [The CC BY-SA 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/) (c) Timo Hoogland 2019-2024 - Examples - [The CC BY-SA 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/) (c) Timo Hoogland 2019-2024 - Max8 - Proprietary Software, Max (c) 1990-2024 Cycling'74 / IRCAM All rights reserved THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: docs/deprecated-docs/00-general.md ================================================ # General Syntax ## new Create a new instance of an instrument or external output. This can be a `sample`, a `synth`, a `loop`, a `polySynth`, `midi`, `modulator` or an `emitter` for osc followed by the name of the sample, the name of the waveshape to use for the synth, the emitter type (currently only supports `osc`) or the midi device name. After that use functions to set parameters for the object. **arguments** - {Instrument} -> the instrument type (sample, synth, loop, polySynth, midi, modulator) - {Type} -> selected sample or synth waveform (based on loaded files) - {Functions+} -> instrument methods seperated by spaces (optional) ```java new synth saw new sample kick_909 new emitter osc new midi "AU DLS Synth 1" ``` Alias: `make`, `sound` By default Mercury has a small library of samples and single-cycle waveforms included in the environment. Follow these links to find out how to include samples and waveforms in Mercury or if you like to see the full list of available sounds. - [How to load other sounds into Mercury](./07-environment.md#sounds) - [How to load sounds in the Mercury Playground](./01-global.md#samples) - [Full list of all the included sounds](https://github.com/tmhglnd/mercury/blob/master/mercury_ide/media/README.md) - [How to load other waveforms into Mercury](./07-environment.md#sounds) - [Full list of all the included waveforms](https://github.com/tmhglnd/mercury/blob/master/mercury_ide/media/README.md) ## list Create a circular array, which is called a `ring` or `list`. (in older versions this was designed to be `ring` because it refers to a "circular array", but for ease of use with beginners `list` makes more sense). This ring can hold integers, floats, symbols and other rings (2-dimensional). Use these to change parameters over time for instruments. The `ring` must be declared with a name before it can be used as a variable in an instrument function. **arguments** - {Name} -> ring name - {Values} -> one or more values - {Function} -> a ring function ```java ring someValues [0 1.618 21 3.14] list someSamples [kick_909 hat_909 snare_909 hat_909] list fromFunction random(20 0 100) ``` Alias: `list`, `array` **Note:** Some variable names are not allowed because they are part of the built-in names for datastructures. These are: `bang, int, float, list, mode, zlclear, zlmaxsize` Read more about all the algorithmic methods available for generating and transforming lists in Mercury under [Ring Methods](./05-ring.md#ring-methods). ## set Use the set function to change Global Settings or call functions for an instrument-instance `name`, `group` or `all`. The instrument must be declared with a `name()` or `group()` before the `set` is called. **arguments** - {Name} -> parameter or instrument name to set value - {Value} -> value to set - {Function} -> instrument function to apply global settings: ```java set tempo 125 set volume 0.8 set scale pentatonic_major D set random_seed 9876 ``` Or for using with instruments: ```java new synth saw name(bass) new sample kick_909 group(drums) new sample snare_909 group(drums) set bass gain(0.5) set drums fx(drive 10) set all fx(reverb 0.8 10) ``` Alias: `give`, `apply` ## print Print the output of a list to the console to see its output. ```java console show list rnd random(12) list sin sine(10 5.4) print rnd print sin //=> PRINT: rnd 11 7 21 11 9 8 4 6 3 8 23 10 //=> PRINT: sin 6 7 2 10 0 11 0 11 1 8 5 5 ``` ## console Show the console to see the printed output or other error messages from the code. Clear the console as well. ```java console show console empty ``` ## silence Disable all sounds that are evaluated **before** this line. Alternatively you can hit the `Alt + .` shortkey to disable the instruments. *Note* : Silencing the instruments is not the same as disabling the Audio (below). In this case the instruments are deleted, but the signal-chain is still processing in order to be able to quickly start the sound when a new instrument is generated. ```java silence ``` Alias: `mute`, `killAll` (deprecated) ## audio Disable/enable the Digital Signal Processing (DSP) engine. This can also be done via the interface and is usually not desirable to use during coding sessions. ``` audio <1-0> ``` ================================================ FILE: docs/deprecated-docs/01-global.md ================================================ # Global Settings (set) *Some settings are different between the Max and Browser version* ## tempo Change the global tempo in Beats Per Minute (BPM), counted in quarter-notes. Second argument sets a ramptime in milliseconds to gradually change the tempo over the provided amount of time (*!WARNING: experimental and may lag/glitch!*) **arguments** - {Number+} -> The BPM as a positive number - {Number/Division} -> The ramptime (optional/experimental) ```java set tempo 128 set tempo 80 5000 ``` ## scale Set the scale in a 12-TET system for which all the played notes will be mapped to. An optional second argument sets the tone-center (or root) for the scale. The default scale and root is `chromatic c` **arguments** - {Name} -> the scale name - {Name} -> the root (optional, default=c) ```java set scale major D# set scale minor_harmonic Eb ``` Currently available scales are: ``` "chromatic" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "major" : [0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9, 11], "minor" : [0, 0, 2, 3, 3, 5, 7, 7, 8, 8, 10, 10], "minor_melodic" : [0, 0, 2, 3, 3, 5, 7, 7, 9, 9, 11, 11], "minor_harmonic" : [0, 0, 2, 3, 3, 5, 7, 7, 8, 8, 11, 11], "dorian" : [0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 10, 10], "phrygian" : [0, 1, 1, 3, 3, 5, 7, 7, 8, 8, 10, 10], "lydian" : [0, 0, 2, 4, 4, 6, 6, 7, 7, 9, 11, 11], "myxolydian" : [0, 0, 2, 4, 4, 5, 5, 7, 7, 9, 10, 10], "locrian" : [0, 1, 1, 3, 3, 5, 6, 6, 8, 8, 10, 10], "hungarian" : [0, 0, 2, 3, 3, 6, 6, 7, 8, 8, 11, 11], "gypsy" : [0, 1, 1, 4, 4, 5, 5, 7, 8, 8, 11, 11], "major_neapolitan" : [0, 1, 1, 3, 3, 5, 7, 7, 8, 8, 11, 11], "minor_neapolitan" : [0, 1, 1, 3, 3, 5, 7, 7, 9, 9, 11, 11], "hexatonic" : [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10], "hexatonic_blues" : [0, 0, 2, 2, 4, 4, 6, 6, 7, 7, 10, 10], "hexatonic_prometheus" : [0, 0, 2, 2, 4, 4, 6, 6, 9, 9, 10, 10], "major_pentatonic" : [0, 0, 2, 2, 4, 4, 7, 7, 7, 9, 9, 9], "minor_pentatonic" : [0, 0, 3, 3, 3, 5, 5, 7, 7, 10, 10, 10] ``` The naming convention and offsets for the roots are: ``` -6 gb Gb ges Ges -5 g G -4 g# G# gis Gis -4 ab Ab as As -3 a A -2 a# A# ais Ais -2 bb Bb bes Bes -1 b B -1 cb Cb ces Ces +0 b# B# bis Bis +0 c C +1 c# C# cis Cis +1 db Db des Des +2 d D +3 d# D# dis Dis +3 eb Eb es Es +4 e E +4 fb Fb fes Fes +5 e# E# eis Eis +6 f F ``` ## scalar Scalar transposition, All the current notes are shifted up or down a certain amount of semitones but remaps the notes to the set scale. This is different from transposing the scales. **arguments** - {Int} -> scalar to shift notes by ```java set scalar 2 ``` ## randomSeed Set the random seed as integer for the psuedorandom number generators used in all functions across the environment. Setting the seed to a fixed integer will help make sure random values keep the same sequence every time you re-evaluate the code. A second optional argument resets the seed every n-bar, which can be useful for random arguments used outside list generation, such as `pan(random)` or `beat(0.5)` **arguments** - {Int+} -> the seed for the psudeorandom number generators (default=0) - {Number} -> reset time in n-bars, or divisions (optional, default=null) ```java set randomSeed 31415 set randomSeed 1618 2 ``` ## volume Set the global volume in floating-point amplitude for all instruments across the entire environment. Additional ramptime in milliseconds can be provided to create fade-in/fade-out or smooth transitions to for dynamics. **arguments** - {Float} -> attenuate the total volume of all instruments (default=1) - {Divison/Int+} -> ramptime in milliseconds or divisions (optional, default=0) ```java set volume 0.5 5000 set volume 0.4 2/1 ``` ## highPass Set the global highPass filter cutoff in Hz for all instruments across the entire environment. Additional ramptime in milliseconds can be provided to create smooth transitions from one value to another. Alias: `hipass` **arguments** - {Float+} -> cutoff frequenzy in Hertz - {Divison/Int+} -> ramptime in milliseconds or division (optional, default=1) ```java set highPass 900 5000 set highPass 800 2/1 ``` ## lowPass Set the global low-pass filter cutoff in Hz for all instruments across the entire environment. Additional ramptime in milliseconds can be provided to create smooth transitions from one value to another. Alias: `lopass` **arguments** - {Float+} -> cutoff frequenzy in Hertz - {Divison/Int+} -> ramptime in milliseconds or division (optional, default=1) ```java set lowPass 900 5000 set lowPass 800 2/1 ``` ## beatRepeat *Mercury4Max only* A beatrepeating effect (sometimes called stutter) that continuously repeats a section of the entire sound that was last played. The repating interval is determined in divisions (`1/4`, `3/16`, etc). It immediately starts repeating at the moment of evaluating the code, so timing is key! You can switch to a different section of the beatrepeat recording with optional the second argument. Maximum recording length is 8 seconds (2x 4/4 bars at 60bpm). Alias: `stutter` **arguments** - {Division} -> beatrepeat time interval in division - {Division} -> beatrepeat offset time in division ```java set beatRepeat 1/4 ``` ## osc *Mercury4Max only* Set the ip-address, in-port and out-port number for the network to transmit OSC-messages over using UDP. Default settings are 8000 (in-port), 9000 (out-port), localhost (127.0.0.1) (ip). **arguments** - {Int+} -> receiving port (default=8000) - {Int+} -> sending port (default=9000) - {Name} -> ip-address in the form of xxx.xxx.xxx.xxx or localhost (default=localhost) ```java set osc default set osc 8000 9000 127.0.0.1 set osc ip 127.0.0.1 set osc in 8000 set osc out 9000 ``` ## midi and midiClock *Mercury4Max only* With the midi object you can get the available devices (ports) that you can use to send midi notes to with a `new midi` instrument. ```java set midi getPorts // prints the available ports to the console new midi "AU DLS Synth 1" note(7 0) duration(250) time(1/4) gain(0.8) ``` >More on the midi instrument under [instruments](./02-instrument.md) Output midiClock sync messages to sync an external device to the tempo of Mercury. The device name can have spaces. Use the `getports` argument to automatically open the console and view the different portnames. Use the `off` message or `silence` or `alt + .` to stop the syncing and send a stop message. **arguments** - {Name} -> getPorts, the midi portname or off (default=off) ```java set midiClock getPorts // returns the port names in console and automatically opens the console set midiClock midiPortName // turn the clock on and // outputs clock-sync to midiport of that name set midiClock off // turn the clock off (default) ``` ## click *Mercury4Max only* Enable a clicktrack/metronome sound to allow you to easily play along with the music. You can adjust the interval for the low pitch separately from the interval of the accent. The accent sounds an octave higher. You can also adjust the channel output for the click so you can hear it separately from the main output. Reset the settings with `default`. **arguments** - {Name} -> `on`, `off` or `default` (default=off) ```java set click on // turn the click on/off (default=off) set click freq 1000 // set the base frequency for the click (default=900) set click length 0.9 // adjust the length of the tone (default=0.65) set click time 1/8 // set the base interval for the low pitch (default=1/4) set click accent 1/2 // set the accent interval for the high pitch (default=1/1) set click gain 0.8 // adjust the volume of the click sound (default=0.75) set click out 3 4 // set the output channel(s) for the click, can be mono or stereo (default=1 2) set click default // reset all attributes to the default settings ``` # crossFade *Mercury Playground only* Set the crossfade for the engine to fade from the previous running code to the newly evaluated code in x-amount of milliseconds or divisions. This feature is only applicable to the browser version because it works differently under the hood than the Max version. **arguments** - {Division/Int+} -> crossfade time in milliseconds or division (default=250) ```java set crossFade 1000 set crossFade 2/1 ``` # samples *Mercury Playground only* With `set samples` you can load samples in the playback buffer so they can be used with the `sample`, `loop` and `polySample` instruments. There are multiple ways to add samples, for example using a `url` from a freesound.org preview file, or by using a soundfile from a raw github content link. `set samples` can only be called **once** in the code, so it is important to add all the sounds you want in that single line. This can lead to a very long line of code, so there are some ways to work around this. For example it is possible to input a `.json` file that consists of name:url pairs for the soundfiles. You don't have to load the samples every time you evaluate, once at the beginning of a session is enough. So after loading you can comment the line and the samples are available until you refresh/restart the browser. Below you can read various scenarios: ## single soundfile ### freesound Load a single soundfile from for example freesound.org. Go to the site and find the file you like, right-click on the file and click 'inspect' (in chromium browser). Search for the `cdn.freesound.org/previews` url in the html, this is the soundfile that needs to be copy-pasted. By default the name of the soundfile will be the name you use in the code. ```java // only evaluate set samples once, when loading is done you can comment the line set samples 'https://cdn.freesound.org/previews/145/145778_2101444-lq.mp3' new sample '145778_2101444-lq' time(1/4) ``` You can load a single soundfile and also adjust the name by creating a list. The first item in the list is the name you want to give the sample. The second item in the list is the url to the file. ```java // only evaluate set samples once, when loading is done you can comment the line set samples [ psykick 'https://cdn.freesound.org/previews/145/145778_2101444-lq.mp3' ] new sample psykick time(1/4) ``` ### github Load a single soundfile from a source like github by locating the file in the repository. For example the url looks like this: `https://github.com/tmhglnd/mercury/blob/master/mercury_ide/media/samples/drums/kick/kick_house.wav`. Now construct a new url starting with `https://raw.githubusercontent.com/` then past the `user/repository/branch` after this but remove the `/blob`! For example the result should look like this: `https://raw.githubusercontent.com/tmhglnd/mercury/master/mercury_ide/media/samples/drums/kick/kick_house.wav` ```java set samples [ housekick 'https://raw.githubusercontent.com/tmhglnd/mercury/master/mercury_ide/media/samples/drums/kick/kick_house.wav' ] new sample housekick time(1/4) ``` ## multiple soundfiles ### lists There are two ways to load a larger collection of samples. The first option is by creating variables of `list`s that store the name and url combination. Then in one single `set samples` line you can add all the names of the lists ```java list s1 [ snare_short 'https://cdn.freesound.org/previews/671/671221_3797507-lq.mp3' ] list s2 [ psykick 'https://cdn.freesound.org/previews/145/145778_2101444-lq.mp3' ] list s3 [ hat_short 'https://cdn.freesound.org/previews/222/222058_1676145-lq.mp3' ] set samples s1 s2 s3 new sample psykick time(1/4) new sample snare_short time(1/16) play(euclid(7 3)) gain(0.5) new sample hat_short time(1/4 1/8) gain(1.3) ``` ### json The second option is creating a `.json` file. This file can be stored on the computer or on for example github. The json file is structured in the following way: `{ "sample-name" : "url-to-file" }`. When clicking `add sounds` the json file can be selected instead of a soundfile and it will be used to load the samples. ```json { "snare_short" : "https://cdn.freesound.org/previews/671/671221_3797507-lq.mp3", "psykick" : "https://cdn.freesound.org/previews/145/145778_2101444-lq.mp3", "hat_short" : "https://cdn.freesound.org/previews/222/222058_1676145-lq.mp3" } ``` ```java set samples new sample psykick time(1/4) new sample snare_short time(1/16) play(euclid(7 3)) gain(0.5) new sample hat_short time(1/4 1/8) gain(1.3) ``` ### base If the base url is the same for all the sample files, for example when loading samples via freesound, you can add a `"_base" :` key, followed by the part of the url that is the same for all the samples. Make sure you include the last `/` so the complete url is correct. ```json { "snare_short" : "671/671221_3797507-lq.mp3", "psykick" : "145/145778_2101444-lq.mp3", "hat_short" : "222/222058_1676145-lq.mp3", "_base" : "https://cdn.freesound.org/previews/" } ``` ================================================ FILE: docs/deprecated-docs/02-instrument.md ================================================ # All Instruments The following methods apply to all the types of instruments: `synth`, `sample`, `loop`, `polySynth`, `polySample`, `midi` and `input`. For instrument specific functions see below: - [Synth](#synth) - [Sample / Loop](#sample-and-loop) - [polySynth](#polysynth) - [polySample](#polysample) *MercuryPlayground only* - [Midi](#midi) - [Input](#input) - [Modulator](#modulator) *Mercury4Max only* ## name Set the name for this instrument. This can be any string of 2 or more characters. The `name` is used as a reference to the instrument when the `set` method is used to call methods for a specific instrument. The name is also used to generate an OSC message that is send out from Mercury to trigger external things in sync with the instrument. **arguments** - {Name} -> an instrument name (default=null) ```js new synth saw name(bob) set bob gain(0.8) time(1/16) new sample kick_909 name(alice) set alice gain(1.2) time(1/4) ``` ``` // expected osc messages: /bob 1 /alice 1 ``` ## group *MercuryPlayground only!* Set one or more group-name(s) for this instrument. This can be any string of 3 or more characters. With the `group` you can apply a line of code to multiple instruments at the same time. The `group` is **not** like a mixing bus, so using for example `gain()` will overwrite the `gain()` function on the line of the instrument. If you use the `name()` function you have to make sure the name is set before the group is applied otherwise the reference won't work correctly. **arguments** - {Name} -> a group name used for multiple instruments (default=none) ```js // the hihat is not included in the group so will // not get the gain(0.8) and fx(reverb 0.9 11) new sample hat_909 time(1/8) new sample kick_909 group(drums) time(1/4) new sample snare_909 group(drums) time(1/2 1/4) set drums gain(0.8) fx(reverb 0.9 11) ``` ## time Set the time interval in which a synth or sample is triggered. This can be an integer, float or expression. `1 = bar`, `1/4 = quarter-note`, `1/12 = 8th triplet`, `3/16 = 3-16th notes` etc. Similarly you can set an offset in the timing. The `time()` will start an internal counter for this instrument, incremented every time it is triggerd (based on the `beat()` method). The counter is used as an index to lookup values from other `list`'s provided as argument in methods for this instrument. Setting the first argument to `free` allows to use external triggering via osc messages. The trigger reacts when a value greater than `0` is received. When another instrument in the code has a `name()` that name can be used as osc-message input trigger for another instrument to synchronize the triggering. Alias: `timing()` **arguments** - {Number/Division} -> the timing division or `free` (default=1/4) - {Number/Division} -> timing offset or osc-message when `free` (optional, default=0) ```js set tempo 130 new sample kick_909 name(kick) set kick time(1/4) new synth saw name(syn) set syn time(1/2 3/16) new sample snare_dnb name(snare) set snare time(free "/snareOSC/amplitude") new sample kick_909 time(1/8) play(0.3) name(kick) new synth saw note(0 0) time(free "/kick") ``` ## play Provide the beat function with a `list` consisting of ones and zeroes. For every time interval defined by the `time()` method, the next value in the list will be used. A one results in a trigger of the instrument and an increment of the internal counter. A zero results in no trigger. An optional second argument resets the internal instrument index after a certain amount of time in n-bars. Alias: `beat() / rhythm()` **arguments** - {FloatList+/Float+} -> a rhythmic pattern of ones and zeroes to play (default=1) ```js list aBeat [1 0 0 1 0 1 1 0 0] new sample hat_909 name(ht) set ht time(1/16) play(aBeat 2) ``` Alternatively you can use floating-point values in a list which result in a probability that the instrument will play. Here 0 means 0% chance, 1=100% and 0.5 is 50%. Inspired by Nick Collins paper on [Algorithmic Composition Methods for Breakbeat Science](https://www.dmu.ac.uk/documents/technology-documents/research/mtirc/nowalls/mww-collins.pdf). ```js list aBeat [1 0.5 0.2 0.8 0.5] new sample hat_909 name(ht) set ht time(1/16) play(aBeat 2) new sample kick_909 time(1/4) ``` ## ratchet Add a ratcheting effect (doubling/tripling of hits) with a probability. A technique that introduces some variety in rhythm that originated with electronic music of Tangerine Dream. The first argument sets the probality a note will be repeated. The second argument sets the amount of repetitions within the time, effectively doubling, tripling or more. **arguments** - {Float+} -> probability of ratchet happening (default=0.1) - {Int+/IntList+} -> amount of repetitions (default=2) ```js new sample hat_909 time(1/8) ratchet(0.3 2) ``` ```js list rtc [2 3 2 4 8] new sample hat_909 time(1/4) ratchet(1 rtc) ``` ## timediv *MercuryPlayground only* Documentation to do... ## warp *Mercury4Max only* Warp a rhythm in more complex ways. More documentation to do... ## wait *MercuryPlayground only* This function is similar to the offset parameter in the `time()` method except that it allows you to set an additional waiting time (or delay) for an instrument in milliseconds. This function is useful to allign/synchronize instruments with external peripherals such as sending MIDI notes or OSC messages. **arguments** - {Int+/Division} -> specify the waiting time in milliseconds or division (default=null) ```js new sample kick_909 time(1/4) // the hihat plays 100ms later than the kick new sample hat_909 time(1/4) wait(100) ``` ## shape Set the envelope generator of a sound. Various modes are possible depending on the amount of arguments. The attack time is the fade-in for the sound, the release is the fade-out for the sound both in milliseconds. The sustain time holds the sound at a static volume for a while. If the sound is triggered before the end of the envelope, the envelope is canceled, faded to 0 in 1ms and starts over. You can specify the times in absolute values using integer/floating points (in ms) or in relative values using beat divisions. Alias: `length() / duration() / envelope() / env()` **arguments** - {Number+/Division/NumberList} -> Attack time in ms or division (optional, default=2) - {Number+/Division/NumberList} -> Decay time in ms or division (optional, default=0) - {Number+/Division/NumberList} -> Release time in ms or division ```js new synth saw shape(1500) time(1) //=> default attack of 2 ms, sustain of 0 ms and a release of 1500 ms new synth saw shape(1000 250) time(1) //=> attack of 1000 ms, default sustain of 0 ms and a release of 250 ms new synth saw shape(10 500 50) time(1) //=> attack of 10 ms, sustain of 500 ms and a release of 50 ms ``` with division: ```js set tempo 100 new synth saw shape(1/2) time(1) //=> default release of 1/2 (about 250 ms at 120 bpm) new synth saw shape(1/4 1/32) time(1) new synth saw shape(1/64 1/8 1/16) time(1) ``` ## gain Set the volume for the instrument in floating-point amplitude. Where `1` is the normalized amplitude, `0.5` is the half softer (-6 dBFS) and `2` is twice as loud (+ 6dBFS). An optional second argument sets the sliding time to go to the next gain value in milliseconds. Alias: `amp() / volume() / velocity()` **arguments** - {Float+} -> the (start) volume of the instrument (default=1) - {Number+} -> the sliding time in division or ms (optional, default=0) - {Bool} -> mute the instrument but still use named sends (default=0) ```js new sample snare_909 name(sn) set sn gain(0.8) ``` **Note:** When using the `midi` instrument the gain will be multiplied by `127` to construct a velocity message. A `gain(0.5)` therefore maps to `63` and a `gain(1)` to `127` ## pan Set the panning position in floating-point for the sound in the stereo-image. `-1` is 100% left channel, `0` is center (both speakers), `1` is 100% right channel. Higher or lower values wrap between -1 and 1. Provide pan with the `random` argument to get a new random panning value every moment of the `time()` counter. Alias: `panning()` **arguments** - {Float} -> the panning position between -1 and 1 (default=0) ```js new sample clap_909 name(hand) set hand pan(random) ``` ## fx Apply an effect to the sound of the instrument to manipulate your sounds timbre in many ways. The first argument is always the `effectname`. The following arguments depend on the selected effect. See [FX Documentation](./04-fx.md) for more details and an up-to-date list of all the available effects for both Mercury4Max and the Mercury Playground. Alias: `effect() / with_fx() / add_fx()` **arguments** - {Name} -> the effect name - {Value+} -> any values based on effectname arguments ```js new synth square name(bass) set bass fx(reverb 0.8 11) ``` # synth The synth and polySynth instruments allow you to play synthesized sounds using a single cycle waveform. These waveforms are loaded in RAM and can be accessed by their filename (without the extension). The default waveforms are `sine`, `triangle`, `square` and `saw`. - [How to load other waveforms into Mercury](./07-environment.md#sounds) - [Full list of all the included waveforms](https://github.com/tmhglnd/mercury/blob/master/mercury_ide/media/README.md) ## note Set the pitch for the instrument to play a note in a melody or chord. The note is specified as a 2-dimensional coordinate system, where the first argument is the semitone offset (can be positive or negative) and the second argument is the octave offset (can be positive or negative). The origin of the system, `note(0 0)`, corresponds by default with midi-pitch `36` or `C2`. Depending on the `set scale` the coordinate system will shift and result in a different pitch for the origin. A `note()` should therefore not be taken as an absolute value, but rather a relative direction where the melody is going to in relation to the scale and root. Detuning/pitchbending can be done by providing a floating-point note number. The value behind the decimal point is the amount of detuning from one semitone to the next. For example `7.5` results in `7` semitones (mapped to the scale if `set scale` is used) and then a `0.5` semitone is added (= 50 cents). Detuning is applied after mapping the integer semitone to a scale. |`note(x y)`|-… |-3 |-2 |-1 |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |… | |---------|---|---|---|---|------|---|---|---|---|---|---|---|---|---|---|---|------|---|---| |4 |… |A# |B |B# |C `84`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `96`|C# |… | |3 |… |A# |B |B# |C `72`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `84`|C# |… | |2 |… |A# |B |B# |C `60`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `72`|C# |… | |1 |… |A# |B |B# |C `48`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `60`|C# |… | |0 |… |A# |B |B# |C `36`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `48`|C# |… | |-1 |… |A# |B |B# |C `24`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `36`|C# |… | |-2 |… |A# |B |B# |C `12`|C# |D |D# |E |F |F# |G |G# |A |A# |B |C `24`|C# |… | **arguments** - {Value/ListValue} -> positive or negative semitone note value or list, x-coordinate (default=0) - {Value/ListValue} -> positive or negative octave value or list, y-coordinate (default=0) ```js set scale major D new synth sine note(2 2) //=> results in midi-note 64 > F4 ``` Also excepts lists to play a melody over time: ```js set scale minor A list mel [0 5 7 3 2 -2 0] new synth sine note(mel 1) time(1/16) ``` Alias: `pitch()` ## useDetune **REMOVED** Detune is now done in the `note()` method by providing a floating-point note number. The value behind the decimal point is the amount of detuning from one semitone to the next. For example `7.5` results in `7` semitones (mapped to the scale if `set scale` is used) and then a `0.5` semitone is added (= 50 cents). Detuning is applied after mapping the integer semitone to a scale. ## slide A portamento/sliding/gliding effect. This will make the synthesizers oscillators slowly slide from one frequency to the next one over a defined period in milliseconds or division. The sliding is logarithmically (meaning it wil slide from midi note to midi note linearly, and when converted to frequency slide logarithmically. This sounds slightly different then when sliding linearly between two frequencies) Alias: `glide`, `portamento` **arguments** - {Number/Division} -> sliding time in milliseconds or division (default=50) ```js list notes [0 7 3] new synth saw note(notes 1) time(1/2) slide(1/8) ``` ## super Add multiple oscillators in unison with a detuning factor to create a *SuperSaw* effect. One oscillator will always be the base frequency of the `note()`, the others are tuned above and below in incremental steps based on the detuning factor. The first argument sets the amount of oscillators (minum of 1, default=1), the second argument sets the detuning factor in semi-tones, the third optional argument sets the oscillator type for the odd numbered oscillators. Alias: `unison` **arguments** - {Int+} -> number of oscillators (default=1, maximum=64) - {Float/FloatList} -> detuning factor in semi-tone, 12=octave - {Name} -> the name of the odd numbered oscillators (optional, default=main oscillator) ```js new synth saw note(0 1) shape(-1) super(5 0.031415) ``` ```js new synth saw note(0 1) shape(-1) super(11 0.0618 square) ``` Detuning can be changed in time with a `list` ```js list voices [3 5 9 21] list detune [0.1 0.5 0.9 12.01 0.3] new synth saw note(0 1) time(1/4) shape(-1) super(voices detune) ``` ## sub Add a second sinewave oscillator one octave lower than the note played for a sub frequency. **arguments** - {Float+} -> amplitude for the sub oscillator (default=0) ```js new synth sine note(0 2) time(1/4) sub(0.8) ``` ## wave2 **DEPRECATED, use super() instead** Add a second oscillator to the synths sound. This can either be a sine, triangle, square or saw. The second argument sets a multiplication ratio for the second oscillators frequency. **arguments** - {Name} -> waveform to add as second wave - {Float} -> tuning in ratio to note() frequency (default=1) - {Float} -> tuning offset in Hertz (optional, default=0) ```js new synth saw note(0 1) time(1/4) wave2(square 0.998) ``` Alias: `osc2()` `super` ## noise Add a noise oscillator to the synth sound. The first argument is the amplitude (gain), the second argument is the "color" of the noise between 0 and 1 (1 = white noise, lower values give a more darker noise sound). When the modulation mode is turned on (with 1) the noise is modulated by the source of the oscillator (or oscillators if super and sub are used). **arguments** - {Float+} -> amplitude of the noise (default = 0) - {Float+} -> color of the noise 0-1 (default = 0.8) - {Bool} -> modulation mode (default = 0) ```js new synth saw note(0 1) time(1/4) noise(0.3 0.8 1) ``` # Sample and Loop The sample and loop instruments allow you to play sound-recordings and loops. These so called "samples" are loaded in RAM and can be accessed by their filename (without the extension). - [How to load other sounds into Mercury](./07-environment.md#sounds) - [How to load sounds in the Mercury Playground](./01-global.md#samples) - [Full list of all the included sounds](https://github.com/tmhglnd/mercury/blob/master/mercury_ide/media/README.md) ## speed Set the playback speed for the sample, where 1 = original speed, 0.5 = half the speed and 2 = twice as fast. Adjusting the playback speed will change the pitch of the sample. A negative value will play the sample backwards starting at the end (or at the `offset()` position) Alias: `rate()` **arguments** - {Number} -> playback speed (default=1) ```js new sample choir time(5) speed(0.5) new sample choir time(5) speed(-0.5) set all fx(reverb 2 17) ``` ## start Set the start (the offset position of the playback) of the sample. 0 = start at the beginning, 0.5 = start midway in the sample. With long decaying samples the offset is very useful if playing the sounds backwards when using for example `speed(-1)`. Alias: `offset` **arguments** - {Float} -> the playback position between 0 and 1 (default=0) ```js list positions randomFloat(8 0 0.5) new sample choir time(1/16) start(positions) ``` ## useNote **REMOVED** ## note The `note` method allows you to tune the sample to a specific pitch instead of using the `speed()` function. The function works the same as the `note` function explained under the `synth`. Please look there for further information. ## tune Set the base note as a MIDI value for the sample to determine how the `note()` function changes the playback speed. For example if your sample was recorded as a `a4` then you will set tune to `69`. `note(0 2)` will be the same as the `tune()` value in the case of a scale set to have `c` as the root. **arguments** - {Number+} -> MIDI pitch as base for tuning (optional, default=60) ```js set scale minor c list notes [0 7 5 3] // tune the kalimba to a3 new sample kalimba_a time(1/4) note(notes 2) tune(57) ``` ## stretch Stretch the entire sample to the length of a full bar. Useful for when working with beats that have to be looped. Stretching is the default when working with the `loop` instrument. This is basically a `new sample` with `stretch(1)`. Optionally you can turn timestrechting on with a second argument to preserve the original pitch of the sample. A third optional argument changes the mode of the stretching, choose from: basic, monophonic, rhythmic, general, extremestretch, efficient. The default is set to efficient. **arguments** - {Int} -> turn stretch to full bar on/off (default=0 for sample default=1 for loop) - {Int} -> turn timestretching on when stretching to full bar, preservering the original pitch (default = 0) - {Name} -> adjust the stretching mode (default=efficient) ```js new sample chimes stretch(1 1 general) speed(-1) ``` ### Stretching modes explained *Mercury4Max only* - `basic` : best option for real-time performance - `monophonic` : best option for any monophonic source without ambience - `rhythmic` : best option for drums and percussion when transient preservation is critical - `general` : balances spectral integrity with transient preservaton - `extremestretch` : optimized for stretching (slowing down) material, limited to a stretch factor between 0.5 and 4 - `effcient` : best option when CPU efficiency is critical # polySynth The polySynth functions the same as the synth in the sense that you choose a waveform, set a `note()`, add a `shape()`, etc. For explanation of those functions see above. The extra feature of the polySynth is that it allows for overlapping notes to generate for example chords. Notes provided to the `note()` function as a 2-dimensional list will be played at the same time as a chord. By default there are 8 voices available at the same time. Voice stealing is `on` by default meaning if a new note is played while all voices are busy the oldest triggered note will be removed. ```js // note the double [[ ]] to generate a 2d-list list chord [ [ 0 4 5 7 8 10 12 ] ] new polySynth sine note(chord 2) time(1/2) shape(1 1/4) ``` ## steal If new notes are triggered while all voices are still in use they will not be played. This behaviour can be changed by setting the stealing to `on` or `1`. **arguments** - {Bool/Name} -> turn voice stealing `on` or `off` (optional, default=on) ```js list notes spread(16 0 36) new polySynth sine note(notes 2) time(1/16) shape(1 1/1) steal(off) ``` ## voices **not implemented yet** ## spread Use the spread function to add little delays with optional randomness between every note from a chord, resulting in the chord sounding broken up in time. **arguments** - {Number+/Division} -> the delaytime between note triggers in ms or division (default=0) - {Number+/Division} -> random delaytime offset added to the delaytime in ms or division (default=0) ```js list notes [[0 3 7 11 12]] new polySynth sine note(notes 2) shape(1 1/1) time(1/1) spread(150 50) ``` # polySample *Mercury Playground only* The polySample functions the same as the sample in the sense that you choose a sample file, set a `speed()`, add a `shape()`, etc. For explanation of those functions see `sample` above. The extra feature of the polySample is that it allows for overlapping sounds. For example useful when generating chords. Notes provided to the `note()` function as a 2-dimensional list will be played at the same time as a chord. By default there are 8 voices available at the same time. For voice-stealing see `steal` under `polySynth`. For setting voice-amount see `voices` under `polySynth`. ```js set tempo 100 set scale dorian eb list notes shuffle(spread(24)) new polySample piano_e time(1/16) note(notes 1) shape(1 1/2) steal(off) tune(64) ``` # Midi The midi instrument allows you to send midi-note messages to other devices or virtual devices on your computer. To setup a basic midi instrument use: ```js set midi getPorts //=> prints the available devices to the console new midi "AU DLS Synth 1" time(1/4) note(0 0) length(100) gain(0.8) ``` ## note Set the pitch for the instrument to play a note in a melody or chord. The note is specified as a 2-dimensional coordinate system, where the first argument is the semitone offset (can be positive or negative) and the second argument is the octave offset (can be positive or negative). The origin of the system, `note(0 0)`, corresponds by default with midi-pitch `36` or `C2`. Depending on the `set scale` the coordinate system will shift and result in a different pitch for the origin. A `note()` should therefore not be taken as an absolute value, but rather a relative direction where the melody is going to in relation to the scale and root. For a detailed table of the note coordinates see `note` under [synth and polySynth only](#synth-and-polysynth-only). **arguments** - {Value/RingValue} -> positive or negative semitone note value or list, x-coordinate (default=0) - {Value/RingValue} -> positive or negative octave value or list, y-coordinate (default=0) ```js set scale major D new midi "AU DLS Synth 1" note(2 2) //=> results in midi-note 64 > F4 ``` Also excepts lists to play a melody over time: ```js set scale minor A list mel [0 5 7 3 2 -2 0] new midi "AU DLS Synth 1" note(mel 1) time(1/16) ``` ## length Replaces the `shape()` function for Synth and Sample. Set the duration of the midi note for it to send the note-off message in milliseconds or division. If the instrument is triggered before the end of the duration, the note-off is canceled and a new note-off is send. **arguments** - {Number/Division} -> Duration time in ms or division ```js new midi "AU DLS Synth 1" length(1500) time(1) //=> duration of 1500 ms triggered once per bar ``` with division: ```js set tempo 100 new midi "AU DLS Synth 1" length(1/2) time(1) //=> duration of 1/2 (1200 ms at 100 bpm) ``` Alias: `duration()` ## out Set the channel output for the midi-note to be send to. **arguments** - {Number} -> Channel to send the midi-note to ```js new midi "AU DLS Synth 1" note(7 2) out(1) new midi "AU DLS Synth 1" note(0 0) out(2) ``` Alias: `channel()` ## chord Turn the chord output (polyphony) on for a midi instrument. This allows you to use 2-dimensional lists where the 2nd dimension is used to generate chords. **arguments** - {Bool} -> Turn chord output on/off ```js list chords [[0 4 7] [2 5 9] [5 9 0]] new midi "AU DLS Synth 1" note(chords 1) chord(on) ``` Alias: `poly` ## program Send program change messages to the specified midi channel of the instrument. The channel number is based on the `out()` method (see above). The default channel `1` is used if no channel is selected. The program change value is an integer from `0` - `127` and can be sequenced as a list. If no value is provided there is no program change send. The value is **only** send when it changes based on the previous value. This is done because some midi devices react every time a program change is received (for example cutting of notes), even if the value stays the same. **arguments** - {Int+} -> Program change value 0-127 (default=off) ```js list notes spread(5 0 12) list changes [0 10 20] new midi default note(notes 1) out(1) program(changes) ``` ## sync Turn midiclock syncing on/off for an individual instrument and send it to the selected port/device from that instrument. **arguments** - {Bool} -> Turn syncing on/off ```js new midi "aMidiDevice" sync(on) new midi "otherDevice" sync(off) ``` Alias: `clock()` ## change Send control change messages to the midi device. This function can have multiple calls in the same instrument, every call can be a different control number. The first argument is the control number, the second argument is the controller value or a list of controller values. **arguments** - {Int+} -> Midi controller number between 0-127 - {Int+/RingInt+} -> Midi controller value between 0-127 ```js list ccValues [10 20 30 40 50] new midi "device" change(13 100) change(21 ccValues) ``` Alias: `cc` # Input Use the input from the soundcard (ADC) as the source for an instrument. The sound can be modified by all the various `fx()`. The volume can be adjusted with `gain()`. An envelope can also be applied on the sound with `shape()` and this envelope can be triggered with `time()` just as with the regular instruments `sample`, `synth`, etc. Use the words `in1`, `in2`, ..., `inx` to choose the input source. *In the browser version you will need to give permission to use the microphone and afterwards you might need to refresh the page* **arguments** - {Name} -> `default` or the input channel number as a string `inX` ```js // use the default input, in most cases channel 1 new input default gain(1) // use a specific channel new input in3 gain(0.9) // add functions like shape, time and fx new input in4 gain(0.9) time(1/16) shape(1 100) fx(reverb) fx(distort) ``` # Modulator The modulator allows you to send a modulation signal as an argument to parameters from functions of other instruments. These parameters are continuously modulated at a specific rate with a specific waveform. The modulation rate is independent from the instruments `time()` (in comparison when using a list as an argument). It is also possible to send the modulation signal directly out to the connected soundcard on a specific channel. This can for example be used for cv modulations. **arguments** - {Name} -> waveform type: `sine`/`sin`, `sawUp`/`phasor`, `sawDown`/`saw`, `square`/`rect`, `triangle`/`tri`, `random`/`rand`, `randomLine`/`randL`, `trigger`/`gate` ```js new modulator name() range( ) time() out() ``` ## modulator name Set the name for the modulator, this name can be used as argument in the functions of an instrument like `synth` and `sample` **arguments** - {Name} -> the modulator name for reference in other functions ```js // set the name to myModulator new modulator sine name(myModulator) // the synth uses the modulator in the gain function new synth saw gain(myModulator) ``` ## modulator time Set the modulation speed in division. The default is `1/1` (one period per bar). **arguments** - {Division} -> The time interval for one period of the modulation waveform (optional, default=1/1) - {Division} -> The time offset for the modulation (optional, default=0) ```js // modulate a sinewave at a period of one per 4 bars new modulator sine time(4/1) ``` ## modulator range Set the modulation range between a low and high value with an option exponential value. The default range is 0 to 1. **arguments** - {Number} -> The low output range (optional, default=0) - {Number} -> The high output range (optional, default=1) - {Number} -> The scaling exponent (optional, default=1) ```js // set the range from 200 to 5000, for example to modulate a filter cutoff new modulator sine range(200 5000) // include the third argument to set the exponential in the scaling new modulator sine range(200 5000 3) ``` ## modulator out **Warning: be careful when sending DC signals with large ranges to your DAC, this could damage your speakers if you choose the wrong output!** Set the output channel from your connected soundcard to send the modulation signal directly to. The default is 0 (no output to DAC). Currently the maximum number of channels that can be used is 16. If the modulation signal is only used for direct output it is not necessary to also `name()` the modulator. **arguments** - {Number+} -> The channel number from 1 till number of outputs available, maximum of 16 (default=0) ```js // send a sinewave modulator signal to DAC channel 3 new modulator sine range(-1 1) out(3) ``` ## modulator trigger When using the mode `trigger`/`gate` the modulator functions like the sequencer in the instruments. Meaning it is also possible to use `play()` to add a rhythm list, use `ratchet()` to add a list of timing subdivisions with probability, use `warp()` to add a list of time warpings. **arguments** - {Name} -> `trigger`/`gate` sets the intrument to use the stepsequencer ```js // generate a euclidean rhythm and use it in the trigger list rtm euclid(16 11) new modulator trigger time(1/8) play(rtm) ratchet(0.1 2) ``` ## modulator hold The hold function transforms the `trigger` into a gate that goes open and closes after a certain amount of time. The time value can be either `ms` or a `division`. If the hold time is longer than the time interval between triggers the gate stays open. A hold of `0` results in the click from the default trigger. **arguments** - {Number+} -> hold time in ms or division (default=0) ```js // trigger every 8th note, and leave the gate open for the length of 50ms new modulator trigger time(1/8) hold(50) // trigger every 8th note, and leave the gate open for the length of a 16th new modulator trigger time(1/8) hold(1/16) ``` ================================================ FILE: docs/deprecated-docs/03-emitter.md ================================================ # Emitter Create an emitter object. Use this object to send messages to other platforms. The emitter objects works similarly to the [instruments](./02-instrument.md) in the sense that it also has the `time`, `beat` and `name` functions by default. The `time` determines the time-interval at which messages are send. The `beat` can turn send moments on or off. See under [Synth/Sample](#synthsample-functions) for further detail. See the shared methods: - [name](./02-instrument.md#name) - [group](./02-instrument.md#group) - [time](./02-instrument.md#time) - [beat](./02-instrument.md#beat) ## osc Create an emitter object of type `osc`. The `name()` method is used to set the opening address of the message to `/`. Any arbitrary function name is used to set as second address in the osc-string. If no name is provided it will default to a unique number for every instrument instance. By adding other functions with any arbitrary name you can send a message with the address in the form of `// ` ```java new emitter osc name() time() ``` example ```java list params [0.25 0.5 0.75] list values [3 1] new emitter osc name(myOSC) time(1/4) set myOSC someParam(params) anotherParam(values) // emits => /myOSC/someParams 0.25 // /myOSC/anotherParam 3 // /myOSC/someParams 0.5 // /myOSC/anotherParam 1 // /myOSC/someParams 0.75 // /myOSC/anotherParam 3 // /myOSC/someParams 0.25 // etc... ``` The messages also support multiple arguments up to a length of 256. Multiple arguments can be provided as rings, symbols, floats or integers. ```java list val1 [0.25 0.5 0.75] list val2 [3 1] new emitter osc name(myOSC) time(1/4) set myOSC aMessage(0.1 val1 val2 100) // emits => /myOSC/aMessage 0.1 0.25 3 100 // /myOSC/aMessage 0.1 0.5 1 100 // /myOSC/aMessage 0.1 0.75 3 100 // /myOSC/aMessage 0.1 0.25 1 100 // etc... ``` **Note:** Some variable names are not allowed because they are part of the built-in names for datastructures. These are: `bang, int, float, list, mode, zlclear, zlmaxsize` ## name Set the name for the OSC emitter. This can be any string of 2 or more characters. The `name` is used as reference to the instrument when the `set` method is used to call methods for a specific object. The `name` is also prepended as first address in the osc-message of the format `// argument`. ## address Alternatively, if you want multiple emitters to send to the same address, you can use the `address()` method. The `address` is prepended as first address in the osc-message in the format: `/
/ argument`. Useful if you want to send messages to the same address, but with different timing-intervals. ```java list params [0.25 0.5 0.75] list values [3 1 4] new emitter osc name(osc1) address(myOSC) time(1/4) set osc1 someParam(params) new emitter osc name(osc2) address(myOSC) time(1/2) set osc2 anotherParam(values) // emits => /myOSC/someParams 0.25 // /myOSC/someParams 0.5 // /myOSC/anotherParam 3 // /myOSC/someParams 0.75 // /myOSC/someParams 0.25 // /myOSC/anotherParam 1 // etc... ``` ## sendOSC You can enable/disable sending messages with the sendOSC function ```java new emitter osc name(osc3) sendOSC(0) ``` ## receiving You can use osc adresses as arguments for other functions by putting the address as argument in the form: `/
//`. For example to control the `gain()` of a `sample` and the `note()` value of a `synth` enter the following: ```java new sample kick_909 time(1/4) gain(/myOSC/sliderValue1) new synth saw note(/myOSC/sliderValue2) shape(1 100) time(1/8) ``` It is possible to scale the incoming osc value to a different range by using `{}` after the address inputting a low and high output range separated by a colon `:`. The scaling function considers an incoming range of `0 - 1` floatingpoint values. For example to control the `note()` and `shape()` ranges in a `synth` enter the following: ```java new synth saw note(/myOsc/sliderValue3{2:19} 0) shape(1 /myOsc/sliderValue4{50:500}) // => converts incoming slider values from 0-1 to 2-19 for note and 0-1 to 50-500 for note length ``` ================================================ FILE: docs/deprecated-docs/04-fx.md ================================================ # Sound Effects (fx) The sound FX currently have a fixed chain when using the Mercury standalone version in Max. The chain of effects is as following: ``` synth / sample / polySynth / loop (mono) | freeze (spectral freezer) | shift (pitchshifter) | vibrato (pitch modulation) | triggerFilter (envelope modulated filter) | kink (distortion) | drive (distortion) | filter (low/hi/band filter with optional LFO modulation) | comb (combfiltering) | degrade (downsampling) | squash (basic compression/distortion) | gain (the volume of the sound) -> sender | panning || double / chorus || || >>====== vv || + || hall (stereo reverb) ++ <<====== << || lfo (low frequency oscillator) || delay (stereo pingpong delay + drywet) || output ``` ``` | mono - mono || stereo = stereo ++ sum ``` ## reverb Add a reverberation effect to the sound, making it sound like it's in a room or big hall. The effect has 2 arguments, the amplitude of the reverb and the reverb-size. The amplitude is specified as floating-point amplitude and the length is a value between `0` and `18` (choosing between 19 presets). The default is `0.5` amplitude and `10` length. **arguments** - {Float+} -> amplitude of reverb (default=0.5) - {Number+} -> size of reverb 0-18 (default=10) - {Number+} -> slide time in ms when size is changed (default=10) - {Float+} -> drywet 0-1 (optional, 1=100% wet, default=0.5) Alias: `fx(hall)` ``` fx(reverb) fx(reverb ) fx(reverb ) fx(reverb ) ``` ```java new sample snare_909 time(1) fx(reverb 0.93 15) ``` ## delay Add a pingpong delay effect to the sound. The effect has 4 arguments, the left delaytime, the right delaytime, the feedback and the damping. The delaytime is specified in bar time divisions, where `0.25` (or `1/4`) is a quarter note. The feedback is specified as a value between `0` and `1`. Positive feedback is allowed and internally compressed/distorted, but watch out for your ears just in case. The damping is a onepole lowpass filter for which the cutoff is specified between `0` and `1` where 0 means full damping, and 1 means none (filter open). Alias: `fx(echo)` **arguments** - {Division} -> delaytime for left (optional, default=3/16) - {Division} -> delaytime for right (optional, default=2/8) - {Float+} -> feedback 0-1 (optional, default=0.8) - {Float+} -> damping 0-1 (optional, default=0.5) - {Float+} -> drywet 0-1 (optional, 1=100% wet, default=0.5) ``` fx(delay) (defaults) fx(delay ) fx(delay ) fx(delay ) fx(delay ) fx(delay ) ``` ```java new sample hat_909 time(1/2) fx(delay 3/16 7/16 0.5 0.7) ``` ## filter Add a filter to the sound. This can be a static filter or a modulated filter depending on the amount of arguments you provide. The filter-type can be a `low`, `high` or `band`-pass filter. The second argument is the cutoff frequency in Hz and the third argument is the resonance between `0` and `1`. Passing a single argument only sets the cutoff, passing two arguments sets the cutoff and resonances. The filter then defaults to `lowpass`. **arguments** - {Name} -> filter type, low, high, band (default=low) - {Number+} -> cutoff frequency in Hz (default=1200) - {Float+} -> resonance between 0-1 (default=0.45) ``` fx(filter) fx(filter ) fx(filter ) fx(filter ) ``` ```java new synth saw note(0 1) shape(-1) fx(filter low 800 0.6) ``` You can provide extra arguments to have the filter modulate between a low and high cutoff-frequency. In this case the arguments are as follows (in order): The filter-type `low / high / band`. The modulation speed in float/expression as musical time division where `0.25` or `1/4` = a quarter note. The high cutoff in Hz, the low cutoff in Hz the resonance between `0` and `1`. The modulation shape tilt between `0` and `1`, where 0 is ramp-down, 1 is ramp-up and 0.5 is triangle form. The exponential curve for the filter as floating point. **arguments** - {Name} -> filter type, low, high, band (default=low) - {Division} -> modulation ratio (default=1/1) - {Number+} -> low modulation frequency in Hz (default=200) - {Number+} -> high modulation frequency in Hz (default=3000) - {Float+} -> resonance between 0-1 (default=0.45) - {Float+} -> modulation slope 0-1 up, down, triangle) (default=0.5) - {Float+} -> exponential scaling (default=2) ```java new synth saw note(0 0) fx(filter low 1/4 100 3500 0.55 0 4) ``` ## triggerFilter A filter with an envelope that is controlled by the trigger of the instrument. Whenever the sequencer triggers an event that would cause the instrument to sound this will also be the event that triggers the start of this filter. The filter has various types, a low and high frequency value for the envelope to move between, an attack and release time in ms or division value and an optional exponent for the slope of the filter. **arguments** - {Name} -> filter type, `low`, `high`, `band` (default=low) - {Number+/Division} -> attack time in ms or division (default=1) - {Number+/Division} -> release time in ms or division (default=1/16) - {Number+} -> high frequency point in the envelope (default=4000) - {Number+} -> low frequency point in the envelope (default=100) - {Float+} -> exponent for the envelope curve (default=1) ```java list beat euclid(8 3) new synth saw note(0 1) time(1/8) play(beat) fx(triggerFilter low 10 1/4 1000 150 0.5) ``` ## double / chorus Add an Automated-Double-Tracking (ADT) or Chorus effect to the sound. When only typing double it will sound like two versions of the sound are created, one left and one right. When typing chorus the original sound is added and the delaytimes are longer. Arguments are the modulation speed in division, the modulation depth in milliseconds, the modulation wave `sine` or `random`, the dry-wet ratio between `0` and `1` and a detune factor between left and right modulation wave in floating. **arguments** - {Division} -> modulation rate (default=4/1) - {Number+} -> modulation depth in ms (default=8 for double, default=45 for chorus) - {Name} -> modulation wave, sine or random (default=random) - {Float+} -> dry-wet (default=1 for double, default=0.5 for chorus) - {Float+} -> modulation rate detune (default=0.94562) ``` fx(double) fx(chorus) fx(chorus ) fx(chorus ) ``` **browser version only:** - {Division} -> modulation rate (default=8/1) - {Number+} -> modulation depth in ms (default=8 for double, default=45 for chorus) - {Float+} -> dry-wet (default=1 for double, default=0.5 for chorus) ``` fx(double) fx(chorus) fx(chorus ) fx(chorus ) ``` ```java new sample clap_808 fx(double) new synth saw fx(chorus 5/1 30) ``` ## freeze Create an FFT-freeze effect on the sound. This will result in a "frozen-in-time"-like sound, where the timbre is still clearly audible. The freezer is triggered at the time interval of the `time()` function. The trigger can be set with a float to give it a probability of triggering, or a list can be provided to let the freezing occor in a rhythmic pattern. The second optional argument determines the sliding time between 2 freeze frames (in n-frames), and the third optional argument sets the amount of frames to store. **arguments** - {Number} -> freeze rhythm or probability (default=1) - {Int} -> interpolation between frames (default=0) - {Int} -> number of frames stored in freezer (default=8) ```java list playHarp [1 0 0 0 0 0 0 0] list trigger [1 0 0 0 0] new sample harp_up time(1/4) beat(playHarp) name(harp) set harp fx(freeze trigger) ``` ## shift Make a time-domain pitchshifting effect to change the pitch of the sound. The first argument sets the shift in semitones (this can also be a floating-point value to create microtonal shifts). The second value sets the wet-dry ratio (default = 1) to combine the original with the shifted sound. You can change the shifting quality (higher quality sounds better but uses more cpu). **arguments** - {Number} -> shifting factor (positive/negative) in semitones (optional, default=-12) - {Float} -> dry-wet mix between 0-1 (optional, default=1) - {Name} -> shifting settings `basic`, `good`, `better`, `best` (optional, default=basic) ```java new sample violin_c time(1/4) fx(shift 7 0.5) ``` ## vibrato Add a vibrato effect to the incoming signal by modulating a short delayline with a sinewave. The depth sets the delayline length in ms, the rate sets the frequency of the sinewave in Hz. **arguments** - {Number+} -> vibrato rate in Hz (optional, default=2) - {Number+} -> vibrato depth in ms (optional, default=5) ```java new sample violin_c time(1/4) fx(vibrato 4 5) ``` ## squash A simple compression/distortion algorithm based on a design by Peter McCulloch. Raise the amount to squash the incoming signal, first creating some kind of simple compression, but quickly introduces nice distortion harmonics. **arguments** - {Number+} -> input gain amount, greater than 1 (optional, default=4) - {Float+} -> dry-wet factor 0-1 (optional, default=1) ```java new sample piano_e time(1) fx(squash 2.3) ``` ## kink A kink distortion algorithm. Creates a bend or "kink" in the audio signal. **arguments** - {Number+} -> distortion amount, greater then 0 (optional, default=5) - {Float+} -> dry-wet factor 0-1 (optional, default=1) ```java new sample violin_c time(1) fx(kink 15) ``` ## distort A distortion/overdrive/soft-clipping effect. Uses the `tanh()` algorithm. Alias: `fx(drive)` **arguments** - {Number+} -> distortion amount, greater then 0 (optional, default=2) - {Float+} -> dry-wet factor 0-1 (optional, default=1) ```java new sample kick_909 fx(drive 15) ``` ## degrade A downsampling/8bit/chiptune effect. The signal is downsample by a factor, where 0 means no downsampling (original samplerate) and 0.5 is half the samplerate etc (e.g. 44100 * 0.5 = 22050). Alias: `fx(chip)` **arguments** - {Float+} -> downsampling amount between 0-1 (default = 0.5) - {Float+} -> dry-wet factor 0-1 (optional, default=1) ```java new synth saw fx(degrade 0.75) ``` ## comb A combfilter effect. This combines a small delayed version of the sound with the original sound resulting in a combfilter, giving a metallic quality to the sound. The first argument is the semitone the filter is tuned at (synced to the scale and allowing for detuning with floating points), the second optional argument is a feedback amount. **arguments** - {Number+} -> filter frequency as note semiton (default=0) - {Float+} -> filter feedback between 0 and 0.99 (default=0.8) - {Float+} -> dry-wet factor 0-1 (optional, default=0.5) ```java new synth saw fx(comb 82 0.4) ``` ## lfo Add a Low Frequency Oscillator effect to the sound. This results in a rapidly fading in/out sounding effect (helicopter sound). Various arguments allow to shape the speed and type of wave for modulation. The first argument is the rate in division. The second argument is the shape type `square`, `up`, `down` or `sine`. With the third argument you can change the lowest amplitude of the modulation and with the optional fourth argument you can change the width (only works with the square) Alias: `fx(tremolo)` **arguments** - {Division} -> speed of the LFO (default=1/16) - {Name} -> type of the wave, square, up, down or sine (default=square) - {Float+} -> dry-wet factor 0-1 (optional, default=1) - {Float+} -> width of the square wave between 0-1 (optional, default=0.5) - {Float+} -> offset of the waveform 0-1 (optional, default=0) ``` fx(lfo) fx(lfo ) fx(lfo