Midistream¶
Package to synthesize and playback MIDI commands from Python for Android.
Midistream is a wrapper for the Bill Farmer Midi Driver, and includes libmidi.so libraries from the MidiDriver build.
Previous version was using system version of Sonivox EAS library and Audiostream for playback.
Generated documentation: https://midistream.readthedocs.org
Quick start development environment¶
midistream is included in PythonHere app, together with the Jupyter Notebook it could be used as a development environment.
Usage examples: https://herethere.me/examples/midi.html
Build¶
The following instructions are for building app with buildozer tool.
buildozer.spec requirements should include midistream and mididriver, path to midistream recipes directory should be set:
requirements =
mididriver,
https://github.com/b3b/midistream/archive/master.zip,
p4a.local_recipes = /path/to/cloned/repo/recipes
App configuration example: buildozer.spec
Examples¶
See examples/ directory.
examples/instrument could be build with buildozer:
cd examples/instrument
buildozer android debug deploy run logcat
API¶
Midi¶
-
class
midistream.
ReverbPreset
[source]¶ Parameter settings for reverb effect.
-
OFF
= -1¶ Reverb effect off
-
LARGE_HALL
= 0¶ Large hall preset
-
HALL
= 1¶ Hall preset
-
CHAMBER
= 2¶ Chamber preset
-
ROOM
= 3¶ Room preset
-
-
class
midistream.
Synthesizer
[source]¶ MIDI Synthesizer.
-
config
¶ Synthesizer configuration dictionary.
-
volume
¶ Master volume in dB, 100 is max.
Getter: Returns the volume for the mix engine. Setter: Set the master volume for the mix engine.
-
reverb
¶ Reverb effect preset.
Getter: Returns curently used ReverbPreset
.Setter: Set ReverbPreset
to use.
-
Helpers¶
Helpers to work with MIDI messages.
-
midistream.helpers.
midi_note_on
(note: int, channel: int = 0, velocity: int = 64) → List[int][source]¶ MIDI 9nH message - note on.
>>> midi_note_on(70) [144, 70, 64] >>> midi_note_on(70, velocity=127, channel=15) [159, 70, 127]
-
midistream.helpers.
midi_note_off
(note: int, channel: int = 0, velocity: int = 0) → List[int][source]¶ MIDI 8nH message - note off.
>>> midi_note_off(70) [128, 70, 0] >>> midi_note_off(70, channel=15) [143, 70, 0]
-
midistream.helpers.
midi_program_change
(program: int, channel: int = 0) → List[int][source]¶ MIDI CnH message - program change.
>>> midi_program_change(80, 1) [193, 80]
-
midistream.helpers.
midi_control_change
(controller: int, value: int = 0, channel: int = 0) → List[int][source]¶ MIDI BnH message - control change.
>>> midi_control_change(7, value=127, channel=1) [177, 7, 127]
-
midistream.helpers.
midi_command_increase_channel
(command: List[int], inc: int) → List[int][source]¶ Increase channel number of a given command.
>>> command = [177, 7, 127] >>> midi_command_increase_channel(command, -7) [170, 7, 127] >>> command [177, 7, 127]
-
class
midistream.helpers.
Control
[source]¶ Control function number for Control Change messages.
See: https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2
-
modulation
= 1¶ Modulation Wheel
-
volume
= 7¶ Channel Volume
-
pan
= 10¶ Pan
-
all_sound_off
= 120¶ All Sound Off
-
-
midistream.helpers.
midi_channels
() → Generator[int, None, None][source]¶ Generator of MIDI channels numbers, with percussion (9) channel omited.
>>> list(midi_channels()) [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15]
-
midistream.helpers.
midi_notes
= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,...¶ All MIDI notes list (from 0 to 127)
-
midistream.helpers.
note_name
(note: int) → str[source]¶ Returns name with accidental and octave number for a given note number.
>>> note_name(60) 'C4' >>> note_name(90) 'Fs6'
-
midistream.helpers.
parse_note
(text: str) → int[source]¶ Parse note number from text.
Parameters: text – [Note name](optional: “s” - sharp, “b” - flat)[octave number] Raises: ValueError >>> parse_note("C4") 60 >>> parse_note("Cs4") 61 >>> parse_note("Cb4") 59
-
class
midistream.helpers.
Note
[source]¶ Note number.
>>> Note.A0 21 >>> Note.As0 22 >>> Note.Ab0 20 >>> Note.G9 127
-
midistream.helpers.
midi_instruments
= {0: 'Acoustic Grand Piano', 1: 'Bright Acoustic Pi...¶ MIDI instruments number => name dictionary
Usage Example¶
>>> from midistream import ReverbPreset, Synthesizer
>>> midi = Synthesizer()
>>> midi.config
{'libVersion': 50727438, 'checkedVersion': 0, 'ma3xVoices': 64, 'numChannels': 2, 'sampleRate': 22050, 'mixBufferSize': 128, 'filterEnabled': 1, 'buildTimeStamp': 1195621085, 'buildGUID': b'1feda229-b9a8-45e9-96f4-73c0a80e7220'}
>>> midi.volume
90
>>> midi.volume = 70 # Set master volume
>>> midi.reverb = ReverbPreset.LARGE_HALL # Enable reverb effect
>>> midi.write([0x90, 60, 127]) # On middle C note with maximum velocity
>>> import time ; time.sleep(2)
>>> midi.write([0x80, 60, 127]) # Off middle C note with maximum velocity
# Using helpers
>>> from midistream.helpers import Note, midi_note_on
>>> midi.write(midi_note_on(Note.C4) + midi_note_on(Note.Es5))