java - 音轨在 Android 中不工作

标签 java android multithreading audio audiorecord

我是 Android 新手。我正在开发一个使用 AudioRecorderAudioTrack 进行录音和播放的应用程序。除此之外,我正在尝试读取和显示录制声音的振幅值。

这是我的课

public class MainActivity extends AppCompatActivity {

private static final String TAG = "RecordSound";
private int BufferSize;
byte[] buffer = new byte[BufferSize];

/* AudioRecord and AudioTrack Object */
private AudioRecord record = null;
private AudioTrack track = null;

/* Audio Configuration */
private int sampleRate = 8000;
private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

private boolean isRecording = true;
private Thread recordingThread = null;

private double lastLevel = 0;
private Thread thread;
private static final int SAMPLE_DELAY = 75;
MediaPlayer mediaPlayer;

RelativeLayout layout;
private ImageView tankHolder;
TextView text;
Button play;
String filename;
final Handler mHandler = new Handler();


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tankHolder = (ImageView)findViewById(R.id.tankHolder);
    text=(TextView)findViewById(R.id.result_text);
    layout=(RelativeLayout)findViewById(R.id.linear);
    play=(Button)findViewById(R.id.btnStartPlay);

    try {
        BufferSize = AudioRecord.getMinBufferSize(sampleRate,
                channelConfig, audioFormat);
    }catch (Exception e){
        e.printStackTrace();
    }


}

@Override
protected void onResume() {
    super.onResume();
    //calling MediaPlayer for alarmtone when the tank is almost full
    mediaPlayer = MediaPlayer.create(this, R.raw.tone);

    startRecording();

    play.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                stopRecording();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}

private void stopRecording() throws IOException{
    if (null != record) {
        isRecording = false;
        record.stop();
        record.release();
        record = null;
        recordingThread = null;
        mHandler.post(runRecord);
        mediaPlayer.stop();
        mediaPlayer.release();
    }
}

final Runnable runRecord=new Runnable() {
    @Override
    public void run() {
        text.setText("working");
        try {
            PlayShortAudioFileViaAudioTrack("/sdcard/recorded.pcm");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
};

private void PlayShortAudioFileViaAudioTrack(String filePath) throws IOException{
    // We keep temporarily filePath globally as we have only two sample sounds now..
    if (filePath==null)
        return;

    //Reading the file..
    File file = new File(filePath); // for ex. path= "/sdcard/samplesound.pcm" or "/sdcard/samplesound.wav"
    byte[] byteData = new byte[(int) file.length()];
    Log.d(TAG, (int) file.length()+"");

    FileInputStream in = null;
    try {
        in = new FileInputStream( file );
        in.read( byteData );
        in.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // Set and push to audio track..
    int intSize = android.media.AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
    Log.d(TAG, intSize+"");

    AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
    at.play();
    // Write the byte array to the track
    at.write(byteData, 0, byteData.length);
    at.stop();
    at.release();

}


private void startRecording()
{
    record = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
            channelConfig, audioFormat, BufferSize);
    if (AudioRecord.STATE_INITIALIZED == record.getState())
        record.startRecording();

    isRecording = true;

/* Run a thread for Recording */
    recordingThread = new Thread(new Runnable() {
        @Override
        public void run() {
            writeAudioDataToFile();
        }
    },"AudioRecorder Thread");
    recordingThread.start();

    thread = new Thread(new Runnable() {
        public void run() {

            while(thread != null && !thread.isInterrupted()){
                //Let's make the thread sleep for a the approximate sampling time
                try{
                    Thread.sleep(SAMPLE_DELAY);}catch(InterruptedException ie){ie.printStackTrace();}
                readAudioBuffer();//After this call we can get the last value assigned to the lastLevel variable

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        if(lastLevel >= 7 && lastLevel <= 15){
                            text.setTextColor(getResources().getColor(R.color.Blue));
                            layout.setBackgroundColor(Color.RED);
                            tankHolder.setImageResource(R.drawable.ftank);
                            if (!mediaPlayer.isPlaying()){
                                mediaPlayer.start();
                            }
                            text.setText(String.valueOf(lastLevel));

                        }else
                        if(lastLevel > 50 && lastLevel <= 100){
                            text.setText(String.valueOf(lastLevel));
                            text.setTextColor(getResources().getColor(R.color.Orange));
                            layout.setBackgroundColor(Color.WHITE);
                            tankHolder.setImageResource(R.drawable.htank);
                            if (mediaPlayer.isPlaying()){
                                mediaPlayer.pause();
                            }
                        }else
                        if(lastLevel > 100 && lastLevel <= 170){
                            text.setText(String.valueOf(lastLevel));
                            text.setTextColor(getResources().getColor(R.color.Yellow));
                            layout.setBackgroundColor(Color.WHITE);
                            tankHolder.setImageResource(R.drawable.qtank);
                            if (mediaPlayer.isPlaying()){
                                mediaPlayer.pause();
                            }
                        }
                        if(lastLevel > 170){
                            text.setText(String.valueOf(lastLevel));
                            text.setTextColor(getResources().getColor(R.color.Blue));
                            layout.setBackgroundColor(Color.WHITE);
                            tankHolder.setImageResource(R.drawable.qtank);
                            if (mediaPlayer.isPlaying()){
                                mediaPlayer.pause();
                            }
                        }
                    }
                });
            }
        }
    },"AudioRecorder Thread");
    thread.start();

}

private void writeAudioDataToFile()
{
    byte data[] = new byte[BufferSize];

/* Record audio to following file */

    String filePath = "/sdcard/recorded.pcm";
    filename = Environment.getExternalStorageDirectory().getAbsolutePath();
    filename +="/audiofile.pcm";
    FileOutputStream os = null;

    try {
        os = new FileOutputStream(filePath);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    int read_bytes = 0;

    if(null != os){
        while(isRecording)
        {
            read_bytes = record.read(data, 0, BufferSize);

            if(AudioRecord.ERROR_INVALID_OPERATION != read_bytes){
                try {
                    os.write(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

private void readAudioBuffer() {

    try {
        short[] buffer = new short[BufferSize];

        int bufferReadResult = 1;

        if (record != null) {

            // Sense the voice...
            bufferReadResult = record.read(buffer, 0, BufferSize);
            double sumLevel = 0;
            for (int i = 0; i < bufferReadResult; i++) {
                sumLevel += buffer[i];
            }
            lastLevel = Math.abs((sumLevel / bufferReadResult));
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

如果我运行,我的 runOnUiThread(new Runnable() { 正在运行并且按下播放按钮时,录制的音频不会播放。 如果我删除 runOnUiThread(new Runnable() {,然后按下播放按钮,录制的音频将毫无问题地播放。 所以我认为问题出在线程上,我尝试实现处理程序类,但我仍然没有得到它。

最佳答案

关于java - 音轨在 Android 中不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40741953/

相关文章:

java - 从android中的json获取数组

android - 膨胀的 AlertDialogs 在 Android 4.X 上不可读,而在 Android 2.X 上看起来很完美

java - 使 Java Servlet 线程安全

.net - 在任务中显示来自 Catch 语句的自定义弹出窗口

java - 用java来表示内存中的文件结构?

java - 在 JBoss Seam 中使用 post 参数重定向到外部网站?

java - 当尝试使用 eclipse juno 服务器运行 struts2 时,出现 HTTP Status 404 错误

php - Android - php字符串编码

c# - STA 线程异常传播

java - 如何判断数组值的序列是否是回文?