207 lines
8.1 KiB
Markdown
207 lines
8.1 KiB
Markdown
|
# Contributing <!-- omit in toc -->
|
||
|
|
||
|
We welcome contributions of all kinds and sizes. This includes everything from simple
|
||
|
bug reports to large features.
|
||
|
|
||
|
## Table of Contents <!-- omit in toc -->
|
||
|
|
||
|
- [Workflow](#workflow)
|
||
|
- [Getting started](#getting-started)
|
||
|
- [Translations](#translations)
|
||
|
- [Stats](#stats)
|
||
|
- [Adding sounds](#adding-sounds)
|
||
|
- [Contributing code](#contributing-code)
|
||
|
- [Architecture](#architecture)
|
||
|
- [Android](#android)
|
||
|
- [Cast Receiver](#cast-receiver)
|
||
|
- [Best Practices](#best-practices)
|
||
|
- [Guiding Principles](#guiding-principles)
|
||
|
- [Releases](#releases)
|
||
|
- [Play Store](#play-store)
|
||
|
- [F-Droid](#f-droid)
|
||
|
|
||
|
## Workflow
|
||
|
|
||
|
- We love GitHub issues!
|
||
|
- For small feature requests, an issue first proposing it for discussion or demo
|
||
|
implementation in a PR suffice
|
||
|
- For big feature requests, please open an issue to avoid wasting time on a feature
|
||
|
that might need reworking
|
||
|
- Small pull requests for things like typos, bug fixes, etc are always welcome
|
||
|
|
||
|
## Getting started
|
||
|
|
||
|
1. Ensure that you have the latest Android SDK tools installed on your machine
|
||
|
1. Fork the repository to create a copy in your GitHub account. The forked repository
|
||
|
should be accessible at `https://github.com/<your-username>/noice`
|
||
|
1. Clone the forked repository to your machine
|
||
|
1. Open the existing project using Android Studio or any editor of your choice
|
||
|
|
||
|
## Translations
|
||
|
|
||
|
Please refer to the [Noice project on
|
||
|
Weblate](https://hosted.weblate.org/engage/noice/) to contribute translations.
|
||
|
|
||
|
### Stats
|
||
|
|
||
|
<p align="center">
|
||
|
<img alt="Cast receiver app architecture" src="https://hosted.weblate.org/widgets/noice/-/horizontal-auto.svg" /><br>
|
||
|
</p>
|
||
|
|
||
|
## Adding sounds
|
||
|
|
||
|
Feel free to add more sounds to Noice taking the following under consideration.
|
||
|
|
||
|
- Looping sounds should be at least 30 seconds and at most 2 minutes long. These
|
||
|
are not hard limits but the goal should be to minimize the ease of recognising
|
||
|
recurring patterns in loops
|
||
|
- If a looping sound doesn't have too many recognisable notes, e.g. cricket
|
||
|
sound, consider using dual samples. Dual samples make it hard to recognise
|
||
|
repeating patterns. See [this
|
||
|
issue](https://github.com/ashutoshgngwr/noice/issues/62) for more details.
|
||
|
- Consider applying the [Compressor
|
||
|
effect](https://en.wikipedia.org/wiki/Dynamic_range_compression#Controls_and_features)
|
||
|
to the new sounds. We recommend the following settings, but these do not
|
||
|
produce the best results for all ambient sounds. To get best results, tweak
|
||
|
these settings, test their output and trust your best judgement.
|
||
|
- Threshold: -32 dB
|
||
|
- Noise Floor: -70 dB
|
||
|
- Ratio: 10:1
|
||
|
- Attack Time: 0.10 sec
|
||
|
- Release Time: 1 sec
|
||
|
- All sounds should be encoded to `mp3` format with the following configuration.
|
||
|
I use [Audacity](https://www.audacityteam.org) for editing audio
|
||
|
- Sample rate: 44.1 kHz
|
||
|
- Bit rate mode: Average
|
||
|
- Quality: Standard, 192 kbps
|
||
|
- Variable Speed: Fast
|
||
|
- Channel Mode: Stereo
|
||
|
- Once you have the sounds ready, copy the audio files to the
|
||
|
[`assets`](https://github.com/ashutoshgngwr/noice/tree/HEAD/app/src/main/assets)
|
||
|
directory and add them to the `LIBRARY` map in
|
||
|
[`Sound.kt`](https://github.com/ashutoshgngwr/noice/blob/HEAD/app/src/main/java/com/github/ashutoshgngwr/noice/sound/Sound.kt),
|
||
|
e.g.
|
||
|
|
||
|
```kotlin
|
||
|
"birds" to Sound(
|
||
|
// relative path of audio files in `assets` directory
|
||
|
arrayOf("birds_0.mp3", "birds_1.mp3"),
|
||
|
|
||
|
// title string resource
|
||
|
R.string.birds,
|
||
|
|
||
|
// sound group in which the sound should be placed
|
||
|
R.string.sound_group__life,
|
||
|
|
||
|
// an array of Pair instances where first string resource represents the description
|
||
|
// of sound and second string resource represents the URL of sound's source. Both of
|
||
|
// these resources are shown on the `About` screen of app.
|
||
|
arrayOf(
|
||
|
Pair(
|
||
|
R.string.credits__sound_birds,
|
||
|
R.string.credits__sound_birds_url
|
||
|
)
|
||
|
)
|
||
|
)
|
||
|
```
|
||
|
|
||
|
## Contributing code
|
||
|
|
||
|
Most of the code is documented but not very thoroughly.
|
||
|
|
||
|
### Architecture
|
||
|
|
||
|
#### Android
|
||
|
|
||
|
The Android app is written in Kotlin. It does not adhere to modern architectures
|
||
|
(e.g. MVVM) or use modern frameworks. The rationale behind the choice was simple
|
||
|
— the view interactions are simple, and the views don't mutate too often.
|
||
|
|
||
|
The following diagram depicts the sound engine architecture in detail. Here
|
||
|
`MediaPlayerService` (a foreground service) controls a `PlayerManager` instance.
|
||
|
A `PlayerManager` controls multiple `Player` instances and can have at most one
|
||
|
`Player` instance for each sound present in the library.
|
||
|
|
||
|
<p align="center">
|
||
|
<img align="center" alt="Android app architecture" src="assets/android-app-architecture.svg" /><br>
|
||
|
</p>
|
||
|
|
||
|
#### Cast Receiver
|
||
|
|
||
|
The Cast receiver app is written in TypeScript. The TypeScript code transpiles
|
||
|
to the plain JavaScript to run in the Chromium instance on Chromecast devices.
|
||
|
The receiver app receives simple commands (JSON) from the `Player` component in
|
||
|
the Android app using Chromecast Sender and Receiver SDKs.
|
||
|
|
||
|
The receiver app has its `PlayerManager` implementation, which reacts to command
|
||
|
messages received from the sender Android app. The receiver app fetches the
|
||
|
audio from the internet instead of employing complicated mechanisms for
|
||
|
streaming audio over the local network. Hence, the sender app only needs to send
|
||
|
`soundKey`s with each of its control messages.
|
||
|
|
||
|
On receiving the following message, the `PlayerManager` on the receiver app will
|
||
|
immediately pause the [`Howl`](https://howlerjs.com/) instances corresponding to
|
||
|
the keys present in `src` array.
|
||
|
|
||
|
```json
|
||
|
{
|
||
|
"src": ["birds_0.mp3", "birds_1.mp3"],
|
||
|
"isLooping": true,
|
||
|
"action": "pause",
|
||
|
"volume": 0.3
|
||
|
}
|
||
|
```
|
||
|
|
||
|
<p align="center">
|
||
|
<img alt="Cast receiver app architecture" src="assets/cast-receiver-architecture.svg" /><br>
|
||
|
</p>
|
||
|
|
||
|
### Best Practices
|
||
|
|
||
|
- Let Android Studio do the code formatting
|
||
|
- Add comments wherever you deem them necessary
|
||
|
- Include tests when adding new features
|
||
|
- When fixing bugs, start with adding a test that highlights how the current behaviour
|
||
|
is broken. This is not mandatory since it is not always possible/approachable
|
||
|
|
||
|
## Guiding Principles
|
||
|
|
||
|
- We allow anyone to participate in our projects. Tasks can be carried out by anyone
|
||
|
that demonstrates the capability to complete them
|
||
|
- Always be respectful of one another. Assume the best in others and act with empathy
|
||
|
at all times
|
||
|
- Collaborate closely with individuals maintaining the project or experienced users.
|
||
|
Getting ideas out in the open and seeing a proposal before it's a pull request helps
|
||
|
reduce redundancy and ensures we're all connected to the decision-making process
|
||
|
|
||
|
## Releases
|
||
|
|
||
|
Noice is regularly updated on Google Play Store and F-Droid. A commit with the following
|
||
|
changes is necessary to prepare a new release.
|
||
|
|
||
|
1. It must bump app version name and code in `app/build.gradle`
|
||
|
2. It should add the release notes in `en-US` locale in the Fastlane metadata. Release notes are
|
||
|
added to a new file at path `fastlane/metadata/android/en-US/changelogs/<version-code>.txt`
|
||
|
3. It should update the app's descriptive assets (Fastlane metadata) if required
|
||
|
4. It should update generated screenshots if required (`fastlane generate_screenshots`)
|
||
|
|
||
|
### Play Store
|
||
|
|
||
|
Noice uses [GitHub actions](https://github.com/ashutoshgngwr/noice/actions) to automatically
|
||
|
build and push releases to Google Play store.
|
||
|
|
||
|
- We have been strictly following [Semantic Versioning](https://semver.org) since 0.4.x
|
||
|
- New translations are considered as a feature
|
||
|
- All releases tagged in Git repository are pushed to beta track on the Play Store. After ample
|
||
|
time, a release is manually promoted to the production track for general availability.
|
||
|
- In case a feature is merged into the master branch and a patch release needs to be created for
|
||
|
the latest public release, create a temporary branch with pattern `Major.Minor.x` e.g., `1.1.x`.
|
||
|
Tag any further patch releases to a commit in this branch. Before the next _non-patch_ release,
|
||
|
the temporary branch can be merged into master.
|
||
|
|
||
|
### F-Droid
|
||
|
|
||
|
F-Droid releases are picked by its builder based on the latest tag. See
|
||
|
[the metadata file](https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/com.github.ashutoshgngwr.noice.yml)
|
||
|
for more information.
|