Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从Activity向自定义视图类传递变量_Java_Android_Audio_Canvas_Fft - Fatal编程技术网

Java 从Activity向自定义视图类传递变量

Java 从Activity向自定义视图类传递变量,java,android,audio,canvas,fft,Java,Android,Audio,Canvas,Fft,我正在使用canvas.drawLine()方法测试将音频绘制到画布中。我能够在画布上进行静态绘制。基本上,我有一个测试应用程序,它有两个按钮开始和停止,还有一个画布,在那里我试图绘制从FFT获得的音频。当我点击开始按钮时,它开始使用AudioRecord类录制声音,并将数据收集到缓冲区中,我通过FFT获得频率。这是在非常早期的阶段。现在我只想弄清楚如何将这些频率值传递给自定义视图类的onDraw方法。以下是从布局开始的相关代码 活动\u main.xml <RelativeLayout

我正在使用
canvas.drawLine()
方法测试将音频绘制到画布中。我能够在画布上进行静态绘制。基本上,我有一个测试应用程序,它有两个按钮开始和停止,还有一个画布,在那里我试图绘制从FFT获得的音频。当我点击开始按钮时,它开始使用
AudioRecord
类录制声音,并将数据收集到缓冲区中,我通过FFT获得频率。这是在非常早期的阶段。现在我只想弄清楚如何将这些频率值传递给自定义视图类的
onDraw
方法。以下是从布局开始的相关代码

活动\u main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.example.testapp.WaveForm
        android:id="@+id/waveForm1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="78dp" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/button1"
        android:layout_alignBottom="@+id/button1"
        android:layout_alignRight="@+id/waveForm1"
        android:layout_marginRight="19dp"
        android:text="STOP" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/waveForm1"
        android:layout_alignParentTop="true"
        android:text="START" />

</RelativeLayout>
正如我在onDraw方法的注释中提到的,我希望传递我在活动中获得的频率值,而不是50。 最后是我的活动:

MainActivity.java

package com.example.testapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class WaveForm extends View {

    private Paint mLinePaint;
    float x ;
    float y;

    public WaveForm(Context context, AttributeSet attrs) {
        super(context, attrs);
        mLinePaint = new Paint();
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setARGB(255, 0, 0, 255);
        mLinePaint.setAntiAlias(true);
        mLinePaint.setStrokeWidth(10);
        x = 0.0f;
        y = 0.0f;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        //Instead of 50 here i would like to pass the value obtained from the Activity class
        canvas.drawLine(x, 0, y, 50, mLinePaint);   
        y = y + 1.0f;
        x = x + 1.0f;
        super.onDraw(canvas);
    }



}
package com.example.testapp;


import android.app.Activity;
import android.graphics.Canvas;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;



public class MainActivity extends Activity {
    boolean recording = false;
    AudioRecord audioRecord;
    double[] x;
    double[] y;
    double currentPoint = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final View myInstance = (View) findViewById(R.id.waveForm1);

        Button start = (Button) findViewById(R.id.button1);
        start.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            int sampleRateInHz=44100;
            int channelConfig = AudioFormat.CHANNEL_IN_MONO;
            int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT);
            audioRecord = new AudioRecord(AudioSource.MIC, sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT,  AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT));
            byte[] audioData = new byte[bufferSizeInBytes/4];

            FFT myFFT = new FFT(audioData.length);
            Canvas canvas = new Canvas();
            recording = true;
            audioRecord.startRecording();
            while(recording) {
            audioRecord.read(audioData,0, bufferSizeInBytes/4);
            //convert to double here
            for(int i=0; i<audioData.length; i++) {
                x[i] = (double)audioData[i];
                y[i] = 0;
            }
            double[] samples = myFFT.fft(x, y);
            for(int i=0; i<samples.length; i++) {
                currentPoint = samples[i];
                myInstance.draw(canvas);
                myInstance.invalidate();
            }
            }

        }
        });
        Button stop = (Button) findViewById(R.id.button2);
        stop.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
        recording = false;
        audioRecord.stop();

        }
        });     
    }     
}
package com.example.testapp;
导入android.app.Activity;
导入android.graphics.Canvas;
导入android.media.AudioFormat;
导入android.media.AudioRecord;
导入android.media.MediaRecorder.AudioSource;
导入android.os.Bundle;
导入android.view.view;
导入android.view.view.OnClickListener;
导入android.widget.Button;
公共类MainActivity扩展了活动{
布尔记录=假;
录音;
双[]x;
双[]y;
双电流点=0;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
最终视图myInstance=(视图)findViewById(R.id.waveForm1);
按钮开始=(按钮)findViewById(R.id.button1);
setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图v){
int-sampleRateInHz=44100;
int channelConfig=AudioFormat.CHANNEL\u在单声道中;
int bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig,AudioFormat.ENCODING_PCM_16BIT);
audioRecord=新的音频记录(AudioSource.MIC、sampleRateInHz、channelConfig、AudioFormat.ENCODING_PCM_16BIT、audioRecord.getMinBufferSize(sampleRateInHz、channelConfig、AudioFormat.ENCODING_PCM_16BIT));
字节[]音频数据=新字节[bufferSizeInBytes/4];
FFT myFFT=新的FFT(音频数据长度);
画布=新画布();
记录=真;
录音。开始录制();
同时(录音){
音频记录读取(音频数据,0,缓冲区大小单位/4);
//在这里转换成双倍

对于(int i=0;i将
currentPoint
指定为静态变量,并使用
MainActivity.currentPoint
从其他类获取变量值。或者,只需使用返回变量的
getter
方法。

波形中为
currentPoint
变量创建getter/Settero在调用
draw
as之前,从
MainActivity
获取值:

public class WaveForm extends View {

    private double currentPoint = 50;
    public void setCurrentPoint(double currentPoint){
         this.currentPoint=currentPoint;
    }
    public double getCurrentPoint(){

       return this.currentPoint;
    }
    @Override
    protected void onDraw(Canvas canvas) {

        canvas.drawLine(x, 0, y, getCurrentPoint(), mLinePaint);   
        ...
    }

}
在调用
onDraw
之前,通过调用
setCurrentPoint
方法,从
main活动
设置
currentPoint
值:

    for(int i=0; i<samples.length; i++) {
        currentPoint = samples[i];
        myInstance.setCurrentPoint(currentPoint);
        myInstance.draw(canvas);
        myInstance.invalidate();
    }

用于(int i=0;我希望它能起作用。我会测试。我在想为什么我在过去的几个小时里都没有考虑这个问题!!!这正如预期的那样起作用。但我仍然认为setter方法会更好。你对此有什么建议吗?别着急!我会尽快让你知道,因为myInstance是视图对象,而不是whole class instance是否可能?我想我无法做到这一点。setCurrentPoint
@Peshal:我认为可能,请尝试使用它,而不是使用静态变量。请看我是如何实例化myInstance的……
最终视图myInstance=(View)findViewById(R.id.waveForm1)所以基本上它不是整个类的一个实例。所以它不允许我做
myInstance.setCurrentPoint(currentPoint)
。我可以用不同的方式实例化这个视图吗,我更喜欢setter的想法too@Peshal:好的,我明白你的意思了。你可以这样尝试:
myInstance.setTag(currentPoint);
并使用
double currentPoint=(Double)getTag();在onDraw方法中。让我知道这种方法工作起来很好。
setTag()
getTag()
正在工作。非常感谢!