Hello again! I’m back from a wonderful vacation and ready to share some more experience of Android programming. Today I’m presenting a simple drum machine app that I made for fun. If you saw the video above, then you probably got the idea how a drum machine works. The design was inspired by one of the greatest drum machines ever – the AKAI MPC. You can have a look at how the original device looked like for example here. Our app is, of course, greatly simplified compared to AKAI MPC, but you can have some fun with it too.
Here’s a screenshot for a better idea of how the UI looks (clickable):
Some interesting features of this app:
- The UI is done using bitmaps and custom controls to imitate the original device
- The latency is low enough not to be annoying (at least on my Droid)
- You can press multiple buttons at once which is very good for long samples such as the bass drum
- The LCD screen control uses a 9-patch bitmap background, and switches between flashing, static and ticker text
- The LCD screen uses a custom TrueType font that is included within the app
Now let’s see how the most interesting features of this app were implemented (as usual, the source is available at the bottom of the article).
Step 1: The Button Grid Control
Drawing the view
The button grid control displays an MxM matrix of buttons. At any moment, each button can either be pressed or idle. Pressing a button starts playing the sample that is tied to this button, while as soon as you release the button the sample stops. Normally the user (the artist?) will keep the button pressed for a while for a long sound such as a boom bass kick and will just tap the button for a short sound such as a snare or a clap.
The reason I decided to implement the whole grid as a single component (see ButtonGridView) rather than implementing a button and putting its multiple instances into a grid layout, is most of all the way multi-touch works on Android. You can override onTouchEvent() in your custom view all right, but once you touch and hold one view, all consequential touches (i.e. second, third) will be sent to the same first view rather than the views you hit with your next touches. Thus, if you hit button A and hold it, then hit button B, the MotionEvent will never be sent to button B – it will be sent to button A with coordinates that lie outside of A’s bounds. Then you need to understand which other button you hit while you are still in A’s code. When all buttons constitute a single view, it starts to make much more sense. (I think the API works that way because it was assumed that multiple touches will always hit the same view, such as in the case of pinch zooming etc.)
By the way, I demonstrated creating custom views in one of my previous articles. Read it if you want to know more about making custom looking views from scratch.
Thus, all buttons are one big custom component that is drawn using two bitmaps – one for the pressed state and one for the idle state. Bitmaps are scaled by Android and look pretty well on my device. I drew both bitmaps in Photoshop.
The most straightforward way to play a sound on Android is the MediaPlayer class. That is, a sound. In our case, when we have many sounds which will often play at the same time, creating a MediaPlayer for each sound and working all through the complex lifecycle of MediaPlayer every time we need to start and stop a sound, sounded crazy to me. However, I did try that, only to see what the latency would be. It was awful and completely not useful for our case.
Now, believe it or not, Android platform developers took care of our case. There is an API that was designed most of all for games but is very good for our drum machine app too. The class is called SoundPool and I really recommend that you get familiar with its lovely, simple and powerful API.
Basically, a SoundPool maintains a set of sound samples which you can trigger and stop with a very small latency using a straightforward API. You can see how it is used in the DrumMachine class in the app code.
After solving the multi-touch UI and the sound challenges, I had a playable drum machine, but having just a grid of gray buttons was too boring so I decided to add an LCD screen view.
Step 2: The LCD Screen Control
The LCD screen is also a custom view made from scratch. It uses a 9-patch bitmap as the background. Basically, it is a modified background bitmap that Android can stretch gracefully for any size, so that borders stay the same size while the stretchable area grows or shrinks. You can read more about nine-patch bitmaps in the Android docs here. In order to be able to draw a 9-patch on a Canvas, I used the NinePatchDrawable class (have a look at the LcdScreenView class in the code).
Perhaps not everyone is aware that you can easily load custom fonts using the Typeface class, namely its createFromAsset() method. The TTF file should be in the asset folder of your app, and the result will be just a Typeface instance that you can use in your Paint definition and, consequently, when drawing a string on the Canvas.
In order to make the LCD logic (flashing, tickering etc.) clear, I separated it into a separate class that does not handle UI issues, only the logic – see LcdScreen vs LcdScreenView.
There’s also the DrumMachineLcdUpdater class that acts as a client of the LcdScreen class and plays with its settings and changes the text from time to time to make the app more interesting to look at.
We just made a simple drum machine app inspired by AKAI MPC. I hope you liked this post, and if you have any further ideas or questions, please feel free to write comments below.
Attachment: the source