Fast Fourier Friday

In theory you can make a system of equations that generates whatever. In practice getting the functions to do something reasonable may take some effort.

    #!/usr/bin/env perl
    use 5.36.0;
    use MIDI;
    my @Midi_Events;

    my $notes = 256;
    my $t     = 0.0;
    my $dt    = 0.1;

    use constant {
        MIDI_CHANNEL  => 0,
        MIDDLE_C      => 60,
        NOTE_DURATION => 24,
        VELO          => 96
    };

    sub compute ($t) {
        MIDDLE_C +
        ( 12 * sin($t) ) +
        ( 7 * cos( $t * 3 ) ) +
        ( 5 * sin( $t / 2 ) )
    }

    sub constrain_pitch ($p) {
        $p > 100 and die "pitch too high";
        $p < 20  and die "pitch too low";
        $p
    }

    sub make_note ($p) {
        state $offset   = 0;
        state $oldpitch = -1;
        if ( $p == $oldpitch ) {
            $offset += NOTE_DURATION;
        } else {
            push @Midi_Events,
              [ note_on => $offset, MIDI_CHANNEL, $p, VELO ],
              [ note_off => NOTE_DURATION, MIDI_CHANNEL, $p, 0 ];
            $offset   = 0;
            $oldpitch = $p;
        }
    }

    for ( 1 .. $notes ) {
        my $pitch = constrain_pitch( sprintf "%.f", compute($t) );
        say $pitch;
        make_note($pitch);
        $t += $dt;
    }

    MIDI::Opus->new(
        {   format => 0,
            ticks  => 96,
            tracks => [ MIDI::Track->new( { events => \@Midi_Events } ) ]
        }
    )->write_to_file( shift // 'out.midi' );

Or much the same in LISP, if you're into that sort of thing.

    (require :asdf)
    ; https://thrig.me/src/smolmidi.git
    (asdf:load-system :smolmidi)

    (defconstant +note-count+ 2048)
    (defconstant +middle-c+ 60)

    (defconstant +delta_time+ 0.1)
    (defun compute (time)
      (+ (* 12 (sin time))
         (* 7  (cos (* time 3)))
         (* 5  (sin (/ time 2)))
         +middle-c+))

    (defun constrain-pitch (pitch)
      (cond ((> pitch 100) (error "pitch too high"))
            ((< pitch  20) (error "ptich too low")))
      pitch)

    (defconstant +velo+ 96)
    (defconstant +note-duration+ 24)

    (let ((offset 0) (oldpitch -1))
      (defun make-note (track pitch)
        (if (= pitch oldpitch)
          (incf offset +note-duration+)
          (progn
            (smolmidi:note-on  track offset          pitch +velo+)
            (smolmidi:note-off track +note-duration+ pitch 0)
            (setf offset 0)
            (setf oldpitch pitch)))))

    (defun make-track ()
      (let* ((track (smolmidi:new-track)))
        (loop repeat +note-count+ with time = 0.0 do
              (let ((pitch (constrain-pitch (round (compute time)))))
                (format t "~a~&" pitch)
                (make-note track pitch)
                (incf time +delta_time+)))
        track))
    (defun make-tracks () (list (make-track)))
    (smolmidi:write-midi-file "snc.midi" (make-tracks))

By changing the equation used and various other filters, quite different music can be produced, for instance with an updated "compute" subroutine and to filter duplicates by a wacky pitch class (mod 7; mod 12 would be more typical) instead of by raw pitch. The note duration is also good to play around with; a short duration such as 8 may better let you hear the shape of the equation as it will be traced out quite rapidly.

    ...
    sub compute ($t) {
        MIDDLE_C +
          ( 12 * sin($t) ) +
          ( 11 * sin( $t * 24 ) ) +
          ( 3 * cos( $t / 7 ) ) +
          ( 7 * cos( $t * 3 ) ) +
          ( 5 * sin( $t / 2 ) );
    }
    ...
    sub make_note ($p) {
        state $offset   = 0;
        state $oldpitch = -1;
        if ( ( $p % 7 ) == $oldpitch ) {
            $offset += NOTE_DURATION;
        } else {
            push @Midi_Events,
              [ note_on => $offset, MIDI_CHANNEL, $p, VELO ],
              [ note_off => NOTE_DURATION, MIDI_CHANNEL, $p, 0 ];
            $offset   = 0;
            $oldpitch = $p % 7;
        }
    }
    ...

Or how about some whole tone action?