2016-08-03 45 views
14

Tôi đang tạo một ứng dụng nhạc trong android.Trong danh sách nhạc này đến từ phía máy chủ. Tôi không biết làm thế nào để hiển thị dạng sóng âm thanh trong Android? như trong trang web soundcloud. Tôi đã đính kèm hình ảnh bên dưới. enter image description hereHiển thị dạng sóng âm thanh

+1

chào Các bạn có bất kỳ giải pháp với điều này tôi cũng bị mắc kẹt trên cùng một vấn đề trong ứng dụng ghi âm. xin vui lòng giúp đỡ nếu bạn có bất cứ điều gì về nó. –

Trả lời

6

Có lẽ, bạn có thể triển khai tính năng này mà không cần thư viện, tất nhiên nếu bạn chỉ muốn hiển thị mẫu âm thanh. Ví dụ:

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

Xin lỗi, viết với một lượng nhỏ nhận xét, nhưng đó là trình hiển thị làm việc. Bạn có thể đính kèm nó vào bất kỳ người chơi nào bạn muốn.

Làm thế nào bạn có thể sử dụng nó: thêm quan điểm này trong cách bố trí xml của bạn, sau đó bạn phải cập nhật trạng thái visualizer với các phương pháp

public void updateVisualizer(byte[] bytes) { 
    playerVisualizerView.updateVisualizer(bytes); 
} 

public void updatePlayerProgress(float percent) { 
    playerVisualizerView.updatePlayerPercent(percent); 
} 

Trong updateVisualizer bạn vượt qua byte mảng với bạn âm thanh mẫu, và trong updatePlayerProgress bạn tự động vượt qua phần trăm, trong khi mẫu âm thanh đang phát.

để chuyển đổi tập tin để byte bạn có thể sử dụng phương pháp helper này

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

và ví dụ (rất lâu), làm thế nào nó trông giống như với thư viện Mosby:

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

Tanx, Làm cách nào tôi có thể sử dụng PlayerVisualizerView? –

+1

Tôi nghĩ bạn đưa ra câu trả lời tốt nhất và đưa ra 50 giải thưởng cho câu trả lời của bạn, nhưng vui lòng thêm chi tiết hơn và hiển thị cách sử dụng. Đã cập nhật –

+0

@HamedGh. Đủ chưa? – Scrobot

Các vấn đề liên quan