Wren is an open source modular software synthesizer for Windows

Elk vogeltje zingt zoals het gebekt is

current version 2020.10.17.0


Quick links

The ZIP of the current 64 bit version Everything executable in one zip file – you'd normally want to download just this file for a manual installation. A manual install will make no changes to the windows registry. For installation advice see the top FAQ entry. Recommended for 64 bit systems as it is a lot faster than the 32 bit version.
The ZIP of the current 32 bit version Everything executable in one zip file – you'd normally want to download just this file for a manual installation. A manual install will make no changes to the windows registry. For installation advice see the top FAQ entry. Recommended for 32 bit systems only, as those can not run the 64 bit version.

Additional links:

The latest sources All source stuff in one zip file (2020.10.17.0 build 175).
The Wren module docs Wren itself will generate these as well when a new version runs for the first time.
Some example patches Just a random collection of patches, some may be nice others less so, they may depend on external files other than the standard dependencies mentioned above (like wave files or data files).
The Wren forum Please use the forum for comments and requests.

Version information

Program version 2020.10.17.0 – build 175
Source version 2020.10.17.0 – build 175
Components version 2020.10.17.0 – build 70
Port Audio DLL version 19.0.2 – also see source code.
Patch version 12
LPC file version 2015.1.18
Looks version 2020.7.18
Formants file version 2016.3.5
Modal file version 2018.5.18
Markov file version 2016.9.9
Forth version 2017.11.19
Mazes version 2020.1.23
This page

wren large logo

Eurasian wren, Troglodytes troglodytes

Original logo made by epwhorl
Original image by Andreas Trepte.

Looks



looks for default theme


default looks

looks for gabe theme


an alternate scheme

General information

  • Wren is a modular software synthesizer, or a virtual modular soft synth. For questions or remarks please use the Wren forum at electro-music.com. I do hang out at the electro-music chatroom too at times. I'm open for requests or for adding user contributions. I'm inclined to fix bugs as well. so please let me know about them.
  • For any legal issues it is best to use my email address to contact me, the address is in every source code file near the top, and near the bottom of this page in the License section.
  • To make the eSpeak text to speech module available it is necessary to install eSpeak.

About ompiling your own version

  • Download the sources, NOTE: this is not always the most recent one ( I'll update sources on request though – and after every so many executable releases). This code, source and executable, is released under the GNU General Public License version 2 – see the license section.
  • You will need Delphi to compile this code (I used XE10), and :
  • You will also need the overbyte ICS package to be present in Delphi.
  • No longer needed for versions after 2020.5.30.0 :: You will also need the Wave Audio package to be present in the project. This package needs not be installed, it being in the search path will do.
  • Then before Wren can be compiled my knobs2013 components must be installed (these are included in the source release as a separate zip file). I used Delphi XE10 to make this code.
    To compile the components into Delphi you need to compile the design time package and then install that one. This is the Knobs2013Design package.

    You'll also want the path to the components to be in your Delphi search path, or the Wren compile will fail.

    Note: After I've made a split into run-time and design-time packages to allow for 64 bit compiliation this will change for versions after 2020.5.30.0 into KnobsPackageDesign which must be compiled for both 32 and 64 bits. You will also need to compile the runtime package KnobssPackageRunTime for both 32 and 64 bits.

Frequently Asked Questions

  • Installation
There is no automatic installationjust a couple of things to do (which makes for a portable installation, and it could be on … say … a thumbdrive):
  • Make a Wren folder somewhere on your hard disk (best to do that in a non µsoft owned folder, so best not in 'Program Files', 'downloads', 'my documents' and not on the desktop either) and unzip the contents of the all-in-one zip file to there. You are now ready to run Wren from that folder.

    For example, create a folder "C:\wren" and copy the contents of the zip file into that folder. Then execute Wren.exe from that folder.
  • On a first start of a new version the program will write out some help files. This may look a bit messy, it will only happen once when a new Wren version is run for the first time (and it can be disabled if wanted).
  • On the first Wren run you should set up the audio devices. This can be done from the main menu: setup/Audio devices.
  • For a quick test you could drag in an oscillator module (Osc) and an output module (AudioOut). You can use Ctrl+F to find these modules quickly (they are on the first (I/O, pick the speaker symbol there) and second (Osc1, pick the leftmost sine symbol there) selector tab respectively).

    Turn down your volume a bit, as this may be loud otherwise.

    Then connect the Osc's output at the bottom right corner to the AudioOut L 1 R inputs.

    Next hit F9, you should have sound now and the output level meter in strip 1 on the right side of the screen should indicate this. Hitting F9, again will stop the sound.
  • It will not run …
  • When an ASIO device is being used things may not work when the ASIO sample rate differs from the Wren sample rate. Check the Settings Screen F3 for this.
  • Had a user report that the program would not run in Windows 7. Turned out his antivirus was blocking it as an unsigned program that was downloaded from the web … with a message saying 'Windows cannot access the specified device, path or file you may not have the appropriate permission'.
    Please fix such issues in your AV software.
  • Had another user report repeatedly popped up access violations. It seems that this can be caused by the PortAudio DLL (or Wren's interaction with it most likely). You can read more about this on an electro-music.com forum thread.
  • When the startup screen appears and disappears again and Wren does not start try to temporarily rename the espeak_sapi.dll to _espeak_sapi.dll, when that helps I'd like to know about it, please send me the Wren.log file then (it is in the Wren folder you did create in the Installation section above).
  • On some computers it was reported that when an audio input was selected PortAudio refused to work (reporting an error on opening the input stream). For Wren releases after 2020.6.24.0 it is possible to explicitely select <nothing<> for the device, this may help.
  • From time to time I'm discovering exciting new bugs, so please let me know about any failures.
  • Stuttering audio
  • When NOT using ASIO, in the device selector (main menu: setup/Audio devices ) use a buffer size like 2048. You can set a buffer size of zero, in which case the PortAudio DLL will decide on a buffer size.
  • When using ASIO the buffer size setting is ignored, and the size recommended by the ASIO driver is being used instead. So for ASIO you will need to set the buffer size from the ASIO control panel (and should set the buffer size in Wren to 0).
  • There may also be a bug in one of the modules causing it to produce denormal values, which will considerably slow down the DSP calculations (as shown in the DSP usage indicator). There is a diagnostic tool to find out about this, in the Debug Screen F5 you can turn on automatic denormal searching. Any modules getting or producing denormals will then be highlighted in the editor. Please report any such issues along along with the patch causing the problems.

    Note: this can not be an issue for the 64 bit version.
  • Your patch may be too complex, have a look at the CPU percentage next to the module selector, at around 80% things can become critical, enlarging the buffer size may help, lowering the Sample rate and/or enlarging the Control decimation in the Settings Screen F3 may help.
  • The 64 bit version performs way better than the 32 bit version, so use that one if possible.
  • There is no sound
  • you will need to select a sound output device from the setup/Audio devices main menu.
  • You will need an output module in the patch to route the patch signals to.
  • Mute may be on, in which case there will be a flashing yellow sign in the top pane indicating this. Use the Action menu to toggle this. The Action menu will also show the current keyboard shortcut for this.
  • When modules are added or wires are changed, nothing happens.
Manual compilation mode may be on, in which case there will be a a flashing white or yellow indicator in the top pane. Use the Action menu to turn manual compilation off. The Action menu will also show the keyboard shortcuts for this.
  • The sound quality is not very good
Try setting the sample rate higher. Out of the box Wren used to run at a sample rate of 44.1 kHz, setting it to 88.2 kHz or 96 kHz makes it sound a lot better.

As of version 2015.9.10.0 I've made the default sample rate to be 88.2 kHz, but when you have an earlier install the existing INI file may still set the sample rate to a lower value. So, please check the Settings Screen F3.

In versions 2019.11.12.0 there was a bug where some audio rate (red) wires might turn blue (control rate). When this is the case redrawing these wires will help. This should not happen anymore in any later versions.

When this does not help please let me know about the issue. along with the badly performing patch.
  • What is the display mess (when I first start a new release)
At startup Wren checks to see if the help information is up to date. When not it will generate new help info, and for some reason in order to generate the images right the images have to be made actually visible on the screen … which looks a bit odd … but it will be only once for each new release.

When you see this on every startup it may be the case that there is no write access allowed to the folder where Wren resides. It's best to not have Wren in a windows owned folder (like 'Program Files', for instance) as such may cause disallowed write access.

I've made an option to disable automatic doc file generation. This option is off by default (so docs will be generated out of the box), and this feature will only work when you use the old wren.ini file, e.g. when you copy the new executable over the old one (or copy the old ini file to the new location). You can always manually generate documentation from the Settings Screen F3 by using the 'generate documentation ...' button there. Note however that when no docs were generated the popups from the module selector will not show a module image, or an old version of the image.
  • General troubleshooting
Try to see the Debug Screen F5, Wren logs some information there. When you right click on it you can highlight the text, and then with another right click copy it. At times I will ask for the information present there to help troubleshoot issues. By default this information is written to a log file in the Wren application directory as well, look for wren.log.
  • Module help
All modules have some built in documentation, you can use F1 on a selected module to see it. When doing for this the first time (or after a program upgrade) the program may have to regenerate the help files, causing some display clutter. The information will be shown in your default web browser.

Right click on a module and select Help from the popup menu, this will show the same description as the generated help file without opening a browser.

Also when you hover over the module selector with the mouse, popups will be shown with some even more compact information along with an image of the module.

The generated help information is also used as a cache for module images to make them look a bit nicer when you hover the mouse over the buttons in the module selector.
  • Can I hear it?
I'll often have a live stream going with at least a large part of the sounds being made by Wren. This usually will be some self playing patch(es), but you may catch me in live bug finding too, YMMV …
  • Can I see it?
There are some third party made basic instruction videos availble on youtube and some more can be seen on the isolator channel
  • Are there any patches available?
I've put up a lot of my Wren patches on my website. Some will need additional (mostly wave) files though to play properly.
  • Where is my patch
Hit F2 to return to the patch editor.
  • Where does that wire go
Click and hold on a connector, the whole connected wire net will be highlighted.
  • I can not read the display values, it's all covered by wires
Use Ctrl+space bar to wiggle the wires, the value might become readable then. Otherwise hover the mouse over the knob controlling the display. Not all controls have a value showing popup yet, but working on that. Alternatively, set the wire size to zero to hide all wires (this is the up/down control in the top pane, labeled with 'wires'). It is also possible to temporarily hide the wires using Ctrl+W, press Ctrl+W again to make them visible again.
  • The wires are not visible in the editor
The wire thickness may have been set to zero, in the editor top pane under 'wires' you can change this with the up/down control. It may also be that the wires were set to be invisible, use Ctrl+W to toggle wire visibility. For me running Wren under Wine on OSX 10.10.3 (Yosemite) showed some issues with wire painting, I have no cure for that.
  • There is a reverb in my patch, but where is it?
Use Ctrl+F to find modules in the patch by name, partial matches will be highlighted as well. For instance, search for 'verb' to find all modules having that bit of text in their title. Found modules will light up their title bar. This feature can be enabled from the Settings Screen F3. Clear the search box by pressing the Esc key.
  • There should be a module with a name like verb, but on what selector page is it?
Use Ctrl+F to find modules in the module selector by name. All modules not found will be hidden, and all pages that become empty this way will be hidden as well. To show all modules again clear the search box. This feature can be enabled from the Settings Screen F3. Clear the search box by pressing the Esc key.
  • Polyphony
Wren is a monophonic synth. Still you can of course have multiple sounds or even multiple synths by patching them. The MIDI interface will need to work on a different channel though for each voice added this way, as it can handle only one note at a time. I've added a four channel MIDI input module to allow for manual patching of a fourfold poly synth.

As of version 2020.8.6.0 Wren is polyphonic and multi timbral.
  • Inputs and outputs
Inputs are round, outputs are square. The color indicates the signal type where red is an audio rate signal and blue is a control rate signal. Yellow indicates a logic level signal, usually -1 or +1 but there are exceptions where the values are 0 or 1. Lime (bright green) indicates a control rate logic signal. You can freely mix all signal types, the color is just a hint, although a Blue or Lime input will not see all samples of a Red or Yellow type signal (often this will not matter). Some modules are rate smart, they will adjust their calculation rate from control rate to audio rate when an audio rate signal gets connected to one of it's inputs.
  • How to add wires
Click and hold on a connector and then drag to another connector, then release the mouse button. You can connect inputs to inputs and inputs to an output. It is not possible to connect an input to multiple outputs, and it is not possible to connect an output to an output. It is not necessary to connect each input to an output separately, you can make a chain connection from input to input … to output. When a connection chain is not connected to an output it will have a highlight color to indicate this, otherwise it will have the color of the output it is connected to (the color can be changed from the connector popup menu).
  • How to (re)move wires
By using Ctrl+normal mouse click, drag the cable to another connector to reconnect it, or into the void (anywhere but on another connector) to make it go away. There also is a connector context menu (accessible with a right moue click) with some options for wire removal.
  • How to change parameters
  • Knobs – it depends on the mode you have set in the Settings Screen F3
    • circular – a mouse drag around he knob changes it.
    • horizontal – a horizontal mouse drag changes it.
    • vertical – a vertical mouse drag changes it.
    Additionally when a knob is active, that is when it's up/down clickers are visible (and it has a red (or fuchsia) border as well then), you can click on the up or down clicker, or use the cursor up / down keys. A knob can be made active by positioning the mouse cursor over it or by tabbing to it.
    You can also enable the mouse wheel on knobs in the Settings Screen F3.
    There is another knob variant that has no knob but only the up / down clickers, this type will listen to the arrow keys when selected (and to the mouse wheel as well, when that was enabled).
  • Sliders – these can be either horizontal or vertical and will behave as if they were knobs, but the mouse drag mode is restricted to horizontal or vertical only. They will respond to the mouse wheel too, when the mouse wheel option was enabled.
  • Selectors – these look like displays, but have a yellow border. You can click on a selector to get to the next value, or right click on them to get a popup menu to select a value from. Selectors also can get focus by positioning the mouse over them, when they have focus to the up/down arrow keys can be used as well to change the values.

    Some selectors act as momentary switches, or buttons, these will have a white border.
When wheel mode is used just hover over the knob and wheel the wheel. Moving the mouse over a knob will set it to be focused, and once a knob is focused the keyboard up/down arrows can be used to change it's values too. A knob can also be selected by tabbing to it. There are also vertical (and horizontal) sliders those will only support the vertical (horizontal) move mode (along with the mouse wheel mode, when enabled). Selectors will also receive focus when the mouse is moved over them.
  • right mouse clicks
  • On a knob – set default value or lock / unlock the knob (a locked knob will not listen to mouse control changes).
  • On a connector – break a connection ‐ there are some options to select from.
  • On a module – Cut copy or delete it, or change its border color etc.
  • On a selector – selectors have a yellow or a white border, you can right click to get a popup menu for selecting a value.
  • On a graph – some preset curves can be selected, a couple of symmetry options are available and the graph can be saved to or loaded from a file.
  • On the editor background – module options, like copy paste, module insertion.
  • Change module caption
Double click on the module caption, an editor pops up then. When done hit Enter to commit the changes or Esc to discard them. A changed module caption when moved over by the mouse will still show the module's type. When the first character of the module title is '@' the module is enabled for receiving OSC messages.
  • How to edit text based controls
Ctrl+left click on it, or tab to it (or click on it) and use the Enter key. This can also be done by right clicking on it and then select Edit from the popu menu. To close the editor use Ctrl+Enter. Module titles and single line editors just use Enter.
  • How to close a text editor
Use Ctrl+Enter to save the changes, or Esc to discard them. You can also click outside the editor to make it go away (and discard changes). Single line editors can be closed with just Enter as well.
  • How to use presets for modules
When you right click on a single module, or on a collection of selected modules you will see an option to save or load the selection as a preset. The control values will be saved to or read from a file then.
  • MIDI setup
  • Trough the main menu item settings/MIDI devices select the MIDI devices to be used for input and output.
  • In the Settings Screen F3 select the MIDI Channel to use and select the (N)RPN preferred seting.
  • NetMIDI setup [obsolete]
[obsolete] Run NetMIDI and Add a server there. In the newly created server tab fill out a couple of details :
  • You can type a name for the connection (this is not a formal thing, just a reminder for yourself).
  • Type a TCP/IP port number, Wren by default uses port 31415, but you can select something else if you wish. This is pretty arbitrary, except that the port number should not be in use by any other running programs – you'll get a conflict message later on when you try to do that.
  • Select some physical MIDI ports from the drop down lists on the right. You need not select both an input and output port when you do not need both.
  • Tick both checkboxes 'Auto start on load' and 'Disable Nagle'.
  • Start the server, Windows may now popup a dialog asking you to allow NetMIDI to open a server port, say yes to that.
  • Windows may complain that the port is in use already, in that case you'll need to provide some other port number.
  • You can check if the MIDI ports work by looking at the lights.
Next you'll want to setup a NetMIDI connection for Wren, you can do that from the Settings Screen F3. Under 'netmidi / midi tangle settings' do the following :
  • When NetMIDI runs on the same computer as Wren enter localhost as the server (or 127.0.0.1). When the programs do not run on the same computer you will need to enter the computer name of the remote computer where NetMIDI runs – or it's IP address.
  • Enter the port number that you filled in for NetMIDI.
  • Click Apply.
  • Click Connect. A client entry should appear in NetMIDI in the unlabeled box left of the lights there. Also in Wren the small 'c' light should light up (in both the Settings Screen F3 and the metering panel).
  • The two extra lights in Wren 'r' and 't' indicate reception and transmission respectively.
  • When you check 'auto connect' in Wren it will try to establish a NetMIDI connection automatically after startup, and it will connect as soon as NetMIDI runs.
  • OSC setup
Each Wren instance can either be an OSC transmitter (client) or an OSC receiver (server), but not both at the same time. The client / server indications are official OSC terms.

There can be multiple listeners (servers) on one computer, but you can have one transmitter (client) only on any single computer (but you could have more transmitters (clients) spread over multiple computers).

When everything is set up correctly the Wren instance should be able to talk to or listen to any OSC enabled device (or software) present on your network (or computer). It is not possible to broadcast OSC messages out of your local network. With the proper holes set in routers etc. it should still be possible to set up a single transmitter (client) to receiver (server) link though.

To set up Wren as an OSC transmitter (client) do the following:
  • In the Settings Screen F3 make sure you give your synth a name, this name will be used as part of the OSC addresses sent around.
  • Then go trough the main menu to the Setup / OSC setup screen for the following settings:
  • The IP address must be set to a broadcasting address to allow for multiple receivers, otherwise the IP address of the single receiver can be used. The address to use depends on your network configuration but selecting 255.255.255.255 should always work. Locally I use 192.168.1.255 as the address which will reach all computers in the address range 192.168.1.x. When everything is on one computer using 127.0.0.1 or localhost works too.
  • The port must be set to a number not in use for any of the participating computers. When you select a port that is in use you will not be able to transmit a test message later on, and OSC errors will be reported in the log (OSC error logging is on by default, OSC message logging is off by default).
  • Check the Use OSC checkbox, then hit OK.
  • Reopen the OSC settings screen and then send test messages using the button, the 't' light should light up on each transmission. When it does not light up you probably selected a port that was already in use, so try another one.
To set up Wren as an OSC receiver (server) do the following:
  • In the Settings Screen F3 make sure you give your synth a name, this name will be used as part of the OSC addresses sent around.
  • Then go trough the main menu to the Setup / OSC setup screen for the following settings:
  • The IP address must be set empty (internally 0.0.0.0 will be used in this case, but the field being empty will open the UDP socket as a listening (server) socket, filling in anything at all will try to open it as a client socket, so make sure that the field is completely empty). When OSC is set up to be a receiver no test messages can be sent from it, and the button do do so will be disabled when the IP addr field is (completely) empty.
  • The port must be set to the same value that was used to set up the transmitter.
  • Check the Use OSC checkbox, then hit OK.
  • Send test messages from the transmitter, the 't' light on the transmitter and the 'r' light on the receiver should both light up on each button click. When they do not light up you probably selected a port that was already in use, so try another one. The test button is only available on the transmitting side.
The test button sends a single OSC message to the address /*/testmessage with a float value of 1.000 an integer value of 1001, and a string value of '1002'.

There is no OSC connect light as OSC is used over UDP, a connectionless protocol, so there is no concept of connection but only of transmitted and received packages of data. There is a light indicating OSC to be active though, the 'a' light (in the I/O control section on the right side of the screen).

The OSC listener (server) implementation used does not send replies to to the transmitter (client).

The lower level protocol used to transmit the OSC messages is UDP. UDP messages are not guaranteed to be received in the same order as they were sent, or in fact not guaranteed to be received or sent at all. Usually it will work, but on a busy network packets may get lost. Also it is possible to send OSC messages faster than the network can get them out, in that case not all messages will be sent.
  • What OSC functionality was implemented
OSC time stamps are not supported, bundled messages can be received but are not processed currently. Bundles are not transmitted currently. All message handling is immediate.

Note that each address can be used only once in a patch, when it occurs multiple times an arbitrary OSC handler will handle it and the other handlers will think it to be handled after that. You can have multiple transmitters using the same address though.

The following addresses are currently being used:
  • /*/testmessage can be sent (from an OSC transmitter only), this is a single OSC message with a float value of 1.000 an integer value of 1001, and a string value of '1002'.
  • /<synthname>/sync can be sent and received by the Sync module. This message has no parameters. The message is received when the current Wren instance is set to be an OSC receiver. the message is transmitted when the current Wren instance is set to be an OSC transmitter. Sync messages are naive, they assume zero time delay between transmitter and receiver.
  • /<synthname>/<user_defined> for the OscMessage module, this will send or receive a single float message. Messages with a matching address with more than one parameter can still be processed as long as the first one is of type 'f' (float). To force a value to be sent out the trigger input needs a low to high transition ‐ you could put an LFO on that, or make a change detector based upon a sample and hold, or use the differentiator module.
  • All modules can receive OSC messages when the module title is set to start with an '@' character. They then can be addressed with a /<synthname>/<modulename_without_@>/<control_name> pattern. The first value in the message must be of type 'f' (float) with a value from zero to one, with zero mapping to the lowest possible knob value and one mapping to it's highest possible value.
  • How to get Wren to play with JACK
What I did:
  • Installed JACK, I've used the mixed 64/32 bit version.
  • Followed the 'Installation and Configuration' section from http://jackaudio.org/faq/jack_on_windows.html
  • Set JACK to run at the same sample rate as that I run Wren on, this seems to be needed or Wren will not open the JackRouter connections (so sample rate conversions seem not to be possible).
  • Started Wren, and then from Setup/Audio Devices (in Wren) selected the ASIO API, and then for both the Input and Output devices I selected JackRouter. Note that this means means that you'll have to use the Port Audio interface.
  • Then for the 'In channels' I selected all four that were present and for the 'Out channels' likewise. The number of channels is configurable for JACK, four being the default. Wren only supports 8 channels, but these should be selectable arbitrarily from the JACK set.
With this I was able to get audio out of Wren into JACK and out of JACK into Wren .. and it looks like I get an exact copy of what I send in channels 1 and 2 back in the inputs 1 and 2.

NOTE: Wren has no native JACK support … of course … I'll look into that, but it will be a long term project ‐ the C header files will need to be ported to Delphi.

NOTE: To see some error reporting in Wren you can try the Debug Screen F5, it may show a reason for not being able to connect to JACK.

NOTE: This will allow for audio integration with your DAW, assuming that the DAW uses ASIO.
  • Using module colors
In the Settings Screen F3 you can set a default color and an opacity value. The opacity value determines the saturation of the module colors. In the patch editor you can select the modules to be colored, then right click on any of the selected modules and select the color option from the popup menu.
It is also possible to use the module standard colors, both for new modules added and from the module popup menu.
Module colors will be saved with the patch.
  • Using wire colors
Wire colors can be changed by right clicking on a connector and then selecting one of the color options from the popup menu.
Wire colors will be saved with the patch.
  • What are the modifiers which can be used on values.
NOTE: this does not work properly.

(blank) nothing
mHz (milli Hertz) aValue = FrequencyToUnits( aValue / 1000)
Hz aValue = FrequencyToUnits( aValue)
kHz aValue = FrequencyToUnits( 1000 * aValue)
bpm aValue = FrequencyToUnits( aValue / 60.0)
degrees or deg aValue = aValue / 360
radians or rad aValue = aValue / ( PI * 2)
percent or % aValue = aValue / 100
ms aValue = aValue / 1000
s nothing
nn aValue = NoteNumberToUnits( aValue)
qsteps or q aValue = aValue / 1000
ct (cents) aValue = aValue / 256
other modifiers will fail

Also in a context where unit modifiers can be used note names may be used, e.g. A0, A0# etc. but note that only sharps can be used, there is no notation for flats. The general notation is N[#][-]n where the bracketed items indicate options, N is a base name and can be AG, # indicates a sharp and [-]n is a numerical octave shift. Note name A4 maps to note number 69 which in turn maps to 440 Hz. The mapping to 440 Hz can be changed in the program options. [Note: Note names do not work yet (except in sequencers – where the feature can not be turned off yet), a couple of headache things there still.]
  • What internal scaling is being used
The mHz, Hz and kHz modifiers use a scaling of 1/128 units per semitone (unless the default scaling was changed), units can be negative values for low frequencies. The nn modifier uses a scaling of 1 per semitone, note numbers can be negative or fractional just like frequencies can be. By default note number 69 (A4) maps to 0 units and there are 12 notes in an octave but this can all be changed by the user. A cent is a fixed interval of 21/1200, it does not scale with the note number mapping (or actually it may, but that needs to be fixed then, please let me know where it hurts).
  • Graphs mode
To use the Graphs mode it needs to be enabled first, this can be done from the Settings Screen F3 in the debug section. Having the graphs disabled may save some memory resources.

When graphs are enabled F4 will bring you to the graphs screen. This can be useful to help understand signals in a patch.

Graphs mode is not a real time mode, so you will need to stop audio generation F9 or it will not work.

The graphs mode output will show output for all eight channels, so you can connect up to eight signals to be graphed simply to an output module. It can be handy to have a mixer before the output module to to trim the levels.

Before generating graphs audio must be stopped and then the 'Debug step' and 'Debug run' will draw the signals present at the output module. When audio is running the debug mode can not be accessed.
  • 'Debug reset' will clear the graph, and it will issue a patch reset.
  • To just clear the graphs use the 'Clear graphs' button.
  • While a debug session runs the reset button F7 will work too, this will reset the patch without clearing the graphs.
As graphing gets pretty slow when a lot of points are present the graphs will be auto cleared when some arbitrary (large) number of points is in the graphs.

You can zoom in on the graphs by dragging out a view area with the right mouse button from top left to bottom right (the reversed drag direction from bottom right to top left will zoom out to full view).

Panning uses a left mouse button drag (this is slow when some data is present). Reversed right mouse button drags will cancel pans as well.

When zoomed in or panned a graphs clear will not cancel zoom or pan, you may want to do that manually to get an image again.
  • The patch randomizer / mutator, what does it do?
The randomizer is just that, it randomizes controls. This can be done for a single conrol (from it's context popup menu), for a single module (from it's context popup menu) or for a group of modules (from the module context popup menu, or from the action menu). The amount of random can be set from the randomizer / mutator window. Low values will leave the patch more as-is than high values.

The mutator implements a primitive genetics tool. The idea is that the parameters of the patch form a genome. This genome can be altered by the mutator in a sexual and in some asexual ways.

The graphic images are a visual interpretation of the parameters present in the patch. Every parameter is represented by an angle, and then a line is drawn under that angle to the next parameter ‐ which forms the worms. Worms are then scaled to fit the cage they are in.

Asexual reproduction can be plain random … which does not really reproduce anything (as all information is lost), or a mutation (which does keep some information and looses some as well). Mutations can be controlled with a probability and a range. The probability sets the chance that a a change occurs, and the range determines how much of a change can occur.

Sexual reproduction picks parts of one genome and parts of another and makes a mix of that. The crossover probability determines how often a parameter pick switch is made from the first to the second 'parent'. Also in sexual reproduction there is some mutation involved.

In the randomizer window the parents are in the breeder bit, the leftmost one being one parent and the rightmost one the other.

The mutate button just mutates the existing worms between the left and the right parent. The randomize button sets random genomes for the same six and the mate button performs the sexual thing with both parents leading to a a sixling … erm … if that is a word.

And then you can drag around stuff, like drag a worm onto the patch worm to make the patch have the dropped params. Or drop something on the left morph and something else on the right one, and then you can do a live morph between those.

The scratch area is just that ‐ drag stuff there for later use in one of the active squares.

Clicking on a worm will copy it to the patch, this happens for the morph and scratch things in the same way … but you can also drag worms to the patch square.

Then when you have a left and a right morph the live morph control can fade between the two. This can also be automated by using a LiveMorph module in the patch, with a checkbox to enable or disable the function, this function is disabled at program startup ‐ to avoid possibly confusing things to happen in a patch.

… when done recursively … that is, pick a nice genome for one parent and another nice one for the other … and breed and repeat … you can do some manual eugenics on patches. And the scratch area can hold a smallish population. Oh and you can kill too of course ‐ that's what the eraser is for ‐ drag drop the eraser on a worm and it ceases to exist (which can be done on the scratch area only). Nice in this case meaning that you like the sound.

For both the randomizer and the mutator exclusions can be set. Some exclusions are set by the system for parameters that would make no sense to be randomized, or which would need patch recompilation when changed. Others can be user enabled or disabled, all from the context menu popup.

Excluded ccontrols and modules will get a red border in the exclusion visibility mode (this can be turned on or off from the action menu). When the randomizer / mutator window is visible (view menu) this mode will be on as well.

There are a couple of keyboard commands to ‐ those are listed in the Action and View menus.

The Wren forum thread may have some info not listed here.

Feature requests

  • ? : Abstractions … as I understood it 'patch as a module', hiding implementation details.
  • Convolution with samples.
  • Stream I/O … like shoutcast probably, but that would mean messing with mp3 coding (e.g Lame).
  • Random wave from some directory … a trigger for selection I guess, or an index input rather.
  • pre computed bandlimited PCM oscillator.
  • 2014-12-05 : Z input on scope.
  • 2014-12-13 : Soft clipping for resonator.
  • 2015-06-19 : Markov chain sequencer (note: the Poetry module is based on a hidden Markov like model internally).
  • 2015-08-28 : True FM on pitch shifter. The modulation now ranges over -24 ‐ +24 semitones.
  • 2015-09-30 : Perceptron, see http://electro-music.com/forum/viewtopic.php?p=413579 for more info on this.
  • 2016-02-04 : Gabe had an idea for an FFT based envelope generator … or more accurate envelope parameters for a handful of frequency bands .. like when you feed it noise but you'd want the highs to decay faster than the lows you could bring down the high frequency fader … something like that. It was illustrated with this image.
  • 2016-04-29 : Nord like drum module(s).
  • 2016-07-05 : VST 32/64 support … had been requested a couple of times … maybe some day I'll dive into that … not using any plugin stuff myself currently though.
  • 2016-07-27 : Celestial bodies? A time module could give like current ms, s, m, h or fraction of day, etc. Could do moon as well ‐ there is some celestial stuff in the Chatty / Hellbo / Zombo code.
  • 2016-09-26 : Implement stuff from the Synthesis Tool Kit …
  • 2017-12-24 : In KS modules fade around the loop filter, as in fade between loop flter in and loop filter out.
  • 2017-12-24 : In SwanSong module add a background and let the swans output color info in addition to X and Y info. Color info as R G B.

Known Issues

  • 2014-04-01 : Setting values from displays associated with knobs does not work. It does seem to work for oscillator frequencies and cents settings though, and for linear LFO frequencies.
  • 2015-09-13 : the unit system is not properly unified .. when I type 0.2 Hz for an audio oscillator it gives me a period time of 5 s alright, but entering 5 s for the value just does not work. Could easily change this, but then typing 5 s for an envelope time would not work .. will need to rethink some stuff there.
  • Wine does not work properly.
  • 2020-01-08: There still seems to be an issue with scales and changing patches or copying stuff over. Will have to look into that at some later stage, it is a tad annoying but nothing is broken really.

Found / fixed issues ~ Changes ~ New modules

Currently working on

  • 2020-10-17 : nothing yet ...

in version 2020.10.17.0

  • 2020-09-11 : Added cents modulation to a couple of oscillator modules (Osc, MultiOsc and MultiPhaseOsc), maybe nice to add a little drift to them when used in poly mode (with connecting an LFO in random walk mode or something).
  • 2020-09-15 : I've added a new range for the Tapper, MidiClockIn and RateConverterr modules, they are now able to control the new 1 minute delay time (DEL long 1:00, for controlling that range on the DelayPoly module). This may break existing patches in that the range after loading an old patch may not be what was set when the patch was saved. So you'll want to check your settings for these three module types.
  • 2020-09-17 : Changed the BPM detection for the MidiClockIn module to react a bit less nervously. This makes the output signals better suitable to control long delay loops. BPM values are now updated only when a sync occurs. Also made the indicated value for the BPM rate indicator to show the filtered value instead of the raw detected value. It behaves reasonable now for a drum loop of over half a minute, it was pretty glitchy for loops of such a length before.
  • 2020-09-17 : Fixed a bug in the FreqCount module, the channel selection was not working properly.
  • Timer - A timer 2020-09-17 : Added a new module type, a timer. This one just displays how long the the run input has been active. The mode can be set such that on every time the run input goes active timing will either continue from where it was (incr. mode) or it will be be reset to zero (once mode). It will display the run time as hours:minutes:seconds.milliseconds (and it will overflow and start at zero again if a day boundary is past).

    Added a couple of outputs to be able to do something with the measured time interval. Output d for fraction of the day, h for fraction of hour, m for fraction of minute and s for fraction of second, all make positive saw waves with a range [0.0, 1.0].
  • 2020-09-23 : Sped up the MovingAverage module, it was silly slow.
  • 2020-09-24 : Added Q modulation to the TritoneBank and ThirdBank modules.
  • 2020-09-27 : Added input type control to the StereoPan module, such that it works the same way as the (mono) Pan module.
  • 2020-09-30 : Added a counter display to the Divider module, to be able to see the current internal state of it. For slowly counting counters this is handy to get an idea about how long it will take before the output flips. In my current patch this will be hours … right 256 * 256 * 7 minutes, and although the triggering input is random, it is good to know about … ow … that's a bit over 318 days, damn, better shorten things a bit!
  • 2020-10-04 : I've change the way poly to mono signal conversion is treated. It used to calculate the sum and then divide by the polyphony. but this made patches to be too soft often. So I decided to divide by the square root of the polyphony instead. This will make the sum of signal paths having identical signals too loud, but also it will make that sum less too soft in cas the signals are uncorrelated. I might end up eventually by not dividing at all … even … you just can not do this right …

    Ok, bad idea as it gives issues with feedback loops, undid it, attenuation is back to what it was, and it will still be needed to have some end stage amplification (or compression) on polyphonic patches to get the levels right.
  • 2020-10-04 : I've made a MonoOverride option for modules to allow modules in a polyphonic patch to be forced to execute in mono mode. This will cause the module to listen to channel 1 only and also it will output on channel 1 only (but maybe the latter will be changed such that it will output on all channels … not sure here). the override to mono can be set from the module popup menu, monofied modules will show with a distinctive (currently white) border.

    modules with mono indicated Okay, changed it so that the ouput will be sent to all channels and not just to the first one.

    Also added a distinctive (currently yellow) border for modules that are intrinsically monophonic. These can still be set to mono mode BTW, in which case their will change in that they do not process an input sum over all polyphony channels, but instead will just use channel 1 on it's own (and their border will go (currently) white in that case.

    Updated the patch layout version to 12 for this while maintainng backwards compatibility.
  • 2020-10-05 : Added a light cross hatch on mono modules to better indicate their status, and removed the border while keeping the colors yellow and white … see image above … hmm, the color mixing for 'lighting up' the hatch could be improved upon, for now I've just changed yellow to lime green.

    That didn't work too well either for me, sooooo, instead I made both white but did a cross hatch for intrinsically mono and a diagonal cross hatch for overriden to mono modules. So, for isnstance, in the image above the Compressor is intrinsically mono, and the Limiter, Volume and AudioOut modules are explicitly monofied, and the two mixers are 'regular polyphonic' modules.

    I guess, as it makes no sense for Limiter, Volume and AudioOut to be poly afrter an intrinsically mono module (the Compressor), this could be automated. That will be for a later date tho, if at all.

    Not always it will be the case that an intrinsically monophonic module will be followed by mono paths only. For instance the regular Delay, or the Reverb module have modulation inputs which can result in polyphonic output behaviour … so automation will need some thought.

    Overall, I do like these changes. It used to be that some extra patching was needed to make parts of the patch mono (by using PolySelect modules here and there) which can now be done by monofication of modules. This both saves some cycles and I just don't want all parts of the patch to be poly all the time.

    When another voice than voice 1 is wanted for a mono section one could still insert a PolyShift module before a monofied section.

    Possible alternatives would have been to use the concept of 'poly cables' (as VCV uses them) or to use abstractions set to a different polyphony than the main patch (as an extension to the 'effects area' idea as used in the NM G2). But I guess I'll just keep what I currently have.
  • 2020-10-06 : Made the visual feedback on mono modules depend on the selected polyphony, it will not be shown for patches with polyphony set to 1. Also made it optional in the Settings Screen F3 to be turned off completely.
  • 2020-10-06 : Another way to look at it it is that an intrinsical mono module is a summing module, in that it sums it's mono input signals over all poly channels (but this may not be true for all of it's inputs, for instance the standard delay modules will sum the incoming audio, but each voice will still have it's own uniquely modulatable tap). Whereas a monofied module is a selecting module, it only processes signals from the first poly channel (and that holds for all of it's inputs).

    So a summing (intrinsically) mono module may still have a polyphonic output, depending on the control signals being polyphonic or not. A monofied module will always have a monofied output as it will only look at signals in the first poly channel (but it will still output into (but identical for) all poly channels of a receiving module).
  • 2020-10-07 : Fixed a bug in the MovingAverage module where filter size changes would make it behave badly (had to clear the filter state). And also the old–data pointer was one off, resulting in incorrect filtering and integrating behaviour. This bug was introduced by the speedup implemented before.
  • 2020-10-12 : Built a simple limiter into the Compressor module (as I always ended up adding one manually), it acts in the same way as the Limiter module, so it is not parameterized, but it can be turned on or off. Limiting, when active, acts upon the Side, L and R outputs (after compression and not in bypass mode, bypass mode always couples the inputs to the outputs directly).
  • 2020-10-14 : For some reason in the Settings Screen F3 the sample rate selector got mislabeled as 'midi delay', fixed this.
  • 2020-10-14 : Added a sample and hold input to the RandSigs module. When it is not connected it does nothing, when it is connected a low to high logic transition on it will copy the internal output state to the actual outputs, and otherwise it will hold the latest output value. This can be used to sync the change of the random values to some external event. When not connected the module behaves like it always did with continues output changes. [UNTESTED as of yet].
  • 2020-10-17 : Added manual BPM control to the MidiClickIn module. This serves two purposes, being a) to be able to set a BPM value manually in case a MIDI clock is not available and b) to remember the latest BPM value in a saved patch, such that when on patch load a MIDI clock is not availble the module will use the BPM value the patch was saved with.

    When an incoming MIDI clock is being detected this will override the manual setting. Currently for some reason when the external MIDI clock is active hovering the mouse over the manual control will act a bit weird, but so be it for now … ok, fixed that too.

    Manual BPM settings can not be fractional, detected BPM rates howver generally will be. A BPM rate saved with a patch will be rounded to the nearest possible manual rate.
  • 2020-10-17 : I've removed all the 'smart' latency control stuff from the MIDI note in modules, it was not working properly. The only way to get it working okay is to have low enough audio latency (small enough audio buffers), all the fancying up is just crap. So anyway, a note is turned on and off like as quickly as possible now.

in version 2020.9.9.0

  • 2020-07-27 : Changed the internal representation of MIDI time to fractional seconds (instead of milli seconds) to have it the same as the synth timing. (Preparing for full MIDI event enqueuement, to be able to get the note-on and CC timing solid too, might also help to get clock sync better …).

    After some experimention I ended up not using an RX queue for now, to make it work properly it would be needed to also implement extra audio latency. The queue would be used to eliminate jitter on received MIDI, but when it is at the cost of added latency it is maybe better to accept some jitter and instead minimize that by selecting short audio queues (an audio queue of 512 frames at 48ks/s makes for a jitter of around 11 ms).
  • 2020-07-30 : The MIDI optimizations broke the handling of RPN data, as this was done by the MidiReceiver object (of class TMidiReceiver) which is no longer used. RpnMode is obeyed by the TX modules only now. Also MIDI RX logging is broken now, TX logging should still work.
  • 2020-07-30 : Started preparing for polyphony, upped the patch version to 11 and made the underlying system ready for propagating value sets over wires (instead of single values). The patch editor has a polyphony count, and so does the synhesizer module, now all the modules will need some work … and there will have to be some polyphony specific modules too.
  • 2020-08-03 : Made a good lot of the modules poly aware, skipping the hard ones a bit though. Now optimizing things a bit as the performance in mono mode is a bit disappointing sofar. Not unhappy though about the poly performance, going from mono to duophony does not double the CPU load, it just increases a bit. Well a bit more than a bit actually, but nothing like doubling.

    Implemented a couple of poly specific modules: PolySplit, PolyMerge, PolySum, PolySelect, PolyShift and PolyStatus – all doing some voice magic. The splitter takes off the voices from the poly bus routing them to individual outs, the merger does the reverse thing, bundling up individual inputs into voices. The PolySelect can select a voice from a bundle and output that on it's output. The PolyShift shifts voice positions in the bundle, voice one can be routed to voice two, and then two will go to three, and in a cyclic manner the highest voice number present is routed to voice one then, the amount of shift steps can be set with a knob. The PolyStatus just outputs the voice number on it's output, scaled from zero to one over the current polyphony, this can be used, for instance, to control a multiplexer which will then do some voice specific selection. Or control the wave shape of a shape modulatable oscillator, so voice one can be a sine, voice two a triangle, etc.

    But it is still a bit crashy at times, and for mono mode the overhead is quite large. The crashyness is related to the recorder module maybe, didn't really check it out, but didn's see it as of yet in patches not having a recorder module in it. Also didn't figure out the 'level issue' yet, a duophonic patch potentially is twice as loud an the mono version of it, but when the voices are independent it will, or can, be at almost the same level. Will probaly be left as an excercise for the user … to get the levels right, or maybe some square root based compensation magic on the final mix, or in all places where a voice mix is being made (like in reverb modules, but that's all a bit arbitrary still).

    I've hard limited the maximum voice count to 16.
  • PolySplit - A polyphonic voice splitter 2020-08-04 : Some notes about the implementation of polyphony. Most modules are completely polyphonic, some are monphonic and some are mixed mode modules.

    Fully polyphonic modules are either stateless (that is no memory of a previous sample set is being kept) or they have a separate internal state per voice. An PolyMerge - A polyphonic voice merger example of a stateless module is a mixer, mixers can be computed on a sample by sample base, they implement just a couple of multiplications and additions. A filter would be an example of a module having state, as the computation of the current sample depends on what samples it saw before. A fully polyphonic filter will keep that information on a per voice base, each voice has it's own memory.

    Monophonic modules are pretty simple too, if they have state it will be shared over all voices. An example of this is the Vocoder module. Monpphonic modules generally will, on their inputs, sum the incoming voices, then they proces that PolySum - A polyphonic voice summer sum as a single signal. Then the results will be distributed over all output voices equally. For clock inputs, for instance, this scheme makes no sense though, in such cases only the input from the first voice will be processed, the output will still be distributed over all voices. Note that polyphonic clocked modules, in contrast, treat the clock separately for each voice, so they will alwyas listen to all voices. Some examples of mono modules are the reverbs, not only would it be expensive, CPU wise, to make them fully polyphonic, it does not seem to make much sense either to have polyphonic reverb. Some more effects will be kept monophonic, like the compressor, where others, like pitch shifters, would be nice in poly mode.

    Then the mixed mode ones, these will have some shared state over the voices. For example the delay based modules may have a monophonic input, that is they listen PolySelect - A polyphonic voice selector to the sum of all voices. They wil then store that sum in a shared delay line, but the outputs can be polyphonic. each voice can have it's own delay modulation. Especially for the very long delays (like five minutes) it would be costly to have a delay line for each voice. I am considering some new fully polyphonic delays, but they will have short–ish delay lines, a couple of seconds, then, not minutes.

    PolyShift - A polyphonic voice shifter At times I have been too lazy to figure out the per voice state for modules, such modules may become polyphonic at some later stage. The MIDI modules for instance need work, their current implementation makes sense in a mono world only.

    I will label mixed mode modules as being polyphonic, for instance the Input module is labeled as poly, but there is no such thing as polyphonic input from a sound card. There are channels though, and those can be routed to separate voices if needed (by using some PolyMerge modules). The output module is mixed mode too, it will sum it's input voices before sending them to the sound card. The Recorder module behaves just like the Output module. The delay modules are labeled as poly as well, as explained in the mixed mode section above.

    All the 'simple' modules have been decided and implemented now as either poly or mono. There are still about 100 module types (of roughly 300) I still need to pay PolyStatus - A polyphonic status thingie attention to. Not only for the mono/poly issue, but poly modules need things to be reorganized a bit as well for optimization reasons, and I started with a non optimized rough version.

    Still, as long as I do not have a recorder module in the patch things seem stable sofar. Also patches with polyphony set to one need a bit more CPU time than in the monophonic program versions before, but I am pretty happy with the poly performance sofar.

    As there is more computation involved per module in poly mode, it may be needed to accept more audio latency, but will have to optimize better to be sure.

    Anyways, a couple of days more work will go into it easily.
  • 2020-08-07 : About 40 module type more polyphonized, still 60 or so undecided ones. Some are a real bitch to have them un-monoed … especially the filter banks took me lot of hours, but all filters are fully polyphonic now, including the voice like vowel filters. Next thing probably should be to change the MIDI modules, or come up with some new ones maybe, poly specific ones.
  • 2020-08-07 : I seem to have fixed the recorder bug, it probably was a bit crashy in the Wren release version too.
  • PolyMidiNoteIn - Polyphonic MIDI input module 2020-08-07 : Decided to add a polyphonic MIDI note in module and leave the old MIDI note in modules as as is (for compatibility with previous mono patches). The new module will set the 'max notes' value (as the Midi8NoteIn module has it) to be equal to the selected patch polyphony. Otherwise it should work exactly the same as the Midi8NoteIn module. With this module a patch can be made as if it were mono, and by upping the polyphony it will give more voices. For mono patches this may need a bit more CPU than in previous Wren versions, but with upped polyphony it will pay off.
  • 2020-08-07 : Polyfied MidiClockIn, Tapper and RateConverter modules. So there now is fully modulatable polyphonic MIDI and Tapper sync. Still 55 module types to consider, some will stay mono.
  • 2020-08-08 : I guess Wren now is a polyphonic multitimbral inter-voice cross-modulating virtual analog modular synthesizer … or something.
  • 2020-08-08 : All modules have had a look at, the following ones were kept monophonic for various reasons :
    AMuse, CellAut, CellAut2, ClockGen, ClockedDelay, ClockedSieve, Compressor, Convoder, Economy, eSpeakVoice, FlangeChorus, GVerb, GenePlayer, GrainDelay, Granulator, LifeSeq, Markov, Midi8NoteIn, MidiCCIn, MidiMultiNoteIn, MidiNoteIn, MidiPCOut MidiPNOut, MidiPlayer, MidiSysexOut, PitchChange, Reverb, RndGranulator, SeqPattern, SeqValues, Sieve, SimpleGranulator, SmallLifeSeq, Smear, Song, SwanSong, Talkie, TextWriter, VitaPHoBium, and Vocoder.

    Most mono modules will listen on the first voice only and will output equally over all voices. Some modules however will mix the incoming voices before processing, especially so for the FX modules. This may still need some fine‐tuning.
  • 2020-08-08 : So now the question is … is it any good … am I going to keep this?

    Anyway, doing some test runs now on mostl large old patches, finding some bugs here and there, and fixing those, but most stuff seems to still be runnable on a poly setting of 1, will test some more …
  • 2020-08-08 : I've changed the divtrig parmameter for the Seq16 and the Seq16Rep modules to have a maximum of 1024 instead of 255, this will cause some patch incompatibilities with previous versions (where the divtrig output was used).
  • DelayPoly - A polyphonic delay module 2020-09-02 : Added a new DelayPoly module which is fully polyphonic but it does not support delay times up to five minutes, only the short and medium ranges. So the time can be set from 100µs to 3s.

    Extended the maximum delay time to be 1 minute with a new long3 range, as I had some patches with delays in that range and wanted those delays to be polyphonic too. The rationale for not supporting 5 minutes is that such can eat up a lot of memory in poly mode (as the maximum length for the range will be allocated to allow for modulation over the full range).
  • PolySelectMulti - Multiple poly voice selector 2020-09-03 : Added a multi channel polyphonic voice slector, and also fixed a bug in the single channel version of it (the PolySelect module, just actually used the module for the first time – it had some shortcomings).
  • 2020-09-03 : I've upped the process priority for Wren to ABOVE_NORMAL_PRIORITY_CLASS, or at least made code to do so, a warning will be issued in the logs when setting the priority failed. The (relative) thread priority for the audio thread was alread set to THREAD_PRIORITY_TIME_CRITICAL, PortAudio apparently does that. Anyway, it's meant to to have it run a bit more smoothly, seems to be a marginal improvement at best.

in version 2020.7.27.0

  • 2020-07-27 : Fixes for MIDI modules. MIDI was not really dropping notes, but note-offs could follow immediately after note-ons, so a trigger out did not get generated. Changed the timing, such that the actual note duration is being tracked now. Another issue was that the MIDI modules were not fast enough, so changed their processing to be at audio rates. The third issue was that the low level MIDI code was posting messages to the GUI thread to signal incoming data. This was changed to let the MIDI driver inject MIDI messages directly into audio thread. This also greatly reduced the sensitivity to GUI events happening.

    Ran some tests on this and on my laptop with an ASIO buffer size of 256 the MIDI modules can now handle 1/16 notes at rates of 240 BPM. Audio buffer size matters still for MIDI timing accuracy, as a note-on event is not synced with the audio thread, only the duration is being calculated in samples now – so there still is note onset jitter, but that's a couple of milli seconds at most with the settings mentioned before.

in version 2020.7.23.0

  • 2020-07-23 : Some issues still with ins and params being mislabeled in places. Fixed the diagnostics for it and fixed the issues with it.
  • 2020-07-23 : Midi is supposed to be dropping notes. I've changed the handling for note-on and -off messages a bit. Also removed the direct control of the mide rx LED, just setting a flag for it and let the GUI task pick that up and turn the LED on. Also removed some memory allocation operations from the MIDI thread by setting a fixed size buffer. which gets then direcrly passed to the synth. The still is a small issue with this as the synth processes the MIDI in the audio thread, which works block wise, meaning that only avery buffer-size-samples the MIDI get to actually be processed. This is jittery with a frame size of 2048 samples, with 256 it is better. Not quite seeing how I could decouple this though.

in version 2020.7.20.0

  • 2020-07-20 : Made some unit testing code for param and in/out pin validation, found several hundreds of issues and amongst those were hidden a handful of bugs which may have resulted in the program to crash under certain conditions.

    I've fixed the bugs, the other issues were all due to irrelevant typos, lazy module naming, strange param names for multi valued controls (xypad and spiral), something with internal values being stored as parameters and how module inheritancce is being used. Anyways, all such issues were manually checked to be ok, and code was written to not show those anymore when the test is being run.

in version 2020.7.18.0

  • 2020-06-25 : Added some x64 specific optimizations; Turned on DAZ and FTZ flags to treat all denormals as zero and reduced the denormal correction functions to be Nops. Furthermore the check for denormals functionality built into the program will never see any for the 64 bit version. This seems to approximately give an extra 20% speed gain (as in 36% -> 30%) for the x64 version.
  • 2020-06-28 : I've made audio caching, such that a used audio file in wave player like modules will be loaded into memory only once. When the same audio is being used in another wave player like module the data will be shared. When the data is no longer used in the patch it will be deleted.

    This speeds up patching too when long waves are being used (as on a structural patch change (wires / modules / added / removed) all resources would be created anew, so audio would have to be reread from memory. In the current situation such data will be kept till after recompilation completed and only then, when the data turns out to be no longer needed, it will be released).
  • 2020-06-28 : Moved the 06-25 optimizations to a wider scope, it encompasses all real-time audio processing now (inccluding the bits for the level meters). It is not however used for offline audio processing, i.e. recording – planning to substantially change the recording mechanism anyway … but for now recording may still give exceptions on subnormals, infinities and NaNs.

    Note: As of 2020-07-02 the old non-real-time recording mechanism was removed, this leaves the debug wave plotting as the one non-real-time mode left, and as I'll probably keep that for a while it should be 64 bit optimized too (as is it can generate invalid floating point results or exceptions now).

    Note as of 2020-07-03 the above got fixed. Graphing is sillily slow though.
  • Recorder - A wave recorder module 2020-07-01 : Made a recorder module. I'ts tape length can be set from 1 to 30 minutes in one minute increments. When the tape is full it will loop, recording over the oldest material. There is a clear button to erase the tape and a write button to write out the tape to a disk file (a WAV file). The number of tape tracks can be set from 1 to 8 (WAV files can have up to 65536 channels). Recording can be start or stopped with the 'active' control. A file to write to must be selected before starting a writeout, or nothing will happen.

    The record output goes active when recording is stoped, connecting it to the clear and write inputs will cause the wave to be written to disk and to then be cleared. The full output goes active when the loop is 100% full, connected to the clear and write outputs will cause a recording to be saved each time the loop gets full.

    The eight audio outputs will output the input signal with a delay time set by the delay controls and the delay modulation input, as if it were a tape montoring signal.

    So … basically it is some sort of a primitive 8 track recorder with a looped tape.

    Made it use date and time prepended to the filename on save, such that when auto save is patched in a new file will be generated without overwriting old ones every time the tape gets full. Auto naming is optional trough the timestamped / normal selector, but it's on by default.

    Made auto normalization to be a user option as well, as when multiple takes are made automatic volume normalization would possibly lead to level inconsitencies between the various tracks. With normalization off they should be gluable in a wave editor.

    Changed the delay setup a bit. There now is a pre delay which can be set all the way from zero to 30 minutes and then there is delay modulation added to that. The modulation can be set from 100µs to 30ms for its maximum length and it can be modulated in a range -1 to 1 times the set value.

    Note: recording 30 minutes with 8 channels @ 96 kbps will fail as the maximum RIFF chunk size of 4 GiB would be exceeded. Some limits will have to be put in to make sure that a valid wave will always be written. And then again. maybe a limit of 2 GiB should be used to avoid problems with software implementing the size fields as signed 32 bit numbers.

    @ 2010-07-02: Ok .. sorted it out, the following time limits will be enforced, and this will work for both the 32 and the 64 bit versions … hmm, not so for the 32 bit version as the total program memory allocation should stay under 2 GiB … so it's impossible to tell upfront … hmm hmm. Ok, the x32 numbers are based on an empty patch, so it will be always less than or equal to the indicated duration. Added an indicator to the module telling the true available time, or in case of an an error some error message.
    sample ratechannel countmax duration x64max duration x32
    44k1 130:00<= 30:00
     230:00<= 30:00
     330:00<= 20:00
     430:00<= 15:00
     530:00<= 12:00
     630:00<= 10:00
     727:59<= 08:00
     824:35<= 07:00
    sample ratechannel countmax duration x64max duration x32
    48k 130:00<= 30:00
     230:00<= 24:00
     330:00<= 16:00
     430:00<= 12:00
     530:00<= 10:00
     630:00<= 08:00
     725:42<= 07:00
     822:35<= 06:00
    sample ratechannel countmax duration x64max duration x32
    88k2 130:00<= 30:00
     230:00<= 15:00
     330:00<= 10:00
     423:52<= 07:00
     519:19<= 06:00
     616:13<= 05:00
     713:59<= 04:00
     812:17<= 03:00
    sample ratechannel countmax duration x64max duration x32
    96k 130:00<= 28:00
     230:00<= 14:00
     330:00<= 09:00
     421:55<= 07:00
     517:45<= 05:00
     614:54<= 04:00
     712:51<= 04:00
     811:17<= 03:00
    @ 2010-07-02: Added a feature, when %patchname% is used in the file name to save under the string %patchname% will be replaced by the name of the patch. So when the patch is called 'silly-putty' and the file name was selected to be 'C:\MyRecordings\cc_%patchname%.wav' the wave data will be written to the file 'C:\MyRecordings\cc_silly-putty.wav'.
  • 2020-07-01 : Fixed a bug for the DelayMod and DelayMix modules, the range selections were not working.
  • 2020-07-02 : I've removed the non real-time recording mode, the new recorder module is to be used instead. The non-real-time mode would stop audio generation and it would record the first two channels only. The new module can record from one to eight channels and real-time audio will keep running while recording.
  • 2020-07-03 : Fixed a bug for the recorder module where it would occasionally access undefined memory on changing channel count or duration.
  • 2020-07-04 : Added volume control to the WavePlayer and the LoopPlayer modules.
  • 2020-07-04 : Added amplitude modulation (am) inputs to all of the LFOs, except for the Tod and ClockGen modules.
  • 2020-07-05 : Added amplitude modulation (am) inputs to all of the audio rate oscillators that did not have it yet, except for the DTMF and the Phasor modules.
  • 2020-07-06 : To get better control over the modulation range for the BPM related modules (MidiClockIn, RateConverter and Tapper) I've added pivot controls to them, they set the 'center' of the modulation.
  • 2020-07-06 : Fixed a bug in the patch writer to make it write out the allowance for randomization of the DataMaker component. This implements, a.o. the graph in the AudioGraph module, for which the randomiztion allowance was not saved. The patch reader did handle the situation correctly already. The patch version was not changed for this. As a side effct the randomization allowance for some other components gets written out too now, but always with a value of 0 (zero, do not allow).
  • 2020-07-06 : Made a folder selection dialog for all the various file types that can be used in for different purposes in a patch. So can have all files neatly stuffed away in separate folders now. See the image below. It is a bit fascistoid this, I'd agree on that … the former freedom drove me mad and I'm making chocolate orange cocos icecream right now.
  • StereoNarrow - A stereo narrower 2020-07-07 : Made a stereo narrower module, it sums he left and right signals and then mixes those with that sum in a controllable way, that way fading from stereo to mono. This can also be used to zoom in on phase issues where in the mono signal left and right would cancel each other when in anti phase. The module is rate smart and will work full rate when audio rate signals get connected to it.
  • audiograph in action 2020-07-07 : Fixed some more issues on the AudioGraph module, it was not allowing randomization by default and the auto-scale feature could not be turned off. It now behaves as intended.
  • 2020-07-07 : Moved all MIDI configuration items to the 'MIDI devices' dialog, which I then renamed into 'MIDI setup'. Also changed how these settings are written into and read from the ini file, you probably will need to reconfigure your MIDI settings.
  • 2020-07-07 : Moved all OSC configuration items to a new 'OSC setup' dialog. Also changed how these settings are written into and read from the ini file, you probably will need to reconfigure your OSC settings (I've added a help button in the OSC setup).
  • 2020-07-07 : Reconfigured the Settings Screen F3 a bit to fill out the holes …
  • 2020-07-08 : Started splitting off parameters from inputs; up to now all knobs and things were treated just like inputs were (except no wires could be connected to it … although I have considered to allow for this at times), when done with this knobs and such will be params and only the true inputs will be inputs. Probably a couple of days work …. Started left with the i/o modules and sofar did 97 of 325 modules - at Modal2 now, more tomorrow.
  • 2020-07-09 : Going on with splitting, 99 done now and moving to the Mix tab. And the mix tab is done, 117 of 325. Switches were easy, 127 now, 137 after ctrl1. And after ctrl2 22 more, makes 139, still not halfway trough, let's first do some error checking now. 10 typo's fixed, and 16 more modules done, 155 now, on to the next tab: math. But dinner first and cherries and icecream!

    Things expanded a little, just passed the 300,000 lines mark again, 2 over it now. +21 for the math modules, makes 176 – more than half done (:-)

    Then 24 more for the logic tab making 200. And that was another 15 from seq1 making 215, the sequencers need a lot of attention, on to the seq2 page … tomorrow (:-)
  • 2020-07-10 : Going on with splitting, 226 done now and moving to the Gen tab. Plus 19 to 245, on to FX tab, 80 to go. 18 more to make 263, on to the Delay tab. And another 14 @ 277 now, next tab is Voice – dinner stuff first though. pwew … done, now check stuff and test stuff (:-)

    Checked all kinds of stuff … like not mixing up i_xxx and p_xxx thingies in the Params[ p_xxx], AddParam( p_xxx), Inputs[ i_xxx] and AddInput( i_xxx), and also i_xxx and p_xxx ranges MUST start at 0 and there MUST not be gaps or things will crash later on …

    I've been thinking about how to enforce this making use of strong typing, but could not think up a way that would not be clumsy (i.e. using type ins = ( i_xxx, i_yyy …); and then must have {$SCOPEDENUMS ON}, and then use Inputs[ Ord( ins.i_xxx)] everywhere) or use variables instead of constants (like var i_xxx; … i_xxxx := AddInput( 'xxx');) which would make things slower by adding an indirection level.

    Also one would like to do type TInputId = type Integer; TInput = record id: TInputId; name: string; end; TInputs = array of TInput maybe. But that would need some typecasting in places, like where the Id's go into set of's. Generics could help there I guess, but still the demand for consecutive numbers starting at 0 would be ugly then.

    So, let's just run it again (:-)

    At least there is basic functionality, an older somewhat more complicated patch seems to run okay. Not bad for after turning it inside out completely.

    Release compile works, with about the same load as before the operation. Had it expected it to be somewhat faster, oh well, it is the separation that it was done for, would have accepted somewhat slower as well.

    Anyways .. time for backups and such.
  • 2020-07-11 : Hmm, it seems to have fukt the 32 bit version somehow. Okay that was unrelated. Something something floating point exception masks mumble mumble. Those always are an interesting subject in the summer course 'how to crash your computer and have no idea why', anyways do NOT put garbage into your flotaing point exception masks.

    The 32 bit version is fine too now.
  • 2020-07-11 : Exploring the generics idea mentioned a couple of sections back:
    
    const
    
      NO_PARM   = 'noparam';
      NO_INPUT  = 'noinput';
      NO_OUTPUT = 'nooutput';
      NO_ID     = -1;
    
    type
    
      TParamId  = type UInt16;
      TInputId  = type UInt16;
      TOutputId = type UInt16;
    
      TIdNameMap<T> = record
        ID   : T;
        Name : string;
      end;
      TIdNameMaps<T> = array of TIdNameMap<T>;
              
    and then later on:
    
      TMod = class
      // Synth module prototype
      ...
      ...
        FParamMaps  : TIdNameMaps<TParamId >; // Maps param      names to Id's
        FInputMaps  : TIdNameMaps<TInputId >; // Maps input  pin names to Id's
        FOutputMaps : TIdNameMaps<TOutputId>; // Maps output pin names to Id's
      ...
      ...
              
    being used as:
    
        function    GetParamCount : Integer;
        function    FindParamID   ( anID: TParamId ): Integer;
        function    FindParamName ( anID: TParamId ): string;
        procedure   AddParam      ( anID: TParamId ; const aName: string);
    
        function    GetInputCount : Integer;
        function    FindInputID   ( anID: TInputId ): Integer;
    
      ... etc
              
    being implemented as:
    
        function    TMod.GetParamCount: Integer;
        begin
          Result := Length( FParamMaps);
        end;
    
        function    TMod.FindParamID( anID: TParamId): Integer;
        var
          i : Integer;
        begin
          Result := NO_ID;
    
          for i := 0 to ParamCount - 1
          do begin
            if   FParamMaps[ i].ID = anID
            then begin
              Result := i;
              Break;
            end;
          end;
        end;
    
        function    TMod.FindParamName( anID: TParamId): string;
        var
          p : Integer;
        begin
          p := FindParamID( anId);
    
          if   p <> NO_ID
          then Result := FParamMaps[ p].Name
          else Result := NO_PARAM;
        end;
    
        procedure   TMod.AddParam( anID: TParamId; const aName: string);
        var
          p : Integer;
          N : string;
        begin
          N := Trim( aName);
          p := FindParamID( anID);
    
          if   p <> NO_ID
          then FParamMaps[ p].Name := N
          else begin
            SetLength( FParamMaps, ParamCount + 1);
            FParamMaps[ ParamCount - 1].ID   := anID;
            FParamMaps[ ParamCount - 1].Name := N;
          end;
        end;
    
      ... etc
              
    Anyways, this all will still accept plain non negative integer constans, so it offers no protection at all. I must have misunderstood the:
    
        type typename = type something;
              
    construct, I'll keep it in tho for clarity towards the casual code reader.
  • 2020-07-11 : Added reset inputs to the Looper and StereoLoopr modules. When they trigger the loop pointer is set back to the start position.
  • 2020-07-11 : The folder selection does not seem to work as intended yet.
  • 2020-07-11 : Custom wire colors can change when the custom color is one of the standard colors and the rate smart module performs a rate change. Fixed this with a kludge by not allowing the user to set those exact colors, except when a choice is made for the default color, Hmm .. no good, will need a better fix. like explicitly setting a custom color.

    That was way more non-trivial than it should have been, but seems fixed now.
  • 2020-07-11 : Fixed the issue where a sped up module would not de-speep when the fast connection was removed. needed a complete clearance of all sped up stuff followed by a repeated fixup until no more work is done. It's a bit ugly, but it works, and things really need to ripple trough all the modules and wires, nothing much can be done about that. Turns out this was related to the wire coloring issue.
  • StereoPan - A stereo panner 2020-07-12 : Added a stereo panner module, will need to change the control curve a bit, panned left or right the levels are too high. With some bounces instead of clips it works nicer, makes the code look symmetric too.
    
          Control :=
              1.0
            + Clip(
                FParams[ p_position ]
              + FParams[ p_posmodamt]
              * FInputs[ i_control  ],
              -1.0,
               1.0
            );
          In1     := FInputs[ i_in1];
          In2     := FInputs[ i_in2];
          Sum     := In1 + In2;
          A1      := Bounce( Control, False);
          A2      := Clip  ( 1.0 - Control, 0.0, 1.0);
          A3      := Clip  ( Control - 1.0, 0.0, 1.0);
          A4      := Bounce( Control , False);
          FOutputs[ o_out1] := A1 * In1 + A2 * Sum;
          FOutputs[ o_out2] := A3 * Sum + A4 * In2;
              
  • MixAudio - Audio mixer redone 2020-07-12 : Changed the layout of the MixAudio module to make it more clear what belongs to what channel, this must be about the first time that a module got larger without extra controls being added (:-)
  • 2020-07-12 : An issue was reported where "at the top left of the edit screen the individual module types are sometimes grayed-out, they do get their color back when I run the cursor over them". Probably the module selector, the only things there having color are the tabs … well some module glyphs have a tad of color … so probably the tabs loosing color?

    Maybe this is related to another thing, where sometimes no tab at all will be selected in which case no module glyphs are being shown.

    Seems not related, when the program starts in full screen mode the tab colors are not set up yet when the program needs them. This is reproducable, good (:-)

    @2020-07-12 : And it was fixable too, but definitely not related to the 'no tab selected' issue, still investigating that one (it's badly reproducible).
  • 2020-07-13 : Added an option to the audio device selector window to select <nothing> for the input- or output-device (or both, but PortAudio will complain on that, thus without any devices selected it will also be impossible now to record, but otherwise nothing too useful in selecting nothing at all). When <nothing> is being selected for inputs no inputs will be opened by PortAudio, likewise for outputs. An input only setting could still be used to record audio.

    On first load with this new feature the audio devices will have to be reselected, but it will be remembered ok once that is done.
  • 2020-07-14 : Made the title fields on the pannel1, 2, 3, 4 and 5 modules larger, so they can double as patch comments, sort of.
  • 2020-07-14 : Added multiplier inputs to the Constant and MConst modules. They operate on the constant value only, not on the add input. This way they can act as a 'constant', or or as an 'add constant' or 'multiply by constant', or as your 'multiply and add' operator for simple FIR filters. Or as a single input chainable mixer.
  • 2020-07-15 : Fixed the 'no tab' issue mentiond on 2020-07-12 too, thanks Airlock for pointing out that shift+space would cause it to happen, that finally made it reproducible, and thus fixable. The fix is not perfect, as there will be a repaint glitch still, but it will do.
  • 2020-07-15 : Hmm .. fukt up the main form, so had to go back into some ill defined backup, there might be some regression isues … yuck … and the Delphi saved backups were no good at all, some very old stuff was there and some already fukt pretty recent stuff … so had to use human memory here … what a fokking mess.

    Had deleted most of the setup stuff from FormMain by accident and no Ctrl+Z was available for some reason, then did a manual save of the unsaved files, but fukt that myself (restoring the pas instead of the dfm and then doing a save), and then there were no usable Dephi backups, and I didn't do a git commit either for a while … pomtidom dom dom oliekoken dom.

    Ok, the no tab issue was refixed, and the no colors issue as well. Multiplier inputs were not affected, neither were title field changes on panels, the <nothing> things should be fine, new modules should be fine, custom wire colors, I'll need ro check those, but prolly ok … folder selection needs a check too, Reset inputs on modules should be ok, floating point issues were redone, the splitting stuf was not affected, the MIDI and OSC config changes look okay, AudioGraph should not be affected, StereoNarrower should be fine, patch writer bug should be fine, BPM stuff idem, am stuff as well, no worries about wave player mods, or recorder bugs, real time recording is gone okay, DelayMod should not be affected, recorder should be ok, the after 06-25 scope expansion should be fine no (after fixing), audio caching and x64 specific optimizations should be fine too – hmm, they were not, but fixed it.

    So. will need to check on custom wire colors, ok that got fukt too and needs be redone, ok, did that but needs a check, seems fine now.
  • 2020-07-15 : Made the Recorder module more simple, and made a new TapeRecorder module having the old Recorder functionaliry, and as the TapeRecorder is more like a delay module put it on the Delay tab.
  • 2020-07-16 : Made the recoreder record in 32 bit float format, so when it is not normalizing on disk write a heavily clipped recording can still be recovered by normalizing it externally (checked that with Reaper, Acoustica and Audacity).
  • 2020-07-16 : Added output type selectors for MConst, Monadic and Dyadic modules.
  • 2020-07-17 : Added modulation inputs to the Reverb module.
  • 2020-07-17 : (un-de-)Normalization was calcuated wrongly in the Reverb module, resulting in math exceptions in the 32 bit version, fixed that.
  • 2020-07-17 : LfoMultiPhase module makes nonsense wave forms. Ah, the warp modulation (which it does not have implemented on the user interface) was set to almost zero. Fixed it.
  • 2020-07-17 : Added a frequency control parameter to the TritoneBank, ThirdBank, TritoneSplitter, ThirdSplitter, TritoneCombiner and ThirdCombiner modules. Before they only had FM inputs with an attenuator.
  • startup screen 2020-07-18 : Changed the startup screen a bit to reflect the current version better. In the Settings Screen F3, and in the title bar, when this is enabled, some extra version info is being displayed as well now (to be able to see if it a release, debug, 32 and / or 64 bit version, stuff like that. This has no effect on the version checking option in the program, as just the basic version info (like 2020.6.24.0, for instance) is being used for that.
folder selection

in version 2020.6.24.0

  • 2020-05-30 : made double buffering for the XYScope module, it is still not fast enough though.
  • 2020-05-31 : Introduced module versioning, such that moddule autocorrection can be applied when an older module version is loaded from a patch. Had to up the patch version for this to 10. The modifications are backwards compatible in that unversioned modules will be assigned version 1, which is the current version for all modules.
  • 2020-06-02 : Changed ModQuantizer to use HighLogic inputs insteadd of Logic inputs.
  • 2020-06-06 : Added more diagnostics to logfile for opening PortAudio as it still was not clear from the current logs if the DLL was available and where it was found. The code now does a walk over the entries found in the PATH environment variable and it will print all found occurances of portaudio.dll.
  • wave viewer loops 2020-06-11 : Made some new code to be able to read more wave types, for now it supports WAV, AIFF, AIFC and SF2 (sound font) files with arbitrary sample rates, arbitrary channel counts, and sample depths of 8, 16, 24, 32 or 64 bits for integer samples and sample depths of 32 or 64 bits for floating point samples.

    Also it can support (multiple) looping regions now [with repeat counts], regions and labels.

    Wave compression is not being supported and sample rate conversion is currently not being applied.

    wave viewer sf2 When present in the WAV file it can read an ACID section too, I've not seen such information yet in AIFF or AIFC files, so no idea how to get that information from those file types. Also loop info in those file types is incompletely written by the wave file editors I've used so far. SF2 files seem to have such information on a per sample base, still need to parse that out in some way though. The MultiWave base class I've made has some flexibility in it for actual modules to make use of such data.

    Not sure yet as to how this will affect what modules and how, a work in progress it is.

    2020-06-12 : Made a display for it too .. it's a bit small all, but for simple loops it would do I guess. To speed things up a bit I started using peak files as otherwise painting the wave takes ages. It still does take ages, but just once so now, after the wave was first used or after it got changed. Peak files are saved into a sub folder (wren-peaks-23A396E5-4A4A-42FB-90B6-3FCA46862F3F) of the folder where the wave or aiff was found, and it will have the same name as the wave it was obtained from with an appended file extension of .wren-peak-23A396E5-4A4A-42FB-90B6-3FCA46862F3F, .guessing those names will never conflict with anything … When the folder can not be created or when it is not writeable no peak file will be used and there will be no warnings, it will just be slow.

    The module shown is just a thest thingy for the new wave stuff, still not sure what exactly to do with it all. something wih looping I guess …

    Not sure yet how to deal with sf2 (sound font) files, for existing wave based modules the contained samples are just being concatenated, but there is room for better stuff I think … I can think up …
  • 2020-06-07 : Just passed the 300,000 lines of code mark.
  • 2020-06-15 : Changed the WavePlayer module to use the new wave file reading code. This means that it will now read WAV, AIFF, AIFC and SF2 files (but it will just concatenate all the samples from the sound font, and it will assume all the sample rates to be the same, the rate of the first sample will be used; loop points are being ignored) with arbitrary sample rates, arbitrary channel counts, and sample depths of 8, 16, 24, 32 or 64 bits for integer samples and sample depths of 32 or 64 bits for floating point samples. Wave compression is not being supported. Sample rate conversions are not being applied, however the playback speed will be adjusted when the system sample rate changes.

    This also means that the Mono / Stereo selection got lost; Mono files will now output on both L and R outputs, and when the wave has more than one channel the first channel will be played on the L output and the second one on the R output. Any further channels will be ignored.

    Furthermore waves will be amplitude normalized when read in, no DC offset correction is applied on normalization. And sample memory size got limited to 128 MiSamples (which for a stereo file will result in 2 GiB of memory being used, all wave data is being kept in memory as 64 bit floats).

    Changed the WavePlayTrig and WavePlayTrig2 modules in the same way.
  • 2020-06-15 : Removed the Wave Audio dependencies from the project (using the code mentioned above). And now it's under 300,000 lines of code again ( and about 20 kB smaller for the resuling executable – it is always amazing how little gain is being obtained from removing code vs. how much a little extra code costs, there must be some law for that).

    Anyways, ready now for some new sample based modules, but first the 2020-06-20 june solstice concert … with existing modules and functionality, more changes after that … best.
  • 2020-06-23 : Now that the event is out of the way … Started working on a 64 bit version, found some odd bugs that I fixed and it seems promising sofar … not yet working is the freeverb reverb module, as it has some 32 bit assembler code in it. Will have to run lots of tests now – and checks for (in)valid type casts and int sizes and such. It runs the current patch I was working in almost half the CPU cycles … hmm … let's say 60 to 66 %, and also PortAudio will now discover 64 bit ASIO drivers (ReaRoute in this case). So, some promising results sofar.

    Sofar tried to open like 20 larger old patches, except for the now fixed scala bug and the reverb that needed a fix they seem to all run fine.

    The executable size is somewhat larger, as is the memory footprint of the program.
  • 2020-06-23 : Rewrote the Reverb module to not use ASM anymore and to work with doubles instead of singles. it now works in the 64 bit version. It also seems to sound way better, odd.
  • 2020-06-23 : Fixed a bug in the Scala lookup routines where a negative notenumber would cause an exception to occur. Also fixed a bug where an exception would be raised when a scale or mapping file did not exist, or where a mapping got set before a scale was set.
  • 2020-06-23 : The SAPI speech module seems broken, not going to fix that as eSpeal can do it all too. Oh and eSpeak still works with the new 64 bit DLL. Opps wrong … SAPI still works too, my test code for it failed instead.
  • 2020-06-24 : Made new compiles for the PortAudi DLL for Win32 and Win64 both in debug and relesae versions. Both versions have FL Studio ASIO blacklisted. Anyway, both the 32 and the 64 bit Wren version can co–exist now with FL Studio using the FL Studio ASIO driver.

in version 2020.5.30.0

  • Midi8NoteIn - A new MIDI multi note input module 2020-05-29 : Added a new midi in module, Midi8NoteIn, a copy of the MidiMultiNoteIn module but with a maximum of eight channels instead of four. The actual channel count can be set with the max. notes control.
  • 2020-05-29 : There was a bug in the MidiMultiNoteIn and the Midi8NoteIn modules, the mode input got never processed. Also had some doubts about how note off messages were being processed, so changed the code for that a bit too.
  • 2020-05-29 : There was a bug in the internal MIDI send code where sending to internal channels (ic1 to ic16 (from all of the MIDI send modules), to modules in the patch directly) did not work correctly.
  • 2020-05-30 : Some more issues with the MidiMultiNoteIn and Midi8NoteIn.

    I've combined the code for both with the MultiNote in using a fixed channel count of 4 and the 8Note one using a user settible limit from 1 to 8. Consider MidiMultiNoteIn to be obsolete, it will have the same performance as the 8Note one set to a 4 notes maximum.

    I've changed the scheduling for note-offs to find the oldest same valued note present to turn off. For aftertouch the youngest same valued note is used to apply the aftertouch to. This does not change the channel selection used for note-on events, for those the selected algorithm will be applied always.

    Fixed an issue with AfterTouch and ChannelPressure not being in range [0.0,1.0].

    Fixed an issue with PitchBend not being in range [-1.0,1.0].
  • 2020-05-30 : the MidiNoteIn, MidiMultiNoteIn and Midi8NoteIn modules did not correctly handle note-on events with velocity zero, it is now treated as a note-off event.

    The MidiNoteOut module can still send note-on events with velocity zero.

in version 2020.5.27.0

  • 2020-04-23: Added a random walk shape type to the LFO modules. The step size for the walk can be set with the warp controls, a low warp value giving a small step.

    Done: for the next release must update the skin stuff for this.
  • 2020-04-26: Made it possible to turn off the patch hints (the ones popping up for knobs and buttonss and such). This to "solve" a nasty issue with wine where the hint windows "hang" and that I do not know how to properly solve. It is a setting in the Settings Screen F3.
  • 2020-04-27: Added some extra controls to the OscTrig module to make it more suitable for Pulsar Synthesis like effects. It now has phase modulation, shape modulation and warp control just like the main Osc module has them.
  • 2020-04-28: Added an output type selector on the Osc and OscTrig modules, to make them more suitable for AM (amplitude modulation) type modulation (instead of RM, or ring modulation).
  • 2020-04-28: Added a modulatable repetition count to the WavePlayer2 module. This to be able to play bursts of short samples. This is also meant to make Pulsar Synthesis easier to accomplish.
  • 2020-04-28: Made two extra inputs on the WavePlayTrig2 module for programmaticly switching the retrig– and the loop–mode.
  • Seq16Rep - A new 16 step sequencer 2020-04-30: Made a new sequencer type (Seq16Rep). This is an extension of the seq16 type where a repetition count can be set for each step (1 to 256 counts). Also a trigger pattern can be selected from n(one - no trigger pulse), s(ingle - one pulse per step), a(ll - one pulse per count) and g(ate - one long pulse over all counts). The repetition count and pattern are modulatable per individual step.

    The Individual trigger outputs (trigs) as well as the main trigger output (trig) will output the selected trigger pattern, the tr. chain output will trigger once for every next step being taken, this can be used for chaining up another squencer such that it can stay in sync.

    Pulse length for trigger pulses can be changed by changing the duty cycle of the the incoming trigger pulse.
  • 2020-04-28: Added a new range for envelope times, the vfast range. it runs from 50µs to 10ms. This applies to all modules that work with changeable envelope timing ranges, those are: PulseDelay, EnvARRetrig, EnvAHD and EnvADSR. The granulators still use fast, I'm considering changing that to vfast to make them more usable. Anyway, audio rate envelopes are pretty nice for Pulsar like Synthesis.
  • 2020-05-01: Added two new signal types HighLogic (orange, audio rate) and HighLogicCtrl (dark green, control rate). These will be used on inputs only (so there will not be wires in these colors). The difference with the regular logic signals (yellow and lime) is that the latter switch for levels > 0.0 and the new types switch for levels > 0.5. This makes it easier for some logic inputs to be controlled from unipolar signals. There had been a couple of existing modules already having the new behaviour, for those modules the colors have been changed to the new colors to make the input type clear.
  • 2020-05-01: Added ranges for granular times too now, it supports the fast and vfast modes (as they existed for envelope times already). The bloody things need more work though as they still sound no good.
  • 2020-05-05: Added relative LFO rate control (r.rate) for setting a global LFO rate multiplier. This is currently not being used anywhere, decided to do MIDI syncing in a more modular way. Oops, correction .. it actually does work as a global LFO rate multiplier, but it does not change the scaling of the delay lines.
  • 2020-05-05: Made some changes to the Tapper module. An extra control mode was added (LFO fast 0.254) to allow for faster tempos with an LFO set to fast range. Some internal clipping was removed to allow for larger BPM ranges. An external tap input was added so this module can now be auto-tapped from an LFO (prably set to run in BPM mode for exact BPM matches) or from a ClockGen module's * 16 or * 96 output. The order of the control modes in the selector was changed, so some older patches may not be compatible without manually correcting the mode(s).
  • MidiClockIn - A MIDI clock receiver 2020-05-06: Made a MIDI clock receiver module, click on the image to see the docs for it. It is to be used for MIDI clock synchronization. The sync output will give a short blip once every measure (24 PPQN is assumed and 4/4 mode).

    Had to modify the overal MIDI reception structure for this, will have to test (N)RPN receivers after these changes.
  • RateConverter - A rate converter module 2020-05-06: Made a RateConverter module, click on the image to see the docs. It is to be used for synchronization of LFOs and delays.
  • 2020-05-07: Added alpha and hysteresis modulation to the CuClipStereo module, just like the mono version already had it.
  • 2020-05-10: On Sequencer reset (Seq16 and Seq16Rep) the first step should become active immediately. Changed some things for it, seems better now.
  • 2020-05-13: Added rate multiplier modulation to the MidiClockIn and Tapper modules. The RateConverter module already had this.
  • 2020-05-13: Added a sync divisor to the MidiClockIn module.
  • 2020-05-13: Added XFade modulation to the Mux module.
  • 2020-05-13: Added an inhibit (inh) input on the EnvAR and EnvARRetrig modules, when it is active the envelope will not be started. This is a HighLogic input, it will be active for signal levels > 0.5.
  • 2020-05-14: Added output type selection for the Noise and NoiseTrig modules (bipolar, positive only etc.). Some are redundant, like the pair 'positive only' and 'inverted positive only', which would end up being 'identical' in the long run.
  • 2020-05-15: Changed the grain modules to use a mixing buffer for sample insertions, this smooths out the discontinuity between the oldest and newest sample in the sample buffer and so makes grain playing less glitchy. I've set the mix area to be 16 samples long which seems to be sufficient, it is a bit of a trade off, a longer fade area makes it substantially slower (limiting the maximum grain count to be used).

    Did that same thing for the GrainDelay module, but that one still seems a bit glitchy …

    Also removed a bug where the grain duration could become zero, which caused a division by zero.
  • 2020-05-15: Changed clipping of the main program window on program load to allow for it to be sized to the screen size (without it being maximized). It used to be clipped 20 pixels short of that (unless it was maximized).
  • 2020-05-15: Removed the slave output from the RateConverter module, it was only passing on it's input – so not too much use for it. (note to self: some patches of the last 10 days will need repair for this).
  • 2020-05-16: Had fukt up the (trig) noise for the regular bipolar output range, fixed that.
  • 2020-05-16: Added 'dust' as a new random signal type for the Noise, NoiseTrig, NoiseLFO and NoiseLFOTrig modules. It consists of randomly timed spikes, the distribution over time is set by the color controls. This is after an idea obtained from SuperCollider – via the Hetrick Dust module for VCV. I've changed the implementation a bit to use two independent noise values for spike–distribution and –magnitude. This is unsynced dust.
  • ValueSync - A value synchronizer 2020-05-16: Added a ValueSync module, a value synchronizer. It acts a bit like a sample and hold but it will pass on the value captured when the pulse input got active only when a sync signal was seen after that. The Q ouput will go on for 1ms after a sync occurred, the captured value will be held untill a new pulse and sync sequence was seen.
  • 2020-05-17: Added 'crackle' as two new random signal types for the Noise, NoiseTrig, NoiseLFO and NoiseLFOTrig modules. There are two versions Crkn for the normal and Crkb for the broken mode. The ideas comes from the HetrickCV Crackle VCV module (and originally from SuperCollider).
  • 2020-05-18: Added an active output on the MidiClockIn module, intially or after receiveing a MIDI Start or Continue message it will be on. It will go off on receiving a MIDI Stop message. When active is offthe latest calculated BPM value will be set to zero and there will be no further sync pulses on the output. However the control and slave outputs will be frozen to where they were, so everything controlled by it will keep running as it was. When started again the sync output will go active briefly.
  • 2020-05-18: Fixed a bug in the global LFO rate setting. All displays of LFOs would react correctly but the actual tate was never acted upon. It now works as intended, but at some later stage I might also want to alter delay times and envelope times.
  • 2020-05-19: Added sequence length modulation to the Seq16 and Seq16Rep modules. The parameter value is being multiplied by the preset number of steps and can make the actual step count both larger and smaller, however the range will still be 1 to 16 steps.
  • 2020-05-21: For the ModGateSeq module the gate modulation inputs were changed to HighLogic (dark green, switching at 0.5) mode.
  • 2020-05-21: Added some functionality to the slew module. Slew can be modulated now and up and down slew have been separated to allow for a different change rate in one direction than the other.
  • 2020-05-26: Added a new signal type to the LFO modules, calling it the 'Random Block' mode. It will produce random levels of random duration, but changes will always be synced to the LFO rate. The chance of change to happen can be set with the warp controls, more warp makes a change more likely. When this signal type is differentiated with one of the Dif modules or wirth the ChangeDetector the result will be a sort of 'synced dust'. The 'dust' type signals from the random modules are unsynced.

in version 2020.4.13.0

  • 2020-02-28: Changed file formats to all (except MIDI files, which are binary) use UTF-8.

    Worst case, that is when you have used non ASCII characters in file names or module names, this may cause Wren to not start up anymore or to not be able to quit. Save your current Wren directories before upgrading to this.

    I've tried to program a fix for this to make things backwards compatible, but can not oversee all possible situations. In case you see any trouble please report ‐ what will fix it is removing the wren.ini file, but I'd prefer to provide a solution without history loss.

    I ran into trouble with the previous version when I wanted to save a patch with a greek name which was not handled correctly. The new version of Wren handled all migration issues for me – YMMV … let me know please – and I'll fix it.
  • 2020-04-13: Made builtin MIDI, making the NetMidi program obsolete.

    MIDI port selection is trough a new menu item setup/MIDI devices (the audio setup menu item was renamed to setup/Audio devices). MIDI Channel selection and (N)RPN preference setting still works trough the Settings Screen F3.
  • 2020-01-18: Made steps modulation on the Quantizer module.
  • LUT - Step value modulation for LUT 2020-01-18: Made step value modulation to the LUT module. This transforms it into something inbetween a constant step and a piecewise linear step processor (depending on the setting of the fade control). The modulation inputs are set to 1.0 when not connected so in that case the old generator only behaviour is maintained (modulation inputs are being multiplied by the slider set step values).

    Also added an AM input, affecting all outputs but not acting on the chain input and also not active when the module is in Note mode.
  • 2020-01-18: Changed 2010 to 2020 in places …
  • 2020-01-22: A new module, a double pendulum simulation.

    This resolves the [2017-08-12 : Double pendulum] request.

    This module can either be free running or clocked, it will be clocked when something gets connected to the clk input. The m1 / m2 control sets the mass ratio DPendulum - Double pendulum simulation between the masses at the ends of the pendulum arms. The sum of the masses is set fixed to 20 kg. The l1 / l2 control sets the length ratio between the lengths of the pendulum arms, the sum of the lengths is set fixed to 20m. The speed control and it's modulation input set the simulation step size, the simulation will not proceed when the speed is zero. For negative speeds the simulation will run in opposite direction (but gravity stays as it is). For large speeds the precission of the simulation will diminish and somewhat longer runs may result in non–chaotic behaviour. The reset input or button can bring the module back to it's starting state. With the G mod. input gravity can be changed, it can be made negative too, unconnected this input will have a value of 1.0 for standard downward gravity.

    dpendulum animation example
    DPendulum animation example
  • 2020-01-23: Changed mazes.4th to version 1.1 - just a color change really. Must not forget to use this one for the next release (it is in the web folder already but needs to be put into the zip-yet-to-be-created.
  • 2020-01-23: There is an issue with the LUT module, xfade is not working correctly when the postion wraps back to the first one. Also outputs 2 and 4 seem to behave different than outputs 1 and 3? Hmm, nope, all ouputs act the same, so that bit is ok.

    XFade is working correctly after all. As it can not look into the future it can not know that the position will wrap back in the next sample. So I've declared it to be a "feature" instead.
  • 2020-01-23: I've changed the triangular wave forms to not use integration anymore but to use a BLAMP'ed trivial waveform instead. This behaves better with wave warping.

    Changed the default bandlimiting to 1.004, close to 1 (which works best overall (it was set to 1.5 or so by default)).

    Affected modules are Osc, MultPhaseOsc, MultiOsc, OscTrig and SquareTrig modules.
  • 2020-01-27: A new module, a dual filter. DualFilter - Double filter Two 12 dB/Octave filters with three selectable configuarations and frequency spread control and pre/post distortion.

    The two filters are connected in series, the first filter frequency is set with the frequency controls and the second filter follows it with a modulatable separation offset (which can be negative by using the separation modulation inputs).

    The filter mode can be set to low pass (lp), high pass (hp) or band pass (bp). In low and high pass modes it will act as a 24 dB / oct. filter where the resonance peak can be split in two by the separation controls. In band pass mode there are two 12 dB / oct. filters where the bandwidth is controlled with the separation controls.

    The lev control sets the input level and there is pre and post filter distortion available.

    The Q control sets the filter Q for both filters, and it can be modulated positively and negatively trough the two modulation inputs.
  • 2020-01-30: Added a divider on the clock out of the Seq16 module. I'm using this for chaining Seq16 modules at a different rate than it's "natural" rate (as set with the number of steps). This would save an extra divider module.
  • 2020-01-31: Added a multiplier input to the PitchShift module, it is multiplied by the shift parameter to, for instance, allow for quick zero to set value jumps or for set value to minus set value jumps.
  • 2020-01-31: Added "add" inputs to the Constant and MConst modules. They can provide a value to be added to the output value.
  • 2020-02-13: A new module, a fast mode LFO. FastLfo - Fast LFO It is fast in that it is computed at audio rate instead of control rate, but otherwise it is the same as the LFO module. This module can be used to control delay line time modulatuion with less zippering than would be caused by using the standard LFO.
  • 2020-03-05: A new module that does … nothing … Noop - Noop It is handy at times for routing wires. and it adds one sample of delay. Just a bit cheaper than a mixer or something you could use for the same purpose. Besides, every program environment needs it's nop 😉
  • 2020-03-19: A genome player module, translating RNA strands into control signals. GenePlayer - Noop This module scans text files for A, C, G and T (or U) characters (case insensitive) and builds a sequence from those with the letters mapped to the numbers 0, 1, 2 and 3 (such that A and T (U) are complemental, as are C and G). U is treated as if it were T.

    Additionally W, S, M, K, R, Y, B, D, H, V and N are recognized, these are (according to their rules) randomly translated in one of A, C, G or T. W into A or T; S into C or G; M into A or C; K into G or T; R into A or G; Y into C or T; B into C, G or T; D into A, G or T; H into A, C or T; V into A, C or G; N into A, C, G or T.

    All other characters (including Z, white space and numerals) will be skipped.

    On playback the letters can be chained into groups of size 1 to 7 (3 would be the central dogma, codons encoding for amino acids (of which some may not exist for random letter sequences, but this module will assume existing sequences)). For a single letter there are four values [0.0, 0.25, 0.5, 0.75] or [0,0, 0,33, 0.67, 1.0] on the scaled output; for a group of two the values woud be [0.0, 0.125, 0.25, 0.375, 0.5. 0.625, 0.75, 0.875] (or their scaled equivalents).

    On each trig the next group will be output, when the unit is in repeat mode it will jump back to the start when everything was played and when it is in once mode it will stop at the end. The res input will reset the sequence to the beginning. The changed output will fire when a value change on the output was seen. The leftmost outputs are complement outputs, for ease of implementation just 1.0 - output.

    That sars2 thingie was a tad boring though to listen to … oh well …

in version 2020.1.18.0

  • 2020-01-16: Embarrassing bug … there are anti aliasing errors in various oscillator modules when PWM or Warp is not set tp 50% (extra aliasing was added instead …). Also the PWM modulation does not work as intended on the PWM enabled modules. The affected modules are Osc, Square, OscTrig, SquareTrig, MultiPhaseOsc and MultiOsc.

    Fixed all of this but the MultiOsc lost its PWM control in the process. It did hower get warp control instead which does PWM too except that the parameter names are different so some repatching will be needed on that.

    Checked LFO PWM as well, which seems to be fine.

    The Square, Saw and Tri waves sound a lot better now and PWM works as intended.
  • MixS2to1 - Solo controls on S2to1mixer 2020-01-09: Added solo buttons and a solo chain input and output to the MixS2to1 module. Making solo active on the left or right pair will block the audio chain inputs and and it will also block the other audio input pair. Also the solo chain output will then be active which is signalled by a yellow light. When the solo MixS5to1 - Solo controlson S5to1 mixer output is connected to a downstream MixS2to1 module that module will block it's local inputs and it will pass on only it's chain inputs. This will be signalled on that module by having an orange solo light.

    Did the same thing for the MixS5to1 module.
  • EnvARRetrig - A and R mod modes on the EnvARRetrig 2020-01-10: Added add, subtract an multiply modes for the A and R times on the EnvARRetrig modules. These control how the modulation inputs will act. In add mode, which is how things currently work and which will be the default setting, the modulation input value is added to the knob value to determince the actual time used. In subtract mode the modulation will be subtracted from the knob value and in multiply mode (which is how the modulation once a long time ago worked - and I wanted to have that again) the modulation input will be multiplied with the knob setting to determine the actual time.
  • Osc - Wave morphing on OSC module 2020-01-13: Added wave morphing to the OSC module. The morph input signal is being multiplied by four and then added to the wave selector control value. From this two waves are selected ( sine, tri), ( tri, saw), (saw, square) or (square, sine) and a mix from those two will be sent to the output, proportionally to the morph input value. It is the red input left of the wave selector.
  • 2020-01-15: RandSigs - Clipping for RandSigs module Added scaled clipping control to the RandSigs module. This to be able to make it spend more time at it's extreme values, which may result in more interesting volume patterns, for example (when used for volume control).
  • 2020-01-16: Added pluck level modulation (AM) to Karplus-Strong based modules (KS and Pluck); Added AM input to HrastFilter (and made it a bit less high - pixel wise); Added AM to the HrastOsc. Added AM on SVF flter input; Moog filter, idem. Also AM now for Square, OscTrig, SquareTrig modules.
  • 2020-01-09: ModGateSeq - A modulated gate sequencer Added a modulated gate sequencer, the modulation inputs can enable or disable a sequencer step. That is, a step manually set to one of the active modes can be turned off by setting the mdulation to zero or smaller. When the modulation is above zero a step set active by the buttons will be made active. Unconnected modulation inputs are set to one, so then the step will follow the button setting.

    Steps that are turned off trough the modulation inputs will flash orange instead of yellow. They will not be skipped, but they will not pulse the output.
  • 2020-01-15: ScaledClip - A scaled clipping module Added a scaled clipper. The input values are first being level scaled according to the input type setting. Then they are being multiplied by the set level (level knob setting multiplied by the level modulation input) and clipped into a [-1.0,1.0] range. Finally the signal is being rescaled according to the selected output type.

    The idea is that signals clipped this way will spend more time at their extreme values, i.e. a saw shaped input will be output as a trapezium shaped wave. But it can be used for all sorts of input values to make them spend more time at the extreme values.

in version 2020.1.6.0

  • 2020-01-03: There are some issues with the TextWriter module (considered to be fixed now):

    Changed the TextWriter module to allow it to only write into an existing folder. Also made it so that the text file will now be rewritten when the prefix settings changed.

    When the folder would not exist (or maybe be located on a disconnected network drive) patch changes would get very slow while windows was looking to find the folder. The requirement for the folder to exist is assumed to solve this issue.

    This will not work when windows still thinks the drive to be present, which happens after network issues. Sometimes it will come back, sometimes it will not in which case opening the drive in explorer will help – mostly.

    Added an option to the Settings Screen F3 to allow the TextWriter module to work at all. By default the mechanism is disabled, so if you've used the TextWriter module before you'll now have to explicitly enable it.
  • 2020-01-06: Delay times for the DelayMix module were not set properly, fixed.
  • 2020-01-06: Added three extra delay ranges for the Delay, DelayMix, DelayStereo, Delay8, RndGranulator, Granulator, SimpleGranulator, GrainDelay, Looper and StereoLooper modules. Actually the ranges are the same, but there are 8192 steps instead off the 256 for the existing ranges. This allows for more precission in setting the delay time. All displayed time will show one or more extra digits too now, not only for the delay modules but for all modules displaying time.
  • 2020-01-06: Upped the patch version to 9 to handle the changes made for the delay times properly. Older version patches should still be read properly. The displayed values though will have one or more extra digits, so things may look a bit different (like 110 ms in the medium range will now be displayed as 109.9 ms, but it still is the same actual delay time). This affects not only the delay based modules, but all modules capable of displaying time (like LFOs and envelopes, for instance). I've changed the display widths a bit for the longer representation to fit.

in version 2020.1.1.0

  • Sometimes it would happen that wire speed fixup was not processed correctly. The ouput module, for instance, would have blue input wires making things sound bad (as the signal would be control-rate then). Put a patch on this which seems to fix it, but it is a bit odd all … it depends on the order wires are drawn, a blue <- blue <- blue <- blue <- red chain should be transferred into an all red chain, but sometimes the leftmost two would stay blue.

    As a temporary fix for current versions this can usually be solved by adding a module and removing it again (maybe twice), or by redrawing the affected wire connections. But the issue may reappear when the patch is loaded again.
  • There is a bug in the HardClip module, and maybe in other modules having the Lock option too. When Lock is set to off, on reloading the module the high level will be set to the inverse low level (which should only happen when Lock is set to Mirror Mode. In the Off mode the high an low levels should be independent.

    Solved it by setting the default pairing mode to off instead of mirrored. All other modules with paired knobs already had the default mode set to off. Things will work okay when the pairing mode is turned on in the patch (on the module) itself.
  • When on the module selector the number of tab button rows gets larger than two, modules become mostly invisible and can no longer be selected. To change this I have made the program check for the number of rows and when it gets larger than two the width of the selector will be accomodated to reduce the number of rows to two.

    This will not change the layout when the number of rows was one or two.
  • Fixed a bug in the "new patchname template" where the $N macro was not treated properly.
  • Changed the way module registration conflicts are handled. This used to cause the ini file to be corrupted, not so anymore (an issue encountered mostly during development of new modules).
  • Fixed the text color for the TEdit components on the Settings Screen F3, to make the text more readable. Default is white on grey now, the actual colors are user selectable (edit font color, under colors).
  • Made it possible to hide groups of controls from the toolbar. When made vissibe they will still be in a pre‐determined order. This can be set from the Settings Screen F3, but also there is a popup menu for it on the tool bar as well as there are items for it in the view menu.
  • Got a bit much going on in the OSC tab in the module selector, split it up into OSC1 and OSC2 tabs. Also rearanged the oscillators a bit better by category.
  • Added a freeze input to the Delay module. It will mix the fixed output and the input and that mix will be the actual input to be recorded into the delay line. When unconnected the module behaves as it ever did.
  • Added A, D, S and R lights on the ADSR module, likewise for A, H and D on the AHD one. And then added A, H and R lights on the two AR type envelopes as well.
  • Added an amplitude modulation (am) input to the GVerb module. When not connected it's value is 1, and it is being multiplied by the in level value to set the input attenuation.
  • Added a "1" output on the GateSeq module, it will be active when the sequencer is on it's first step.
  • Made a shuffle input on the seq16 module, it will randomly swap some slider values when activated.
  • Added an End Of Cycle (eoc) output to the EnvARRetrig module. Feeding it back into the trigger input will turn it into an LFO. It can also be used to make a sequence of triggered envelopes. The eoc output will only fire when the envelope curve was completed, so when the module is triggered too fast for completion to occur (it retriggers) this output will not go active.

    Added the eoc output to the EnvAR module as well. This module will not retrigger so it will always complete it's cycle and so eoc will fire always.
  • Added an AM input to the filterbank modules.
  • WavePlayTrig - A triggered wave player Added a triggered wave player module, and a variation on it with variable start point and duration and some more control over the parameters. These are level triggered modules, the sample will start playing once the trigger input goes within the range set with the trigger level and the trigger range. This makes it possible to fire samples from a saw shaped LFO, each at its own time.

    There is a loop mode setting allowing the wave to be played once or repeatedly (as long as the trigger condition is met). The trigger mode can be set to normal or to retriggerable ‐ in normal mode the wave will have to finish before it can restart, in retriggerable mode it can be restarted while playing by making the WavePlayTrig2 - Another triggered wave player trigger condition false and then true again.

    The playback speed can be controlled with the speed and the freq and/or fm controls, negative speeds (playing the wave backwards) are allowed too.
  • Economy - A wealth distribution simulation Added a wealth distribution simulation thingie. It has a pool of 1001 clients and on every internal update clock a transaction will be performed by two clients. Clients can transact only when they have more wealth than - kappa. When they transact the transaction will be some fraction of the wealth of the poorest of the two clients. This fraction ranges from 0% to 5%. When chi (the tax factor) is set to zero this will pretty quickly explode into an oligarchy where one client has all the wealth and the rest in maximum debt (as set by kappa). When chi is upped a fraction of the value of the transaction will be transferred from the richest to the poorest in the transaction and this will stabilize the system. The total internal wealth will be equal to 1001 times the set capital value (which is capital per capita), at least after a reset was issued (when tweaked wildly this may not be true).

    On every input clock a random client is selected and it's wealth will be put on the output. Also a minimum and a maximum wealth is maintained, those values will (also when the clock goes active) be sent to the max and min outputs.

    Now all of this really makes just a fancy random generator where small numbers will occur more often than large numbers (and where larger numbers will be spread out more in range as well), and as such it might be of musical use, especially when combined with the MinMaxRange module (see below) to make the output range more predictable. But also, it seems to make a nice rainy type of noise.

    The internal update clock will either run at the sample rate or at the control rate, depending on the module being connected to a fast (red/yellow) or to slow (blue/green) modules only. The min and max values are recalculated once every 1001 internal clocks. For fast output clocking the min and max values may not always be accurate (as it could clock faster than the 1001 cycle period time). The numbers on the left show the current min and max wealth.

    1001, a thousand and one nights she sat beside the sultan's bed. But also it is 7 x 11 x 13.
  • MinMaxRange - A range scaler with min and max inputs Made a MinMaxRange module. This is a scaler module for the case where the minimum and maximum values of a signal are known (as for instance in the Economy module above). The module will transfer a signal (sig) that moves within a range min to max into a range [0,1].

    When the minimum value happens to be larger than the maximum value the module will still return valid output values, but it will work inversely (where the largest input value will map to zero instead of one).

    Signals that are outside the [min,max] range will also be handled but will end up as an output signal outside the range [0,1] .

    When the minimum and maximum values are almost equal the minimum value will be returned for whatever the signal value happens to be.
  • EqDivQuantizer - An equal division quantizer Made an equal division quantizer. An "octave" can be set which will be divided into the set number of divisions, all intervals thus created being equal in size. An "octave" of 2 is the usual octave, and 12 divisions will then create the usual 12EDO, 12TET or chromatic scale. The input range can be trimmed down with the range controls, these are common for all four channels.

    The lights will indicate errors in the entered values (i.e. values that are not understood by Wren.
  • Branches - A quad Bernoulli gate after the Mutable
          Instruments braches module Made a replica of the Mutable Instruments Branches module, or the Bernoulli gate as it is also named. The Wren version has four gates, however they share a common mode- and p-parameter.

    The module has four modes of operation:
    • normal: on a rising input edge with probability p the topmost output will be turned on and otherwise it will be the bottom one. On a falling edge both outputs are being turned off.
    • toggle: on a rising input edge with probability p the inactive output will be turned on and otherwise it will be the active one again. On a falling edge both outputs will be turned off.
    • lnormal: or latched normal, as the normal mode, except the currently active output will stay active until the other one gets active.
    • ltoggle: or latched toggle, as the toggle mode, except the currently active output will stay active until the other one gets active.
    Made the output indicators bi-color, as the Mutable one has them. Dark means both outputs are off, yellow means the top output is active and orange indicates the bottom one being active.

    The probability p is determined by the sum of the p knob and the p input. The resulting value will be clipped to a [0,1] interval.
  • RateMult - A Quare wave rate multiplier Made a square wave rate multiplier. It Takes a square shaped input and then turns every edge in it into a pulse. It does not try to square up the signal, so the duty cycle information is lost. Modules can be cascaded to get 4, 8 etc. rate multiplications (but the pulses will not be spread out evenly then).

in version 2019.11.12.0

  • 2019-11-12: Oops … made a bug in the WavePlayer which causes it to not always play, fixed it for version 2019.11.12.0.
  • 2019-11-12: An undocumented new module for Gabe to check out.

in version 2019.11.11.0

  • Fixed a bug causing occasional memory allocaton errors in the eSpeak module.

    Added a check to see if ESpeak had actually been installed by reading HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{7192AA2F-F759-43E9-91E7-226371EF6B2F}\1.0\0\win32 from the registry, when that key is present and it's (default) value points to an existing file, it is assumed ESpeak was installed (at one time at least …). I'm not sure this will always work … this key is defined in the ESpeak source code for version 1.48.04, but it might break on later ESpeak versions.
  • Fixed a bug in the ProgDivider module which caused it to set out of range division values under some conditions. Also the divider could get out of sync when the counts were changed, that is it would get triggered on the oposite input edge, fixed this too.
  • Fixed the multiplex module such that it will no longer go out of range and also fixed the crossfading for it to work properly when less than the maximum amount of steps is set. The demultiplexer had the same issues, fixed those too.

    Added a changed output to both the mux and demux modules which will generate a short trigger pulse whenever the selected step changes.
  • Removed a handful of range errors and divisions by zero and such. Did not run with range, overflow etc. checking enabled for a a good while ‐ I should have! (after all it's Pascal :-)
  • It seems to not be possible to have a single quote character in a patch name. Something to look into. Ok, this was a patch writer issue it did not do proper quote escapement (the patch reader already did it right). The same problem would arise on module titles with quotes in it. I've fixed this for both cases. User typed string values in edit controls were properly escaped already. Now there still may be an issue with multi‐line string values … k … the patch reader would not read line‐feed characters, which is fine for everything except for the value popup editor ‐ fixed this as well.
  • When oscillators are copied from a patch into another one in another instance of Wren with a different tuning being set, the new tuning is either not being applied or not visible in the user interface. Currently the only way to fix it seems to be to alter the tuning and then undo that. This will probably apply to all tuning sensitive modules, filters for instance. Indeed, the tuning of the imported modules is applied to the patch instead of the tuning of the patch being applied to the imported modules. This will probably go wrong with importing saved module clusters from file as well. Fixed it, only loading a completely new patch will affect the current tuning parameters, and none of the pasting or module read options will do so.
  • Fixed a "bug" on the Looper and StereoLooper module where it would not output any sound until the speed knob changed position. Also changed the speed input for the WavePlayer module to have a default value of 1 (to make the wave being played without any furter connections, when you'd want a "standing wave" connect the speed input to a constant zero value).

    Later I've added a selector for the speed mode, by default it is on which makes the wave to be played at regular speed. When turned off it makes the wave stand still. When the speed input is connected to something however this will override the speed mode setting. So you can now have it function in both the old and the new way.

    When the wave stands still it can still be played by varying the pos input, for instance by connecting a saw shaped LFO to it.
  • Fixed a bug for the Constant, SeqValues, Lut and Knobs4 modules where, when the mode was set to "note", the value knobs and sliders affected by this mode would loose their value on module copy or patch reload. These were all cases where the step count of the associated control would change with the selected mode.
  • Fixed a bug for the SeqValues module where wrongly colored dots could be set on the P, S and E controls.
  • Changed the Vocoder FFT overlap from 75% to 50%, with the Hann window used 75% created some nasty squeals at 1/3 of the sample rate (which of course I didn't hear in my old ear ;-) ‐ but the spectral analyzer …

    And while at it, I made the FFT size user selectable. A larger size first will sound better afte which it tends to smear things, but also a larger size will give more processing delay.
  • Changed the WavePlayer module to always play at the same rate, indepent of the current sample rate. It still only accepts 44k1 stereo or mono wav files.
  • Made the VU meter update rate independent of the lights update rate, it is fixed now at a 23.8Hz rate.
  • Added two macro's to the TextWriter module. %patchname% will be substituted by the name of the current patch and %prefix% will be replaced by the TextWriter prefix value, which can be set trough the Settings Screen F3 ( when prepend prefix is checked it will be prepended always, when it is not checked it will be prepended only when the %prefix% macro is used in the TextWriter module ‐ the prefix value itself can be left blank too when no prefix is wanted).
  • Added an active input to the eSpeaker, when active speech will proceed, when not it will be frozen in-place. With an SR flip-flop triggered from an LFO and reset from, for instance, the word trigger out of the module, speech onset can be synced to the LFO. It will still be async while it runs, and this will cause clicks due to the abrupt starting and stopping, but at least it's synced a bit.
  • Added inverted outputs to the RangeConverter module, where the regular ones go up the inverted ones go down (over the same range), and vice versa.
  • Added changed outputs (in the column marked "C") to the seq16 module. These will go active briefly when the associated sequencer output changes.

    And also added clear inputs for "one", "some" and "all", similar to the randomizer. The some inputs will clear or randomize four steps that are separated by four steps. The starting step is chosen randomly from the first four inputs.

    Added three extra chain inputs, to make it possible to chain all four sequencer lines. Some patches may need modification (connect the original one chain input to the three new ones) for it to function the same way as it did before. This is the columne of inputs marked with "c"
  • Added an "am" (amplitude modulation) input to the basic Osc module.
  • Added an "am" (amplitude modulation) input to the Looper and StereoLooper modules.
  • Added shape warping to the basic LFO module. This acts like PWM for a square output, a triangle can be morphed from saw to ramp, etc. This works for all the wave forms, but the random waves will not be much different on warping.
  • Added a range selector to the ARRetrig envelope module. This allows for way longer times to be set for it. For patch compatibility it will come up with the default fast mode (it always had).
  • Added module feedback to the edit history window, a selected history item will now highlight the associated module in the patch editor.
  • Added a brownian noise mode to various random generators.
  • Added a Filter mode to the PulseDelay module, this will cause it to only be able to re‐fire after the input was inactive for a couple of sample times ( depending on the control rate divisor). The ouput is quaranteed to stay low for a couple of sample times after the stretch period ended. This makes it possible to set a maximum rate for the output to fire. For instance, when the input rate is 1Hz and the filter time is set to 2.5s the ouput will fire no more often than once every 2.5s, so in this case it will fire once every three seconds. This differs from the stretch mode where with the same settings the ouput would never go low.
  • PADSynth - a PADSynth module Added a PADSynth like module, it use IFFT to generate sound from a spectrum which is created by a set of faders and some extra controls for spread, peak bandwidth and bandwidth scaling with frequency. Some of the controls are clicky as the IFFT has to be recalculated (and I was too lazy to make fades for that). Also this does not fully implement the PADSynth, it just uses it's basic ideas as laid out by Nasca Octavian Paul ‐ anyways, it can make some nice sounds.

    The faders set the spectrum, the bw (bandwidth) controls set the width of the spectral peaks.

    The spread parameter manipulate how the spectral peaks will be spread.

    The module works by generating an in‐memory waveform from the spectrum. This waveform can be played at different rates and from different positions by using the position speed and frequency controls. At some stage I should modify this to have multiple wave forms to be generated with cross fading implemented over that, too lazy for that now.

    The module has a stereo output, a diffrent tap point is used that for that on the calculated wave.

    The IFFT size to be used can be set, small values will act a bit weird, anything up from 8192 seems okay. Values from 64 to 262144 can be used.
  • The 300th module :-)

    GrainDelay - a GrainDelay module Added a new granulator type module, working better than the three existing ones. It has a delay line able to hold 5 minutes of audio and a maximum of 128 grains can be set (provided that the CPU can cope with that).

    It has grain controls for pre-delay, spread (or grain distance), pan, duration, frequency, speed and amplitude. All these controls can be modulated. Additionally the amount of grains can be set from 1 to 128, and this can be modulated too.

    Several grain envelope types can be set to change the sound character: bell, pulse, exp, reverse exp, tri and box, for all of these there is a noisy variation as well.
  • Smear - a Smear module Added a smearing module … why? because I could. It smears the phase of the incoming signal with a controllable random amount and it adds some delay, FFT based.
  • MinMaxMix - A MinMaxMix module Added a MinMaxMix module after an idea from an idea from Ricko at the electro-music.com forum. When both input signals are positive the ouput gives the largest one of them. When both are negative the output is the smallest one. When the signs are opposite the sum of both inputs will be sent to the output.
  • PhaseSplitter - A phase splitter module Added a PhaseSplitter module, it will split the incoming signal into two signals that are 90 degrees out of phase. This can be used as a building block for various audio effects. for instance the Bode frequency shifter internally makes use of the same splitter code.
  • Detector - A detector module Added a Detector module, it will split the incoming signal into two signals that are 90 degrees out of phase, thus "complixifying" it. It will then use the complex signal to derive instantaneous amplitus\de, phase and frequency. This works properly only for sine shaped signals, but also "sort of" (as in "nicely") for more complex signals. I've used it to analize a voice signal to control an oscillator to implement pitch shifts on that voice.
  • AbsAdder - An absolute value adder Added an AbsAdder module, it adds up positive input values only, all negative inputs are clipped to zero. This is a sort of a "Micky Mouse" logic "OR" function, the ouput will never go negative.
  • DTMF - A DTMF tone generator Added a DTMF tone generator. It's input value range 0 .. 1 is scaled into a range 0 .. 15 which then is used to select a symbol from [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, #, *]. The symbol then is converted into two tones according to the following table:

      1209 Hz 1336 Hz 1477 Hz 1633 Hz
    697 Hz123A
    770 Hz456B
    852 Hz789C
    941 Hz*0#D
  • Sieve - A number sieve module Added two Xenakis like number sieve modules, one with a blue (addressing) input control and a clocked version.

    Wren's notation for basic modules is:

    • [n,m] : a sieve module with modulus n and residue m [3,1] -> {1,4,7...}.
    • {numbers|n} : a litteral number sequence, f.i. {1,5,13,14,21|24} n is the modulus, 24 in this example. ClockedSieve - A clocked number sieve module
    • fibonacci : the fibonacci sequence {0,1,1,2,3,5,8,13...}.
    • prime : the prime numbers {2,3,5,7,11,13...}.
    • hanoi : the hanoi disc sequence {0,1,4,5,8...}.
    • hanoipegs1 : hanoi peg sequence 1 - non alternating {0,1}, {0,1,3,5} , {0,1,3,5,6,6,7,8}.
    • hanoipegs2 : hanoi peg sequence 2 - alternating {0,2}, {0,1,3,5}, {0,2,3,4,6,6,8,10}.
    • hofstadterq : the Hofstadter Q sequence, chaotic.
    • metafib(n) : genralization of hanoi, n being the order, a whole number.
    • random(f) : a sequence of random numbers, f selects the chance for any number to be present in the sequence. 0 <= f <= 1, f.i random(0.33).
    These can be combined using the following operators:

    • + : the union of two sieves: [3,0]+[4,0] -> {0,3,4,6,8,9,12...}, the numbers combined (logical or function).
    • * : the intersection of two sieves: [3,0]*[4.0] -> {0,12,24...}, the numbers present in both (logical and function).
    • ^ : the symmetric difference of two sieves: [3,0]^[4,0] -> {3,4,6,8,9,15...}, the numbers in one but not in the other (logical xor function).
    • ! : the complement of a sieve: ![3,0] -> {1,2,4,5,7...}, the numbers not in the sequence (logical not function).
    Parenthesis can be used to enforce an evaluation order, f.i. as in (([3,0]+4,0)* fibonacci)+prime to first evaluate the left +, then the * and the right + last.

    A simplified formula will be calculated when the formula changes, or when the external period changes. The simplification does not use prime decomposition, it will compute a sequence and from that it will make a sequence of modules joined through union.

    The evaluate input will force reevaluation of the formula, this can be useful when a random module is present to obtain a new random sieve.

    Otherwise this module functions like the Values module, except that the start value will always be 0 (zero) and the end value is set by the external period. This means the input value changing over the standard range as set up with the input range selector will address all sieve values.

    The difference (top) output will output differences between sieve sequence values, in case the last sequence value was selected it will be the value of the last minus the first element (this cyclic behaviour was not present in the original concept).

    Negative numbers can not be used in sieves and the random sieve's probability control is the only floating poin number being used. The ouptuts will still use float values, as they are scaled to standard output ranges ([0,1, [1,0], [-1,0], [0,-1], [-1,1] or [1,-1].

    The simplified formula is displayed above the user supplied formula, or an error will be displayed when the user supplied formula could not be parsed.

    The currently selected sequence and diffrence values are displayed in white, these are the unscaled values.

    The changed output will go active when the ouput value was changed, the difference output may not have changed then.

    The regualar (bottom) output will be scaled such that the external period results in an internal output of 1, this can be changed then with the output type selector.

    The difference (top) output will be scaled such that the largest difference value present will result in an output value of 1, again this can be rescaled using the output type selector.

    For more information on the subject try googling for Xenakis sieve, or Xenakis sieve algorithm. It may find a 221 page paper by Dimitrios Exarchos (Iannis Xenakis and Sieve Theory), I've found that to be a very useful text.

Older release notes

License information

(C) COPYRIGHT 1999 … 2020 Blue Hell / Jan Punter

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation;

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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Blue Hell is a trade mark owned by

    Jan Punter

    Oogstplein 6

    7545 HP Enschede

    the Netherlands

    https://bluehell.nl/

    

You can send me a PM through the electro-music.com forum, my user name there is Blue Hell.

All rights attributed to Blue Hell are owned by Jan Punter.

For GNU license details see license.txt.

Acknowledgements:

  • The icons for the 'gabe' look were made by .. gabe, also known as LfoHead on the electro-music forum. Thanks Gabe, they are great!
  • The Hrast modules and the file HrastUnit.pas are Copyright HrastProgrammer.
  • The included freeverb unit is copyright 'Thaddy de Koning / Jezar' and was modified by me to fit in better.
  • The included OSCif unit was downloaded from github and modified for use in Wren.
  • The included portaudio material is Copyright (c) 1999-2006 Ross Bencina and Phil Burk. The DLL provided here was compiled from this source [you will have to obtain the ASIO SDK yourself through Steinerg, it is NOT included. The source contains some hints about how to do this] using Visual Studio 2013 Express. I had to make some minor changes to the configuration in order to get the code to compile under VS2017. Also see http://www.portaudio.com/.
  • The included FFTW material (used for Fourier transforms in some modules) is Copyright © 2003, 2007-11 Matteo Frigo, Copyright © 2003, 2007-11 Massachusetts Institute of Technology. It was modified to be used in Wren.
  • The Talkie related code and the words.lpc file are Copyright 2011 Peter Knight This code is released under GPLv2 license, and it was modified to be used in Wren.
  • The included GVerb code came from github, the copyright message reads : Copyright (C) 1999 Juhana Sadeharju, published under a GNU General public license. I translated the C code to Pascal.
  • The resonator code was modeled after Katjaas complex integrator that I found at katjaas.nl.
  • The frequency shifter was copied from the Ladspa bode shifter that I found at github.
  • ModTerragen uses some code that I found at mobeard.org.
  • For some of the envelope generators I found inspiration at musicfsp.org.
  • The Formant filter found it's origin at musicdsp.org.
  • Some ideas that are in the Euclidean modules came from the electro-music forum and pdpatchrepo.info.
  • The SVF module (not the Hrast SVF but the plain SVF) used some ideas found at musicdsp.org and in the following pdf file: www.music.mcgill.ca/~ich/classes/FiltersChap2.pdf.
  • The Pink Filter found it's origin at musicdsp.org.
  • The Lorenz and Rössler attractor modules are based on code made by Thaddy de Koning (www.thaddy.com - (c) 2005) / Russell Borogove (www.tinygod.com - (c) 2004).
  • The WaveWiper was made after an idea published by PHOBoS, I got it from electro-music.com.
  • Some wave wrapper modes were based on code and ideas found at muffwiggler.com.
  • The 'Poetry' generator was modeled after an idea by Johnathan Mackenzie from his Phd thesis 'Using Strange Attractors To Model Sound'.
  • The convolution code was built after the code found at github.
  • The Rungler was built after an idea from Rob Hordijk, for more info look at hordijk-synths.info.
  • Some of the speech synth ideas and some of it's code came from the Tiny Speech Synth by 'stan 1901'.
  • The BSpline code used in the DataMaker component was written by M. v. Engeland, I made a couple of minor changes only to make it work in Delphi XE5/XE10. Please see the source code (BSplines.pas in the knobs2013 directory) for details.
  • For the speech stuff I have used C++ code from the Tiny Speech Synth written by Stepanov Andrey which I translated to Delphi. See tss.pas and Speech.pas for details.
  • The TuneSmithy idea came from Robert Inventor.
  • The PADSynth idea came from Nasca Octavian Paul.
  • The Moog filter type was found at github. The following information was requested to be made available on reproduction of the code:

    Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  • For the DaringFireball mark-down processor used in generating the help docs I used code from Grahame Grieve. This in turn was a port of the TxtMrk mark-down implementation by René Jeschke. I've modified the code a bit for layout / readability reasons.
  • Andreas Trepte supplied the original picture of the wren, this was made into a logo by epwhorl and I modified it a bit later.

I may have forgotten some but I believe the list above to be fairly complete – please check the source code for more information. Thanks to all who so generously published their code for others to use and learn from.



fin