亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android使用音頻信息繪制動(dòng)態(tài)波紋

 更新時(shí)間:2016年02月13日 17:13:14   作者:SpikeKing  
這篇文章主要介紹了Android使用音頻信息繪制動(dòng)態(tài)波紋 的相關(guān)資料,需要的朋友可以參考下

在一些音樂(lè)類(lèi)應(yīng)用中, 經(jīng)常會(huì)展示隨著節(jié)奏上下起伏的波紋信息, 這些波紋形象地傳達(dá)了聲音信息, 可以提升用戶體驗(yàn), 那么是如何實(shí)現(xiàn)的呢? 可以使用Visualizer類(lèi)獲取當(dāng)前播放的聲音信息, 并繪制在畫(huà)布上, 使用波紋展示即可. 我來(lái)講解一下使用方法.

音樂(lè)

主要

(1) Visualizer類(lèi)提取波紋信息的方式.
(2) 應(yīng)用動(dòng)態(tài)權(quán)限管理的方法.
(3) 分離自定義視圖的展示和邏輯.

1. 基礎(chǔ)準(zhǔn)備

Android 6.0引入動(dòng)態(tài)權(quán)限管理, 在這個(gè)項(xiàng)目中, 會(huì)使用系統(tǒng)的音頻信息, 因此把權(quán)限管理引入這個(gè)項(xiàng)目, 參考. Gradle配置引入了Lambda表達(dá)式, 參考.

頁(yè)面布局, 使用自定義的波紋視圖控件.

<!--波紋視圖-->
<me.chunyu.spike.wcl_visualizer_demo.visualizers.WaveformView
android:id="@+id/main_wv_waveform"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

效果

波紋


2. 首頁(yè)邏輯

添加動(dòng)態(tài)權(quán)限管理, 在啟動(dòng)頁(yè)面時(shí), 獲取應(yīng)用所需的音頻權(quán)限.
RendererFactory工廠類(lèi)創(chuàng)建波紋的繪制類(lèi)SimpleWaveformRender.
startVisualiser方法獲取當(dāng)前播放音樂(lè)的音頻信息.
注意頁(yè)面關(guān)閉, 在onPause時(shí), 釋放Visualiser類(lèi).

public class MainActivity extends AppCompatActivity {
private static final int CAPTURE_SIZE = 256; // 獲取這些數(shù)據(jù), 用于顯示
private static final int REQUEST_CODE = 0;
// 權(quán)限
private static final String[] PERMISSIONS = new String[]{
Manifest.permission.RECORD_AUDIO,
Manifest.permission.MODIFY_AUDIO_SETTINGS
};
@Bind(R.id.main_wv_waveform) WaveformView mWvWaveform; // 波紋視圖
private Visualizer mVisualizer; // 音頻可視化類(lèi)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
RendererFactory rendererFactory = new RendererFactory();
mWvWaveform.setRenderer(rendererFactory.createSimpleWaveformRender(ContextCompat.getColor(this, R.color.colorPrimary), Color.WHITE));
}
@Override protected void onResume() {
super.onResume();
PermissionsChecker checker = new PermissionsChecker(this);

if (checker.lakesPermissions(PERMISSIONS)) {
PermissionsActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS);
} else {
startVisualiser();
}
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == PermissionsActivity.PERMISSIONS_DENIED) {
finish();
}
}
// 設(shè)置音頻線
private void startVisualiser() {
mVisualizer = new Visualizer(0); // 初始化
mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
@Override
public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
if (mWvWaveform != null) {
mWvWaveform.setWaveform(waveform);
}
}
@Override
public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
}
}, Visualizer.getMaxCaptureRate(), true, false);
mVisualizer.setCaptureSize(CAPTURE_SIZE);
mVisualizer.setEnabled(true);
}
// 釋放
@Override protected void onPause() {
if (mVisualizer != null) {
mVisualizer.setEnabled(false);
mVisualizer.release();
}
super.onPause();
}
}

Visualizer類(lèi)

new Visualizer(0), 初始化; setCaptureSize, 獲取波紋數(shù)量; setEnabled, 啟動(dòng)監(jiān)聽(tīng);
setDataCaptureListener, 第一個(gè)參數(shù)是回調(diào), 使用WaveFormData或FftData; 第二個(gè)是更新率; 第三個(gè)是判斷使用WaveFormData; 第四個(gè)是判斷使用FftData, 第三\四個(gè)均與回調(diào)的返回值有關(guān).

3. 波紋視圖

頁(yè)面框架, 分離顯示和邏輯, 使用接口渲染, 輸入畫(huà)布Canvas和波紋Waveform.

/**
* 音頻波紋視圖
* <p>
* Created by wangchenlong on 16/2/11.
*/
public class WaveformView extends View {
private WaveformRenderer mRenderer; // 繪制類(lèi)
private byte[] mWaveform; // 波紋形狀
public WaveformView(Context context) {
super(context);
}
public WaveformView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WaveformView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public WaveformView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setRenderer(WaveformRenderer renderer) {
mRenderer = renderer;
}
public void setWaveform(byte[] waveform) {
mWaveform = Arrays.copyOf(waveform, waveform.length); // 數(shù)組復(fù)制
invalidate(); // 設(shè)置波紋之后, 需要重繪
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mRenderer != null) {
mRenderer.render(canvas, mWaveform);
}
}
}

數(shù)組復(fù)制Arrays.copyOf(), 在設(shè)置波紋后重繪頁(yè)面invalidate().

4. 波紋邏輯

核心部分renderWaveform, 渲染波紋.
把頁(yè)面分為網(wǎng)格樣式, 根據(jù)波紋值, 繪制曲線; 沒(méi)有波紋, 繪制居中水平直線.

/**
* 波紋渲染邏輯
* <p>
* Created by wangchenlong on 16/2/12.
*/
public class SimpleWaveformRenderer implements WaveformRenderer {
private static final int Y_FACTOR = 0xFF; // 2的8次方 = 256
private static final float HALF_FACTOR = 0.5f;
@ColorInt private final int mBackgroundColor;
private final Paint mForegroundPaint;
private final Path mWaveformPath;
private SimpleWaveformRenderer(@ColorInt int backgroundColor, Paint foregroundPaint, Path waveformPath) {
mBackgroundColor = backgroundColor;
mForegroundPaint = foregroundPaint;
mWaveformPath = waveformPath;
}
public static SimpleWaveformRenderer newInstance(@ColorInt int backgroundColor, @ColorInt int foregroundColour) {
Paint paint = new Paint();
paint.setColor(foregroundColour);
paint.setAntiAlias(true); // 抗鋸齒
paint.setStrokeWidth(8.0f); // 設(shè)置寬度
paint.setStyle(Paint.Style.STROKE); // 填充
Path waveformPath = new Path();
return new SimpleWaveformRenderer(backgroundColor, paint, waveformPath);
}
@Override public void render(Canvas canvas, byte[] waveform) {
canvas.drawColor(mBackgroundColor);
float width = canvas.getWidth();
float height = canvas.getHeight();
mWaveformPath.reset();
// 沒(méi)有數(shù)據(jù)
if (waveform != null) {
// 繪制波形
renderWaveform(waveform, width, height);
} else {
// 繪制直線
renderBlank(width, height);
}
canvas.drawPath(mWaveformPath, mForegroundPaint);
}
private void renderWaveform(byte[] waveform, float width, float height) {
float xIncrement = width / (float) (waveform.length); // 水平塊數(shù)
float yIncrement = height / Y_FACTOR; // 豎直塊數(shù)
int halfHeight = (int) (height * HALF_FACTOR); // 居中位置
mWaveformPath.moveTo(0, halfHeight);
for (int i = 1; i < waveform.length; ++i) {
float yPosition = waveform[i] > 0 ?
height - (yIncrement * waveform[i]) : -(yIncrement * waveform[i]);
mWaveformPath.lineTo(xIncrement * i, yPosition);
}
mWaveformPath.lineTo(width, halfHeight); // 最后的點(diǎn), 水平居中
}
// 居中畫(huà)一條直線
private void renderBlank(float width, float height) {
int y = (int) (height * HALF_FACTOR);
mWaveformPath.moveTo(0, y);
mWaveformPath.lineTo(width, y);
}
}

繪制移動(dòng)moveTo, 繪制直線lineTo.

動(dòng)畫(huà)效果

通過(guò)繪制波紋, 可以類(lèi)似地繪制一些連續(xù)數(shù)據(jù), 更加直觀地展示, 提升用戶體驗(yàn).

相關(guān)文章

最新評(píng)論