显示音频波形

我正在android中制作一个音乐应用程序。这个音乐列表来自服务器端。 我不知道如何在android中显示音频波形? 比如在soundcloud网站上。 我在下面附上了图片。 在此处输入图像描述

也许,您可以在没有库的情况下实现此function,当然,如果您只想要音频样本的可视化。 例如:

public class PlayerVisualizerView extends View { /** * constant value for Height of the bar */ public static final int VISUALIZER_HEIGHT = 28; /** * bytes array converted from file. */ private byte[] bytes; /** * Percentage of audio sample scale * Should updated dynamically while audioPlayer is played */ private float denseness; /** * Canvas painting for sample scale, filling played part of audio sample */ private Paint playedStatePainting = new Paint(); /** * Canvas painting for sample scale, filling not played part of audio sample */ private Paint notPlayedStatePainting = new Paint(); private int width; private int height; public PlayerVisualizerView(Context context) { super(context); init(); } public PlayerVisualizerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } private void init() { bytes = null; playedStatePainting.setStrokeWidth(1f); playedStatePainting.setAntiAlias(true); playedStatePainting.setColor(ContextCompat.getColor(getContext(), R.color.gray)); notPlayedStatePainting.setStrokeWidth(1f); notPlayedStatePainting.setAntiAlias(true); notPlayedStatePainting.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent)); } /** * update and redraw Visualizer view */ public void updateVisualizer(byte[] bytes) { this.bytes = bytes; invalidate(); } /** * Update player percent. 0 - file not played, 1 - full played * * @param percent */ public void updatePlayerPercent(float percent) { denseness = (int) Math.ceil(width * percent); if (denseness < 0) { denseness = 0; } else if (denseness > width) { denseness = width; } invalidate(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); width = getMeasuredWidth(); height = getMeasuredHeight(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bytes == null || width == 0) { return; } float totalBarsCount = width / dp(3); if (totalBarsCount < = 0.1f) { return; } byte value; int samplesCount = (bytes.length * 8 / 5); float samplesPerBar = samplesCount / totalBarsCount; float barCounter = 0; int nextBarNum = 0; int y = (height - dp(VISUALIZER_HEIGHT)) / 2; int barNum = 0; int lastBarNum; int drawBarCount; for (int a = 0; a < samplesCount; a++) { if (a != nextBarNum) { continue; } drawBarCount = 0; lastBarNum = nextBarNum; while (lastBarNum == nextBarNum) { barCounter += samplesPerBar; nextBarNum = (int) barCounter; drawBarCount++; } int bitPointer = a * 5; int byteNum = bitPointer / Byte.SIZE; int byteBitOffset = bitPointer - byteNum * Byte.SIZE; int currentByteCount = Byte.SIZE - byteBitOffset; int nextByteRest = 5 - currentByteCount; value = (byte) ((bytes[byteNum] >> byteBitOffset) & ((2 < < (Math.min(5, currentByteCount) - 1)) - 1)); if (nextByteRest > 0) { value < <= nextByteRest; value |= bytes[byteNum + 1] & ((2 << (nextByteRest - 1)) - 1); } for (int b = 0; b < drawBarCount; b++) { int x = barNum * dp(3); float left = x; float top = y + dp(VISUALIZER_HEIGHT - Math.max(1, VISUALIZER_HEIGHT * value / 31.0f)); float right = x + dp(2); float bottom = y + dp(VISUALIZER_HEIGHT); if (x < denseness && x + dp(2) < denseness) { canvas.drawRect(left, top, right, bottom, notPlayedStatePainting); } else { canvas.drawRect(left, top, right, bottom, playedStatePainting); if (x < denseness) { canvas.drawRect(left, top, right, bottom, notPlayedStatePainting); } } barNum++; } } } public int dp(float value) { if (value == 0) { return 0; } return (int) Math.ceil(getContext().getResources().getDisplayMetrics().density * value); } } 

对不起,代码中有少量评论,但它正在运行可视化工具。 您可以将它附加到您想要的任何玩家。

如何使用它:在xml布局中添加此视图,然后必须使用方法更新可视化器状态

 public void updateVisualizer(byte[] bytes) { playerVisualizerView.updateVisualizer(bytes); } public void updatePlayerProgress(float percent) { playerVisualizerView.updatePlayerPercent(percent); } 

updateVisualizer您使用音频样本传递bytes数组,并在updatePlayerProgress动态传递百分比,同时播放音频样本。

要将文件转换为字节,您可以使用此辅助方法

 public static byte[] fileToBytes(File file) { int size = (int) file.length(); byte[] bytes = new byte[size]; try { BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file)); buf.read(bytes, 0, bytes.length); buf.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bytes; } 

例如(很快),使用Mosby库看起来如何:

 public class AudioRecorderPresenter extends MvpBasePresenter { public void onStopRecord() { // stopped and released MediaPlayer // ... // some preparation and saved audio file in audioFileName variable. getView().updateVisualizer(FileUtils.fileToBytes(new File(audioFileName))); } } }