簡體   English   中英

音頻畫布繪制android

[英]audio canvas draw android

我想使用畫布實時從麥克風中提取輸入信號,但是我遇到了一個問題,我正在使用的代碼正在繪制不同的信號(看起來不像常規的音頻信號),並且可視化工具太快了。它與持續時間或時期有關,但是我對這個畫布概念很陌生嗎?

這是輸出的屏幕截圖

package com.example.soundvisualizer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import java.io.PrintStream;
import java.util.Arrays;

public class CDrawer extends SurfaceView

  implements SurfaceHolder.Callback

{

  private Context mContext;
  private CDrawThread mDrawThread;
  private SurfaceHolder mHolder;

  private Boolean isCreated = false;
  /** 
   * This is where you instance the drawer
   * You relly don't need to care about the parameters, they are set in the xml-layout
   * @param Apply the baseContext of you current acitivty 
   * @param AttributeSet
   */
  public CDrawer(Context paramContext, AttributeSet paramAttributeSet)
  {
    super(paramContext, paramAttributeSet);
    System.out.println("CDrawer()");
    mHolder = getHolder();
    mContext = paramContext;
    mHolder.addCallback(this);
    mDrawThread = new CDrawThread(mHolder, paramContext, new Handler()
    {
      public void handleMessage(Message paramMessage)
      {
      }
    });
    mDrawThread.setName("" + System.currentTimeMillis());
    setFocusable(true);
  }

  public Boolean GetDead2()
  {
    return mDrawThread.GetDead2();
  }

  /**
   * restarts the thread
   * @param Is the thread dead?
   */
  public void Restart(Boolean paramBoolean)
  {
      if (isCreated) {
    if (mDrawThread.GetDead2().booleanValue())
    {
      mDrawThread.SetDead2(Boolean.valueOf(false));
      if ((!paramBoolean.booleanValue()) || (!mDrawThread.GetDead().booleanValue()))

      mHolder = getHolder();
      mHolder.addCallback(this);
      System.out.println("Restart drawthread");
      mDrawThread = new CDrawThread(mHolder, mContext, new Handler()
      {
        public void handleMessage(Message paramMessage)
        {
        }
      });
      mDrawThread.setName("" + System.currentTimeMillis());
      mDrawThread.start();
      return;
    }
    Boolean No1,No2 = true;
    while (true)
    {
      while (No2 = true)
      {

        try
        {
          Thread.sleep(10000L);
          System.out.println("Just chilling in Restart");
          No2 = false;
          mDrawThread.SetDead2(Boolean.valueOf(true));
        }
        catch (InterruptedException localInterruptedException)
        {
          localInterruptedException.printStackTrace();
        }
        return;
      }

     if (!mDrawThread.GetDead().booleanValue())
        continue;
      mHolder = getHolder();
      mHolder.addCallback(this);
      System.out.println("Restart drawthread");
      mDrawThread = new CDrawThread(mHolder, mContext, new Handler()
      {
        public void handleMessage(Message paramMessage)
        {
        }
      });
      mDrawThread.setName("" +System.currentTimeMillis());
      mDrawThread.start();
      return;
    }
      }
  }

  public void SetRun(Boolean paramBoolean)
  {
    mDrawThread.setRun(paramBoolean);
  }

  public CDrawThread getThread()
  {
    return mDrawThread;
  }

  /**
   * Called when there's a change in the surface
   */
  public void surfaceChanged(SurfaceHolder paramSurfaceHolder, int paramInt1, int paramInt2, int paramInt3)
  {
    mDrawThread.setSurfaceSize(paramInt2, paramInt3);
  }

  /**
   * Creates the surface
   */
  public void surfaceCreated(SurfaceHolder paramSurfaceHolder)
  {
    System.out.println("surfaceCreated");
    if (mDrawThread.getRun().booleanValue())
    {
      System.out.println("11111");
      isCreated = true;
      mDrawThread.start();

    }
    while (true)
    {
      System.out.println("22222");
      Restart(Boolean.valueOf(false));
      return;
    }
  }

  /**
   * Surface destroyd
   */
  public void surfaceDestroyed(SurfaceHolder paramSurfaceHolder)
  {
    int i = 1;
    while (true)
    {
      if (i == 0)
        return;
      try
      {
        mDrawThread.join();
        i = 0;
      }
      catch (InterruptedException localInterruptedException)
      {
      }
    }
  }

  /**
   * The Drawer Thread, subclass to cDrawer class
   * We want to keep most of this process in a background thread,
   * so the UI don't hang 
   *  @author Pontus Holmberg (EndLessMind)
   *  Email: the_mr_hb@hotmail.com
   */
  class CDrawThread extends Thread
  {
    private Paint mBackPaint;
    private Bitmap mBackgroundImage;
    private short[] mBuffer;
    private int mCanvasHeight =20;
    private int mCanvasWidth = 20;
    private Paint mLinePaint;
    private int mPaintCounter = 0;
    private SurfaceHolder mSurfaceHolder;
    private Boolean m_bDead = Boolean.valueOf(false);
    private Boolean m_bDead2 = Boolean.valueOf(true);
    private Boolean m_bRun = Boolean.valueOf(true);
    private Boolean m_bSleep = Boolean.valueOf(false);
    private int m_iScaler =20;
    private int counter = 0;
    /**
     * Instance the Thread
     * All the parameters i handled by the cDrawer class
     * @param paramContext
     * @param paramHandler
     * @param arg4
     */
    public CDrawThread(SurfaceHolder paramContext, Context paramHandler, Handler arg4)
    {
      mSurfaceHolder = paramContext;
      mLinePaint = new Paint();
      mLinePaint.setAntiAlias(true);
      mLinePaint.setARGB(255, 255, 0, 0);
      mLinePaint = new Paint();
      mLinePaint.setAntiAlias(true);
      mLinePaint.setARGB(255, 255, 0, 255);
      mBackPaint = new Paint();
      mBackPaint.setAntiAlias(true);
      mBackPaint.setARGB(255, 0, 0, 0);
      mBuffer = new short[2048];
      mBackgroundImage = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);

    }

    /**
     * Allow you to change the size of the waveform displayed on the screen
     * Or scale of you so will
     * @return returns a new scale value
     */
   /* public int ChangeSensitivity()
    {
      m_iScaler = (5 + m_iScaler);
      if (m_iScaler > 20)
        m_iScaler = 1;
      return m_iScaler;
    }*/

    public Boolean GetDead()
    {
      return m_bDead;
    }

    public Boolean GetDead2()
    {
      return m_bDead2;
    }

    public Boolean GetSleep()
    {
      return m_bSleep;
    }

    public void SetDead2(Boolean paramBoolean)
    {
      m_bDead2 = paramBoolean;
    }

    public void SetSleeping(Boolean paramBoolean)
    {
      m_bSleep = paramBoolean;
    }

    /**
     * Calculate and draws the line
     * @param Canvas to draw on, handled by cDrawer class
     */
    public void doDraw(Canvas paramCanvas)
    {
      if (mCanvasHeight == 1)
        mCanvasHeight = paramCanvas.getHeight();
      paramCanvas.drawPaint(mBackPaint); 
      /**
       * Set some base values as a starting point
       * This could be considerd as a part of the calculation process
       */
      int height = paramCanvas.getHeight();
      int BuffIndex = (mBuffer.length / 2 - paramCanvas.getWidth()) / 2;
      int width = paramCanvas.getWidth();
      int mBuffIndex = BuffIndex;
      int scale = height / m_iScaler;
      int StratX = 0;
      if (StratX >= width)
      {
        paramCanvas.save();
        return;
      }
    int cu1 = 0;
    /**
     * Here is where the real calculations is taken in to action
     * In this while loop, we calculate the start and stop points
     * for both X and Y
     * 
     * The line is then drawer to the canvas with drawLine method
     */
    while (StratX < width -1)
    {
      int StartBaseY = mBuffer[(mBuffIndex - 1)] / scale;

      int StopBaseY = mBuffer[mBuffIndex] / scale;
      if (StartBaseY > height / 2)
      {
          StartBaseY = 1 + height / 2;
        int checkSize = height / 2;
        if (StopBaseY <= checkSize)
            return;
        StopBaseY = 2 + height / 2;
      }

        int StartY = StartBaseY + height / 2;
        int StopY = StopBaseY + height / 2;
        paramCanvas.drawLine(StratX, StartY, StratX +1, StopY, mLinePaint);
        cu1++;
        mBuffIndex++;
        StratX++;
        int checkSize_again = -1 * (height / 2);
        if (StopBaseY >= checkSize_again)
          continue;
        StopBaseY = -2 + -1 * (height / 2);
      }
    }

    public Boolean getRun()
    {
      return m_bRun;
    }

    /**
     * Updated the Surface and redraws the new audio-data
     */
    public void run()
    {
      while (true)
      {
        if (!m_bRun.booleanValue())
        {
          m_bDead = Boolean.valueOf(true);
          m_bDead2 = Boolean.valueOf(true);
          System.out.println("Goodbye Drawthread");
          return;
        }
        Canvas localCanvas = null;
        try
        {
          localCanvas = mSurfaceHolder.lockCanvas(null);
          synchronized (mSurfaceHolder)
          {
              if (localCanvas != null) 
            doDraw(localCanvas);

        }
        }
        finally
        {
          if (localCanvas != null)
            mSurfaceHolder.unlockCanvasAndPost(localCanvas);
        }
      }
    }

    public void setBuffer(short[] paramArrayOfShort)
    {
      synchronized (mBuffer)
      {
        mBuffer = paramArrayOfShort;
        return;
      }
    }

    public void setRun(Boolean paramBoolean)
    {
      m_bRun = paramBoolean;
    }

    public void setSurfaceSize(int paramInt1, int paramInt2)
    {
      synchronized (mSurfaceHolder)
      {
        mCanvasWidth = paramInt1;
        mCanvasHeight = paramInt2;
        mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, paramInt1, paramInt2, true);
        return;
      }
    }
  }
}

在CDrawThread.run()方法中,您以最快的速度繪制設備,因此最簡單的解決方案是首先確定希望更新圖形的間隔(例如,每16 ms更新一次,每秒60fps)和每幀:

  1. 記錄開始時間
  2. 畫圖
  3. 將所需的更新間隔減去在繪圖上花費的時間,然后休眠該時間

例如(偽代碼,使用后果自負):

private static final int INTERVAL = 16;

public void run()
    {
      while (true)
      {
        long start=System.currentTimeMillis();  //<<< record redraw start time
        if (!m_bRun.booleanValue())
        {
          m_bDead = Boolean.valueOf(true);
          m_bDead2 = Boolean.valueOf(true);
          System.out.println("Goodbye Drawthread");
          return;
        }
        Canvas localCanvas = null;
        try
        {
          localCanvas = mSurfaceHolder.lockCanvas(null);
          synchronized (mSurfaceHolder)
          {
              if (localCanvas != null) 
            doDraw(localCanvas);

        }
        }
        finally
        {
          if (localCanvas != null)
            mSurfaceHolder.unlockCanvasAndPost(localCanvas);
        }
        SystemClock.sleep(INTERVAL - (System.currentTimeMillis() - start)); //<<< sleep
      }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM