saurabhmesh17

AudioRecord/AudioTrack-UsingFile27thAug2014

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