简体   繁体   English

Android:-将录制的音频文件转换为float数组

[英]Android:- convert a recorded audio file into a float array

I am making a simple android application where I record something from a smartphone mic, save it in a file and then play that file. 我正在制作一个简单的android应用程序,在其中录制智能手机麦克风中的内容,将其保存在文件中,然后播放该文件。

Now I want to apply a high pass filter to that audio file, but to do so, I need to first convert the audio file into a float array. 现在,我想对该音频文件应用高通滤波器,但是要这样做,我需要先将音频文件转换为float数组。 Can someone please help me out with it. 有人可以帮我解决这个问题。

Thanks 谢谢

package abc.com.please;

import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;


public class MainActivity extends AppCompatActivity {

private static MediaRecorder mediaRecorder = new MediaRecorder();
private static MediaPlayer mediaPlayer;

private static String audioFilePath;
private static Button stopButton;
private static Button playButton;
private static Button recordButton;

private boolean isRecording = false;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    recordButton = (Button) findViewById(R.id.recordButton);
    playButton = (Button) findViewById(R.id.playButton);
    stopButton = (Button) findViewById(R.id.stopButton);

    if (!hasMicrophone())
    {
        stopButton.setEnabled(false);
        playButton.setEnabled(false);
        recordButton.setEnabled(false);
    } else {
        playButton.setEnabled(false);
        stopButton.setEnabled(false);
    }

    audioFilePath =
            Environment.getExternalStorageDirectory().getAbsolutePath()
                    + "/myaudio.3gp";


    recordButton.setOnClickListener(new View.OnClickListener(){

        public void onClick (View v)
        {

            isRecording = true;
            stopButton.setEnabled(true);
            playButton.setEnabled(false);
            recordButton.setEnabled(false);

            try {
                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                                   mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mediaRecorder.setOutputFile(audioFilePath);
                  mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                mediaRecorder.prepare();
                mediaRecorder.start();
            }catch (Exception e) {
                e.printStackTrace();

            }



        }
    });

    stopButton.setOnClickListener(new View.OnClickListener() {
        public void onClick (View view)
        {

            stopButton.setEnabled(false);
            playButton.setEnabled(true);
            if (isRecording)
            {
                recordButton.setEnabled(false);
                isRecording = false;
                mediaRecorder.stop();
                mediaRecorder.release();
                recordButton.setEnabled(true);
            }
            else
            {
                Toast.makeText(getApplicationContext(),"No recording going      on",Toast.LENGTH_SHORT).show();
            }
        }});

    playButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view)

        {

            playButton.setEnabled(false);
            recordButton.setEnabled(false);
            stopButton.setEnabled(true);
            try {
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setDataSource(audioFilePath);
                mediaPlayer.prepare();
                mediaPlayer.start();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    });
}

protected boolean hasMicrophone() {
    PackageManager pmanager = this.getPackageManager();
    return pmanager.hasSystemFeature(
            PackageManager.FEATURE_MICROPHONE);
}








}

The details of the bytes-to-float conversion are going to depend on the file format that you use for your audio file. 字节到浮点转换的详细信息将取决于您用于音频文件的文件格式。 I cannot tell what that format is from your code. 我无法从您的代码中得知该格式是什么。 If your file is WAV, 44100 fps, 16-bit, little-endian, stereo (this is a standard Java, "CD quality" format) you can try making use of the following code I wrote. 如果您的文件是WAV,44100 fps,16位,小尾数立体声(这是标准Java,“ CD质量”格式),则可以尝试使用我编写的以下代码。 The key conversion point is when two bytes are concatenated and converted to a single numeral (where "buffer" contains data being read in from the audio file: 关键的转换点是将两个字节连接起来并转换为一个数字时(其中“缓冲区”包含从音频文件中读取的数据):

float audioVal = ( buffer[bufferIdx++] & 0xff )
                        | ( buffer[bufferIdx++] << 8 );

If it is big endian, reverse the order of the shifts. 如果是大字节序,则反转移位顺序。 If 24 or 32 bit, then you would OR in shifts of << 16 and << 24, respectively. 如果是24或32位,那么您将分别进行<< <<和<< 24的移位。 With 16-bit, the result will make use of the range of a short, so division by 32767 is needed to normalize the result to [-1..1]. 对于16位,结果将利用short的范围,因此需要除以32767才能将结果归一化为[-1..1]。

I've been using the following in the Java context for a while without problems, but I don't know if Android supports javax.sound.sampled.AudioInputStream, etc. Maybe it is still useful to see the conversion in context of a file read? 我已经在Java上下文中使用以下内容一段时间了,但是没有问题,但是我不知道Android是否支持javax.sound.sampled.AudioInputStream等。也许在文件上下文中查看转换还是有用的读? The code assumes that we have the "CD Quality" audio format and that the audio file is not longer than Integer.MAX number of frames. 该代码假定我们具有“ CD Quality”音频格式,并且该音频文件的长度不超过Integer.MAX的帧数。

public float[] loadSoundFileURL(URL url) throws UnsupportedAudioFileException,
        IOException
{
    AudioInputStream ais = AudioSystem.getAudioInputStream(url);

    int framesCount = (int)ais.getFrameLength();

    // assuming stereo format, so two entries per frame
    float[] temp = new float[framesCount * 2];
    long tempCountdown = temp.length;

    int bytesRead = 0;
    int bufferIdx;
    int clipIdx = 0;
    byte[] buffer = new byte[1024];
    while((bytesRead = ais.read(buffer, 0, 1024)) != -1)
    {
        bufferIdx = 0;
        for (int i = 0, n = (bytesRead >> 1); i < n; i ++)
        {
            if ( tempCountdown-- >= 0)
            {
                temp[clipIdx++] = 
                        ( buffer[bufferIdx++] & 0xff )
                        | ( buffer[bufferIdx++] << 8 ) ;
            }
        }
    }

    // QUESTION: better to do following in above loop?
    for (int i = 0; i < temp.length; i++)
    {
        temp[i] = temp[i] / 32767f;
    }

    return temp;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM