<jupyter_start><jupyter_text>Midiprocessing<jupyter_code>from adaptivetuning import Midiprocessing<jupyter_output><empty_output><jupyter_text>A Midiprocessing objects receives midi messages from a controller (e.g. a midi-keyboard) or reads a midi file. On every note-on and note-off message, it calls some given callback function.<jupyter_code>m = Midiprocessing()<jupyter_output><empty_output><jupyter_text>You can stop a Midiprocessor by calling its stop method or by setting a threading.Event you pass when calling play_port or play_file, but when we are working in a single thread, the midi processing will block the thread and prevent us from stopping it. For a simple test of Midiprocessing in a single thread, we can specify a maximal number of notes it will process, after that it will stop automatically.<jupyter_code>m.max_notes = 5<jupyter_output><empty_output><jupyter_text>We have to specify what to do with the received messages.<jupyter_code>m.note_on_callback = lambda pitch, amp: print('Note on:', pitch, amp)
m.note_off_callback = lambda pitch: print('Note off', pitch)
m.stop_callback = lambda: print('Stop')<jupyter_output><empty_output><jupyter_text>Let's read a midi file and play it first 5 notes!<jupyter_code>m.read_file("midi_files/BWV_0227.mid")
m.play_file()<jupyter_output>Note on: 71 0.7874015748031497
Note on: 67 0.7874015748031497
Note on: 64 0.7874015748031497
Note on: 52 0.7874015748031497
Note off 71
Note off 67
Note off 64
Note off 52
Note on: 71 0.7874015748031497
Stop<jupyter_text>We can control an Audiogenerator object with a Midiprocessing object by connecting the callbacks with the corresponding methods of the Audiogenerator. The register_audiogenerator method can do that for us.<jupyter_code>import sc3nb
sc = sc3nb.startup()
#sc = None
from adaptivetuning import Audiogenerator
a = Audiogenerator(sc = sc)
a.set_synth_def_with_dict(Audiogenerator.presets['piano'])
m.register_audiogenerator(a)
m.max_notes = 30
m.read_file("midi_files/BWV_0227.mid")
m.play_file()<jupyter_output><empty_output><jupyter_text>Let's hear the first two bars of Bach's '<NAME>' with a stretched timbre and a stretched scale!<jupyter_code>a.partials_pos = {'method': 'harmonic', 'nr_partials': 10, 'octave': 2.8}
a.partials_amp = [0.6**i for i in range(10)]
a.scale.octave_interval = 2.8
a.scale.tune_all_equal_temperament()  # 12TET with streched octave
m.play_file()<jupyter_output><empty_output><jupyter_text>If we want to play something ourselves, we need some kind of midi port, for example from a midi keyboard. If a midi keyboard is connected to your machine, you should see if in the following list:<jupyter_code>m.get_port_names()<jupyter_output><empty_output><jupyter_text>Let's play exactly 30 notes with our midi device.<jupyter_code>m.port_name = 'MPK mini'
m.play_port()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08479943701618578, 'fraction_numerical': 0.04609429978888107, 'mean_word_length': 6.725543478260869, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '559491', 'license': 'MIT', 'n_tokens_mistral': 1078, 'n_tokens_neox': 969, 'n_words': 302, 'path': 'examples/3_midiprocessing_example.ipynb', 'repo_name': 'ArneKramerSunderbrink/adaptivetuning', 'size': '2853'}