Browse Source

修改节拍器部分

Pq 2 years ago
parent
commit
4be3e55904

+ 1 - 0
metronome/build.gradle

@@ -40,6 +40,7 @@ dependencies {
     testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
     implementation project(':BaseLibrary')
+    implementation project(':live_teaching')
     //ARouter
     annotationProcessor("com.alibaba:arouter-compiler:$rootProject.ext.android.arouter_api_version")
 }

+ 156 - 0
metronome/src/main/java/com/cooleshow/metronome/MetronomeActivity.java

@@ -5,12 +5,43 @@ import androidx.viewbinding.ViewBinding;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.SoundPool;
 import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.View;
 
 import com.cooleshow.base.ui.activity.BaseActivity;
+import com.cooleshow.metronome.constants.MetronomeConfig;
+import com.cooleshow.metronome.constants.MetronomeType;
 import com.cooleshow.metronome.databinding.ActivityMetronomeLayoutBinding;
+import com.cooleshow.metronome.widget.CircularSeekBar;
 
 public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBinding> {
+    public MetronomeType currentBeatType;
+    public int currentBeatRate = MetronomeConfig.DEFAULT_PLAY_RATE;
+    private SoundPool soundPool;
+    private int tickVoiceId;
+    private int tockVoiceId;
+
+    public int playPosition = 0;
+    private Handler mHandler = new Handler();
+    private Runnable mRunnable = new Runnable() {
+        @Override
+        public void run() {
+            long delayMillis = (long) (1 / (currentBeatRate / 60d) * 1000);
+            boolean tickOrTock = isTickOrTock();
+            if (tickOrTock) {
+                soundPool.play(tickVoiceId, 1F, 1F, 0, 0, 1F);
+            } else {
+                soundPool.play(tockVoiceId, 1F, 1F, 0, 0, 1F);
+            }
+            playPosition++;
+            mHandler.postDelayed(mRunnable, delayMillis);
+        }
+    };
 
     public static void start(Context context) {
         Intent intent = new Intent(context, MetronomeActivity.class);
@@ -25,10 +56,135 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
     @Override
     protected void initView() {
         viewBinding.toolbarInclude.toolbar.setBackgroundColor(Color.TRANSPARENT);
+        currentBeatType = MetronomeType.METRONOME_44_TYPE;
+        viewBinding.tvCurrentBeat.setText(currentBeatType.getName());
+        viewBinding.tvSpeed.setText(String.valueOf(currentBeatRate));
     }
 
     @Override
     protected ActivityMetronomeLayoutBinding getLayoutView() {
         return ActivityMetronomeLayoutBinding.inflate(getLayoutInflater());
     }
+
+    @Override
+    protected void initData() {
+        super.initData();
+        initListener();
+        mteronomeSoundPool();
+    }
+
+    private void play() {
+        mHandler.removeCallbacksAndMessages(null);
+        soundPool.stop(tickVoiceId);
+        soundPool.stop(tockVoiceId);
+        mHandler.post(mRunnable);
+    }
+
+    private void mteronomeSoundPool() {
+
+        SoundPool.Builder builder = new SoundPool.Builder();
+        //传入最多播放音频数量,
+        builder.setMaxStreams(2);
+        //AudioAttributes是一个封装音频各种属性的方法
+        AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
+        //设置音频流的合适的属性
+        attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
+        //加载一个AudioAttributes
+        builder.setAudioAttributes(attrBuilder.build());
+
+        soundPool = builder.build();
+
+        tickVoiceId = soundPool.load(this, com.daya.live_teaching.R.raw.tick, 0);
+        tockVoiceId = soundPool.load(this, com.daya.live_teaching.R.raw.tock, 0);
+    }
+
+    private int lastProgress = 0;
+
+    private void initListener() {
+        viewBinding.tvPlay.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                play();
+            }
+        });
+        viewBinding.cirSeekbar.setSeekBarChangeListener(new CircularSeekBar.OnSeekChangeListener() {
+            @Override
+            public void onProgressChange(CircularSeekBar view, int newProgress) {
+                Log.i("newProgress", "newProgress:" + newProgress);
+                Log.i("newProgress", "lastProgress:" + lastProgress);
+                int difference = newProgress - lastProgress;
+                if (Math.abs(difference) > 10) {
+                    lastProgress = newProgress;
+                    return;
+                }
+                int result = difference / MetronomeConfig.PLAY_RATE_UNIT;
+                if (difference < -1) {
+                    result = -1;
+                }
+                if (difference > 1) {
+                    result = 1;
+                }
+                if (result == 0) {
+                    return;
+                }
+                Log.i("newProgress", "result:" + result);
+                if (isCanChange(result)) {
+                    currentBeatRate += result;
+                } else {
+                    return;
+                }
+                if (currentBeatRate < MetronomeConfig.MIN_PLAY_RATE) {
+                    currentBeatRate = MetronomeConfig.MIN_PLAY_RATE;
+                }
+                if (currentBeatRate > MetronomeConfig.MAX_PLAY_RATE) {
+                    currentBeatRate = MetronomeConfig.MAX_PLAY_RATE;
+                }
+                lastProgress = newProgress;
+                viewBinding.tvSpeed.setText(String.valueOf(currentBeatRate));
+            }
+        });
+    }
+
+    public boolean isCanChange(int result) {
+        if (result < 0) {
+            return currentBeatRate != MetronomeConfig.MIN_PLAY_RATE;
+        } else {
+            return currentBeatRate != MetronomeConfig.MAX_PLAY_RATE;
+        }
+    }
+
+    private boolean isTickOrTock() {
+        if (currentBeatType.getValue() == MetronomeType.METRONOME_12_TYPE.getValue() && playPosition % 1 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_22_TYPE.getValue() && playPosition % 2 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_14_TYPE.getValue() && playPosition % 1 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_24_TYPE.getValue() && playPosition % 2 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_34_TYPE.getValue() && playPosition % 3 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_44_TYPE.getValue() && playPosition % 4 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_38_TYPE.getValue() && playPosition % 3 == 0) {
+            return true;
+        } else if (currentBeatType.getValue() == MetronomeType.METRONOME_68_TYPE.getValue() && playPosition % 6 == 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        try {
+            soundPool.release();
+            soundPool = null;
+            mHandler.removeCallbacksAndMessages(null);
+        } catch (Exception e) {
+
+        }
+    }
 }

+ 13 - 0
metronome/src/main/java/com/cooleshow/metronome/constants/MetronomeConfig.java

@@ -0,0 +1,13 @@
+package com.cooleshow.metronome.constants;
+
+/**
+ * Author by pq, Date on 2022/9/16.
+ */
+public class MetronomeConfig {
+    public static final int DEFAULT_PLAY_RATE = 90;//默认播放速度
+    public static final int MIN_PLAY_RATE = 50;//最小播放速度
+    public static final int MAX_PLAY_RATE = 200;//最大播放速度
+    public static final int PLAY_RATE_UNIT = 10;//10个进度 +1或者-1速度
+    public static String rhythns[] = {"1/2", "2/2", "1/4", "2/4", "3/4", "4/4", "3/8", "6/8"};
+
+}

+ 45 - 0
metronome/src/main/java/com/cooleshow/metronome/constants/MetronomeType.java

@@ -0,0 +1,45 @@
+package com.cooleshow.metronome.constants;
+
+/**
+ * Author by pq, Date on 2022/9/16.
+ */
+public enum MetronomeType {
+    METRONOME_12_TYPE(0, "1/2"),
+    METRONOME_22_TYPE(1, "2/2"),
+    METRONOME_14_TYPE(2, "1/4"),
+    METRONOME_24_TYPE(3, "2/4"),
+    METRONOME_34_TYPE(4, "3/4"),
+    METRONOME_44_TYPE(5, "4/4"),
+    METRONOME_38_TYPE(6, "3/8"),
+    METRONOME_68_TYPE(7, "6/8");
+
+    private int value;
+    private String name;
+
+    private MetronomeType(int value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public static MetronomeType setValue(int code) {
+        MetronomeType[] var1 = values();
+        int var2 = var1.length;
+
+        for (int var3 = 0; var3 < var2; ++var3) {
+            MetronomeType c = var1[var3];
+            if (code == c.getValue()) {
+                return c;
+            }
+        }
+
+        return METRONOME_14_TYPE;
+    }
+}

+ 5 - 3
metronome/src/main/java/com/cooleshow/metronome/widget/CircularSeekBar.java

@@ -557,14 +557,16 @@ public class CircularSeekBar extends View {
         boolean up = false;
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
-                moved(x, y, up);
+//                moved(x, y, up);
                 break;
             case MotionEvent.ACTION_MOVE:
-                moved(x, y, up);
+                if(!up){
+                    moved(x, y, up);
+                }
                 break;
             case MotionEvent.ACTION_UP:
                 up = true;
-                moved(x, y, up);
+//                moved(x, y, up);
                 break;
         }
         return true;

+ 2 - 0
metronome/src/main/res/layout/activity_metronome_layout.xml

@@ -25,6 +25,7 @@
     <com.cooleshow.metronome.widget.CircularSeekBar
         android:layout_width="220dp"
         android:layout_height="220dp"
+        android:id="@+id/cir_seekbar"
         app:layout_constraintBottom_toBottomOf="@+id/iv_plate"
         app:layout_constraintLeft_toLeftOf="@+id/iv_plate"
         app:layout_constraintRight_toRightOf="@+id/iv_plate"
@@ -104,6 +105,7 @@
         android:layout_height="wrap_content"/>
 
     <TextView
+        android:id="@+id/tv_current_beat"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:includeFontPadding="false"