mirror of https://github.com/NekoX-Dev/NekoX.git
202 lines
6.1 KiB
Java
202 lines
6.1 KiB
Java
package org.telegram.ui.Components;
|
|
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Paint;
|
|
import android.view.View;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
import org.telegram.ui.Cells.ChatMessageCell;
|
|
|
|
import java.util.Random;
|
|
|
|
public class AudioVisualizerDrawable {
|
|
|
|
private final CircleBezierDrawable[] drawables;
|
|
|
|
private final int[] tmpWaveform = new int[3];
|
|
private final float[] animateTo = new float[8];
|
|
private final float[] current = new float[8];
|
|
private final float[] dt = new float[8];
|
|
|
|
private float idleScale;
|
|
private boolean idleScaleInc;
|
|
|
|
private final Paint p1;
|
|
|
|
private View parentView;
|
|
private final Random random = new Random();
|
|
|
|
public float IDLE_RADIUS = AndroidUtilities.dp(6) * 0.33f;
|
|
public float WAVE_RADIUS = AndroidUtilities.dp(12) * 0.36f;
|
|
public float ANIMATION_DURATION = 120;
|
|
public int ALPHA = 61;
|
|
|
|
|
|
public AudioVisualizerDrawable() {
|
|
drawables = new CircleBezierDrawable[2];
|
|
for (int i = 0; i < 2; i++) {
|
|
CircleBezierDrawable drawable = drawables[i] = new CircleBezierDrawable(6);
|
|
drawable.idleStateDiff = 0;
|
|
drawable.radius = AndroidUtilities.dp(24);
|
|
drawable.radiusDiff = 0;
|
|
drawable.randomK = 1f;
|
|
}
|
|
p1 = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
}
|
|
|
|
final int MAX_SAMPLE_SUM = 6;
|
|
private float[] lastAmplitude = new float[MAX_SAMPLE_SUM];
|
|
private int lastAmplitudeCount;
|
|
private int lastAmplitudePointer;
|
|
|
|
|
|
public void setWaveform(boolean playing, boolean animate, float[] waveform) {
|
|
if (!playing && !animate) {
|
|
for (int i = 0; i < 8; i++) {
|
|
animateTo[i] = current[i] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
boolean idleState = waveform != null && waveform[6] == 0;
|
|
float amplitude = waveform == null ? 0 : waveform[6];
|
|
|
|
if (waveform != null && amplitude > 0.4) {
|
|
lastAmplitude[lastAmplitudePointer] = amplitude;
|
|
lastAmplitudePointer++;
|
|
if (lastAmplitudePointer > MAX_SAMPLE_SUM - 1) {
|
|
lastAmplitudePointer = 0;
|
|
}
|
|
lastAmplitudeCount++;
|
|
} else {
|
|
lastAmplitudeCount = 0;
|
|
}
|
|
|
|
if (idleState) {
|
|
for (int i = 0; i < 6; i++) {
|
|
waveform[i] = ((random.nextInt() % 500) / 1000f);
|
|
}
|
|
}
|
|
float duration = idleState ? ANIMATION_DURATION * 2 : ANIMATION_DURATION;
|
|
if (lastAmplitudeCount > MAX_SAMPLE_SUM) {
|
|
float a = 0;
|
|
for (int i = 0; i < MAX_SAMPLE_SUM; i++) {
|
|
a += lastAmplitude[i];
|
|
}
|
|
a /= (float) MAX_SAMPLE_SUM;
|
|
if (a > 0.52f) {
|
|
duration -= ANIMATION_DURATION * (a - 0.40f);
|
|
}
|
|
}
|
|
for (int i = 0; i < 7; i++) {
|
|
if (waveform == null) {
|
|
animateTo[i] = 0;
|
|
} else {
|
|
animateTo[i] = waveform[i];
|
|
}
|
|
if (parentView == null) {
|
|
current[i] = animateTo[i];
|
|
} else if (i == 6) {
|
|
dt[i] = (animateTo[i] - current[i]) / (ANIMATION_DURATION + 80);
|
|
} else {
|
|
dt[i] = (animateTo[i] - current[i]) / duration;
|
|
}
|
|
}
|
|
|
|
animateTo[7] = playing ? 1f : 0f;
|
|
dt[7] = (animateTo[7] - current[7]) / 120;
|
|
}
|
|
|
|
float rotation;
|
|
|
|
public void draw(Canvas canvas, float cx, float cy, boolean outOwner, Theme.ResourcesProvider resourcesProvider) {
|
|
if (outOwner) {
|
|
p1.setColor(Theme.getColor(Theme.key_chat_outLoader, resourcesProvider));
|
|
p1.setAlpha(ALPHA);
|
|
} else {
|
|
p1.setColor(Theme.getColor(Theme.key_chat_inLoader, resourcesProvider));
|
|
p1.setAlpha(ALPHA);
|
|
}
|
|
this.draw(canvas, cx, cy);
|
|
}
|
|
|
|
public void draw(Canvas canvas, float cx, float cy) {
|
|
for (int i = 0; i < 8; i++) {
|
|
if (animateTo[i] != current[i]) {
|
|
current[i] += dt[i] * 16;
|
|
if ((dt[i] > 0 && current[i] > animateTo[i]) || (dt[i] < 0 && current[i] < animateTo[i])) {
|
|
current[i] = animateTo[i];
|
|
}
|
|
parentView.invalidate();
|
|
}
|
|
}
|
|
|
|
if (idleScaleInc) {
|
|
idleScale += 0.02f;
|
|
if (idleScale > 1f) {
|
|
idleScaleInc = false;
|
|
idleScale = 1f;
|
|
}
|
|
} else {
|
|
idleScale -= 0.02f;
|
|
if (idleScale < 0) {
|
|
idleScaleInc = true;
|
|
idleScale = 0;
|
|
}
|
|
}
|
|
|
|
float enterProgress = current[7];
|
|
float radiusProgress = current[6] * current[0];
|
|
|
|
if (enterProgress == 0 && radiusProgress == 0) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
tmpWaveform[i] = (int) (current[i] * WAVE_RADIUS);
|
|
}
|
|
drawables[0].setAdditionals(tmpWaveform);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
tmpWaveform[i] = (int) (current[i + 3] * WAVE_RADIUS);
|
|
}
|
|
drawables[1].setAdditionals(tmpWaveform);
|
|
float radius = AndroidUtilities.dp(22) +
|
|
AndroidUtilities.dp(4) * radiusProgress +
|
|
IDLE_RADIUS * enterProgress;
|
|
|
|
if (radius > AndroidUtilities.dp(26)) {
|
|
radius = AndroidUtilities.dp(26);
|
|
}
|
|
drawables[0].radius = drawables[1].radius = radius;
|
|
|
|
canvas.save();
|
|
rotation += 0.6;
|
|
canvas.rotate(rotation, cx, cy);
|
|
canvas.save();
|
|
float s = 1f + 0.04f * idleScale;
|
|
canvas.scale(s, s, cx, cy);
|
|
drawables[0].draw(cx, cy, canvas, p1);
|
|
canvas.restore();
|
|
|
|
canvas.rotate(60, cx, cy);
|
|
s = 1f + 0.04f * (1f - idleScale);
|
|
canvas.scale(s, s, cx, cy);
|
|
drawables[1].draw(cx, cy, canvas, p1);
|
|
canvas.restore();
|
|
}
|
|
|
|
public void setParentView(View parentView) {
|
|
this.parentView = parentView;
|
|
}
|
|
|
|
public View getParentView() {
|
|
return parentView;
|
|
}
|
|
|
|
public void setColor(int color) {
|
|
p1.setColor(color);
|
|
}
|
|
}
|