GithubHelp home page GithubHelp logo

solidsnake745 / midi_device_controller Goto Github PK

View Code? Open in Web Editor NEW
6.0 6.0 0.0 375 KB

An Arduino based library for controlling various devices via the MIDI interface

License: GNU General Public License v3.0

C++ 98.09% C 1.91%

midi_device_controller's People

Contributors

solidsnake745 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

midi_device_controller's Issues

Implement usbMIDI.read() like functionality for Hairless MIDI

Want to encapsulate functionality around parsing serial data from Hairless MIDI into MIDI messages for consumption through this framework.

Create a singleton instance for hairless MIDI data similar to usbMIDI for Teensy.

Create similar methods to:

  • usbMIDI.read()
  • usbMIDI.setHandleNoteOn()
  • usbMIDI.setHandleNoteOff()
  • usbMIDI.setHandlePitchChange()
  • usbMIDI.setHandleControlChange()
  • usbMIDI.setHandleProgramChange()

Refactor defaulting settings into relevant constructors

In order to better group, understand, and maintain where settings from Settings.h are being consumed, want to move those sets into their relevant constructors. May later on make them constructor arguments, but for not entirely sure that's necessary.

Classes currently consuming settings:

  • MIDI_Device_Controller
  • MIDI_Chain_Controller
  • MIDI_Device
  • MIDI_Device_Node
  • MIDI_Device_Chains

Remove MIDI_DeviceController.bendChannelTest()

Was broken in the shift from using primitive arrays to class objects to represent devices. Need to update so it works with the new device object class approach.

In the past, found the Arduino Uno/Duemilanove was not fast enough to bend entire channels (OK for single device bends). This test function is mainly for confirming if the controller is fast enough to do pitch bending for an entire channel.

This will probably end up getting refactored into device chains.

Build an optional pitch factor cache

Currently, pitch bending calculates the factor to bend by during every call. The range of values is predictable and can be cached in memory to speed up operation. Build a static class to house this functionality like MIDI_Periods and include a setting to toggle on and off.

Add initialize method to instantiate MIDI_Collection_Controller

Low on priority, but including the MIDI_Collection_Controller header file automatically creates and instantiates its singleton instance; even if the consumer isn't really using it.

To reduce memory footprint and allow consumers to knowingly opt into it's functionality, I want to refactor the instantiation into an initialize method.

Add functionality to address specific use cases

Want to simplify use of this library by including classes that encapsulate configuration and processing of MIDI events from different frameworks.

Thinking they will share two common methods, but with different parameters depending on case:

  1. setup() - Configures controller for given use case and may have overloads specific to use case
  2. process() - Processes MIDI data for given use case and may have overloads specific to use case

Use cases in mind currently:

  1. USB MIDI Controller for up to 8 FDDs (Teensy + MIDI application to MIDI Device [MIDI Event Data])
  2. Serial Moppy (Arduino/Teensy + Moppy application to Serial Device [Pin and Period Data])
  3. Hairless MIDI [https://projectgus.github.io/hairless-midiserial/] (Arduino/Teensy + MIDI application to Hairless MIDI to Serial Device [MIDI Event Data])

Create MIDI_Device_Factory

Need to separate and centralize MIDI_Device instantiation methods for creating various devices.
Will help organize the various types of current and future devices and provide consumers with a clean list of possible devices.

Current types of MIDI_Devices:

  1. FDD
  2. Stepper Motor
  3. HDD

Refactor ID concept

There's no need for devices to have unique IDs. There isn't really an advantage over just associating devices to their position in the MIDI device controller collection (array). Refactor out to reduce complexity and optimize device referencing.

  • Replace id variables with index
  • Concerns Device and MIDI_DeviceController classes - confirm other uses
  • Change getDevice to retrieve directly from array index rather than searching
  • Update related print functions

Rename processing notes related methods/properties from 'processing' to 'processingNotes'

Updating naming scheme around note processing to better convey what it represents to consumers.
Will make it easier for them to understand what this does in the domain.

Current New
_isProcessing _isPlayingNotes
_autoProcessing _autoPlayNotes
setAutoProcess setAutoPlay
startProcessing startPlaying
stopProcessing stopPlaying
resetProcessing *process
isProcessing isPlayingNotes

*Changing to encompass all running all relevant processes rather than just handling stopping the interrupt process. Also better follows other Arduino library implementations of this concept.

Troubleshoot issues with FDD_Controller test sketch

As a means to ensure the original requirements are still functioning, I have a test sketch that configures a (Teensy) microcontroller as a MIDI FDD Controller. Once updated with the latest changes from adding in DeviceChain_Controller, this stopped working properly. Need to update and add logging to trace where the issue is occurring. Could be a simple logic oversight, but currently there is no way to confirm as logging in DeviceChain_Controller is broken.

  • Issue occurs when trying to open FL Studio while the controller is connected
  • Could be from a call to startProcessing or an oversight in device chains (specifically RR)
  • Need to fix logging in DeviceChain_Controller and related classes anyway

Add logic and setting to shift pitchbend values

Recently discovered pitch bending was broken while working on intro course.

Issue occurring was all pitch bend commands would sound wrong - resulting note after bending was far too high. For the notes tested with, the bend values should have resulted in lower tones - not higher; suggesting the bend value used was larger than expected.

After researching further, looks like there were two separate paths of failure that can be fixed with one change.

To summarize:

  1. Pitch bending failed when using serial MIDI through Hairless MIDI
  2. Pitch bending also failed when using Teensy's built in usbMIDI
  3. Built pitch bending test sketch with Teensy to debug input from both frameworks
  4. Found Teensy has updated pitch bend values from 0 to 16383 (expected range) to -8192 to 8192
  5. Found Hairless MIDI is sending the expected range, but the logic used to parse the serial is still imperfect and causing misinterpretation of the MIDI events and their data

For now, addressing only the need to shift the new values into the expected range to fix existing functionality for my own instruments. Need to address the issue with Hairless MIDI in #30.

Center usage around MIDI_Collection_Controller

Having used it couple times, would be simpler to just be able to add devices to the collection instances with an assignment strategy; rather than making the user create the objects, assign them to the MIDI_Device_Controller, and THEN configure the different chains,

Want something along the lines of creating collections by passing in device references (straight from factory creation) and then assignment strategy. Can probably reuse recursive decay from MIDI_Collection_Controller to do this.

Rename MIDI_Device to MIDI_Pitch

Looking over the naming scheme again, would be more straight forward to correlate device names to output types. With that in mind, want to update the following:

Current Desired
MIDI_Device MIDI_Pitch
(TODO: Create this device) MIDI_Pulse
MIDI_Shift_Register MIDI_Shift_Register

Need to apply change to multiple files/places:

Current New
MIDI_Device MIDI_Pitch
Base_MIDI_Device_Collection Base_MIDI_Pitch_Device_Collection
-addDevice addPitchDevice
-addDevices addPitchDevices
-removeDevice removePitchDevice
MIDI_Device_Node MIDI_Pitch_Node
MIDI_Device_Controller MIDI_Device_Controller (NO NAME CHANGE)
-_devices _pitchDevices
-_enabledDevices _enabledPitchDevices
-reloadEnabledDevices reloadEnabledPitchDevices
-addDevice addPitchDevice
-addDevices addPitchDevices
-getDevice getPitchDevice
-deleteDevice deletePitchDevice
-resetPositions resetPitchDevicePositions
-calibratePositions calibratePitchDevicePositions
-playNote playPitchNote
-pitchBend bendPitchNote
-stopNote stopPitchNote
-getMaxDevices getMaxPitchDevices
-testDeviceInterrupt testPitchDeviceInterrupt
MIDI_Collection_Controller MIDI_Pitch_Collection_Controller
MIDI_Device_Factory MIDI_Device_Factory (NO NAME CHANGE)
MAX_DEVICES MAX_PITCH_DEVICES

Refactor MIDI_Shift_Register into MIDI_SN74HC595

Want to restructure the shift register implementation so it's more decoupled from note assignment. Also want to be able to re-use some of its mechanisms in other implementations such as MCP23017 and MCP23S17. Will create another controller to manage note to interface + output mappings: MIDI_Pulse_Controller.

Create device class for solenoids

Creating a class to represent a device for drums. Encapsulates a chain of solenoids and utilizes the SPI bus.

  1. Single instance only for now -
    1. Make factory method private, give access to MIDI Device Controller
    2. Add single instance to MIDI Device Controller
    3. Add method to MIDI Device Controller to instantiate
    4. Instantiation should handle setting up SPI bus
  2. Update processNotes with a section dedicated to this device
  3. Has a setting for duration - length a given note can be on (used mainly to limit how long solenoids remain on)
  4. Has a setting for configuring number of registers are being used
  5. Base implementation off prototype sketch

Revise all logging

I've just been arbitrarily throwing in log statements all across the library at level 5. Just wanted logging to be available to troubleshoot specific issues or see related information.

Need to go back across the entire library and ensure logging is consistent, appropriately given a level, and accurate (copied log statements that don't apply).

Will probably get to this much later, just creating an issue to remind myself of the need.

Add method to create device chains and add devices directly from MIDIDevice_Controller

While testing DeviceChain_Controller during #15, realized the issue I was running into could easily trip up others. To avoid this, add/create methods in DeviceChain_Controller to handle creating derived instances of chains and populating them with device from MIDI_DeviceController.

Thinking a single method that has two three parameters is the cleanest implementation.
Method takes in the index to add the chain to, an enum of device chain type (direct, stacking FA, RR) and an array of uint8_t correlating to the devices to add.

Implement instances of SerialDebug per class

Need to separate debugging per class being logged. Best change seems to make SerialDebug an instantiable object with it's own setting member(s). It's already a pretty minimal class so no need to enforce a single instance. Logging functionality will be driven from those settings then; allowing customization per class.

  • Update SerialDebug to be multi-instance instead of single, static instance
  • Add an instance to every class currently using it
  • Remove overly complicated compiler injection mechanism currently in use
  • Replace macros with instance calls

Re-update naming for consistency

Want to rename MIDI chains to collections as it is easier to understand.

Current naming scheme:

MIDI_ {1} *_{2}
Standard prefix Class or subclass name/desc Final class name/desc (*optional)
Current New
MIDI_Chain_Controller MIDI_Collection_Controller
MIDI_Chain_Factory MIDI_Collection_Factory
MIDI_Device_Chain Base_MIDI_Device_Collection
Direct_Chain *Direct_Collection
FirstAvailable_Chain *FirstAvailable_Collection
RoundRobin_Chain *RoundRobin_Collection

*Temporary naming, doesn't entirely fit well, come back and review

Add ESP32 support

Want to be able to leverage WiFi capabilities for this project. Need to change a few things in order to compile and test on a development board.

Create Device Chain Controller

Continuation of #8 - Create a controller meant to manage device chains. Will allow for easily grouping devices to allow for pooling/distributing notes per some configured strategy. Current strategies are direct, stacking, and round robin. Very similarly structured to MIDI_DeviceController (singleton instance, allows for adding/removing device chains).

Delete out defaults functionality

After #9 is resolved, should refactor out Defaults.h as it's a bit unnecessary and not flexible. After config classes or the like are implemented, those can contain specific pin configurations and other related information and will only be included if consumers specifically choose to.

  • Delete out uses of Defaults
  • Refactor out defaulting functionality from Devices/MIDIDeviceController

Add a method for configuring multiple devices

Having the ability to configure a collection (array) of devices will simplify making configurations for various use cases/scenarios and is fairly simple to do before further designing #9.

  1. Add method to MIDI_DeviceController
  2. Parameters: reference to array containing devices and size of the array
  3. Experiment with dynamically determining array size for iteration

Reorganize file structure

Now that consumers only need to include a single header, want to place more of the files within sub-folders. At the same time, want to create an MDC_Extras file for controlling which add ons are included.

Delete out device chain functionality

Deciding to separate out device chain functionality. It's able to stand by itself for now so want to reduce dependencies by refactoring into it's own library. Most likely to be called DeviceChainController.

This issue just covers removing it from this repo/library.

Add Doxygen documentation

I'm really fond of Doxygen documentation and want to use it to document my library. Documentation is important to give users a clean overview of available functionality.

  1. Learn how to use Doxygen
  2. Use it to document code
  3. Include documentation somehow and possibly host it as a website (or just include for users to open themselves)

Various updates to MIDI_Shift_Register after first use

Ran into a couple issues after using MIDI_Shift_Register in real time - Wasn't properly stopping notes.

Also noticing some improvements that need to be made:

  1. Delete getRegisterValue
  2. Add write direction setting + functionality
  3. Refactor common logic into validate note function
  4. Add test for interrupt process
  5. Add parent controller reference and call noteAssigned in playNote
  6. Refactor MSR instantiation into MIDI_Device_Factory
  7. Add reset all function to shift register and call on device controller stopPlaying

Update keywords.txt

Created the keywords file a long time ago before a lot of the final code was written. Need to go back and update keywords and decide what type of keyword they are. This causes key terms to be highlighted in the Arduino IDE.

MIDI_Chain_Factory.createChain() doesn't calculate number of devices correctly

While working on the latest PCB prototype, ran into an issue while trying to use device chains.

  1. Tried creating 3 device chains with 2 devices each
  2. After adding additional debugging, realized the number of devices calculated in this method is wrong (technical details to follow)
  3. Need to re-implement this functionality
  4. Believe the best approach would be to use a paramater pack to take in the desired device IDs rather than relying on a passed in array.

Had forgotten that while passing arrays to methods they are passed by pointer and therefore using sizeof on it results in just the size of the pointer; not the total size of the array. Using a parameter pack is actually easier for consumers too as they can simply concatenate as many desired IDs as they like. The method is already setup to handle bad inputs and continue you on so it should work fine.

Fill out readme with more info

Checked in a very simple description of the library as the readme for now.
Want to update it with more details about the library, it's use, and key concepts.

  1. Describe the concept of devices and the MIDI device controller
  2. Describe concept of stepper motors and stepping??
  3. Describe device chains and how they're used to group together devices for note assignment
  4. ???

Refactor MDC.processNotes logic into MIDI_Device

After implementing MIDI_Shift_Register, realized it's a lot more straight forward to encapsulate operation logic into the device itself. Want to go back and change the existing code to better accommodate future additions to the interrupt process.

Refactor MIDI_Device_Chains into separate files

Currently all of the device chain classes exist in a single file. Want to separate into one file per class.

  1. Direct_Chain
  2. FirstAvailable_Chain
  3. RoundRobin_Chain
  4. Direct_Chain
  5. MIDI_Device_Chain

Add in classes for MIDI message handling

Had previously made two classes around parsing MIDI messages into an object and then executing callbacks based on those messages, Want to update and include those classes to address the use cases outlined in #9.

  1. MIDI_Message - Represents a MIDI message and abstracts the MIDI 3 byte structure into a more friendly interface
  2. MIDI_Handler - Object encapsulating the functionality around responding to MIDI events

Add example sketches

Like any good Arduino library, I should have example sketches of how to use the library.

Need to know the most common use cases people are running into and create examples for those.

Current thoughts:

  1. Sketch that demonstrates setting up 1 floppy drive and repeats a tone (maybe scale?) infinitely on it
  2. Sketch that demonstrates setting up 8 floppy drives and demos playing notes or something
  3. Sketch that demonstrates auto processing
  4. ???

Create central Settings.h and add logging settings

Currently there are various settings/constants defined in various header files. Want to combine them into a single header to allow control across the entire library from a single place. Also want to add flags/settings for controlling logging here.

  1. Create Settings.h
  2. Gather all existing settings into this header
  3. Add include everywhere settings are being referenced
  4. Add settings for logging per class
  5. Hookup logging settings to the instantiation of _debug per class

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.