如何从录制原始音频中获取频率?

Posted

技术标签:

【中文标题】如何从录制原始音频中获取频率?【英文标题】:how to get frequency from Recording raw audio? 【发布时间】:2017-02-11 08:57:48 【问题描述】:

我想同时从我的录音中获取频率

这是我的代码:

我的 SoundProcessing .java 和 Main 类

public class SoundProcessing extends Activity 

private WaveformView mRealtimeWaveformView;
private RecordingThread mRecordingThread;
private PlaybackThread mPlaybackThread;
private static final int REQUEST_RECORD_AUDIO = 13;

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

    mRealtimeWaveformView = (WaveformView) findViewById(R.id.waveformView);
    mRecordingThread = new RecordingThread(new AudioDataReceivedListener() 
        @Override
        public void onAudioDataReceived(short[] data) 
            mRealtimeWaveformView.setSamples(data);
        
    );
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            if (!mRecordingThread.recording()) 
                startAudioRecordingSafe();
             else 
                mRecordingThread.stopRecording();
            
        
    );

和我的 RecordingThread.java:

公共类 RecordingThread

private static final String LOG_TAG = RecordingThread.class.getSimpleName();
private static final int SAMPLE_RATE = 44100;

public RecordingThread(AudioDataReceivedListener listener) 
    mListener = listener;


private boolean mShouldContinue;
private AudioDataReceivedListener mListener;
private Thread mThread;

public boolean recording() 
    return mThread != null;


public void startRecording() 
    if (mThread != null)
        return;

    mShouldContinue = true;
    mThread = new Thread(new Runnable() 
        @Override
        public void run() 
            record();
        
    );
    mThread.start();


public void stopRecording() 
    if (mThread == null)
        return;

    mShouldContinue = false;
    mThread = null;


private void record() 
    Log.v(LOG_TAG, "Start");
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);

    // buffer size in bytes
    int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT);

    if (bufferSize == AudioRecord.ERROR || bufferSize == AudioRecord.ERROR_BAD_VALUE) 
        bufferSize = SAMPLE_RATE * 2;
    

    short[] audioBuffer = new short[bufferSize / 2];

    AudioRecord record = new AudioRecord(MediaRecorder.Audiosource.DEFAULT,
            SAMPLE_RATE,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT,
            bufferSize);

    if (record.getState() != AudioRecord.STATE_INITIALIZED) 
        Log.e(LOG_TAG, "Audio Record can't initialize!");
        return;
    
    record.startRecording();

    Log.v(LOG_TAG, "Start recording");

    long shortsRead = 0;
    while (mShouldContinue) 
        int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length);
        shortsRead += numberOfShort;

        // Notify waveform
        mListener.onAudioDataReceived(audioBuffer);
    

    record.stop();
    record.release();

    Log.v(LOG_TAG, String.format("Recording stopped. Samples read: %d", shortsRead));


还有我的 AudioDataReceivedListener.java

public interface AudioDataReceivedListener 

    void onAudioDataReceived(short[] data);

【问题讨论】:

【参考方案1】:

为了获得信号的频率,您必须对其进行分析,例如使用傅里叶变换。在技​​术应用中,您使用快速/离散傅里叶变换 (FFT)。原始音频是随时间记录的信号,FFT 可让您查看信号中包含哪些频率。

在您的情况下,意味着您需要在 audioBuffer 上应用 FFT。有 Java 类和 C/C++ 代码(使用 NDK)。对于实时应用程序,C/C++ 应该更快。

【讨论】:

以上是关于如何从录制原始音频中获取频率?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 FFT 应用于录音以获取频率?

在java中录制音频并确定实时是不是播放了x频率的音调,如果是这样的话

如何在每个FFT计算中检索不同的原始频率并且在java中没有任何频率泄漏

如何更改录制音频的音高并在后台保存?

从 iPhone 上的音频流中获取 Hz 频率

如何使用 MediaRecorder 获取录制声音的每个频率?