Python to .repatch (Mutator)

This forum is for developers of Rack Extensions to discuss the RE SDK, share code, and offer tips to other developers.
Billy+
Posts: 4150
Joined: 09 Dec 2016

Post 03 Nov 2023

Enlightenspeed wrote:
29 Oct 2023
Hi Billy,

I was curious about this, so did some digging around for my own amusement. Turns out MIDI is an uglier beast than I originally imagined! I've written some code for reading it now (without using any Python imports) but in order to help you with your cause, and to turn it into repatch files, could you give me a small subset of the dictionary you are using?

I would only need about 20 entries worth, including the original header if it has one.

I'm going on hols to the sunshine in less than a week now, so I'll be unlikely to get much done with it until I'm back, thus a little patience may be required.

Cheers,
Brian
hey sorry for the delay, i've got stuff going on in the real world - is it ok to drop you a pm within the next few days?

i downloaded your code and have only really just had a few hours with it and have a few questions that i will respond to in the main forum asap.

Billy+
Posts: 4150
Joined: 09 Dec 2016

Post 04 Nov 2023

10000-midifiles.png

Code: Select all

import random                       # needed for random string
import os                           # needed for current_directory
try:
    from midiutil import MIDIFile   # needed to make midi files
except ImportError:
    print('missing midiutil')


'''
One possible way to add a check to make sure none of the random strings are identical is to use a set data structure in Python.
A set is a collection of unique elements that does not allow duplicates.
You can create an empty set and add each random string to it as you generate them.
If the length of the set is equal to the number of random strings, then there are no duplicates.
'''

def rando(count):
    aset = set()
    while len(aset) < (count):
        string16 = ''.join(random.choices('hmsr', k=16))
        aset.add(string16)

    return aset


def process_notes(notes, bpm, output, human):
    num_notes = len(notes)
    duration_16th_note = (60 / bpm) / 2
    track = 0
    time = 0
    channel = 9
    pitch = 60
    volume = 0

    notice = 'random rhythm file'

    midi_file = MIDIFile(1)
    midi_file.addTrackName(track, time, notes)
    midi_file.addTempo(track, time, bpm)
    midi_file.addCopyright(track, time, notice)

    current_directory = os.getcwd()
    saveas = f'{current_directory}\{output}'

    print(f'Sequencing : Pattern [{notes}] saving as [{output}] in [{current_directory}]')

    for i in range(num_notes):
        note = notes[i]
        if note == 'h':
            volume = 100 
            if human: volume = 100 + random.randint(-7, 7)
        elif note == 'm':
            volume = 75
            if human: volume = 75 + random.randint(-10, 10)
        elif note == 's':
            volume = 50
            if human: volume = 50 + random.randint(-5, 5)
        elif note == 'r':
            time += duration_16th_note
            if debug:
                print(f"Note {i+1:02}: {note}, Onset: {time}, Duration: {duration_16th_note}")
            continue

        midi_file.addNote(track, channel, pitch, time, duration=duration_16th_note, volume=volume )
        time += duration_16th_note
        if debug:
            print(f"Note {i+1:02}: {note}, Volume: {volume}, Onset: {time}, Duration: {duration_16th_note}")

    with open(saveas, "wb") as output_file:
        midi_file.writeFile(output_file)


if __name__ == '__main__':
    global debug
    # setting debug to True will print more info.
    debug = False
    # this is set to 0 by default to stop you running without understanding ;)
    # Maximum number of files in a single FAT32 folder: 65,534
    amount = 0
    if amount == 0:
        print('read me first..')
    else:
        strings = rando(amount)
        for string in strings:
            process_notes(string, 120, (string)+'.mid', human=True)



ok so I've knocked together a script that will produce as many midi files "within reason" as you want,
I tested it on 10000 and without playing all the files it seems to function as expected.

working with these is much simpler than wild midi files (I got the Clean MIDI subset from https://colinraffel.com/projects/lmd/).
You do not have the required permissions to view the files attached to this post.

User avatar
Enlightenspeed
RE Developer
Posts: 1082
Joined: 03 Jan 2019

Post 10 Nov 2023

Billy+ wrote:
03 Nov 2023
hey sorry for the delay, i've got stuff going on in the real world - is it ok to drop you a pm within the next few days?

i downloaded your code and have only really just had a few hours with it and have a few questions that i will respond to in the main forum asap.
Hi Billy,

I have now returned from the sunshine!!! I also have a nasty wee bugger of a cold, so am trying to preserve energy where I can over the next few.

Fire away with the questions :)

Cheers,
B

  • Information
  • Who is online

    Users browsing this forum: CommonCrawl [Bot] and 0 guests