Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show waveform of audio

I am making one music application in android.In this music list coming from server side. I don'tknow how to show waveform of audio in android ? like in soundcloud website. I have attached image below.enter image description here

like image 884
Alpha Avatar asked Aug 03 '16 13:08

Alpha


People also ask

How do I see waveforms in audacity?

The waveform view can be switched to a dB logarithmic view by right-clicking on the track's Vertical Scale and selecting "dB" from the dropdown context menu. The default linear Waveform view is very convenient for editing since the majority of audible work is on the screen. When zoomed in edit points are easy to find.

What is the waveform of a sound wave?

Term: Waveform (sound) The generic term waveform means a graphical representation of the shape and form of a signal moving in a gaseous, liquid, or solid medium. For sound, the term describes a depiction of the pattern of sound pressure variation (or amplitude) in the time domain.


1 Answers

Perhaps, you can implements this feature without libraries, of course if you want only visualisation of audio sample. For example:

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);     } } 

Sorry, code with a small amount of comments, but it is working visualizer. You can attach it to any players you want.

How you can use it: add this view in your xml layout, then you have to update visualizer state with methods

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

In updateVisualizer you pass bytes array with you audio sample, and in updatePlayerProgress you dynamically pass percentage, while audio sample is playing.

for converting file to bytes you can use this helper method

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; } 

and for example(very shortly), how it looks like with Mosby library:

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

UPD: I created the library for resolving this case github.com/scrobot/SoundWaveView. It still in status "WIP"(work in progress), but soon I will complete it.

like image 110
Scrobot Avatar answered Oct 23 '22 16:10

Scrobot