Android: Audio Recording with voice level visualization

后端 未结 4 1432
再見小時候
再見小時候 2021-02-01 08:32

I need to create a android application which is for recording voice while showing the voice(sound) level visualization.

I already created an audio recording application

4条回答
  •  梦毁少年i
    2021-02-01 09:14

    I like Ali's answer, but here's a simpler version that performs much better. The real speed comes from making the view class's onDraw method as fast as possible. Store the correct values in memory first by doing any computations not required for drawing outside the draw loop, and pass fully populated structures to draw routines to allow the hardware to optimize drawing many lines.

    I launched my RecordingActivity and set it full screen, but you can create a layout resource or add the view anywhere.

    Actvity:

    public class RecordingActivity extends Activity {
        private VisualizerView visualizerView;
        private MediaRecorder recorder = new MediaRecorder();
        private Handler handler = new Handler();
        final Runnable updater = new Runnable() {
            public void run() {
                handler.postDelayed(this, 1);
                int maxAmplitude = recorder.getMaxAmplitude();
                if (maxAmplitude != 0) {
                    visualizerView.addAmplitude(maxAmplitude);
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_recording);
            visualizerView = (VisualizerView) findViewById(R.id.visualizer);
            try {
                recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                recorder.setOutputFile("/dev/null");
                recorder.prepare();
                recorder.start();
            } catch (IllegalStateException | IOException ignored) {
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            handler.removeCallbacks(updater);
            recorder.stop();
            recorder.reset();
            recorder.release();
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            handler.post(updater);
        }
    }
    

    View:

    public class VisualizerView extends View {
        private static final int MAX_AMPLITUDE = 32767;
    
        private float[] amplitudes;
        private float[] vectors;
        private int insertIdx = 0;
        private Paint pointPaint;
        private Paint linePaint;
        private int width;
        private int height;
    
        public VisualizerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            linePaint = new Paint();
            linePaint.setColor(Color.GREEN);
            linePaint.setStrokeWidth(1);
            pointPaint = new Paint();
            pointPaint.setColor(Color.BLUE);
            pointPaint.setStrokeWidth(1);
        }
    
        @Override
        protected void onSizeChanged(int width, int h, int oldw, int oldh) {
            this.width = width;
            height = h;
            amplitudes = new float[this.width * 2]; // xy for each point across the width
            vectors = new float[this.width * 4]; // xxyy for each line across the width
        }
    
        /**
         * modifies draw arrays. cycles back to zero when amplitude samples reach max screen size
         */
        public void addAmplitude(int amplitude) {
            invalidate();
            float scaledHeight = ((float) amplitude / MAX_AMPLITUDE) * (height - 1);
            int ampIdx = insertIdx * 2;
            amplitudes[ampIdx++] = insertIdx;   // x
            amplitudes[ampIdx] = scaledHeight;  // y
            int vectorIdx = insertIdx * 4;
            vectors[vectorIdx++] = insertIdx;   // x0
            vectors[vectorIdx++] = 0;           // y0
            vectors[vectorIdx++] = insertIdx;   // x1
            vectors[vectorIdx] = scaledHeight;  // y1
            // insert index must be shorter than screen width
            insertIdx = ++insertIdx >= width ? 0 : insertIdx;
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            canvas.drawLines(vectors, linePaint);
            canvas.drawPoints(amplitudes, pointPaint);
        }
    }
    

提交回复
热议问题