在iOS应用程序中创建很容易。任何人告诉我在录制和播放音频时创建Sinwave动画的简便方法。我被尝试了很多方面,但我不能。是否有任何第三方框架?
任何人都可以帮帮我..
答案 0 :(得分:16)
使用以下代码获取类似ios的波形...从录音机获取振幅并传递给updateAmplitude()函数以获得语音变化。
public class WaveFormView extends View {
private static final float defaultFrequency = 1.5f;
private static final float defaultAmplitude = 1.0f;
private static final float defaultIdleAmplitude = 0.01f;
private static final float defaultNumberOfWaves = 5.0f;
private static final float defaultPhaseShift = -0.15f;
private static final float defaultDensity = 5.0f;
private static final float defaultPrimaryLineWidth = 3.0f;
private static final float defaultSecondaryLineWidth = 1.0f;
private float phase;
private float amplitude;
private float frequency;
private float idleAmplitude;
private float numberOfWaves;
private float phaseShift;
private float density;
private float primaryWaveLineWidth;
private float secondaryWaveLineWidth;
Paint mPaintColor;
Rect rect;
boolean isStraightLine = false;
public WaveFormView(Context context) {
super(context);
setUp();
}
public WaveFormView(Context context, AttributeSet attrs) {
super(context, attrs);
setUp();
}
public WaveFormView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setUp();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WaveFormView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setUp();
}
private void setUp() {
this.frequency = defaultFrequency;
this.amplitude = defaultAmplitude;
this.idleAmplitude = defaultIdleAmplitude;
this.numberOfWaves = defaultNumberOfWaves;
this.phaseShift = defaultPhaseShift;
this.density = defaultDensity;
this.primaryWaveLineWidth = defaultPrimaryLineWidth;
this.secondaryWaveLineWidth = defaultSecondaryLineWidth;
mPaintColor = new Paint();
mPaintColor.setColor(Color.WHITE);
}
public void updateAmplitude(float ampli, boolean isSpeaking) {
this.amplitude = Math.max(ampli, idleAmplitude);
isStraightLine = isSpeaking;
}
@Override
protected void onDraw(Canvas canvas) {
rect = new Rect(0,0,canvas.getWidth(),canvas.getWidth());
canvas.drawColor(Color.BLUE);
/*canvas.drawRect(rect, mPaintColor);*/
if(isStraightLine) {
for (int i = 0; i < numberOfWaves; i++) {
mPaintColor.setStrokeWidth(i == 0 ? primaryWaveLineWidth : secondaryWaveLineWidth);
float halfHeight = canvas.getHeight() / 2;
float width = canvas.getWidth();
float mid = canvas.getWidth() / 2;
float maxAmplitude = halfHeight - 4.0f;
float progress = 1.0f - (float) i / this.numberOfWaves;
float normedAmplitude = (1.5f * progress - 0.5f) * this.amplitude;
Path path = new Path();
float multiplier = Math.min(1.0f, (progress / 3.0f * 2.0f) + (1.0f / 3.0f));
for (float x = 0; x < width + density; x += density) {
// We use a parable to scale the sinus wave, that has its peak in the middle of the view.
float scaling = (float) (-Math.pow(1 / mid * (x - mid), 2) + 1);
float y = (float) (scaling * maxAmplitude * normedAmplitude * Math.sin(2 * Math.PI * (x / width) * frequency + phase) + halfHeight);
if (x == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
mPaintColor.setStyle(Paint.Style.STROKE);
mPaintColor.setAntiAlias(true);
canvas.drawPath(path, mPaintColor);
}
} else {
canvas.drawLine(5,canvas.getHeight()/2,canvas.getWidth(),canvas.getHeight()/2,mPaintColor );
canvas.drawLine(0,canvas.getHeight()/2,canvas.getWidth(),canvas.getHeight()/2,mPaintColor);
canvas.drawLine(-5, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight()/2,mPaintColor );
}
this.phase += phaseShift;
invalidate();
}
}
答案 1 :(得分:0)
基于@Vennila的答案。
这是WaveFormView
的Kotlin版本。
class SiriVisualView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private var phase = 0f
private var amplitude = 1.5f // wave height
private var frequency = 1.2f // number of waves
private var idleAmplitude = 0.05f // default height
private var numberOfWaves = 8.0f // number of wave lines
private var phaseShift = -0.1f // wave speed
private var primaryWaveLineWidth = 2.0f // outer line stroke
private var secondaryWaveLineWidth = 0.5f // inner line stroke
private var density = 5f
var mPaintColor: Paint = Paint()
var isStraightLine = false
fun updateViewColor(@ColorInt color: Int) {
mPaintColor.color = color
}
fun updateSpeaking(isSpeaking: Boolean) {
isStraightLine = isSpeaking
}
fun updateAmplitude(ampli: Float) {
amplitude = Math.max(ampli, idleAmplitude)
}
fun updateSpeed(phase: Float) {
phaseShift = phase
}
/** Here you can override default wave values and customize SiriVisualView
updateNumberOfWaves()
updatePrimaryLineStroke()
. . .
*/
override fun onDraw(canvas: Canvas) {
if (isStraightLine) {
var i = 0
while (i < numberOfWaves) {
mPaintColor.strokeWidth = if (i == 0) primaryWaveLineWidth else secondaryWaveLineWidth
val halfHeight = height / 2.toFloat()
val width = width.toFloat()
val mid = width / 2.toFloat()
val maxAmplitude = halfHeight - 4.0f
val progress = 1.0f - i.toFloat() / numberOfWaves
val normedAmplitude = (1.5f * progress - 0.5f) * amplitude
val path = Path()
val multiplier = Math.min(1.0f, progress / 3.0f * 2.0f + 1.0f / 3.0f)
var x = 0f
while (x < width + density) {
// We use a parable to scale the sinus wave, that has its peak in the middle of the view.
val scaling = (-Math.pow(
1 / mid * (x - mid).toDouble(),
2.0
) + 1).toFloat()
val y = (scaling * maxAmplitude * normedAmplitude * Math.sin(2 * Math.PI * (x / width) * frequency + phase) + halfHeight).toFloat()
if (x == 0f) {
path.moveTo(x, y)
} else {
path.lineTo(x, y)
}
x += density
}
mPaintColor.style = Paint.Style.STROKE
mPaintColor.isAntiAlias = true
canvas.drawPath(path, mPaintColor)
i++
}
} else {
for(i in 5 downTo -5 step 5) {
canvas.drawLine(
i.toFloat(),
height / 2.toFloat(),
width.toFloat(),
height / 2.toFloat(),
mPaintColor
)
}
}
phase += phaseShift
invalidate()
}
}
将视图添加到XML文件
<linc.com.visualtest.SiriVisualView
android:id="@+id/siriView"
android:layout_width="0dp"
android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
在“活动”或“片段”中更新和自定义视图
siriView.apply {
updateSpeaking(true)
updateViewColor(Color.WHITE)
updateAmplitude(0.5f)
updateSpeed(-0.1f)
}
以下是SiriVisualView的屏幕截图