Android Open Source - Backyard-Brains-Android-App Recording Saver






From Project

Back to project page Backyard-Brains-Android-App.

License

The source code is released under:

GNU General Public License

If you think the Android project Backyard-Brains-Android-App listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Backyard Brains Android App/*ww  w .jav a2 s  .co  m*/
 * Copyright (C) 2011 Backyard Brains
 * by Nathan Dotz <nate (at) backyardbrains.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.backyardbrains.audio;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;

public class RecordingSaver implements ReceivesAudio {

  public static final String TAG = RecordingSaver.class.getCanonicalName();
  private ByteArrayOutputStream mArrayToRecordTo;
  private BufferedOutputStream bufferedStream;
  private DataOutputStream dataOutputStreamInstance;
  private File bybDirectory;

  public RecordingSaver(String filename) {
    initializeAndCreateFile(filename);
  }

  /**
   * Create a the BackyardBrains directory on the sdcard if it doesn't exist,
   * then set up a file output stream in that directory which we'll use to
   * write to later
   * 
   * @param filename
   */
  private void initializeAndCreateFile(String filename) {

    bybDirectory = createBybDirectory();

    mArrayToRecordTo = new ByteArrayOutputStream();
    try {
      bufferedStream = new BufferedOutputStream(mArrayToRecordTo);
    } catch (Exception e) {
      throw new IllegalStateException("Cannot open file for writing", e);
    }
    dataOutputStreamInstance = new DataOutputStream(bufferedStream);

  }

  /**
   * Create our directory on the SD card
   * 
   * @return the File instance of our directory
   */
  private File createBybDirectory() {
    File BybDirectory = new File(Environment.getExternalStorageDirectory()
        + "/BackyardBrains/");
    BybDirectory.mkdirs();
    return BybDirectory;
  }

  /**
   * Our data comes in big-endian, but we need to write 16-bit PCM in
   * little-endian, so we'll loop through the buffer, reversing bytes as we
   * spit out to the our data output stream.
   */
  @Override
  public void receiveAudio(ByteBuffer audioInfo) {
    ShortBuffer sb = audioInfo.asShortBuffer();
    while (sb.hasRemaining()) {
      try {
        dataOutputStreamInstance
            .writeShort(Short.reverseBytes(sb.get()));
      } catch (IOException e) {
        throw new IllegalStateException(
            "Could not write bytes out to file");
      }
    }
  }

  /**
   * close the stream that our data is being sent to, then convert the array
   * we've been caching to in RAM to a wave file after it's done writing PCM
   * to the disk.
   */
  public void finishRecording() {
    try {
      bufferedStream.close();
      new ConvertToWavefile().execute(mArrayToRecordTo);
    } catch (IOException e) {
      throw new IllegalStateException("Cannot close buffered writer.");
    }
  }

  private class ConvertToWavefile extends
      AsyncTask<ByteArrayOutputStream, Void, String> {

    /**
     * Takes a ByteArrayOutputStream provided to our execute() method, and
     * add a PCM WAVE header and write it out to the disk.
     * 
     * @param byteData
     * @return
     * @throws IOException
     */
    private String convertToWave(ByteArrayOutputStream byteData)
        throws IOException {
      byte[] mFileToRecordTo2 = byteData.toByteArray();
      File outputFile = new File(bybDirectory, new SimpleDateFormat(
          "d_MMM_yyyy_HH_mm_s_a").format(new Date(System
          .currentTimeMillis()))
          + ".wav");
      FileOutputStream out = new FileOutputStream(outputFile);
      DataOutputStream datastream = new DataOutputStream(out);

      int mSampleRate = 44100;
      int mChannels = 1;
      int mBitsPerSample = 16;

      long subchunk2size = mFileToRecordTo2.length / 2 // # of samples
          * mChannels * (mBitsPerSample / 2);

      long chunksize = subchunk2size + 36;
      int byteRate = mSampleRate * mChannels * mBitsPerSample / 8;

      datastream.writeBytes("RIFF");
      datastream.writeInt(Integer.reverseBytes((int) chunksize));
      datastream.writeBytes("WAVEfmt ");
      datastream.writeInt(Integer.reverseBytes(16));
      datastream.writeShort(Short.reverseBytes((short) 1));
      datastream.writeShort(Short.reverseBytes((short) mChannels));
      datastream.writeInt(Integer.reverseBytes(mSampleRate));
      datastream.writeInt(Integer.reverseBytes(byteRate));
      datastream.writeShort(Short.reverseBytes((short) (mChannels
          * mBitsPerSample / 8))); // block align
      datastream.writeShort(Short.reverseBytes((short) mBitsPerSample));
      datastream.writeBytes("data");
      datastream.writeInt(Integer.reverseBytes((int) subchunk2size));

      datastream.write(mFileToRecordTo2);
      out.close();
      datastream.close();
      return outputFile.getName();
    }

    /**
     * Whip through the list of ByteArrays (currently only the one) and
     * convert each to proper WAV formats
     */
    @Override
    protected String doInBackground(ByteArrayOutputStream... params) {
      StringBuilder s = new StringBuilder();
      for (ByteArrayOutputStream f : params) {
        try {
          String writtenFile = convertToWave(f);
          s.append(" - " + writtenFile);
          // f.delete();
          // f = null;
        } catch (IOException e) {
          Log.e(TAG, "Couldn't write wav file ");
          e.printStackTrace();
          f = null;
        }
      }
      Log.d(getClass().getCanonicalName(),
          "Finished writing out " + s.toString());
      return "Finished writing file to SD Card" + s.toString();
    }

  }

}




Java Source Code List

com.backyardbrains.BackyardAndroidActivity.java
com.backyardbrains.BackyardBrainsApplication.java
com.backyardbrains.BackyardBrainsConfigurationActivity.java
com.backyardbrains.FileListActivity.java
com.backyardbrains.TriggerActivity.java
com.backyardbrains.audio.AudioService.java
com.backyardbrains.audio.MicListener.java
com.backyardbrains.audio.ReceivesAudio.java
com.backyardbrains.audio.RecordingSaver.java
com.backyardbrains.audio.RingBuffer.java
com.backyardbrains.audio.TriggerAverager.java
com.backyardbrains.drawing.ContinuousGLSurfaceView.java
com.backyardbrains.drawing.OscilloscopeRenderer.java
com.backyardbrains.drawing.ThresholdGlSurfaceView.java
com.backyardbrains.drawing.ThresholdRenderer.java
com.backyardbrains.view.ScaleListener.java
com.backyardbrains.view.TwoDimensionScaleGestureDetector.java
com.backyardbrains.view.UIFactory.java