a MIDI interface for the OPL2 Audio Board and OPL3 Duo!
To make the experience fit your profile, pick a username and tell us what interests you.
The last two weeks I did a lot of work on the composer module of OPL Studio. This will be the module where you can arrange your drum and melody sequences into songs. Sequences are placed on a grid where they will be shown as sequence blocks.
I had already spent some time on this module quite some weeks ago, but I got stranded when I started to make things too complicated for myself. I had started on a very complex implementation where I wanted to make draggable sequence blocks and complex selections possible in the editor. I got rid of that idea for now in order to get things done. Making the editor more fancy will be for later.
The biggest change in the compser is the song grid. This used to be handled partially in the composer app module and partially in spearate UI elements making it very complex. The sequence blocks could only be rendered as 4 beat long blocks, which made it impossible to render blocks for sequences that are longer than 4 beats. Adding insult to injury, the sequence blocks could only be aligned by 4 beats and the code wasn't built to allow for efficient repaints.
In the new code sequence blocks are handled more efficiently as small 1 beat long segments. It can render the left, middle and right sides of blocks to be more efficient with less repainting while scrolling. Another part of the song gird UI that has now been fixed thanks to the smaller sequence blocks is the play head. This is a red line that passes over whe grid while the song plays to indicate the beat being played. The play head now updates currectly as playout progresses without leaving artifacts in the UI and slowing down while scrolling.
I also want to render the sequence number on top of the block, but haven't implemented that yet.
To add a sequence to the song you press and hold a cell in the song grid with the pointer. This will open a new dialog: the sequence selection dialog.
In this dialog all sequences that were created in the drum and melody sequence editors are shown in a grid of toggle buttons. The buttons show the sequence number and the pattern and colors that were assigned. Tabs on top of the dialog allow to switch between drum and melody sequences. The play button on the bottom left of the dialog can be used as a preview button for the sequence that was selected.
Right now it's finally possible to arrange sequences into songs, though the composer module is still far from being finished. There are still bugs to fix, features to implement (loading and saving would be nice!) and time needed to play with the module to see if it all works as I intended.
Lately I've been thinking about the buttons and potentiometer controls I added. I'm not sure how useful they will be. Especially the potentiometers might have been not the best choice. They always give an absolute value which would not be ideal unless the potentiometers are always used for the same function. Otherwise rotary encoders, which give a relative up / down value would be more appropriate. Right now the potentiometers don't even have a function yet.
Also the buttons are not of any use right now, other than looking fllashy with their lights I haven't given them any function and it's not something that I'm missing right now.
So I'm still thinking that maybe I should get rid of the buttons and the pots and make it a smaller device...
Ever since I added the melody sequencer to OPL Studio I never was really happy with it. Compared to the drum sequencer it always felt a bit clumsy and awkward to work with. It was time to once again refactor the melody sequencer an take care of all the annoyances I had with it.
One of my issues was that the sequences, both drum and melody, were too short. They were always only 16 steps. So the first thing I changed was to make all sequences have a flexible length between 16, 32, 48 or 64 steps. This ment some rework for the sequence code as well as for the UI where I had do add some spinners to select the sequence length and the bar that's being edited.
For the melody sequencer my biggest issue was that I never liked how is made its recordings from MIDI. I was always missing the beat and although it could kind of do step recording it was very inconvenient as it would also start the MIDI clock when you entered a note. To fix this I rewrote most of the melody sequencing code. I implemented a step recording mode that works like typing text on a keyboard. When recording is enabled and the MIDI clock is not running you are in step recording mode. The sequence button of the active step will blink and when you play a note on the keyboard it will be registered. When you release the key the sequencer will advance to the next step, just like typing text where the cursor moves to the next character position. To add longer notes to the sequence you simply hold down the key and the sequencer will start to step automatically with a slow interval. Making this change was a game changer for me when it comes to the usability of the melody sequencer. It's now feeling much more solid and usable!
Of course live recording is also still possible when arecording mode is enabled and the MIDI clock is running then key strokes will also be recorded to the sequence.
I also made a change to the clock divider on the melody sequences. Before you could set any arbitrary division between 1 and 16. This is now changed to selecting a note length between 16th, 8th or 4th note.
Lastly, I had moved the setting to switch the metronome on or off during recording to the settings panel in an earlier change. That was a mistake! When I really started to use the melody sequencer I found that I wanted to be able to switch the metronome on or off all the time. So I restored the metronome and I gave it it's own toggle button with a nice icon among the transport controls.
I also spend some time on less sexy things like adding support to load more instrument bank formats. I added support for Adlib Timbre Banks and Apogee Sound System Timbre files.
In the demo below you can see how I load a new instrument bank from an Apogee file on the SD card and how I use the newly implemented changes on the sequencers.
Today I tested the DIN MIDI input on the main board and implemented serial MIDI in the OPL Studio code. Code wise this is not a huge update, but this puts another check in the box for another item on my to do list. Next to the serial MIDI code I've also started on a controller for the front panel that for now will only handle the button lights. I made a demo video to show the front panel lights blink in tune with the music and the MIDI data is of course coming through the DIN plug.
It has been a very exciting week for the OPL Studio project wherer thing are really starting to take shape.
This week the first prototype PCBs for the project arrived! They turned out really nice and I immediately started building them up. The OPL Studio will have 3 layers. I'm extremely happy with my current design. It feels sturdy, has some nice weight to it and most of all, gone are all the headaches due to breadboard wiring! :)
On the bottom is the main board wher the Teensy is plugged in and where the OPL3 Duo!, SD card, MIDI and Eurorack interface are found. There are some logic chips on the board to help interfacing with the buttons, pots, lights etc. I thought it would be a good idea to not let the Teensy poll the controls, but let a separate controller take care of this task. I'll call it the Arduino part since it will be using an Atmel 328p. I have not yet fully assembled and tested the main board. So far only the Teensy, SD card, speaker and interface to the button lights and LCD have been tested. Bodge wire count so far: 1.
The 2nd layer is the PCB that contains the push buttons with LEDs, potentiometers and 3 status LEDs. This is also where the 3rd layer, the LCD plugs in. On this board the button LEDs and the power and SD status LEDs are already working.
I still have plenty ideas of what I want to change and add to the boards, but for now I couldn't be happier with it!
This is a new feature that I've been thinking about since the beginning of the project and I'm very excited about. Compound instruments allow me to trigger multiple patches when a single note is played. For example you can play a piano, an organ and a bass drum patch at the same time on 1 MIDI channel. It also allows creating more complex sounds because you will be layering different patches on top of each other.
A compound instrument can be constructed from 4 instrument patches. The first patch, the base instrument, will trigger the 3 sub instruments whenever it's played. To make things more interesting each sub instrument has a few parameters to influence it. The first parameter is of course the patch for the sub instrument. Next to that you can change the volume, panning (in the future), transpose (not in case of drum patches) and a set a delay before the sub instrument starts playing after the main instrument is triggered.
This is a lot of fun to play around with and it can give some very interesting sounds! Besides assembling the first prototype PCB this has taken all my time this week to nicely integrate the code, make the UI, test it and play around :)
Spinners would already keep incrementing and decrementing their value when you hold the + or - button, but still spinners with a big value range, such as those for instrument patches or tempo, it could take a long time to find the value you want. In this update spinners with a big range will start to make bigger value changes when you hold their buttons longer.
While I was trying out the lights for the buttons I added a little bit of code to the MIDI controller that can blink the lights when it receives note on events on certain channels. It will blink the buttons for the first 7 channels and the drum channel on the 8th button. I thought that it would look really gimmicky, but I must say that I ended up quite liking it, though the LEDs are way too bright currently and it get annoying fast if the thing is flashing its lights from the corner of your eyes. This will be fixed by some higher value resistors. I'll also add a setting to enable / disable the blinking, because I thiink it's not something I want all the time and the lights may end up getting some more serious function later.
Since writing my last log I've had a few very long and frustrating debug sessions. I was facing an increasing number of unexplained bugs where synthesizer functions would mysteriously stop working even though I was sure I had left the code in a working state. Only after dumping a huge amount of logs over serial, all of which looked fine, I finally found the issue after a full week of debugging. My mystery bugs were caused by intermittent connections on my breadboard! Frustrated, yet relieved I decided that it was time to start working on a more permanent home for the project.
So I've been busy with KiCad to design the first prototype PCBs. There will be two PCBs that will be stacked on top of each other: a main board and a control board. The control board will have 8 LED push buttons and 8 potentiometers to change various parameters. This board will also connect to the LCD screen. The bottom board will be the main board that holds the Teensy, SD card reader, DIN MIDI in and thru connectors, 8 control voltage / trigger inputs for Eurorack synths, and all the (logic) components to connect everything together.
While I was stuck with my mystery bugs I did however continue working on another part of the OPL Studio software that wouldn't depend on the OPL3 Duo synthesizer. I started to work on the settings screens. Right now three settings screens are ready.
The first is display settings where you can change the background color and pattern and screen brightness.
The second settings screen is for the pointer. Here you can recalibrate the stylus and enable or disable the UI click sounds.
This MIDI settings allow you to change the clock source between MIDI clock and the internal clock. You can enable or disable the metronome sound during recording and you can select the depth of pitch bends between 1 seti-tome or the default 2 semi-tones. That last setting I included because I found that there are quite a number of MIDI tunes that don't respect the GM standard 2 semi-tone pitch bend and therefore they will sound broken.
Up to a little while ago the drum and melody sequencers would remain playing in the background when you were using other parts of the OPL Studio UI. However after the last round of refactoring to enable playing the various sequences in the Sequence Composer I had to disable this background playing. Now after a bit more refactoring this functionality is back again and better than before! The audio now has priority over the UI. this means that when I need to render a lot to the screen, for example when a window is opened or closed, the rendering process periodically holds briefly to allow processing MIDI and sequencer events.
What about the Sequence Composer? For now I put it on hold while I figure out how to make its very complex UI work. Dragging and dropping the sequence blocks is still a tall order, so I may go for something simpler...
A lot of work has been done this week on the Sequence Composer module. The idea is that you can compose loops and simple songs from the drum and melody sequence that you create in the two sequencer modules. To do this you have a grid of 6 tracks where you can place the sequences represented by different color blocks (sequence blocks).
Without having covered the basics of a grid with sequence blocks that you can scroll through I started on the most difficult part for this module. I wanted to be able to drag and drop sequence blocks in my editor! Without thinking it through I started working on dragging a single block. This was already a difficult thing to do and while working on the code I though of more and more edge cases I'd need to cover, such as dragging multiple sequence blocks, making the editor scroll when I drag block over the edge, what happens when two block overlap. it was becoming a real nightmare and after 3 or 4 failed attempts I decided to park it for now and first get the 'easy' part over with.
The easy part would be a scrollable grid filled with sequence blocks that all have the same size. Later sequence blocks can have different lengths due to a sequence taking more bars to play because of its clock divider, but that's not important now. Keeping rendering efficiency into account was still important to do from the start, so I made the grid and sequence blocks in such a way that only the part that will actually change while scrolling is updated. This turned out to be a relatively simple UI task to implement.
The screenshot below shows the result of rendering random sequence blocks in the editor. Each sequence has an identifier D for drum and M for melodic followed by the sequence number. To make them easier to recognice each sequence can be given a unique color and pattern as well.
What is needed next is to link sequence blocks to a sequence. For this quite some refactoring was needed, especially for the drum sequences that were not stored as individual objects yet like the melody sequences. So this has been changed now. Both drum and melody sequences are now objects that inherrit from a common Sequence class. As a bonus this allows me to now play any sequence at any time. Exactly what I need for the editor.
This was quite a big effort and after testing that I didn't break anything it will now be time to link sequences and sequence blocks and make a start on an actually functioning editor!
Last week seemed like not much was happening on the project, though looking back I did lot of small jobs and improvements to finish up on things.
First is the patch editor. The buttons to clear an operator, patch or all patches now work. The latter two will first show a confirmation dialog before clearing. The buttons to copy and past operators and patches are now also working. And finally for the patch editor there is now also an error message if loading patches from a file fails.
Next up is the drum sequencer. This one has some bigger changes. First off are the buttons on the top to run and stop the sequencer. Earlier these were shared with the melody sequencer, but this is no longer the case. The buttons are now bigger, they have new icons and there is no longer a record button in the drum sequencer.
Another change is that drum sequences now also have a color and pattern representation that helps identifieng sequences in the composer. With this change the spinner control for the track has moved to a new line below the spinner to select the pattern.
There was some unfinished work in the Drum Controller that did not allow for more than 1 drum sequence of 8 tracks. This is now fixed and it allows to have 16 drum sequences of 8 tracks each. There is still some work to be done here, because the way drum sequences work now will become a problem for the sequence composer.
Lastly there are now some buttons on the bottom of the drum sequencer that allow you to clear tracks, single sequences and all sequences as well as buttons to copy and paste tracks and sequences. The copy / past button actions are not yet implemented, but the clear buttons all work including dialog boxes that ask to confirm before clearing a single sequence or all sequences.
Some of the other small improvements include:
The big new thing this week is the sequence composer. This is a new module that allows you to arrange drum and melody sequences into more complex loops or songs.
The sequence composer shows a grid of 6 rows and up to 256 beats. The cells will contain blocks for the drum and melody sequences that make up your song. The blocks will show with the color and pattern that you selected in the sequence editors to make it easier to see the structure of a song.
This will be a very complex module due to the UI interaction where sequence blocks should be able to be moved around by dragging them with the pointer. Graphics performance wise it will be very demanding as a lot of repainting is needed while a song is also playing in the background. Currently this is not yet possible; the module is now only rendering an empty grid, but it does show the current measure (bar) of the song and it can be moved with the scrollbar below the grid.
The sequence composer allows setting two loops within the song that can be individually enabled. Each loop has a cue button to immediately jump to the start of the loop. Looping is a new feature within the Transport Controller, which handles all timing and clocks.
When the transport controller is running the grid will scroll per 4 measures depending on the song tempo and position. There will be an indicator for the current song position in the form of a line.
For the sequence composer there are also rewind and fastforward buttons that take advantage of some Transport Controller improvements. With the rewind button you can step back 1 measure in the song when clicked or rewind to the beginning of the song by holding the button. The fast forward button works the same way:...Read more »
The title says it al, I don't like working with SD cards and the Arduino SD library. It's alwyas like Russian Roulette whether a card will initialize or not. I've spend too much time messing arounds with different SD cards, inserting them, removing them, reformatting, trying different breakout boards, rewiring and I could go on. Eventually I'm blaming it on my breadboard and all the long wires flapping around. I hope that when I build this on a real PCB things will be more stable.
So the file chooser dialog box is here! It was a lot of work to get this one implemented. I restared the controller code for the SD card 3 times before I had something that was performing good enough and would not claim all of the Teensy's memory.
Initially I though to walk through the directory on the SD card and return file properties to the UI when it needed to render. This prooved to be really, really slow! Another problem was that the FAT file system is index based so my files and folders would be read in the order I had put them on the card. What I wanted was to show the files sorted in a natural way, folders first then files sorted alphabetically and respecting numbers. This meant reading out the contents of a directory and storing all the entries in a large String array and sorting it. To keep an eye on memory usage I limited to number of entries per directory to 255 and I'm only using the DOS 8+3 filenames. If memory allows it maybe I will allow for more files and long filenames later...
I'm also allowing to filter on specific filetype(s) when reading a directory to make it more easy to find files and to not run into this 255 entry limit, hopefully. After retrieving the filtered items from the folder I'm sorting the array of item names multiple times (Bubble sort FTW cause I'm too lazy) before the files are rendered in the file chooser.
This process can take several seconds if you have a folder with many items so while the directory contents are read I show an hourglass icon to indicate that the UI is blocked. This is also where I still need to add the MIDI update code so it will not appear to hang.
I happy with how the file chooser turned out. I've started to put it to use in the Patch Editor module where I'm now able to load the first type of instrument bank: The Adlib BNK file. I's already great to be able to switch from the default instruments to another set but I will add support for more file types and also saving instrument patches I still need to start on.
What I still had to do last time is to add a dialog box in the melody sequencer to choose a color and pattern for your sequence. This will make it easier for you to recognise sequences later in the composer module that I still have to get started on. The idea for the composter is that you can arrange drum and melody sequences to create bigger sequences, loops and maybe simple tunes.
Next to this dialog I also managed to fix a few bugs in the mixer panel. It would not always update the patch names when a program change happened and the solo / mute also had a very subtle bug where it would mute the wrong channel very briefly. For the mixer panel that should wrap things up for now. Maybe some small additions later...
This week I've spent most of the time n getting the SD card to work. This has been kind of a pain due to broken SD cards, confusing library code and faulty wiring. For the SD card I want to use an external module instead of the card reader on the Teensy. This is so that I'm not tied to the layout of the Teensy and I can put the SD card anywhere I want in the final version. I decided to use the cardreader that's built-in to the back of the LCD display for now. For the library I thought to use SdFat since I had used it in the past and it had a smaller footprint than the default SD library. Unfortunately there was a new version that I couldn't get to work. Too many configuration options and confusing code. Since I have the luxury of a Teensy I opted for the regular SD library to get the job done!
So after spending a lot of time on the very basics of just getting the interfact to the SD card working I got to the point where I can now list the items in a folder and draw them on the screen. I made a little test screen as you can see below. Still a long way from loading / saving files.
There is something strange with the SPI interface of the SD card reader on the LCD display. If the card reader is connected to the SPI bus then it will clobber any data sent to the OPL3 Duo after writing to the LCD. This happens regardless of having an SD card in or not. It's strange, but given that the card reader seems to be added to the display as a 'nice to have since we have the space for it on the PCB' it wouldn't surprise me if some corners were cut...
Finally for this log I made a longer demo video that shows the current state of the OPL Studio. In this one I'm sampling the MIDI events on one of the channels from a song I'm playing from my laptop. It shows how to trigger a recording when a note-on MIDI event is received. After recording the sequence I move it to MIDI channel 1 so I can change the parameters of the instrument patch and hear the result at the same time. I play around with the patch until I have something I like and finally i'm adding a drum sequence to finish things off.
There are now two new dialog boxes: an alert dialog and a choice dialog. They are nothing special; you can show 3 lines of text and show an icon on them. When the dialog is closed the application module can take the result of the dialog and handle it accordingly.
For the melody sequencer I added most of the missing pieces. You can now select the MIDI channel to record / play on, change the instrument patch, the volume control works and the clock divider has been implemented. Some bugs in the internal clock have also been fixed so the melody sequencer can now use both the internal and the external MIDI clock.
The biggest change for the melody sequencer is that you can now have up to 64 different sequences. This is still a bit buggy in the editor module, though through playing with it a lot I'm making it more stable and also making the UI of the editor more intuitive. I'm already happy that after refactoring the melody sequences there are no crashes due to broken pointers :)
Soon I will start on the implementation for the SD card. Not being able to save and load files starts to get annoying while testing. I find myself playing with the device for a long time which is a lot of fun, but not being able to save the rhythms and instrument patches is getting annoying. This will be a lot of work, because I want the file browser to make use of the same UI. I have some file icons and mock-ups drawn already.
I've made some designs on paper for a simple effect module where playing certain instruments can trigger playing up to 3 other instruments (layers?). Per layer you can change the instrument patch, volume, panning, transpose and set a trigger delay. This way you can layer instruments to create more complex sounds or create chorus effects. There will also be an option to retrigger the effect while a note is sustained and this way you can create arpeggios.
I'm also starting to think about some physical controls and how to implement them. I'm thinking about at least having some rotary encoders to break out the main operator settings (ADSR, output level, feedback, etc) and some push buttons with LEDs to select the active operator. For the physical controls I'm thinking to add an Arduino, or rather just an Atmega328p to monitor all buttons and encoders. I don't want to put the burden of monitoring the controls on the Teensy as well. The Atmega can communicate with the Teensy over the SPI bus and it could be used for other tasks as well in the future.
Become a member to follow this project and never miss any updates