SurfaceView绘制录音波形图

本文简单记录由View绘制转为SurfaceView绘制的波形图问题.

上代码:

  1 public class VoiceLineView extends View {
  2     private final int LINE = 0;
  3     private final int RECT = 1;
  4 
  5     private int middleLineColor = Color.BLACK;
  6     private int voiceLineColor = Color.BLACK;
  7     private float middleLineHeight = 4;
  8     private Paint paint;
  9     private Paint paintVoicLine; 11     /**
 12      * 灵敏度
 13      */
 14     private int sensibility = 4;
 15 
 16     private float maxVolume = 100;
 17 
 18 
 19     private float translateX = 0;
 20     private boolean isSet = false;
 21 
 22     /**
 23      * 振幅
 24      */
 25     private float amplitude = 1;
 26     /**
 27      * 音量
 28      */
 29     private float volume = 10;
 30     private int fineness = 1;
 31     private float targetVolume = 1;
 32 
 33 
 34     private long speedY = 50;
 35     private float rectWidth = 25;
 36     private float rectSpace = 5;
 37     private float rectInitHeight = 4;
 38     private List<Rect> rectList;
 39 
 40     private long lastTime = 0;
 41     private int lineSpeed = 90;
 42 
 43     List<Path> paths = null;
 44 
 45     public VoiceLineView(Context context) {
 46         super(context);
 47     }
 48 
 49     public VoiceLineView(Context context, AttributeSet attrs) {
 50         super(context, attrs);
 51         initAtts(context, attrs);
 52     }
 53 
 54     public VoiceLineView(Context context, AttributeSet attrs, int defStyleAttr) {
 55         super(context, attrs, defStyleAttr);
 56         initAtts(context, attrs);
 57     }
 58 
 59     private void initAtts(Context context, AttributeSet attrs) {
 60         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.voiceView);
 61         mode = typedArray.getInt(R.styleable.voiceView_viewMode, 0);
 62         voiceLineColor = typedArray.getColor(R.styleable.voiceView_voiceLine, Color.BLACK);
 63         maxVolume = typedArray.getFloat(R.styleable.voiceView_maxVolume, 100);
 64         sensibility = typedArray.getInt(R.styleable.voiceView_sensibility, 4);
 65         if (mode == RECT) {
 66             rectWidth = typedArray.getDimension(R.styleable.voiceView_rectWidth, 25);
 67             rectSpace = typedArray.getDimension(R.styleable.voiceView_rectSpace, 5);
 68             rectInitHeight = typedArray.getDimension(R.styleable.voiceView_rectInitHeight, 4);
 69         } else {
 70             middleLineColor = typedArray.getColor(R.styleable.voiceView_middleLine, Color.BLACK);
 71             middleLineHeight = typedArray.getDimension(R.styleable.voiceView_middleLineHeight, 4);
 72             lineSpeed = typedArray.getInt(R.styleable.voiceView_lineSpeed, 90);
 73             fineness = typedArray.getInt(R.styleable.voiceView_fineness, 1);
 74             paths = new ArrayList<>(20);
 75             for (int i = 0; i < 20; i++) {
 76                 paths.add(new Path());
 77             }
 78         }
 79         typedArray.recycle();
 80     }
 81 
 82     @Override
 83     protected void onDraw(Canvas canvas) { 87             drawMiddleLine(canvas);
 88             drawVoiceLine(canvas); 90             run();
 91     }
 92 
 93     private void drawMiddleLine(Canvas canvas) {
 94         if (paint == null) {
 95             paint = new Paint();
 96             paint.setColor(middleLineColor);
 97             paint.setAntiAlias(true);
 98         }
 99         canvas.save();
100         canvas.drawRect(0, getHeight() / 2 - middleLineHeight / 2, getWidth(), getHeight() / 2 + middleLineHeight / 2, paint);
101         canvas.restore();
102     }
103 
104     private void drawVoiceLine(Canvas canvas) {
105         lineChange();
106         if (paintVoicLine == null) {
107             paintVoicLine = new Paint();
108             paintVoicLine.setColor(voiceLineColor);
109             paintVoicLine.setAntiAlias(true);
110             paintVoicLine.setStyle(Paint.Style.STROKE);
111             paintVoicLine.setStrokeWidth(2);
112         }
113         canvas.save();
114         int moveY = getHeight() / 2;
115         for (int i = 0; i < paths.size(); i++) {
116             paths.get(i).reset();
117             paths.get(i).moveTo(getWidth(), getHeight() / 2);
118         }
119         for (float i = getWidth() - 1; i >= 0; i -= fineness) {
120             amplitude = 4 * volume * i / getWidth() - 4 * volume * i * i / getWidth() / getWidth();
121             for (int n = 1; n <= paths.size(); n++) {
122                 float sin = amplitude * (float) Math.sin((i - Math.pow(1.22, n)) * Math.PI / 180 - translateX);
123                 paths.get(n - 1).lineTo(i, (2 * n * sin / paths.size() - 15 * sin / paths.size() + moveY));
124             }
125         }
126         for (int n = 0; n < paths.size(); n++) {
127             if (n == paths.size() - 1) {
128                 paintVoicLine.setAlpha(255);
129             } else {
130                 paintVoicLine.setAlpha(n * 130 / paths.size());
131             }
132             if (paintVoicLine.getAlpha() > 0) {
133                 canvas.drawPath(paths.get(n), paintVoicLine);
134             }
135         }
136         canvas.restore();
137     }
138 
139   167 
168     public void setVolume(int volume) {
169         if (volume > maxVolume * sensibility / 25) {
170             isSet = true;
171             this.targetVolume = getHeight() * volume / 2 / maxVolume;
172         }
173     }
174 
175     private void lineChange() {
176         if (lastTime == 0) {
177             lastTime = System.currentTimeMillis();
178             translateX += 1.5;
179         } else {
180             if (System.currentTimeMillis() - lastTime > lineSpeed) {
181                 lastTime = System.currentTimeMillis();
182                 translateX += 1.5;
183             } else {
184                 return;
185             }
186         }
187         if (volume < targetVolume && isSet) {
188             volume += getHeight() / 30;
189         } else {
190             isSet = false;
191             if (volume <= 10) {
192                 volume = 10;
193             } else {
194                 if (volume < getHeight() / 30) {
195                     volume -= getHeight() / 60;
196                 } else {
197                     volume -= getHeight() / 30;
198                 }
199             }
200         }
201     }
202 
221     public void run() {225             invalidate();227     }
228 
229 }

上面是View的canvas实现的波形图绘制,cpu占用率比较高,在20%左右,一边录音一边绘制,手机发烫是最明显的感觉了.

下面我们换成SurfaceView绘制的

public class VoiceLineSurfaceView extends SurfaceView implements Runnable,SurfaceView.Callback {
    private final int LINE = 0;
    private final int RECT = 1;

    private int middleLineColor = Color.BLACK;
    private int voiceLineColor = Color.BLACK;
    private float middleLineHeight = 4;
    private Paint paint;
    private Paint paintVoicLine;/**
     * 灵敏度
     */
    private int sensibility = 4;

    private float maxVolume = 100;


    private float translateX = 0;
    private boolean isSet = false;

    /**
     * 振幅
     */
    private float amplitude = 1;
    /**
     * 音量
     */
    private float volume = 10;
    private int fineness = 1;
    private float targetVolume = 1;


    private long speedY = 50;
    private float rectWidth = 25;
    private float rectSpace = 5;
    private float rectInitHeight = 4;
    private List<Rect> rectList;

    private long lastTime = 0;
    private int lineSpeed = 90;
   private SurfaceHolder surfaceHolder;
    List<Path> paths = null;
private boolean isWaveDrawing = false;
private boolean isMiddleLineDrawing = true;
private Thread thread;
private Canvas canvas;

public VoiceLineSurfaceView(Context context) {
        super(context);
    }

    public VoiceLineSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAtts(context, attrs);
    }

    public VoiceLineSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAtts(context, attrs);
    }

    private void initAtts(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.voiceView);
        mode = typedArray.getInt(R.styleable.voiceView_viewMode, 0);
        voiceLineColor = typedArray.getColor(R.styleable.voiceView_voiceLine, Color.BLACK);
        maxVolume = typedArray.getFloat(R.styleable.voiceView_maxVolume, 100);
        sensibility = typedArray.getInt(R.styleable.voiceView_sensibility, 4);
            middleLineColor = typedArray.getColor(R.styleable.voiceView_middleLine, Color.BLACK);
            middleLineHeight = typedArray.getDimension(R.styleable.voiceView_middleLineHeight, 4);
            lineSpeed = typedArray.getInt(R.styleable.voiceView_lineSpeed, 90);
            fineness = typedArray.getInt(R.styleable.voiceView_fineness, 1);
            paths = new ArrayList<>(20);
            for (int i = 0; i < 20; i++) {
                paths.add(new Path());
            }
        typedArray.recycle();
    setZOrderOnTop(true);
    getHolder().setFormat(PixelFormat.TRANSLUENT);
    surfaceHolder =  getHolder();
    surfaceHolder.addCallback(this);
    }
private void drawMiddleLine(Canvas canvas) {
        if (paint == null) {
            paint = new Paint();
            paint.setColor(middleLineColor);
            paint.setAntiAlias(true);
        }
        canvas.save();
        canvas.drawRect(0, getHeight() / 2 - middleLineHeight / 2, getWidth(), getHeight() / 2 + middleLineHeight / 2, paint);
        canvas.restore();
    }

    private void drawVoiceLine(Canvas canvas) {
        lineChange();
        if (paintVoicLine == null) {
            paintVoicLine = new Paint();
            paintVoicLine.setColor(voiceLineColor);
            paintVoicLine.setAntiAlias(true);
            paintVoicLine.setStyle(Paint.Style.STROKE);
            paintVoicLine.setStrokeWidth(2);
        }
        canvas.save();
        int moveY = getHeight() / 2;
        for (int i = 0; i < paths.size(); i++) {
            paths.get(i).reset();
            paths.get(i).moveTo(getWidth(), getHeight() / 2);
        }
        for (float i = getWidth() - 1; i >= 0; i -= fineness) {
            amplitude = 4 * volume * i / getWidth() - 4 * volume * i * i / getWidth() / getWidth();
            for (int n = 1; n <= paths.size(); n++) {
                float sin = amplitude * (float) Math.sin((i - Math.pow(1.22, n)) * Math.PI / 180 - translateX);
                paths.get(n - 1).lineTo(i, (2 * n * sin / paths.size() - 15 * sin / paths.size() + moveY));
            }
        }
        for (int n = 0; n < paths.size(); n++) {
            if (n == paths.size() - 1) {
                paintVoicLine.setAlpha(255);
            } else {
                paintVoicLine.setAlpha(n * 130 / paths.size());
            }
            if (paintVoicLine.getAlpha() > 0) {
                canvas.drawPath(paths.get(n), paintVoicLine);
            }
        }
        canvas.restore();
    }
public void setVolume(int volume) {
        if (volume > maxVolume * sensibility / 25) {
            isSet = true;
            this.targetVolume = getHeight() * volume / 2 / maxVolume;
        }
    }

    private void lineChange() {
        if (lastTime == 0) {
            lastTime = System.currentTimeMillis();
            translateX += 1.5;
        } else {
            if (System.currentTimeMillis() - lastTime > lineSpeed) {
                lastTime = System.currentTimeMillis();
                translateX += 1.5;
            } else {
                return;
            }
        }
        if (volume < targetVolume && isSet) {
            volume += getHeight() / 30;
        } else {
            isSet = false;
            if (volume <= 10) {
                volume = 10;
            } else {
                if (volume < getHeight() / 30) {
                    volume -= getHeight() / 60;
                } else {
                    volume -= getHeight() / 30;
                }
            }
        }
    }
@Override
public void surfaceCreated(){
}
@Override
public void surfaceChanged(){
isMiddleLineDrawing = true;
thread = new Thread(this);
thread.start();
}
@Override
public void surfaceDestroyed(){
isMiddleLineDrawing = false;
}
@Override
public void run() {
  while(isMiddleLineDrawing){
    canvas = surfaceHolder.lockCanvas();
    if(canvas==null){
    return;
    }
    canvas.drawColor(Color.TRANSLUENT,PorterDuff.Mode.CLEAR);
    if(isWaveDrawing){
    drawVoiceLine(canvas);
    }
    drawMiddleLine(canvas);
    surfaceHolder.unlockCanvasAndPost(canvas);
  }
 }

public void setDrawing(boolean drawing){
  isMiddleLineDrawing = true;
  isWaveDrawing = drawing;
}

}

 

posted @ 2018-06-11 09:05  你要  阅读(1347)  评论(0编辑  收藏  举报