Skip to content

Commit

Permalink
Adding the Oberheim Teo-5, which is under the hood a Sequential softw…
Browse files Browse the repository at this point in the history
…are-wise.
  • Loading branch information
christofmuc committed Jan 29, 2025
1 parent eef9d04 commit ae3e380
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
47 changes: 47 additions & 0 deletions adaptations/Oberheim_Teo-5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
# Copyright (c) 2021 Christof Ruch. All rights reserved.
#
# Dual licensed: Distributed under Affero GPL license by default, an MIT license is available for purchase
#
import sys
from typing import List

import sequential
import testing

this_module = sys.modules[__name__]


#
# Configure the GenericSequential module
#
def teo5_bank_name(bank) -> str:
return str(bank) if bank < 10 else chr(ord("A") + (bank - 10))


def teo5_program_name(program) -> str:
bank = program // 16
program = program % 16
return teo5_bank_name(bank) + f"{program:02d}"


sequential.GenericSequential(name="Oberheim Teo-5",
manufacturer=0x10, # Oberheim, not Sequential
device_id=0x5a,
banks=16,
patches_per_bank=16,
name_len=20,
name_position=159,
friendlyBankName=teo5_bank_name,
friendlyProgramName=teo5_program_name,
).install(this_module)


# Test data picked up by test_adaptation.py
def make_test_data():
def programs(data: testing.TestData) -> List[testing.ProgramTestData]:
yield testing.ProgramTestData(message=data.all_messages[2], name='OB-X Pad', number=2, friendly_number="002")
yield testing.ProgramTestData(message=data.all_messages[17], name='Waterfall Cavern', number=17, friendly_number="101")
yield testing.ProgramTestData(message=data.all_messages[80], name='FlyLike a TEO', number=80, friendly_number="500")

return testing.TestData(sysex="testData/Oberheim_Teo5/TEO5_Factory_Programs_v1.00.syx", program_generator=programs, friendly_bank_name=(11, "B"))
13 changes: 8 additions & 5 deletions adaptations/sequential/GenericSequential.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
# Prophet 5 - 0b00110010 0x32 (this is the Rev 4 of course) or 0b00110011 0x33 (Desktop module?)
# Take 5 - 0x35 (they left 0x34 empty - maybe the desktop Prophet 5 and...?)
# Trigon-6 - 0b00111001 0x39 (the manual is not updated but uses the Prophet 6 ID)
# Teo-5 - 0b01011010 0x5a (the manual is not updated but uses the Take 5 ID) - this also additionally uses the MIDI ID for Oberheim, 0x10

class GenericSequential:

def __init__(self, name, device_id, banks, patches_per_bank,
manufacturer=0x01, # Default is Sequential, obviously
name_len=None,
name_position=None,
file_version=None,
Expand All @@ -45,6 +47,7 @@ def __init__(self, name, device_id, banks, patches_per_bank,
self.__id_list = id_list
self.__banks = banks
self.__patches_per_bank = patches_per_bank
self.__manufacturer = manufacturer
self.__name_len = name_len
self.__name_position = name_position
self.__file_version = file_version
Expand Down Expand Up @@ -78,7 +81,7 @@ def channelIfValidDeviceResponse(self, message):
and message[1] == 0x7e # Non-realtime
and message[3] == 0x06 # Device request
and message[4] == 0x02 # Device request reply
and message[5] == 0x01 # Sequential / Dave Smith Instruments
and message[5] == self.__manufacturer
and message[6] in self.__id_list):
# Family seems to be different, the Prophet 12 has (0x01, 0x00, 0x00) while the Evolver has (0, 0, 0)
# and message[7] == 0x01 # Family MS is 1
Expand Down Expand Up @@ -106,7 +109,7 @@ def createEditBufferRequest(self, channel):
def isEditBufferDump(self, message):
return (len(message) > 3
and message[0] == 0xf0
and message[1] == 0x01 # Sequential
and message[1] == self.__manufacturer
and message[2] in self.__id_list
and (self.__file_version is None and message[3] == 0b00000011 # Edit Buffer Data
or message[3] == self.__file_version and message[4] == 0b00000011)) # Edit Buffer Data
Expand All @@ -125,15 +128,15 @@ def createProgramDumpRequest(self, channel, patchNo):
program = patchNo % self.numberOfPatchesPerBank()
if self.__file_version is None:
# Modern style
return [0xf0, 0x01, self.__id, 0b00000101, bank, program, 0xf7]
return [0xf0, self.__manufacturer, self.__id, 0b00000101, bank, program, 0xf7]
else:
# Evolver style
return [0xf0, 0x01, self.__id, self.__file_version, 0b00000101, bank, program, 0xf7]
return [0xf0, self.__manufacturer, self.__id, self.__file_version, 0b00000101, bank, program, 0xf7]

def isSingleProgramDump(self, message):
return (len(message) > 3
and message[0] == 0xf0
and message[1] == 0x01 # Sequential
and message[1] == self.__manufacturer
and message[2] in self.__id_list
and (self.__file_version is None and message[3] == 0b00000010 # Program Data
or message[3] == self.__file_version and message[4] == 0b00000010)) # Program Data
Expand Down
Binary file not shown.

0 comments on commit ae3e380

Please sign in to comment.