ForSynth, a small sound synthesizer project 🔊

I have just released Forsynth 0.1 “Stockhausen”:

You can build it using fpm or the script.

It’s more fun to compute
It is a translation of a C project I am using with my students. Music, like graphism, helps teaching programming: as Kraftwerk sung in 1981, “It’s more fun to compute”.

That first version is named “Stockhausen”, one of the first composer to investigate sound and music using sinusoidal generators. And that’s all you can do with that first version: play sinusoidal waves! I have around sixteen more C procedures to translate in Fortran: next ones will be add_note() because a note is a sum of sinus (harmonics), and add_major_chord() because a chord is a sum of notes.

But you can already have fun by using Frequency Modulation to create weird sounds. For example replace the sinus by sin(omega*(1.0+0.001*sin(t*500)) * t + phi) and you should hear:
FM synthesizers were a revolution in the early 80’s and invaded pop music.

All comments, ideas and contributions are welcome. I would be happy to learn “new” Fortran paradigms if it brings interesting features in that small fun project.

Concerning the license, if you are interested by the project, please tell me your opinion. I personally like the GPL but I know it can be perceived as an inconvenient.


The project is now much more interesting with these new routines:

  • add_note() to generate a note with a sum of harmonics.
  • add_major_chord()
  • add_minor_chord()
  • ADSR_envelope()
  • add_karplus_strong() for plucked-strings
  • apply_delay_effect()

The main program now calls demo1() which plays and repeat Am C G Dm chords on track 1 with a synth, and plays a stochastic melody on track 2 using the A C G D notes played with plucked-strings (and applies delay on that track). The output file is named demo1.wav.

The Karplus-Strong algorithm is a quite simple algorithm but very interesting:

1 Like

Here is a string simulation code that I wrote some time ago:

1 Like

Thanks @certik ,
it will be something to try. Physical modeling synthesis was introduced in commercial synthesizers in the middle of the 90’s. Have you ever tried to make it sound?
Concerning the MIT license, if I have well understood I could copy parts of the code if I copy the text of the license and copyright with it, whatever the license I choose for my project?

1 Like

@certik , you might have forgotten to push your local changes. The available .f90 files seem to be just copies from your fortran-utils library.

@ivanpribec isn’t it that file ?

1 Like

I have no experience with teaching programming with graphics or music, but I really agree that these kinds of things are fun for learning or using computer programs :slight_smile:
In my case, I started programming with game programing in (a variant of) BASIC, to make a (very primitive) 2D shooter and adventure games… The machine power at that time is too weak, so the game play was rather slow, though. I guess recent PCs (or even smartphones) are really nice because the power should be more than sufficient for such a fun programming.

1 Like

Yes, my experience is that it is very motivating for students because the program produces something concrete for their senses: sound, pictures (or even movies)…
Concerning sound, you can give them the procedures that create the WAV file and ask them to write various procedures to compute waveforms, sound effects, algorithmic music, etc. And you can adapt it to any level: for example it’s also possible to teach things around Fourier, like FFT to make sound filters. Sound being waves, most mathematics and physics concerning waves can be used and teached in that way.

Concerning graphism, I use sometimes a C project which writes POV-Ray files, then calls POV-Ray to generate the pictures, and ffmpeg to build a movie.
This year I also used the STL format used by 3D printers. It can also be used just to visualize 3D objects on screen. Simple but efficient. A good opportunity to do geometry in 3D space.

1 Like

@ivanpribec, yes it is the file: src/tests/test_wave.f90 · 26a0ad4612e3f2e1ac8d5e0eb42b96ae49e7b3e2 · Ondřej Čertík / stringsim · GitLab

@vmagnin the file is using a simple finite difference solver to solve the non-linear string equation, from the referenced paper which explains the details, and it is for a piano string, although it should work as a guitar string also. So physically it is solving the actual equations. Yes I tested how it sounds and it’s not bad — it decays and I tested it against a real piano, and it is quite similar.

1 Like

P.S. I should convert it to use fpm, no need to physically copy files from my utilities project anymore!

1 Like

This is really cool to see! Looking through the forsynth.f90 file it looks like the duration (among other settings) are hard-set at compile time with global scope parameters. Are you thinking of making these parameters tweek-able (edit: at runtime) ?

1 Like

Yes, it is a translation from C of a small project. My first objective is to translate fast a few more C subroutines. When over, the code can be refactorized.
DURATION could be an argument of the create_WAV_file or write_header subroutine. Also the number of TRACKS: for the moment it’s 8 tracks, but the demos use only the tracks 1 and 2… Concerning the RATE or MAX_AMPLITUDE, it does not seem really useful, the hard-set values correspond to the quality of a CD.
Any ideas and help are welcome. I don’t know for example if OOP could bring something, or coarrays (I have not yet learned that feature), or any other Fortran feature I have not think of?

OOP could be nice, especially for folks looking to link in a library into their own codes. It’s helpful to know which parameters would be best left hard-set in a dictionary. I’ll see if I can mock up an OOP implementation on a fork, to help explore what this could look like and potentially offer in terms of functionality. I’m looking forward to the remaining routines you’re bringing in!

1 Like

I have added the remaining routines (there are still some other routines, but still experimental in the C version). And released Forsynth 0.2 “Daft Punk”

Your proposition will be a good opportunity for me to learn OOP in Fortran. I am eager to see the result! Feel free to refactor the code. For example the way the envelope is managed is not elegant.

@alozada has also posted a proposition here: Build and check files · Issue #1 · vmagnin/forsynth · GitHub

And I had some idea that we could probably use function pointers to tell some routines to use a particular signal or envelope or filter…

On my side, I think I will create a module scales where I will compute the frequencies of all notes and store them into arrays. And also create arrays to store some musical scales, like chromatic scale, C major, Am, a blues scale, a pentatonic scale, etc. It will be useful for composing.

And if someone finds good algorithms for drums… I tried things like \frac{sin(x)}{x} or Karplus-Strong extended to drums. But I have not yet found something convincing for good bass drums.

Tell me also your feeling about the license (no license for the moment).

1 Like

I’m generally comfortable with MIT and Apache 2.0 licenses for open-source projects that I work on. That being said, the Anti-Capitalist Software license is an interesting option if you want to restrict usage to individuals, NPOs, co-ops and B-Corps, and educational institutions.

Of course enforcing the license is always a challenge in the open-source world, and the ACSL has not yet been demonstrated to hold up in court. As the website states

Is this actually enforceable?
Copyright is easier to apply to how a work is used than to who uses it, and this license has not been tested in court. That said, using ACSL software against its terms would open the user to litigation. ACSL may be best considered a strong deterrent, as well as a way to state the politics and moral center of your code.

While replying in the thread on Fortran calling R I discovered a nice-looking book - Sound Analysis and Synthesis with R. Chapter 4 (in the previous link) describes some of the objects used for manipulating sound.

1 Like

I have just released ForSynth 0.3 “Éliane Radigue”, a hobby long term musical project under GPL-3.0-or-later license. As indicated by the version number, don’t expect a stable API for the moment. I have made heavy refactoring, especially moving toward OOP, and I will continue. See the and files for more information.

You can now run the seven examples with the fpm run --example command. Start with that nice example:

$ fpm run --example chords_and_melody

And play the chords_and_melody.wav generated file.

Any ideas and comments welcome, especially on my Fortran OOP programming as I am still a beginner.

1 Like

ForSynth 0.4 “Jean-Claude Risset” has been released. The most interesting changes are:

  • new effects: apply_reverse_effect, apply_fade_in() and apply_fade_out() subroutines.
  • add_broken_chord() writes a broken chord using an array containing the intervals. It uses plucked strings obtained with the Karplus-Strong algorithm.
  • An ADSR_envelope object can now be passed optionally to basic signals.
  • The method mix_tracks() now accepts an optional array with the panoramic settings of each track (for stereo).
  • New examples:
    • a Shepard scale, giving the illusion of an ever increasing pitch in the first half of the tape and an ever decreasing pitch in the 2nd half.
    • A Shepard-Risset glissando, giving the illusion of an ever increasing pitch. It is the continuous version of the Shepard scale. Not yet perfect, something is resisting my efforts… :thinking:
    • A simulation of Doppler effect, with a car passing in front of you.
    • arpeggios.f90: arpeggios played in various ways using the circles of fifths. Well, it is nor Bach nor “Golden Brown”, but it does not sound ridiculous for something quickly coded without much thinking. That is the magic of the circle… :magic_wand: