Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't play a reversed .wav file with MediaPlayer

Tags:

java

android

wav

I've created an app that records audio, saves the sample to the sd card then plays it back, using the record and play buttons. I need to reverse this sample. I can do all this and the the reversed sample is saved on the SD card under a different name. The original sample is test.wav and the same sample reversed is save as revFile.wav. when i try play revFile.wav android says it can't play this format.

I've litterally put the sample in an array then reversed the contents, something is telling me that there could be header info at the start of the sample that needs striping first, any ideas. thanks.

Here's what i have so far.

public class recorder extends Activity  {
    MediaRecorder myRecorder = null;
    DataInputStream dis = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void onClickPlay(View v){
        Log.v("onClickplay", "play clicked");

        try{
            MediaPlayer mp = new MediaPlayer();
            mp.setDataSource(Environment.getExternalStorageDirectory().getPath() + "/test.wav");
            mp.prepare();
            mp.start();
        } catch(Exception e3) {
            e3.printStackTrace();
        }
        TextView text = (TextView)findViewById(R.id.TextView01);
        text.setText("playing");
    }

    public void onClickRecord(View v){
        Log.v("onClickRecord", "record clicked");

        File path = Environment.getExternalStorageDirectory();
        Log.v("file path", ""+path.getAbsolutePath());

        File file = new File(path, "test.wav");
        if(file.exists()){
            file.delete();
        }
        path.mkdirs();
        Log.v("file path", ""+file.getAbsolutePath());
        myRecorder = new MediaRecorder();
        myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        myRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        myRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        myRecorder.setOutputFile(file.getAbsolutePath()); 
        Log.i("myrecorder", "about to prepare recording");
        try{
            myRecorder.prepare();
        } catch(Exception e) {
            e.printStackTrace();
        }

        Log.i("myrecorder", "prepared");
        myRecorder.start();   // Recording is now started
        Log.i("myrecorder", "recording");
        TextView text = (TextView)findViewById(R.id.TextView01);
        text.setText("recording");
    }

    public void onClickStop(View v){
        Log.v("onClickStop", "stop clicked");

            try{
             myRecorder.stop();
             myRecorder.reset();   // You can reuse the object by going back to setAudioSource() step
             myRecorder.release(); // Now the object cannot be reused
            }catch(Exception e){} 

            TextView text = (TextView)findViewById(R.id.TextView01);
             text.setText("recording stopped");

        }    



public void onClickReverse(View v){
        Log.v("onClickReverse", "reverse clicked");

        File f = Environment.getExternalStorageDirectory();
        String path = f.getAbsolutePath();
        path = path + "/test.wav";
        Log.v("path = ", ""+path);
        Log.v("dir = ", ""+f.getAbsolutePath());
        Log.v("test file exists? = ", ""+f.getAbsolutePath()+"/test.wav");

        File f2 = new File(path);
        Log.v("f2 = ", ""+f2.getAbsolutePath());

        try {
            InputStream is = new FileInputStream(f2);
            BufferedInputStream bis = new BufferedInputStream(is);
            dis = new DataInputStream(bis);
        } catch (Exception e) {
            e.printStackTrace();
        }

        int fileLength = (int)f2.length();
        byte[] buffer = new byte[fileLength];

        /*File reversedFile = Environment.getExternalStorageDirectory();
          File revFile = new File(reversedFile, "reversedFile.wav");
          Log.v("reversedfile path", ""+ revFile.getAbsolutePath());

          if(revFile.exists()){
              revFile.delete();
          }

          reversedFile.mkdirs();
    */

        byte[] byteArray = new byte[fileLength +1];
        Log.v("bytearray size = ", ""+byteArray.length);

        try {
            while(dis.read(buffer) != -1 ) {
                dis.read(buffer);
                Log.v("about to read buffer", "buffer");

                byteArray = buffer;
            }

            Log.v(" buffer size = ", ""+ buffer.length);
        } catch (IOException e) {
            e.printStackTrace();
        }

          byte[] tempArray = new byte[fileLength];

          int j=0;
          for (int i=byteArray.length-1; i >=0; i--) {
              tempArray[ j++ ] = byteArray[i];
          }

          File revPath = Environment.getExternalStorageDirectory();
          Log.v("revpath path", ""+revPath.getAbsolutePath());

          File revFile = new File(revPath, "revFile.wav");
          Log.v("revfile path ", ""+revFile.getAbsolutePath());
          if(revFile.exists()){
              revFile.delete();
          }

          revPath.mkdirs();

          try {
              OutputStream os = new FileOutputStream(revFile);
              BufferedOutputStream bos = new BufferedOutputStream(os);
              DataOutputStream dos = new DataOutputStream(bos);
              Log.v("temparray size = ", ""+ tempArray.length);
              dos.write(tempArray);
              dos.flush();
              dos.close();
          } catch (Exception e) {
              e.printStackTrace();
          }

          try{
              MediaPlayer mp = new MediaPlayer();
              mp.setDataSource(Environment.getExternalStorageDirectory().getPath()
                                                                    +"/revFile.wav");

              mp.prepare();
              mp.start();
         } catch(Exception e3) {
                e3.printStackTrace();
         }
          TextView text = (TextView)findViewById(R.id.TextView01);
           text.setText("playing reversed file");
      }

}// end of onclickrev
like image 647
turtleboy Avatar asked Feb 26 '23 07:02

turtleboy


1 Answers

The WAV file format includes a 44-byte header chunk. Most WAV files consist of this 44 byte header, followed by the actual sample data. So, to reverse a WAV file, you should first copy the 44 byte header from the original file, and then copy the inverted sample data from the original after the header. If you just reverse the byte order of the original entire file, it definitely won't work. It also won't work if you copy the header and then reverse the byte order of the remainder of the file (actually it will sort of work, except what you get will be just noise). You actually need to reverse the frames, where the frame size is dependent on the bytes-per-sample and whether the file is stereo or mono (for example, if the file is stereo and 2 bytes per sample, then each frame is 4 bytes).

Note that not all WAV files are "canonical" like this. WAV files are actually a variant of RIFF files, so technically you need much more complicated code to find the various parts of the header and sample data within the original file. However, most WAV files are just the header followed by the samples (and this will certainly be true if you're recording the audio yourself), in which case you can save yourself a lot of work.

Joe Cullity's link is a good description of the WAV file format.

like image 159
MusiGenesis Avatar answered Mar 06 '23 17:03

MusiGenesis