2016-08-03 11 views
14

Tworzę jedną aplikację muzyczną w Androidzie. W tej liście muzyki od strony serwera. Nie wiem, jak pokazać przebieg audio w Androidzie? jak na stronie soundcloud. Załączam obraz poniżej. enter image description herePokaż przebieg audio

+1

cześć Jeżeli masz jakieś rozwiązanie z tym utknąłem na tym samym problemie w aplikacji do nagrywania. proszę o pomoc, jeśli masz coś na ten temat. –

Odpowiedz

6

Być może możesz zaimplementować tę funkcję bez bibliotek, oczywiście jeśli chcesz tylko wizualizować próbkę audio. Na przykład:

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

Niestety, kod z małą ilością komentarzy, ale jest wizualizera pracy. Możesz dołączyć go do dowolnych graczy.

Jak można go używać: dodaj ten pogląd w układzie xml, to trzeba zaktualizować stan Visualizer z metod

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

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

W updateVisualizer przekazać bajtów tablicę z wami próbki audio, a w updatePlayerProgress dynamicznie przekazać procent, gdy odtwarzana jest próbka audio.

do konwersji pliku do bajtów można użyć tej metody pomocnika

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

i na przykład (bardzo krótko), jak to wygląda z biblioteką 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, Jak mogę użyć PlayerVisualizerView? –

+1

Myślę, że dajesz najlepszą odpowiedź i dajesz +50 nagrodę, ale proszę dodać więcej szczegółów i pokazać użycie. –

+0

@HamedGh zaktualizowany. Wystarczy? – Scrobot

Powiązane problemy