Skip to content

Commit dac4e4e

Browse files
committed
v1.5-添加音频可视化接口 扩展so库平台
1 parent 7dffc81 commit dac4e4e

File tree

19 files changed

+880
-8
lines changed

19 files changed

+880
-8
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
3. 实时获取录音的音量、及录音byte数据
77
4. 获取wav/mp3录音文件的时长
88
5. 可配置录音的采样率、位宽 - v1.04更新
9+
5. 录音可视化 - v1.05更新
910

1011
### 博客
1112
https://www.jianshu.com/p/c0222de2faed
@@ -94,6 +95,15 @@ https://www.jianshu.com/p/c0222de2faed
9495
}
9596
});
9697
```
98+
* 音频可视化数据监听
99+
```java
100+
recordManager.setRecordFftDataListener(new RecordFftDataListener() {
101+
@Override
102+
public void onFftData(byte[] data) {
103+
audioView.setWaveData(data);
104+
}
105+
});
106+
```
97107
3. 录音控制
98108
* 开始录音
99109
```java
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package com.main.zlw.zlwaudiorecorder;
2+
3+
import android.content.Context;
4+
import android.graphics.Canvas;
5+
import android.graphics.Color;
6+
import android.graphics.Paint;
7+
import android.graphics.Path;
8+
import android.graphics.Point;
9+
import android.support.annotation.Nullable;
10+
import android.util.AttributeSet;
11+
import android.view.View;
12+
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
16+
/**
17+
* @author zhaolewei on 2018/8/17.
18+
*/
19+
public class AudioView extends View {
20+
21+
/**
22+
* 频谱数量
23+
*/
24+
private static final int LUMP_COUNT = 128;
25+
private static final int LUMP_WIDTH = 6;
26+
private static final int LUMP_SPACE = 2;
27+
private static final int LUMP_MIN_HEIGHT = LUMP_WIDTH;
28+
private static final int LUMP_MAX_HEIGHT = 200;//TODO: HEIGHT
29+
private static final int LUMP_SIZE = LUMP_WIDTH + LUMP_SPACE;
30+
private static final int LUMP_COLOR = Color.parseColor("#6de8fd");
31+
32+
private static final int WAVE_SAMPLING_INTERVAL = 3;
33+
34+
private static final float SCALE = LUMP_MAX_HEIGHT / LUMP_COUNT;
35+
36+
private ShowStyle upShowStyle = ShowStyle.STYLE_HOLLOW_LUMP;
37+
private ShowStyle downShowStyle = ShowStyle.STYLE_WAVE;
38+
39+
private byte[] waveData;
40+
List<Point> pointList;
41+
42+
private Paint lumpPaint;
43+
Path wavePath = new Path();
44+
45+
46+
public AudioView(Context context) {
47+
super(context);
48+
init();
49+
}
50+
51+
public AudioView(Context context, @Nullable AttributeSet attrs) {
52+
super(context, attrs);
53+
init();
54+
}
55+
56+
public AudioView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
57+
super(context, attrs, defStyleAttr);
58+
init();
59+
}
60+
61+
private void init() {
62+
lumpPaint = new Paint();
63+
lumpPaint.setAntiAlias(true);
64+
lumpPaint.setColor(LUMP_COLOR);
65+
66+
lumpPaint.setStrokeWidth(2);
67+
lumpPaint.setStyle(Paint.Style.STROKE);
68+
}
69+
70+
public void setWaveData(byte[] data) {
71+
this.waveData = readyData(data);
72+
genSamplingPoint(data);
73+
invalidate();
74+
}
75+
76+
77+
public void setStyle(ShowStyle upShowStyle, ShowStyle downShowStyle) {
78+
this.upShowStyle = upShowStyle;
79+
this.downShowStyle = downShowStyle;
80+
}
81+
82+
83+
@Override
84+
protected void onDraw(Canvas canvas) {
85+
super.onDraw(canvas);
86+
wavePath.reset();
87+
88+
for (int i = 0; i < LUMP_COUNT; i++) {
89+
if (waveData == null) {
90+
canvas.drawRect((LUMP_WIDTH + LUMP_SPACE) * i,
91+
LUMP_MAX_HEIGHT - LUMP_MIN_HEIGHT,
92+
(LUMP_WIDTH + LUMP_SPACE) * i + LUMP_WIDTH,
93+
LUMP_MAX_HEIGHT,
94+
lumpPaint);
95+
continue;
96+
}
97+
98+
switch (upShowStyle) {
99+
case STYLE_HOLLOW_LUMP:
100+
drawLump(canvas, i, false);
101+
break;
102+
case STYLE_WAVE:
103+
drawWave(canvas, i, false);
104+
break;
105+
default:
106+
break;
107+
}
108+
109+
switch (downShowStyle) {
110+
case STYLE_HOLLOW_LUMP:
111+
drawLump(canvas, i, true);
112+
break;
113+
case STYLE_WAVE:
114+
drawWave(canvas, i, true);
115+
break;
116+
default:
117+
break;
118+
}
119+
}
120+
}
121+
122+
/**
123+
* 预处理数据
124+
*
125+
* @return
126+
*/
127+
private static byte[] readyData(byte[] fft) {
128+
byte[] newData = new byte[LUMP_COUNT];
129+
byte abs;
130+
for (int i = 0; i < LUMP_COUNT; i++) {
131+
abs = (byte) Math.abs(fft[i]);
132+
//描述:Math.abs -128时越界
133+
newData[i] = abs < 0 ? 127 : abs;
134+
}
135+
return newData;
136+
}
137+
138+
/**
139+
* 绘制曲线
140+
*
141+
* @param canvas
142+
* @param i
143+
* @param reversal
144+
*/
145+
private void drawWave(Canvas canvas, int i, boolean reversal) {
146+
if (pointList == null || pointList.size() < 2) {
147+
return;
148+
}
149+
float ratio = SCALE * (reversal ? -1 : 1);
150+
if (i < pointList.size() - 2) {
151+
Point point = pointList.get(i);
152+
Point nextPoint = pointList.get(i + 1);
153+
int midX = (point.x + nextPoint.x) >> 1;
154+
if (i == 0) {
155+
wavePath.moveTo(point.x, LUMP_MAX_HEIGHT - point.y * ratio);
156+
}
157+
wavePath.cubicTo(midX, LUMP_MAX_HEIGHT - point.y * ratio,
158+
midX, LUMP_MAX_HEIGHT - nextPoint.y * ratio,
159+
nextPoint.x, LUMP_MAX_HEIGHT - nextPoint.y * ratio);
160+
161+
canvas.drawPath(wavePath, lumpPaint);
162+
}
163+
}
164+
165+
/**
166+
* 绘制矩形条
167+
*/
168+
private void drawLump(Canvas canvas, int i, boolean reversal) {
169+
int minus = reversal ? -1 : 1;
170+
float top = (LUMP_MAX_HEIGHT - (LUMP_MIN_HEIGHT + waveData[i] * SCALE) * minus);
171+
172+
canvas.drawRect(LUMP_SIZE * i,
173+
top,
174+
LUMP_SIZE * i + LUMP_WIDTH,
175+
LUMP_MAX_HEIGHT,
176+
lumpPaint);
177+
}
178+
179+
/**
180+
* 生成波形图的采样数据,减少计算量
181+
*
182+
* @param data
183+
*/
184+
private void genSamplingPoint(byte[] data) {
185+
if (upShowStyle != ShowStyle.STYLE_WAVE && downShowStyle != ShowStyle.STYLE_WAVE) {
186+
return;
187+
}
188+
if (pointList == null) {
189+
pointList = new ArrayList<>();
190+
} else {
191+
pointList.clear();
192+
}
193+
pointList.add(new Point(0, 0));
194+
for (int i = WAVE_SAMPLING_INTERVAL; i < LUMP_COUNT; i += WAVE_SAMPLING_INTERVAL) {
195+
pointList.add(new Point(LUMP_SIZE * i, waveData[i]));
196+
}
197+
pointList.add(new Point(LUMP_SIZE * LUMP_COUNT, 0));
198+
}
199+
200+
201+
/**
202+
* 可视化样式
203+
*/
204+
public enum ShowStyle {
205+
/**
206+
* 空心的矩形小块
207+
*/
208+
STYLE_HOLLOW_LUMP,
209+
210+
/**
211+
* 曲线
212+
*/
213+
STYLE_WAVE,
214+
215+
/**
216+
* 不显示
217+
*/
218+
STYLE_NOTHING
219+
}
220+
}
221+

app/src/main/java/com/main/zlw/zlwaudiorecorder/MainActivity.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import com.zlw.main.recorderlib.RecordManager;
1818
import com.zlw.main.recorderlib.recorder.RecordConfig;
1919
import com.zlw.main.recorderlib.recorder.RecordHelper;
20-
import com.zlw.main.recorderlib.recorder.listener.RecordDataListener;
20+
import com.zlw.main.recorderlib.recorder.listener.RecordFftDataListener;
2121
import com.zlw.main.recorderlib.recorder.listener.RecordResultListener;
2222
import com.zlw.main.recorderlib.recorder.listener.RecordSoundSizeListener;
2323
import com.zlw.main.recorderlib.recorder.listener.RecordStateListener;
@@ -46,6 +46,9 @@ public class MainActivity extends AppCompatActivity {
4646
RadioGroup rgSimpleRate;
4747
@BindView(R.id.tbEncoding)
4848
RadioGroup tbEncoding;
49+
@BindView(R.id.audioView)
50+
AudioView audioView;
51+
4952
private boolean isStart = false;
5053
private boolean isPause = false;
5154
final RecordManager recordManager = RecordManager.getInstance();
@@ -55,6 +58,7 @@ protected void onCreate(Bundle savedInstanceState) {
5558
super.onCreate(savedInstanceState);
5659
setContentView(R.layout.activity_main);
5760
ButterKnife.bind(this);
61+
audioView.setStyle(AudioView.ShowStyle.STYLE_HOLLOW_LUMP, AudioView.ShowStyle.STYLE_HOLLOW_LUMP);
5862
initEvent();
5963
initRecord();
6064
AndPermission.with(this)
@@ -171,6 +175,13 @@ public void onResult(File result) {
171175
Toast.makeText(MainActivity.this, "录音文件: " + result.getAbsolutePath(), Toast.LENGTH_SHORT).show();
172176
}
173177
});
178+
179+
recordManager.setRecordFftDataListener(new RecordFftDataListener() {
180+
@Override
181+
public void onFftData(byte[] data) {
182+
audioView.setWaveData(data);
183+
}
184+
});
174185
}
175186

176187
@OnClick({R.id.btRecord, R.id.btStop})

app/src/main/res/layout/activity_main.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,9 @@
156156
android:layout_height="wrap_content"
157157
android:text="停止" />
158158

159+
<com.main.zlw.zlwaudiorecorder.AudioView
160+
android:id="@+id/audioView"
161+
android:layout_width="match_parent"
162+
android:layout_height="400dp" />
163+
159164
</LinearLayout>

doc/demo.jpg

10.2 KB
Loading
833 KB
Binary file not shown.
707 KB
Binary file not shown.
531 KB
Binary file not shown.
897 KB
Binary file not shown.
841 KB
Binary file not shown.

0 commit comments

Comments
 (0)