Skip to content

Python library for handling Casio registration bank (.RBK) files

License

Notifications You must be signed in to change notification settings

michgz/casio-registrations

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

37 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

casio-registrations

Python library for handling Casio registration bank (.RBK) files

Quick start

An example of how to use the library:

from casio_rbk.casio_rbk import RegistrationBank, Part
from casio_rbk.patch_name import patch_name
import warnings

with open("BANK01.RBK", "r+b") as f:
    # Read from file
    rb = RegistrationBank.readFile(f)
    
    # For the first three registrations in the bank (out of either 4 or 8)
    for r in rb[0:3]:
    
        # Part L off, U1 full volume, U2 unchanged
        vols = r.getVolumes()
        r.setVolumes(127, vols[1], 0)
    
        if not r.isMonoCompatible():
          # If any patches are not mono compatible, may wish to raise a warning
          # message here. Not required.
          raise Warning("Not mono compatible, panning will not give fully mono channel separation")
    
        # Part U1 panned hard left, U2 hard right, L unchanged
        pans = r.getPans()
        r.setPans(0, 127, pans[2])
    
    # Write the bank back to file
    rb.writeFile(f)
    
    # Print the instrument patch name of the U1 part
    print("Patch in U1 of first Reg is: " + patch_name(*rb[0].getPatchBank(Part.U1)))

Documentation

RegistrationBank

A RegistrationBank class object bundles together a set of Registration objects. Depending on the model of keyboard, there are either 4 or 8 Registrations in each RegistrationBank.

A RegistrationBank should always be created by reading in a file with the readFile() function. There's no way to create one from scratch.

Member functions of this class:

readFile()

Creates a new object with data from a .RBK file

🟦 Usage:

  • @classmember readFile(cls, fileHandle)

🟦 Parameters:

  • fileHandle   handle to a file that has been opened with binary read ("rb") or binary read/write ("r+b") mode

🟦 Returns:

  • a RegistrationBank object

Example:

from casio_rbk import RegistrationBank
# Read from a file
with open("BANK01.RBK", "rb") as f1:
    MyRegBank = RegistrationBank.readFile(f1)
...

writeFile()

Writes the data to a .RBK file

🟦 Usage:

  • writeFile(self, fileHandle)

🟦 Parameters:

  • fileHandle   handle to a file that has been opened with binary write ("wb") or binary read/write ("r+b") mode

Example:

from casio_rbk import RegistrationBank
...
# Write to a file
with open("BANK02.RBK", "wb") as f2:
    MyRegBank.writeFile(f2)

Iterating and subscripting

The RegistrationBank contains 4 or 8 Registration objects, which can be accessed by iteration or subscripts (like an array).

Example:

for MyReg in MyRegBank1:
    ...  # do something with the Registration

Registration

A Registration class object defines a collection of settings for a Casio keyboard. Settings include volume and pan for each keyboard part and lots of other stuff. Member functions of this class:

setVolumes()

Set volumes of the first three keyboard parts (U1, U2 and L):

🟦 Usage:

  • setVolumes(self, u1_vol, u2_vol, l_vol)

🟦 Parameters:

  • u1_vol   Volume to set on U1 part. Integer 0 -- 127
  • u2_vol   Volume to set on U2 part. Integer 0 -- 127
  • l_vol   Volume to set on L part (called "L1" on some keyboards). Integer 0 -- 127

Example:

MyRegBank[0].setVolumes(127, 0, 127)    # Turn off U2 while leaving U1 & L at full volume

The setVolumes() function is equivalent to:

from casio_rbk.casio_rbk import Registration, Atom
import struct
...
b = reg[Atom.Volume]
reg[Atom.Volume] = struct.pack('3B', u1_vol, u2_vol, u3_vol) + b[3:]

setPans()

Set stereo pan of the first three keyboard parts (U1, U2 and L):

🟦 Usage:

  • setPans(self, u1_pan, u2_pan, l_pan)

🟦 Parameters:

  • u1_pan   Pan to set on U1 part. Integer 0 -- 127; centre pan is 64
  • u2_pan   Pan to set on U2 part. Integer 0 -- 127; centre pan is 64
  • l_pan   Pan to set on L part (called "L1" on some keyboards). Integer 0 -- 127; centre pan is 64

Example:

MyRegBank[1].setPans(0, 127, 64)    # Pan U1 hard left and U2 hard right

The setPans() function is equivalent to:

from casio_rbk.casio_rbk import Registration, Atom
import struct
...
b = reg[Atom.Pan]
reg[Atom.Pan] = struct.pack('3B', u1_pan, u2_pan, u3_pan) + b[3:]

isMonoCompatible()

Checks the stereo pan compatibility of the first three keyboard parts (U1, U2, L). If any is not compatible it returns False, otherwise True. Panning can still be used, but will not result in fully mono-left or mono-right channel separation.

🟦 Usage:

  • isMonoCompatible(self)

🟦 Parameters: None

Example:

import warnings
if not MyRegBank[1].isMonoCompatible():
  raise Warning("Panning will not give fully mono channel separation")

getVolumes()

Get volume settings of the first three keyboard parts (U1, U2 and L):

🟦 Usage:

  • getVolumes(self)

🟦 Returns:

  • 3-tuple of integers 0 -- 127

Example:

vols = MyRegBank[1].getVolumes()
print(f"U1 volume is {vols[0]}")
print(f"U2 volume is {vols[1]}")

getPans()

Get stereo pan settings of the first three keyboard parts (U1, U2 and L):

🟦 Usage:

  • getPans(self)

🟦 Returns:

  • 3-tuple of integers 0 -- 127; centre pan is 64

Example:

pans = MyRegBank[1].getPans()
print(f"U1 pan is {pans[0]}")
print(f"L  pan is {pans[2]}")

getPatchBank()

Gets the patch and bank settings on one of the first five parts.

🟦 Usage:

  • getPatchBank(self, part)

🟦 Parameters:

  • part   Part number to get the patch and bank for. Integer 0 - 4.

🟦 Returns:

  • tuple (patch number, bank MSB number)

Example:

from casio_rbk import RegistrationBank, Part
...
(patch, bankmsb) = MyRegBank[2].getPatchBank(Part.U2)
print(f"Patch number of U2 part = {patch}")
print(f"Bank MSB number of U2 part = {bankmsb}")

The getPatchBank() function is equivalent to:

from casio_rbk.casio_rbk import Registration, Atom
import struct
...
(patch, bankmsb) = struct.unpack_from('2B', reg[Atom.Patch], 2*part)

Iterating and subscripting

The Registration object looks like a Python dictionary which can be iterated or subscripted. Keys are integers in range 1 - 255 and values are bytestrings containing some data.

This is an advanced use-case for the class. In most cases the three functions above will do everything that's needed.

Example:

from casio_rbk import Registration, Atom, Part
...
# Change the Volume of U2 part to 115. ADVANCED - SHOULD NORMALLY USE setVolumes() INSTEAD!!
vols = bytearray(MyReg[Atom.Volume])
vols[Part.U2] = 115
MyReg[Atom.Volume] = bytes(vols)

Atom

Defines possible values for subscripting a Registration object. Only 3 values are defined so far:

Atom.Patch = 0x10
Atom.Volume = 0x11
Atom.Pan = 0x12

Part

Defines possible part parameter values for input to the getPatchBank() function:

Part.U1 = 0
Part.U2 = 1
Part.L = 2
Part.Auto_Harmony = 4

patch_name

The patch_name module translates Patch and Bank MSB values into instrument names specific to the CT-X keyboards. It has only one function defined:

patch_name()

🟦 Usage:

  • patch_name(patch, bank_msb)

🟦 Parameters:

  • patch   Patch number. Integer 0 - 127
  • bank_msb   Bank MSB number. Integer 0 - 120

🟦 Returns:

  • String giving the patch name

The tuples returned from function getPatchBank can be used as input provided they are preceded by an asterisk "*".

Example:

from casio_rbk.casio_rbk import RegistrationBank, Part
from casio_rbk.patch_name import patch_name
...
print("Patch in U1 is: " + patch_name(*MyRegBank[0].getPatchBank(Part.U1)))

Unit Tests

Run unit tests by calling

python -m unittest casio_rbk/tests/tests.py

About

Python library for handling Casio registration bank (.RBK) files

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages