This app started as a project at my university. Back then, I had tried several music production apps on android and I was kinda disappointed by all of them using piano-like keyboards. As an amateur musician, and knowing some bits of piano playing, I just don't see them practical on a touchscreen because you don't get the same feeling from the keys. I mean, there's no real physical separation between the keys, and you cannot have the sensation of pushing on a key... So then, why don't you let your fingers slide on the screen instead of lifing them and pressing again to play a new note ?
It's starting from those consideration that I got the image of a circular keyboard in my mind. You would hold your device with one hand, while the other could have access to all the keys because they would be organized in a circle. Indeed, the tips of the fingers form an arc, just stretch your hand and see for yourself ! Using this idea, I was convinced that it would be very easy to play a chord, and then switch to another by moving the position of 1, 2 or 3 fingers.
So, I started implementing what I refer now as the ring-shaped keyboard. And it was actually quite a challenge, because android doesn't provide any buttons of this sort ! Finally, I got around it by creating custom View objects, where I would draw a little piece of the ''arc'' button and rotate it to bring it to the right place. First, I used bitmaps spanning the entire screen for each bitmap, which was a disaster for the memory. So I limited the size of those bitmaps, and using a lot of non straightforward trigonometry, could solve the issue.
At some point I started thinking about the number of keys displayed. Including all the pitches in an octave plus the upper octave note, that would make 13 keys to display. I thought it was a bit much, especially comparing the size of the touchscreens and from our fingers ! That is also a problem I think can plague synthesizer on mobiles. With so little keyboards, it gets quite hard to reach that tiny black key, no ? So, each key should be made bigger, and some must then be left out. Which ones ? Well, those black keys that we're not gonna use most of the time anyway !
But then, I was not very keen on the idea of limiting the musician user to the standard scales only. Because I think you always need that half step to give a distinctive feel to your composition. That's when I got my genious idea (yes I'm quite proud of it) to be able to add or remove keys. The key is no longer a static object always there on the keyboard, instead it is a dynamic object that can be added when the player needs it ! And this idea complies quite well to the ''gestures vocabulary'' already introduced on the touchscreens devices : a key is added by pulling 2 keys apart (very similar to the pinch and zoom gesture) and a key is removed by throwing it out of the ring. Plus, it was very fun to program this part ! In the end, I'm quite satisfied with this part of the program, although I want to redo the graphics completely for a future release...
So, I started implementing what I refer now as the ring-shaped keyboard. And it was actually quite a challenge, because android doesn't provide any buttons of this sort ! Finally, I got around it by creating custom View objects, where I would draw a little piece of the ''arc'' button and rotate it to bring it to the right place. First, I used bitmaps spanning the entire screen for each bitmap, which was a disaster for the memory. So I limited the size of those bitmaps, and using a lot of non straightforward trigonometry, could solve the issue.
At some point I started thinking about the number of keys displayed. Including all the pitches in an octave plus the upper octave note, that would make 13 keys to display. I thought it was a bit much, especially comparing the size of the touchscreens and from our fingers ! That is also a problem I think can plague synthesizer on mobiles. With so little keyboards, it gets quite hard to reach that tiny black key, no ? So, each key should be made bigger, and some must then be left out. Which ones ? Well, those black keys that we're not gonna use most of the time anyway !
But then, I was not very keen on the idea of limiting the musician user to the standard scales only. Because I think you always need that half step to give a distinctive feel to your composition. That's when I got my genious idea (yes I'm quite proud of it) to be able to add or remove keys. The key is no longer a static object always there on the keyboard, instead it is a dynamic object that can be added when the player needs it ! And this idea complies quite well to the ''gestures vocabulary'' already introduced on the touchscreens devices : a key is added by pulling 2 keys apart (very similar to the pinch and zoom gesture) and a key is removed by throwing it out of the ring. Plus, it was very fun to program this part ! In the end, I'm quite satisfied with this part of the program, although I want to redo the graphics completely for a future release...
The other big programming part was of course the sound engine. I wanted something that could play sounds in a very flexible manner, even when the effects are tinkered with, or when the pulse is changed. In my initial idea, I also wanted to give the possibility to connect multiple devices running Ronde together, so that multiple keyboards would be available to play! To achieve this, the devices had to be synced together. And one device could be defined to play the sounds created by all the others. This heavily influenced the conception of the sound engine, since I decided that it would be implemented in a separate service that would receive messages either from the app itself (the MainActivity class) or from the app running on another device, through wifi connection. This proved to work ok, but I dropped the feature for the goolge play release, because it was not very stable. Might be that I will work on it again at some point in the future.
Instead, I thought to give the user to play multiple sounds on the same device by adding a tab system, where each tab is assigned to a sound and can have it's specific recorded notes. This also required the addition of a mixer, to set the volume of each sound relative to the others.
All in all, I found the most interesting part to program was the sound generation. I did everything from scratch, implementing the sounds and effects based on the knowledge I've had from these effect from real standalone synthesizer. The app includes a range of .wav sound files as basic waveforms (these files have to start and end with a 0 PCM value to avoid clipping) and I wrote an algorithm that would remove or add samples to match the frequency of the pressed key. The effects I chose to include were fairly simply ones programmatically. The detune effect is achieved by generating the sound multiple times in parallel with slightly different frequencies. The portamento effect applies a frequency shift from the last note the finger rested on. It works only when you slide the finger from one key to another, not when you press, release and press another key. This is an interesting concept because the portamento effect follows each of your finger independently. This means you can have a portamento one a whole chord. I think it is a unique feature since, from what I've seen until now, other synthesizers always restricts to single note play (mono mode) when using portamento. The vibrato and tremolo effects simply applies a sine variation on the volume or the frequency. And the ADSR is just what it is, not requiring more explanation.
Being the first time I worked on direct sound generation, I'm pretty satisfied with the result. Although, as a note for the future, I think the produced sound are generally pretty ''rough'' and that I should implement sample interpolation (possibly through fourier transform) to get it more smooth. Also, the effects curves are probably biased and I should work on more precise math. For example, the portamento effect is linear in frequency, but might sound better if following a linear evolution of the notes (twelfth root curve).
I also have to mention the problems introduced by the poor design of android's audio systems. On my test tablet, the audio buffer had the minimal length of 200ms. This caused a lot of problem to achieve a precise playback of the recorded notes. Furthermore, it drastically increased the input latency, as, in addition to the touchscreen latency to record the user click, the sound generation is always delayed to the next buffer generation, which makes 200ms more latency in the worst case scenario. I've discovered that it is a problem a lot of developer encounter on android systems.
So, a lot of talk for this first post in the end... I might go into more details about some of the features in the future. Before releasing it today, I put the app on hold for a long time, until starting again a month ago or so. My work lately has been mainly to fix the playback imprecision and bugs, adding the input quantization to help users with the latency, fixing the UI for mobile phones and added a nice progression bar to know well... how the loop progresses !
The goal of this blog is (for me) to keep some record of the progress made on the app and (for you) to get a glimpse of the design choices I made.. and if you have some alternatives, some features to comment or that you would like to see implemented, please say it so you and I will consider it !