All Projects → SumiMakito → RhythmView

SumiMakito / RhythmView

Licence: Apache-2.0 license
No description, website, or topics provided.

Programming Languages

kotlin
9241 projects

banner

release license

RhythmView - Visualizes rhythms for you.

Demo app

Try all preset visual effects and play with the options like a master!

Google Play Store

If you have difficulties accessing the Play Store, you may find APK files in releases.

Preview

preview

Quick start

1. Add the dependency

Firstly, add lines below in the project-level build.gradle:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Then, add lines below in the module-level build.gradle:

Replace <VERSION> with the latest version name.

dependencies {
    compile 'com.github.SumiMakito:RhythmView:<VERSION>'
}

2. Add the view to a layout

RhythmView does not have custom attributes in the XML layout.

<com.github.sumimakito.rhythmview.RhythmView
    android:id="@+id/rhythmView"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:padding="30dp" />

3. Access in Java/Kotlin code

// Kotlin
rhythmView.onRhythmViewLayoutChangedListener = { view: RhythmView ->
    // ... setup RhythmView
}      
// Java
rhythmView.setOnRhythmViewLayoutChangedListener(view -> {
    // ... setup RhythmView
});

Example: Ripple & PlaybackSource

// Java
...
public class PlayerActivity extends Activity {
    private MediaPlayer mediaPlayer; // to avoid the MediaPlayer being collected by GC
    private boolean mediaPlayerInitialized = false;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        int resolution = 8;
        ...
        // the listener will be triggered every time RhythmView's onLayout() is called,
        // data source and visual effect SHOULD be re-initialized in response to layout
        // changes
        rhythmView.setOnRhythmViewLayoutChangedListener(view -> {
            // initialize the MediaPlayer only once
            if(!mediaPlayerInitialized){
                mediaPlayer = MediaPlayer.create(this, R.raw.music);
                mediaPlayer.setLooping(true);
            }
            // initialize the preset data source
            PlaybackSource dataSource = new PlaybackSource(mediaPlayer, resolution);
            // initialize the visual effect
            Ripple ripple = new Ripple(rhythmView, 8);
            // set colors for high, medium, low frequencies and particles
            ripple.setColorHF(0xffef9a9a);
            ripple.setColorMF(0xffef9a9a);
            ripple.setColorLF(0xffef9a9a);
            ripple.setColorParticle(0xffef9a9a);
            // set the data source for the visual effect
            ripple.setDataSource(dataSource);
            // start the playback only once
            if(!mediaPlayerInitialized){
                mediaPlayer.start();
                mediaPlayerInitialized = true;
            }
        });
        // set the album cover (this operation can be done outside the listener)
        rhythmView.setAlbumCover(coverBitmap);
        ...
    }
    ...
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // remember to release the MediaPlayer instance
        mediaPlayer.release();
    }
    ...
}
// Kotlin
...
class PlayerActivity : Activity() {
    private var mediaPlayer: MediaPlayer? = null // to avoid the MediaPlayer being collected by GC
    private var mediaPlayerInitialized = false
    ...
    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        ...
        val resolution = 8
        ...
        // the listener will be triggered every time RhythmView's onLayout() is called,
        // data source and visual effect SHOULD be re-initialized in response to layout
        // changes
        rhythmView.onRhythmViewLayoutChangedListener = { view: RhythmView ->
            // initialize the MediaPlayer only once
            if (!mediaPlayerInitialized) {
                mediaPlayer = MediaPlayer.create(this, R.raw.music)
                mediaPlayer!!.setLooping(true)
            }
            // initialize the preset data source
            val dataSource = PlaybackSource(mediaPlayer!!, resolution)
            // initialize the visual effect
            val ripple = Ripple(view, 8)
            // set colors for high, medium, low frequencies and particles
            ripple.colorHF = 0xffef9a9a
            ripple.colorMF = 0xffef9a9a
            ripple.colorLF = 0xffef9a9a
            ripple.colorParticle = 0xffef9a9a
            // set the data source for the visual effect
            ripple.dataSource = dataSource
            // start the playback only once
            if (!mediaPlayerInitialized) {
                mediaPlayer!!.start()
                mediaPlayerInitialized = true
            }
        }
        // set the album cover (this operation can be done outside the listener)
        rhythmView.albumCover = coverBitmap
        ...
    }
    ...
    override fun onDestroy() {
        super.onDestroy()
        // remember to release the MediaPlayer instance
        mediaPlayer!!.release()
    }
    ...
}

Metrics & Specs

innerWidth = width - paddingLeft - paddingRight
innerHeight = height - paddingTop - paddingBottom

innerSize = min(innerWidth, innerHeight)

centerX = paddingLeft + innerWidth * 0.5
centerY = paddingTop + innerHeight * 0.5

maxDrawingWidth = innerSize * maxDrawingWidthScale * 0.5
radius = (innerSize - 2 * maxDrawingWidth - 2 * innerDrawingPaddingScale * innerSize) * 0.5
minDrawingRadius = radius + innerDrawingPaddingScale * innerSize

API definitions

RhythmView

coverSpinningSpeed

Type: Float

Default: 0.5f

Unit: Degrees per frame

To control the spinning speed of the cover image.

Positive value for CW spinning. Negative value for CCW spinning.

isPaused

Type: Boolean

Default: false

If true, the cover will stop spinning.

To stop the visual effect, please try to stop the MediaPlayer instance bind with the data source.

showFpsCounter

Type: Boolean

Default: false

If true, an FPS counter will display at the top left corner of the view.

innerDrawingPaddingScale

Type: Float

Default: 0.01f

maxDrawingWidthScale

Type: Float

Default: 0.24f

albumCover

Type: Bitmap(?Kotlin)

Default: null

The cover image for the RhythmView. Will display in a round shape.

Square images are recommended. Set to null to disable.

Non-square-shaped images will be resized and fit in to a squared area for clipping.

Donation

Cheers! Would you like to buy me a cup of Caramel Makito Macchiato?

You can donate with PayPal or Alipay.

License

Apache-2.0 license

RhythmView is available under the Apache-2.0 license.

See the LICENSE file for more info.

Copyright © 2017-2018 Makito.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].