ForSynth 0.5: music, acoustics 🔊 and data sonification

ForSynth 0.5 “Daphne Oram” was just released in the wild. Since version 0.4 last year, the main novelties in this hobby project are:

  • the src/sonification.f90 module with sonify_from_array() and sonify_from_file() subroutines, to transform your data into a WAV file. The app/sonify.f90 associated command eases its use. Its options allow to autocenter the “signal”, to downsample it if the tone is too low, and to repeat it. By “signal”, I mean any array of reals with some oscillations. By default, you need 44100 samples per second.
  • example/radioactivity.f90: you can hear the simulation of the radioactive decay of a population of atoms heard with a Geiger counter, with chords in a whole tone scale and a Morse code message (src/morse_code.f90 is offering basic Morse code support). Listen to the Ogg file.
  • example/multiplication_bells.f90: a demo heavily using the add_bell() signal added in src/signals.f90. It is based on Jean-Claude Risset’s bell signal #430 (in his 1969 report) with 11 partials (bells have no harmonics but partials). Some partials are very close to simulate the beating that can be heared when a bell is ringing (due to the fact that real bells are never perfectly symetrical). Listen to the Ogg file.
  • src/audio_effects.f90: a basic apply_dynamic_effect() that can be used for downward/upward compression or expansion, or as a limiter depending on the parameters.
  • example/shepard_risset_glissando.f90: I have finally fixed that example. Each sin(\omega t) is in fact sin(\omega (t) \times t) and using a common time for all components was causing problems as t was increasing (the global pitch was slowly increasing instead of staying stable). In this new version, each component has its proper time: sin(\omega (t_j) \times t_j). Listen to the ever increasing Shepard-Risset glissando and the ever decreasing glissando.
  • In example/README.md, links to listen to the OGG files of every example were added.
  • Finally, a FORD documentation is now available.
  • See the release notes for more information.

If you try the sonification feature, please share your audio data. I love sounds, especially weird sounds :slight_smile:

And if you wonder who is Daphne Oram (1925-2003), listen to Pulse Persephone (1965).

6 Likes

Hey @vmagnin. Great work! ForSynth has been on my need-to-check-out list for a while (as someone who’s been into sound synthesis and audio engineering for 2 decades). Question: In its current form, how quick/easy would it be to use the lib to demonstrate classic data series manipulation like low-pass filters? And have you tested it with LFortran? I’m wondering, because it may come in handy when I create new Fortran-based teaching materials for data science (I try to diversify application examples, and using sound would be quite fresh and interesting).

1 Like

Thanks @fxm,

for the moment, audio effects are limited to the simplest ones: apply_delay_effect, apply_fuzz_effect, apply_tremolo_effect, apply_autopan_effect, apply_reverse_effect, apply_dynamic_effect. But you can of course apply any kind of filter if you have such codes. The main class in ForSynth is tape_recorder_class which contains the audio tracks (just arrays of reals). Any code acting on an array of reals can therefore be used to manipulate the sound.

And of course, contributions are welcome if you are familiar with sound synthesis! Generally, I have some time to work on it each Spring (northern hemisphere), one year after the other. It is a hobby project, so it advances slowly. In fact, I started around 2014 but in C language. I used it many times as a final project (4x2 hours) in a programming course. Generally, students are first intimidated then really take fun with it. Curiously, I have never really succeeded in really guiding them toward synthesizing fun or weird sounds (but their department is Materials Science, not electronics or computer science). They prefer to reproduce the melodies of well-known songs. And its twin project ForMIDI was also used successfully for that.

Finally, I have not yet tested it with LFortran. I am using GFortran and Intel ifx.

1 Like

Thanks for the explanation, @vmagnin.

This is exactly what I was hoping for! :slight_smile: The idea would be for students to implement different data series filters and apply them on arrays of all kinds (time series, bitmaps, sound) so students get a better intuitive feeling for the methods and the structure behind different data. I don’t know how soon I’d be able to include it anywhere, but I’ll bookmark it as a resource for it!

I understand well. I had started working on a game engine in 2018 and was only able to return to it over summers, but without continuity, it takes extra time to get back into it.

1 Like

If you look at forsynth/src/audio_effects.f90 at main · vmagnin/forsynth · GitHub you can see for example that applying a delay effect is just adding to the sample i a sample j placed before on the track, multiplied by a dampening factor Amp<1:

        id = nint(delay / dt)
        do i = nint(t1*RATE), min(nint(t2*RATE), tape%last)
            j = i - id
            if (j > 0) then
                tape%left(track,  i) = tape%left(track,  i) + Amp * tape%left(track,  j)
                tape%right(track, i) = tape%right(track, i) + Amp * tape%right(track, j)
            end if
        end do

Very simple but it sounds good! And you can even apply two different delays to try to sound like The Edge :sweat_smile: Listen the plucked strings in that example.

1 Like

With the new sonification subroutines, it is even easier, like in the file forsynth/test/sonify.f90 at main · vmagnin/forsynth · GitHub :

    ! Generating a simple signal:
    array = [(sin(i*0.01_wp)*cos(i*0.1_wp), i = 1, N)]
    call sonify_from_array(signal=array, output_file="test_array_sonification.wav", downsampling=4, repetitions=4)
1 Like

Thanks, @vmagnin. That’s all really helpful. Bookmarked the thread also, so it’ll be easier to get into at a later point. :slight_smile:

1 Like