最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

音樂

主要

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

1. 基礎(chǔ)準備

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

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

<!--波紋視圖-->
<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. 首頁邏輯

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

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; // 音頻可視化類
@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類

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

3. 波紋視圖

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

/**
* 音頻波紋視圖
* <p>
* Created by wangchenlong on 16/2/11.
*/
public class WaveformView extends View {
private WaveformRenderer mRenderer; // 繪制類
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ù)組復制
invalidate(); // 設(shè)置波紋之后, 需要重繪
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mRenderer != null) {
mRenderer.render(canvas, mWaveform);
}
}
}

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

4. 波紋邏輯

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

/**
* 波紋渲染邏輯
* <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();
// 沒有數(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); // 最后的點, 水平居中
}
// 居中畫一條直線
private void renderBlank(float width, float height) {
int y = (int) (height * HALF_FACTOR);
mWaveformPath.moveTo(0, y);
mWaveformPath.lineTo(width, y);
}
}

繪制移動moveTo, 繪制直線lineTo.

動畫效果

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

相關(guān)文章

最新評論

自贡市| 来安县| 惠东县| 酒泉市| 九龙城区| 鄄城县| 巴青县| 兴城市| 内江市| 井陉县| 青田县| 济源市| 昌宁县| 高雄市| 南投市| 河东区| 泽州县| 宽甸| 四子王旗| 莆田市| 尉犁县| 易门县| 遵化市| 布尔津县| 顺昌县| 资源县| 聂拉木县| 共和县| 安塞县| 盐边县| 黄山市| 朝阳区| 长阳| 福贡县| 太谷县| 宁城县| 东光县| 合阳县| 三门县| 毕节市| 庄河市|