2017-02-10 75 views
1

我正在製作一個簡單的android應用程序,用於從智能手機麥克風錄製某些內容,將其保存在文件中,然後播放該文件。Android: - 將錄製的音頻文件轉換爲浮點陣列

現在我想對該音頻文件應用高通濾波器,但要這樣做,我需要先將音頻文件轉換爲浮點數組。有人能幫助我嗎?

感謝

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); 
} 








} 
+0

入住這 [堆棧溢出問題] [1] [1]:http://stackoverflow.com/questions/6235016/convert-wav-audio-format-byte-array-to-浮點 –

回答

1

字節到浮充轉換的細節將取決於您使用的音頻文件的文件格式。我無法確定代碼中的格式。如果您的文件是WAV,44100 fps,16位,小端,立體聲(這是一種標準的Java,「CD質量」格式),您可以嘗試使用我編寫的以下代碼。密鑰變換點是當兩個字節被連接並轉換爲單個數字(其中,「緩衝液」包含數據被從音頻文件中讀取:

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

如果是大端,扭轉偏移的順序。如果是24位或32位,那麼你將分別在<和< 16和< 24位上進行或運算,結果將使用一個短的範圍,所以除以32767需要進行歸一化結果爲[-1..1]

我一直在Java上下文中使用以下一段時間沒有問題,但我不知道Android是否支持javax.sound.sampled.Aud ioInputStream等等。也許在讀取文件的上下文中看到轉換仍然有用嗎?該代碼假定我們具有「CD質量」音頻格式,並且音頻文件不超過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; 
}