Synchronized Metronome on Android! 🎹 🎼 🎶 (it was bad.)
Tags: devgrad2020, octograd2020
Published: 2020-05-21 09:41:20

So here is my final project during my undergrad final year, and i got to be honest... **it was bad**. And i will explain why. 

### Table of Contents
   * [Background](#background)
   * [Idea and Implementation](#stack)
   * [Results and Regrets](#results)
   * [Future Works (!!!)](#future-works)

### Background <a name="background"></a>

Besides only as a developer, i am also a musician. And i need to find a way "How to make sure everyone in a small band stay in tempo without any complicated in-ear-monitoring setup?". Hence why this idea came to my mind.

I chose to use Nearby Connections API only because i have used it in my other project. And it also claimed that it is ["high-bandwidth, low-latency, and fully encrypted to enable fast, secure data transfers."] (https://developers.google.com/nearby/connections/overview).

### Idea & Implementation <a name="stack"></a>

The idea is to create a simple metronome app that can connect to other devices that uses the same app using client-server approach. The server can play/pause/set tempo/configure the metronome, while other devices/clients that is joined to the server can only receives the server's command. 

I decided to use [MVVM](https://www.raywenderlich.com/34-design-patterns-by-tutorials-mvvm) approach to my app. There are only two `Fragment`s that serves as UI: the metronome page and the client-finding page. And there are only two `Service`s that will run in the background: the metronome, and the connection manager. Every changes is applied to the UI using [Binding Adapters](https://developer.android.com/topic/libraries/data-binding/binding-adapters) and every function calls (and returns) from the UI to the `Service`s has to go from the only global `ViewModel`. 

As mentioned, there are two services; `MetronomeService` is responsible to do all the metronome stuff, and the `ConnectionManagerService` - as the name implies - manages all the connection stuff. `ConnectionManagerService` is also the only instance that has all the Nearby Connection API implementations. 

### Results and Regrets <a name="results"></a>

The whole idea turns out to be a huge mistake. I cannot even sync the metronome ticks while being played together! It somehow started all synced but gradually turned not synced when played with the exact same tempo. I also implemented naive latency compensation but turns out Nearby's latency was too spread out. Nearby mentioned that they used combination of Bluetooth and Wi-Fi and it turns out to be true. But when the switch from Bluetooth to Wi-Fi happens, the latency just spikes uncontrollably between devices in the same server.

The mistakes turns out to be on both Services. On `MetronomeService`, *there is a possibility* that the low latency audio not consistently played throughout devices. And on `ConnectionManagerService`, the lack of granular control in Nearby makes things just... uncontrollable.

### Future Works (!!!) <a name="future-works"></a>     

I really want this project to be successful and help musicians to do gigs better. It wont be updated in near future but i have made a simple roadmap for this app:
   * **Complete UI/UX redesign**. The current ones looks like a bunch of placeholders.
   * **Replace current metronome audio implementation with something better**. [Oboe](https://github.com/google/oboe) came out to my mind when i am thinking about this but i didn't have much time to implement that.
   * **Replace Nearby with Native Wi-Fi API**. I do not know if it's possible but i was thinking to make the device that acts as a server also acts as a Wi-Fi Router that only accepts connections from clients that uses the app. I know there will be security obstacles to tackle out of this idea but if you have insights about what to use/what to do, please let me know!
   * **More metronome features!** Right now, it is only a metronome that plays a beep in constant beats per minute. I want to add more features such as subdivisions, more sounds, accentuations, etc.

I really want to thank all stakeholders who helped me in this project. It was really a learning process throughout the project. By the way, here's the repo!

{% github https://github.com/barjuandavis/wesync_kotlin %}

And happy graduation to all of us!