Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/generate-pa…
Browse files Browse the repository at this point in the history
…ttern-docs
  • Loading branch information
loparcog committed Jan 3, 2024
2 parents f8af6ca + 6507045 commit 9e5ed11
Show file tree
Hide file tree
Showing 53 changed files with 1,386 additions and 253 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ dist/
dev
audio
midi
build
TODO.md
3 changes: 2 additions & 1 deletion auxiliary/scripts/generate-docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ def main(args):
contents = open("isobar/pattern/%s.py" % prefix, "r").readlines()
if args.markdown:
print("## %s" % prefix.title())
print("View source: [%s.py](https://github.com/ideoforms/isobar/tree/master/isobar/pattern/%s.py)" % (prefix, prefix))
print(
"View source: [%s.py](https://github.com/ideoforms/isobar/tree/master/isobar/pattern/%s.py)" % (prefix, prefix))
print()
print("| Class | Function |")
print("|-|-|")
Expand Down
19 changes: 19 additions & 0 deletions auxiliary/scripts/generate-shorthand-aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3

import re
import isobar

def main():
classes = vars(isobar)
class_names = classes.keys()
pattern_class_names = sorted(filter(lambda name: re.match("^P[A-Z]", name), class_names))
for class_name in pattern_class_names:
try:
cls = classes[class_name]
abbreviation = cls.abbreviation
except AttributeError:
abbreviation = class_name.lower()
print(f"from ..pattern import {class_name} as {abbreviation}")

if __name__ == "__main__":
main()
6 changes: 3 additions & 3 deletions isobar/chord.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ def __init__(self, intervals=[], root=0, name="unnamed chord"):
Chord.dict[name] = self

def __str__(self):
return "%s %s%s" % (self.name, self.semitones(), (" + %d" % self.root) if self.root > 0 else "")
return "%s [%s]" % (self.name, ",".join(str(n) for n in self.semitones))

@property
def semitones(self):
semitones = [0] + [sum(self.intervals[0:n + 1]) for n in range(len(self.intervals))]
semitones = [self.root] + [sum(self.intervals[0:n + 1], self.root) for n in range(len(self.intervals))]
return semitones

@staticmethod
Expand All @@ -46,7 +46,7 @@ def arbitrary(name="chord"):
break
intervals.append(interval)

return Chord(intervals, 0, name if name else "chord", random.randint(0, 12))
return Chord(intervals, 0, name)


Chord.major = Chord([4, 3, 5], 0, "major")
Expand Down
3 changes: 2 additions & 1 deletion isobar/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
EVENT_SCALE = "scale"
EVENT_OCTAVE = "octave"
EVENT_TRANSPOSE = "transpose"
EVENT_PITCHBEND = "pitchbend"
EVENT_EVENT = "event"
EVENT_ACTION = "action"
EVENT_ACTION_ARGS = "args"
Expand Down Expand Up @@ -79,7 +80,7 @@
EVENT_AMPLITUDE_LEGACY = "amp"

ALL_EVENT_PARAMETERS = [
EVENT_TYPE, EVENT_ACTIVE, EVENT_CHANNEL, EVENT_AMPLITUDE, EVENT_DURATION,
EVENT_TYPE, EVENT_ACTIVE, EVENT_CHANNEL, EVENT_AMPLITUDE, EVENT_DURATION, EVENT_PITCHBEND,
EVENT_GATE, EVENT_NOTE, EVENT_DEGREE, EVENT_KEY, EVENT_SCALE, EVENT_OCTAVE,
EVENT_TRANSPOSE, EVENT_EVENT, EVENT_ACTION, EVENT_ACTION_ARGS, EVENT_CONTROL,
EVENT_OSC_ADDRESS, EVENT_OSC_PARAMS, EVENT_VALUE, EVENT_TIME, EVENT_PATCH,
Expand Down
3 changes: 0 additions & 3 deletions isobar/io/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
__version__ = "0"
__author__ = "Daniel Jones <http://www.erase.net/>"

from .output import OutputDevice
from .dummy import DummyOutputDevice
from .midi import MidiInputDevice, MidiOutputDevice, get_midi_output_names, get_midi_input_names
Expand Down
8 changes: 5 additions & 3 deletions isobar/io/cv/output.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ..output import OutputDevice

try:
import numpy as np
import sounddevice
except ModuleNotFoundError:
pass
Expand Down Expand Up @@ -32,6 +33,7 @@ def __init__(self, device_name=None, sample_rate=44100):
To query possible names, call get_cv_output_devices().
sample_rate (int): Audio sample rate to use.
"""
super().__init__()
try:
self.stream = sounddevice.OutputStream(device=device_name,
samplerate=sample_rate,
Expand All @@ -40,18 +42,18 @@ def __init__(self, device_name=None, sample_rate=44100):
self.stream.start()

except NameError:
raise Exception("For CV support, the sounddevice module must be installed")
raise Exception("For CV support, the sounddevice and numpy modules must be installed")

# Expert Sleepers ES-8 supports entire -10V to +10V range
self.output_voltage_max = 10
self.channels = self.stream.channels
self.channel_notes = [None] * self.channels
self.middle_c = 60
self.midi_c0 = 0

print("Started CV output with %d channels" % self.channels)

def _note_index_to_amplitude(self, note):
note_float = (note - self.middle_c) / (12 * self.output_voltage_max)
note_float = (note - self.midi_c0) / (12 * self.output_voltage_max)
if note_float < -1.0 or note_float > 1.0:
raise ValueError("Note index %d is outside the voltage range supported by this device" % note)
print("note %d, float %f" % (note, note_float))
Expand Down
1 change: 1 addition & 0 deletions isobar/io/dummy/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def __init__(self):
"""
Dummy output device.
"""
super().__init__()
self.current_time = 0.0
self.events = []

Expand Down
4 changes: 3 additions & 1 deletion isobar/io/midi/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def __init__(self, device_name=None, send_clock=False, virtual=False):
send_clock (bool): Whether to send clock sync/reset messages.
virtual (bool): Whether to create a "virtual" rtmidi device.
"""
super().__init__()
try:
if device_name is None:
device_name = os.getenv("ISOBAR_DEFAULT_MIDI_OUT")
Expand Down Expand Up @@ -95,4 +96,5 @@ def set_song_pos(self, pos=0):
self.midi.send(msg)

def __del__(self):
del self.midi
if hasattr(self, "midi"):
del self.midi
1 change: 1 addition & 0 deletions isobar/io/midifile/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class MidiFileOutputDevice (OutputDevice):
"""

def __init__(self, filename):
super().__init__()
self.filename = filename
self.midifile = MidiFile()
self.miditrack = MidiTrack()
Expand Down
1 change: 1 addition & 0 deletions isobar/io/osc/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def __init__(self, host, port):
host: Hostname to send OSC messages to
port: Port number to send OSC messages to
"""
super().__init__()
try:
self.osc = SimpleUDPClient(host, port)

Expand Down
2 changes: 1 addition & 1 deletion isobar/io/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class OutputDevice:
def __init__(self):
pass
self.added_latency_seconds = 0.0

@property
def ticks_per_beat(self):
Expand Down
1 change: 1 addition & 0 deletions isobar/io/signalflow/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def __init__(self, graph=None):
device_name (str): The name of the target device to use.
If not specified, uses the system default.
"""
super().__init__()
if graph:
self.graph = graph
else:
Expand Down
1 change: 1 addition & 0 deletions isobar/io/socketio/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SocketIOOutputDevice (OutputDevice):
"""

def __init__(self, host="localhost", port=9000):
super().__init__()
import socketIO_client
self.socket = socketIO_client.SocketIO(host, port)

Expand Down
3 changes: 2 additions & 1 deletion isobar/io/supercollider/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ def __init__(self, host="127.0.0.1", port=57110):
"""
Args:
host: Hostname to send OSC messages to
port: =Port number to send OSC messages to
port: Port number to send OSC messages to
"""
super().__init__()
try:
self.server = supercollider.Server()

Expand Down
3 changes: 3 additions & 0 deletions isobar/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ class Key:

def __init__(self, tonic=0, scale=Scale.major):
if type(tonic) == str:
#--------------------------------------------------------------------------------
# Constructor specifies a note name and a scale name (e.g, "C# minor")
# TODO unit test for this
#--------------------------------------------------------------------------------
if " " in tonic:
tonic_str, scale_str = tuple(tonic.split(" "))
tonic = note_name_to_midi_note(tonic_str)
Expand Down
1 change: 1 addition & 0 deletions isobar/pattern/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .static import *
from .tonal import *
from .fade import *
from .midi import *

__all__ = []
key = value = None
Expand Down
Loading

0 comments on commit 9e5ed11

Please sign in to comment.