evacuated-noice/docs/CONTRIBUTING.md

6.7 KiB

Contributing

We welcome contributions of all kinds and sizes. This includes everything from simple bug reports to large features.

Table of Contents

Workflow

  • We love Git 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. Fork the repository to create a copy in your GitHub account. The forked repository should be accessible at https://git.nogafam.es/<your-username>/evacuated-noice
  2. Clone the forked repository to your machine
  3. Open the existing project using Android Studio or any editor of your choice

translations

work in progress

Stats

Cast receiver app architecture

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 for more details.

  • Consider applying the Compressor effect 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 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 directory and add them to the LIBRARY map in Sound.kt, e.g.

    "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.

Android app architecture

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 soundKeys with each of its control messages.

On receiving the following message, the PlayerManager on the receiver app will immediately pause the Howl instances corresponding to the keys present in src array.

{
  "src": ["birds_0.mp3", "birds_1.mp3"],
  "isLooping": true,
  "action": "pause",
  "volume": 0.3
}

Cast receiver app architecture

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.

Releases

The goal is to replace upstream Noice entirely 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

Not supported.

F-Droid

F-Droid releases are picked by its builder based on the latest tag. See the metadata file for more information.