Advertisement
saurabhmesh17

Android API for Playback and Recording

Aug 19th, 2014
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.26 KB | None | 0 0
  1. package com.example.audiorecplayusingbuffer;
  2.  
  3. /* This Program is used to Record and Playback Some audio
  4.  * The Recorded Audio is written to a BUFFER, and same BUFFER is used for Playback
  5.  * */
  6.  
  7. import java.io.DataInputStream;
  8. import java.io.File;
  9. import java.io.FileInputStream;
  10. import java.io.FileNotFoundException;
  11. import java.io.FileOutputStream;
  12. import java.io.IOException;
  13. import android.support.v7.app.ActionBarActivity;
  14. import android.support.v4.app.Fragment;
  15. import android.media.AudioFormat;
  16. import android.media.AudioManager;
  17. import android.media.AudioRecord;
  18. import android.media.AudioTrack;
  19. import android.media.MediaRecorder.AudioSource;
  20. import android.os.Bundle;
  21. import android.os.Environment;
  22. import android.util.Log;
  23. import android.view.LayoutInflater;
  24. import android.view.Menu;
  25. import android.view.MenuItem;
  26. import android.view.View;
  27. import android.view.ViewGroup;
  28. import android.widget.Button;
  29.  
  30. public class BufferMain extends ActionBarActivity {
  31.  
  32.     private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
  33.  
  34.     private static final int RECORDER_BPP = 16;
  35.     private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
  36.     private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
  37.     private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
  38.     private static final int RECORDER_SAMPLERATE = 8000;
  39.     private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
  40.     private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
  41.     private static final String TAG = "AUDIO_RECORD_PLAYBACK_SAURABH";
  42.  
  43.     private AudioRecord recorder = null;
  44.     private int bufferSize = 0;
  45.  
  46.     /* Threads for Recording/Playing */
  47.     private Thread recordingThread = null;
  48.     //private Thread playingThread = null;
  49.  
  50.     /* Flags for Recording/Playing */
  51.     private boolean isRecording = false;
  52.     private boolean isPlaying = false;
  53.    
  54.     private boolean flag = false;
  55.    
  56.     private byte[] AudioBuffer = new byte[640];     /* Global Buffe for Playing Audio */
  57.    
  58.     @Override
  59.     protected void onCreate(Bundle savedInstanceState) {
  60.         super.onCreate(savedInstanceState);
  61.         setContentView(R.layout.activity_buffer_main);
  62.  
  63.         setButtonHandlers();
  64.  
  65.         enableButton(R.id.btnStartRec,true);
  66.         enableButton(R.id.btnStopRec,false);
  67.  
  68.         enableButton(R.id.btnStartPlay,false);
  69.         enableButton(R.id.btnStopPlay,false);
  70.  
  71.         bufferSize = AudioRecord.getMinBufferSize(8000,
  72.                 AudioFormat.CHANNEL_IN_MONO,
  73.                 AudioFormat.ENCODING_PCM_16BIT);
  74.        
  75.         /*if (savedInstanceState == null) {
  76.             getSupportFragmentManager().beginTransaction()
  77.                     .add(R.id.container, new PlaceholderFragment()).commit();
  78.         }*/
  79.        
  80.         while(flag)
  81.         {
  82.             startRecording();
  83.             stopRecording();
  84.            
  85.             StartPlaying();
  86.         }
  87.        
  88.     }
  89.    
  90.     /* Assign OnClickListener to Buttons */
  91.     private void setButtonHandlers() {
  92.         ((Button)findViewById(R.id.btnStartRec)).setOnClickListener(btnClick);
  93.         ((Button)findViewById(R.id.btnStopRec)).setOnClickListener(btnClick);
  94.         ((Button)findViewById(R.id.btnStartPlay)).setOnClickListener(btnClick);
  95.         ((Button)findViewById(R.id.btnStopPlay)).setOnClickListener(btnClick);
  96.     }
  97.  
  98.     /* Function to Enable/Disable Buttons */
  99.     private void enableButton(int id,boolean isEnable){
  100.         ((Button)findViewById(id)).setEnabled(isEnable);
  101.     }
  102.  
  103.     private String getFilename(){
  104.         String filepath = Environment.getExternalStorageDirectory().getPath();
  105.         File file = new File(filepath,AUDIO_RECORDER_FOLDER);
  106.  
  107.         if(!file.exists()){
  108.             file.mkdirs();
  109.         }
  110.         return (file.getAbsolutePath() + "/" + "audiofile" + AUDIO_RECORDER_FILE_EXT_WAV);
  111.     }
  112.  
  113.     private String getTempFilename(){
  114.         String filepath = Environment.getExternalStorageDirectory().getPath();
  115.         File file = new File(filepath,AUDIO_RECORDER_FOLDER);
  116.  
  117.         if(!file.exists()){
  118.             file.mkdirs();
  119.         }
  120.  
  121.         File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);
  122.  
  123.         if(tempFile.exists())
  124.             tempFile.delete();
  125.  
  126.         return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
  127.     }
  128.  
  129.     public AudioRecord findAudioRecord()
  130.     {
  131.         for (int rate : mSampleRates) {
  132.             for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
  133.                 for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
  134.                     try {
  135.                         Log.d(TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
  136.                                 + channelConfig);
  137.                         int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
  138.  
  139.                         if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
  140.                             // check if we can instantiate and have a success
  141.                             AudioRecord recorder = new AudioRecord(AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);
  142.  
  143.                             if (recorder.getState() == AudioRecord.STATE_INITIALIZED) {
  144.                                 Log.d(TAG, "================== Final Values: rate " + rate + "Hz, audioFormat: " + audioFormat + ", channel: "
  145.                                         + channelConfig+" ==================");
  146.                                 return recorder;
  147.                             }
  148.                         }
  149.                     } catch (Exception e) {
  150.                         Log.e(TAG, rate + "Exception, keep trying.",e);
  151.                     }
  152.                 }
  153.             }
  154.         }
  155.         return null;
  156.     }
  157.  
  158.     private void startRecording()
  159.     {
  160.         recorder = findAudioRecord();
  161.         int i = recorder.getState();
  162.         if(i==1)
  163.             recorder.startRecording();
  164.  
  165.         isRecording = true;
  166.         recordingThread = new Thread(new Runnable() {
  167.             @Override
  168.             public void run() {
  169.                 writeAudioDataToFile();
  170.             }
  171.         },"AudioRecorder Thread");
  172.         recordingThread.start();
  173.     }
  174.  
  175.    
  176.     private void writeAudioDataToBuffer()
  177.     {
  178.         byte data[] = new byte[bufferSize];
  179.         String filename = getTempFilename();
  180.         FileOutputStream os = null;
  181.  
  182.         try {
  183.             os = new FileOutputStream(filename);
  184.         } catch (FileNotFoundException e) {
  185.             // TODO Auto-generated catch block
  186.             e.printStackTrace();
  187.         }
  188.  
  189.         int i, read = 0;
  190.         //if(null != os){
  191.             while(isRecording){
  192.                 Log.d(TAG, "===== Recording Audio =====");
  193.                 read = recorder.read(data, 0, bufferSize);
  194.  
  195.                 if(AudioRecord.ERROR_INVALID_OPERATION != read){
  196.                     for(i=0; i<bufferSize; i++)
  197.                     {
  198.                         data[i] =
  199.                     }
  200.                 }
  201.             }
  202.  
  203.             try {
  204.                 os.close();
  205.             } catch (IOException e) {
  206.                 e.printStackTrace();
  207.             }
  208.         //}
  209.     }
  210.    
  211.    
  212.    
  213.     private void writeAudioDataToFile()
  214.     {
  215.         byte data[] = new byte[bufferSize];
  216.         String filename = getTempFilename();
  217.         FileOutputStream os = null;
  218.  
  219.         try {
  220.             os = new FileOutputStream(filename);
  221.         } catch (FileNotFoundException e) {
  222.             // TODO Auto-generated catch block
  223.             e.printStackTrace();
  224.         }
  225.  
  226.         int read = 0;
  227.         if(null != os){
  228.             while(isRecording){
  229.                 //Log.d(TAG, "===== Recording Audio =====");
  230.                 read = recorder.read(data, 0, bufferSize);
  231.  
  232.                 if(AudioRecord.ERROR_INVALID_OPERATION != read){
  233.                     try {
  234.                         os.write(data);
  235.                     } catch (IOException e) {
  236.                         e.printStackTrace();
  237.                     }
  238.                 }
  239.             }
  240.  
  241.             try {
  242.                 os.close();
  243.             } catch (IOException e) {
  244.                 e.printStackTrace();
  245.             }
  246.         }
  247.     }
  248.  
  249.     private void stopRecording()
  250.     {
  251.         if(null != recorder){
  252.             isRecording = false;
  253.  
  254.             int i = recorder.getState();
  255.             if(i==1)
  256.                 recorder.stop();
  257.             recorder.release();
  258.             Log.d(TAG, "===== Recording Audio Completed ===== ");
  259.  
  260.             recorder = null;
  261.             recordingThread = null;
  262.         }
  263.  
  264.         copyWaveFile(getTempFilename(),getFilename());
  265.         deleteTempFile();
  266.     }
  267.  
  268.     private void deleteTempFile()
  269.     {
  270.         File file = new File(getTempFilename());
  271.         file.delete();
  272.     }
  273.  
  274.     private void copyWaveFile(String inFilename,String outFilename){
  275.         FileInputStream in = null;
  276.         FileOutputStream out = null;
  277.         long totalAudioLen = 0;
  278.         long totalDataLen = totalAudioLen + 36;
  279.         long longSampleRate = RECORDER_SAMPLERATE;
  280.         int channels = 1;
  281.         long byteRate = (RECORDER_BPP/8) * RECORDER_SAMPLERATE * channels;
  282.  
  283.         byte[] data = new byte[bufferSize];
  284.  
  285.         try {
  286.             in = new FileInputStream(inFilename);
  287.             out = new FileOutputStream(outFilename);
  288.             totalAudioLen = in.getChannel().size();
  289.             totalDataLen = totalAudioLen + 36;
  290.  
  291.             Log.d(TAG, "File size: " + totalDataLen);
  292.  
  293.             WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
  294.                     longSampleRate, channels, byteRate);
  295.  
  296.             while(in.read(data) != -1){
  297.                 out.write(data);
  298.             }
  299.             in.close();
  300.             out.close();
  301.         } catch (FileNotFoundException e) {
  302.             e.printStackTrace();
  303.         } catch (IOException e) {
  304.             e.printStackTrace();
  305.         }
  306.     }
  307.  
  308.     private void WriteWaveFileHeader(
  309.             FileOutputStream out, long totalAudioLen,
  310.             long totalDataLen, long longSampleRate, int channels,
  311.             long byteRate) throws IOException {
  312.  
  313.         byte[] header = new byte[44];
  314.  
  315.         header[0] = 'R';  // RIFF/WAVE header
  316.         header[1] = 'I';
  317.         header[2] = 'F';
  318.         header[3] = 'F';
  319.         header[4] = (byte) (totalDataLen & 0xff);
  320.         header[5] = (byte) ((totalDataLen >> 8) & 0xff);
  321.         header[6] = (byte) ((totalDataLen >> 16) & 0xff);
  322.         header[7] = (byte) ((totalDataLen >> 24) & 0xff);
  323.         header[8] = 'W';
  324.         header[9] = 'A';
  325.         header[10] = 'V';
  326.         header[11] = 'E';
  327.         header[12] = 'f';  // 'fmt ' chunk
  328.         header[13] = 'm';
  329.         header[14] = 't';
  330.         header[15] = ' ';
  331.         header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
  332.         header[17] = 0;
  333.         header[18] = 0;
  334.         header[19] = 0;
  335.         header[20] = 1;  // format = 1
  336.         header[21] = 0;
  337.         header[22] = (byte) channels;
  338.         header[23] = 0;
  339.         header[24] = (byte) (longSampleRate & 0xff);
  340.         header[25] = (byte) ((longSampleRate >> 8) & 0xff);
  341.         header[26] = (byte) ((longSampleRate >> 16) & 0xff);
  342.         header[27] = (byte) ((longSampleRate >> 24) & 0xff);
  343.         header[28] = (byte) (byteRate & 0xff);
  344.         header[29] = (byte) ((byteRate >> 8) & 0xff);
  345.         header[30] = (byte) ((byteRate >> 16) & 0xff);
  346.         header[31] = (byte) ((byteRate >> 24) & 0xff);
  347.         header[32] = (byte) (2 * 16 / 8);  // block align
  348.         header[33] = 0;
  349.         header[34] = RECORDER_BPP;  // bits per sample
  350.         header[35] = 0;
  351.         header[36] = 'd';
  352.         header[37] = 'a';
  353.         header[38] = 't';
  354.         header[39] = 'a';
  355.         header[40] = (byte) (totalAudioLen & 0xff);
  356.         header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
  357.         header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
  358.         header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
  359.  
  360.         out.write(header, 0, 44);
  361.     }
  362.  
  363.     private View.OnClickListener btnClick = new View.OnClickListener() {
  364.         @Override
  365.         public void onClick(View v) {
  366.             switch(v.getId()){
  367.             case R.id.btnStartRec:{
  368.                 Log.d(TAG, "Start Recording");
  369.                 enableButton(R.id.btnStartRec,false);
  370.                 enableButton(R.id.btnStopRec,true);
  371.                 startRecording();
  372.                 enableButton(R.id.btnStopPlay,false);
  373.                 break;
  374.             }
  375.             case R.id.btnStopRec:{
  376.                 Log.d(TAG, "Stop Recording");
  377.                 enableButton(R.id.btnStartRec,true);
  378.                 enableButton(R.id.btnStopRec,false);
  379.                 stopRecording();
  380.                 enableButton(R.id.btnStartPlay,true);
  381.                 break;
  382.             }
  383.             case R.id.btnStartPlay:{
  384.                 Log.d(TAG, "Play Recording");
  385.                 enableButton(R.id.btnStartRec,false);
  386.                 enableButton(R.id.btnStopRec,false);
  387.                 StartPlaying();
  388.                 enableButton(R.id.btnStartPlay,false);
  389.                 enableButton(R.id.btnStopPlay,true);
  390.                 break;
  391.             }
  392.  
  393.             case R.id.btnStopPlay:{
  394.                 Log.d(TAG, "Stop Playing");
  395.                 //StopPlaying();
  396.                 enableButton(R.id.btnStartPlay,true);
  397.                 enableButton(R.id.btnStopPlay,false);
  398.                 enableButton(R.id.btnStartRec,true);
  399.                 break;
  400.             }
  401.             }
  402.         }
  403.     };
  404.  
  405.     public void StartPlaying()
  406.     {
  407.         int minBufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
  408.         Log.d(TAG, "===== Value of  minBufferSize : ["+minBufferSize+"]===== ");
  409.         int bufferSize = minBufferSize;
  410.         AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO,
  411.                 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
  412.  
  413.         int i = 0;
  414.         byte[] temp = new byte[bufferSize];
  415.         try {
  416.             FileInputStream fin = new FileInputStream("/sdcard/AudioRecorder/audiofile.wav");
  417.             Log.d(TAG, "===== opening file : /sdcard/AudioRecorder/audiofile.wav ===== ");
  418.  
  419.             DataInputStream dis = new DataInputStream(fin);
  420.  
  421.             at.play();
  422.             while((i = dis.read(temp, 0, bufferSize)) > -1){
  423.                 at.write(temp, 0, i);
  424.                 //Log.d(TAG, "===== Playing Audio ===== ");
  425.             }
  426.             Log.d(TAG, "===== Playing Audio Completed ===== ");
  427.             at.stop();
  428.             at.release();
  429.             dis.close();
  430.             fin.close();
  431.  
  432.         } catch (FileNotFoundException e) {
  433.             // TODO
  434.             e.printStackTrace();
  435.         } catch (IOException e) {
  436.             // TODO
  437.             e.printStackTrace();
  438.         }      
  439.     }
  440.    
  441.     @Override
  442.     public boolean onCreateOptionsMenu(Menu menu) {
  443.  
  444.         // Inflate the menu; this adds items to the action bar if it is present.
  445.         getMenuInflater().inflate(R.menu.buffer_main, menu);
  446.         return true;
  447.     }
  448.  
  449.     @Override
  450.     public boolean onOptionsItemSelected(MenuItem item) {
  451.         // Handle action bar item clicks here. The action bar will
  452.         // automatically handle clicks on the Home/Up button, so long
  453.         // as you specify a parent activity in AndroidManifest.xml.
  454.         int id = item.getItemId();
  455.         if (id == R.id.action_settings) {
  456.             return true;
  457.         }
  458.         return super.onOptionsItemSelected(item);
  459.     }
  460.  
  461.     /**
  462.      * A placeholder fragment containing a simple view.
  463.      */
  464.     public static class PlaceholderFragment extends Fragment {
  465.  
  466.         public PlaceholderFragment() {
  467.         }
  468.  
  469.         @Override
  470.         public View onCreateView(LayoutInflater inflater, ViewGroup container,
  471.                 Bundle savedInstanceState) {
  472.             View rootView = inflater.inflate(R.layout.fragment_buffer_main,
  473.                     container, false);
  474.             return rootView;
  475.         }
  476.     }
  477.  
  478. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement