Android Open Source - MicDroid Audio Helper






From Project

Back to project page MicDroid.

License

The source code is released under:

GNU General Public License

If you think the Android project MicDroid 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

/* AudioHelper.java
//ww w . jav a2  s .c o m
   Copyright (c) 2010 Ethan Chen

   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 2 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, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.intervigil.micdroid.helper;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder.AudioSource;
import android.util.Log;

import com.intervigil.micdroid.Constants;
import com.intervigil.micdroid.R;

public class AudioHelper {
    private static final String TAG_AUDIOHELPER = "AudioHelper";
    private static final String MANUFACTURER_SAMSUNG = "samsung";
    private static final String DEVICE_ID_GALAXY_S = "gt-i9000";
    private static final String DEVICE_ID_CAPTIVATE = "sgh-i897";
    private static final String DEVICE_ID_VIBRANT = "sgh-t959";
    private static final String DEVICE_ID_FASCINATE = "sch-i500";
    private static final String DEVICE_ID_EPIC = "sph-d700";
    private static final String DEVICE_ID_MESMERIZE = "sch-i500";

    /**
     * Convert Android AudioFormat.CHANNEL_CONFIGURATION constants to integers
     * 
     * @param androidChannels
     *            Android AudioFormat constant
     */
    public static int getChannelConfig(int androidChannels) {
        switch (androidChannels) {
        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
            return 1;
        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
            return 2;
        default:
            return 1;
        }
    }

    /**
     * Convert Android AudioFormat.ENCODING_PCM constants to integers
     * 
     * @param androidEncoding
     *            Android AudioFormat constant
     */
    public static int getPcmEncoding(int androidEncoding) {
        switch (androidEncoding) {
        case AudioFormat.ENCODING_PCM_8BIT:
            return 8;
        case AudioFormat.ENCODING_PCM_16BIT:
            return 16;
        default:
            return 8;
        }
    }

    /**
     * Convert integers to AudioFormat.CHANNEL_CONFIGURATION constants
     * 
     * @param numChannels
     *            number of channels, typically 1 or 2
     */
    public static int getAndroidChannelConfig(int numChannels) {
        switch (numChannels) {
        case 1:
            return AudioFormat.CHANNEL_CONFIGURATION_MONO;
        case 2:
            return AudioFormat.CHANNEL_CONFIGURATION_STEREO;
        default:
            return AudioFormat.CHANNEL_CONFIGURATION_DEFAULT;
        }
    }

    /**
     * Convert integers to AudioFormat.ENCODING_PCM constants
     * 
     * @param bitsPerSample
     *            bits in a sample of audio, typically 8 or 16
     */
    public static int getAndroidPcmEncoding(int bitsPerSample) {
        switch (bitsPerSample) {
        case 8:
            return AudioFormat.ENCODING_PCM_8BIT;
        case 16:
            return AudioFormat.ENCODING_PCM_16BIT;
        default:
            return AudioFormat.ENCODING_DEFAULT;
        }
    }

    /**
     * Gets an AudioTrack object using the current playback settings
     * 
     * @param context
     *            Context which we are getting recorder for
     */
    public static AudioTrack getPlayer(Context context)
            throws IllegalArgumentException {
        AudioTrack player = null;
        int sampleRate = PreferenceHelper.getSampleRate(context);
        int bufferSizeAdjuster = PreferenceHelper
                .getBufferSizeAdjuster(context);

        Log.i(TAG_AUDIOHELPER,
                String.format("AudioTrack initialized with saved configuration! sample rate: %d, buffer adjuster: %d",
                        sampleRate, bufferSizeAdjuster));

        int bufferSize = AudioTrack.getMinBufferSize(sampleRate,
                Constants.DEFAULT_CHANNEL_CONFIG, Constants.DEFAULT_PCM_FORMAT)
                * bufferSizeAdjuster;

        player = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                Constants.DEFAULT_CHANNEL_CONFIG, Constants.DEFAULT_PCM_FORMAT,
                bufferSize, AudioTrack.MODE_STREAM);

        if (player.getState() != AudioTrack.STATE_INITIALIZED) {
            throw new IllegalArgumentException(
                    String.format("unable to initialize AudioTrack instance, sample rate: %d, channels: %d, buffer: %d",
                            sampleRate, Constants.DEFAULT_CHANNEL_CONFIG, bufferSize));
        }

        return player;
    }

    /**
     * Gets the validity of the current recorder settings, particularly sample
     * rate; This function wraps getRecorderBufferSize(Context)
     * 
     * @param context
     *            Context which we are getting recorder information about
     */
    public static boolean isValidRecorderConfiguration(Context context) {
        return getRecorderBufferSize(context) != AudioRecord.ERROR_BAD_VALUE;
    }

    /**
     * Gets the buffer size needed for the current recorder settings This
     * function wraps AudioRecord.getMinBufferSize(SampleRate, ChannelConfig,
     * PcmFormat) which means this function can return
     * AudioRecord.ERROR_BAD_VALUE for invalid settings or AudioRecord.ERROR
     * when the system is unable to query hardware for proper settings
     * 
     * @param context
     *            Context which we are getting recorder information about
     */
    public static int getRecorderBufferSize(Context context) {
        int bufferSize = 0;
        int sampleRate = PreferenceHelper.getSampleRate(context);

        if (sampleRate > 0) {
            bufferSize = AudioRecord.getMinBufferSize(sampleRate,
                    Constants.DEFAULT_CHANNEL_CONFIG,
                    Constants.DEFAULT_PCM_FORMAT);
        }
        return bufferSize;
    }

    /**
     * Gets an AudioRecord object using the current recording settings
     * 
     * @param context
     *            Context which we are getting recorder for
     */
    public static AudioRecord getRecorder(Context context)
            throws IllegalArgumentException {
        AudioRecord recorder = null;
        int sampleRate = PreferenceHelper.getSampleRate(context);
        int bufferSize = PreferenceHelper.getBufferSize(context);
        int bufferSizeAdjuster = PreferenceHelper.getBufferSizeAdjuster(context);
        int audioSource = AudioSource.MIC;

        Log.i(TAG_AUDIOHELPER,
                String.format("AudioRecord initialized with saved configuration! sample rate: %d, buffer: %d, buffer adjuster: %d",
                        sampleRate, bufferSize, bufferSizeAdjuster));

        recorder = new AudioRecord(audioSource, sampleRate,
                Constants.DEFAULT_CHANNEL_CONFIG, Constants.DEFAULT_PCM_FORMAT,
                bufferSize * bufferSizeAdjuster);

        if (recorder.getState() != AudioRecord.STATE_INITIALIZED) {
            throw new IllegalArgumentException(
                    String.format("unable to initialize AudioRecord instance, sample rate: %d, channels: %d, buffer: %d",
                            sampleRate, Constants.DEFAULT_CHANNEL_CONFIG, bufferSize));
        }

        return recorder;
    }

    /**
     * Attempts to autoconfigure current Context's sample rate, buffer size,
     * or buffer size adjuster . Will show a pop-up warning if configuration
     * failed to initialize an AudioRecord instance.
     * 
     * @param context
     *            Context which we are attempting to configure
     */
    public static void configureRecorder(Context context) {
        AudioRecord rec = null;
        int sampleRate = PreferenceHelper.getSampleRate(context);
        int bufferSize = PreferenceHelper.getBufferSize(context);
        int bufferSizeAdjuster = PreferenceHelper.getBufferSizeAdjuster(context);

        if (sampleRate < 0 || bufferSize < 0 || bufferSizeAdjuster < 0) {
            if (AudioHelper.isSamsungGalaxyS()) {
                // bypass checking, go with defaults
                bufferSize = 6144;
                bufferSizeAdjuster = 1;
                sampleRate = Constants.SAMPLE_RATE_22KHZ;
                Log.i(TAG_AUDIOHELPER,
                        String.format("AudioRecord initially configured! sample rate: %d, buffer size: %d, buffer size adjuster: %d",
                                sampleRate, bufferSize, bufferSizeAdjuster));
                PreferenceHelper.setSampleRate(context, sampleRate);
                PreferenceHelper.setBufferSize(context, bufferSize);
                PreferenceHelper.setBufferSizeAdjuster(context, bufferSizeAdjuster);
                return;
            }

            if (bufferSizeAdjuster < 1) {
                // clamp buffer size adjuster to minimum of 1
                bufferSizeAdjuster = 1;
            }

            // try a new sample rates until we find one that works
            do {
                switch (sampleRate) {
                    case -1:
                        // set the default to 22050Hz, so slower devices perform
                        // better
                        sampleRate = Constants.SAMPLE_RATE_22KHZ;
                        break;
                    case Constants.SAMPLE_RATE_44KHZ:
                        sampleRate = Constants.SAMPLE_RATE_22KHZ;
                        break;
                    case Constants.SAMPLE_RATE_22KHZ:
                        sampleRate = Constants.SAMPLE_RATE_11KHZ;
                        break;
                    case Constants.SAMPLE_RATE_11KHZ:
                        sampleRate = Constants.SAMPLE_RATE_8KHZ;
                        break;
                    default:
                        // start the loop over again with a larger buffer size
                        bufferSizeAdjuster *= 2;
                        sampleRate = Constants.SAMPLE_RATE_22KHZ;
                }

                bufferSize = AudioRecord.getMinBufferSize(
                        sampleRate,
                        Constants.DEFAULT_CHANNEL_CONFIG,
                        Constants.DEFAULT_PCM_FORMAT);
                if (bufferSize != AudioRecord.ERROR && bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                    if (bufferSize <= 4096) {
                        bufferSize = 4096 * 3/2;
                    }
                    rec = new AudioRecord(
                            AudioSource.MIC,
                            sampleRate,
                            Constants.DEFAULT_CHANNEL_CONFIG,
                            Constants.DEFAULT_PCM_FORMAT,
                            bufferSize * bufferSizeAdjuster);

                    if (rec != null && rec.getState() == AudioRecord.STATE_INITIALIZED) {
                        rec.release();
                        rec = null;
                        Log.i(TAG_AUDIOHELPER,
                                String.format("AudioRecord initially configured! sample rate: %d, buffer size: %d, buffer size adjuster: %d",
                                        sampleRate, bufferSize, bufferSizeAdjuster));
                        PreferenceHelper.setSampleRate(context, sampleRate);
                        PreferenceHelper.setBufferSize(context, bufferSize);
                        PreferenceHelper.setBufferSizeAdjuster(context, bufferSizeAdjuster);
                        return;
                    }
                    if (rec != null) {
                        rec.release();
                        rec = null;
                    }
                }
            } while (bufferSizeAdjuster < Constants.DEFAULT_BUFFER_LIMIT);

            // failure to configure!
            DialogHelper.showWarning(context,
                    R.string.unable_to_configure_audio_title,
                    R.string.unable_to_configure_audio_warning);
        }
    }

    /**
     * Tries to figure out if the current phone is Galaxy S based, since it has
     * recording issues This is pretty nasty since we are string matching, but
     * unless I can get a better way to do it...
     * 
     * @param
     */
    public static boolean isSamsungGalaxyS() {
        String manufacturer = android.os.Build.MANUFACTURER.toLowerCase();
        String model = android.os.Build.MODEL.toLowerCase();
        String device = android.os.Build.DEVICE.toLowerCase();
        Log.i(TAG_AUDIOHELPER, String.format(
                "manufacturer: %s, model: %s, device: %s", manufacturer, model, device));

        if (manufacturer.equals(MANUFACTURER_SAMSUNG)) {
            if (device.equals(DEVICE_ID_GALAXY_S)) {
                Log.i(TAG_AUDIOHELPER, "Samsung Galaxy S detected");
                return true;
            }

            if (device.equals(DEVICE_ID_CAPTIVATE)) {
                Log.i(TAG_AUDIOHELPER, "ATT, Samsung Captivate detected");
                return true;
            }

            if (device.equals(DEVICE_ID_VIBRANT)) {
                Log.i(TAG_AUDIOHELPER, "T-Mobile US, Samsung Vibrant detected");
                return true;
            }

            if (device.equals(DEVICE_ID_EPIC)) {
                Log.i(TAG_AUDIOHELPER, "Sprint, Samsung Epic 4G detected");
                return true;
            }

            if (device.equals(DEVICE_ID_FASCINATE)) {
                Log.i(TAG_AUDIOHELPER, "Verizon, Samsung Fascinate detected");
                return true;
            }

            if (device.equals(DEVICE_ID_MESMERIZE)) {
                Log.i(TAG_AUDIOHELPER, "Samsung Mesmerize detected");
                return true;
            }
        }
        return false;
    }
}




Java Source Code List

com.intervigil.micdroid.AutotalentTask.java
com.intervigil.micdroid.Constants.java
com.intervigil.micdroid.FileNameEntry.java
com.intervigil.micdroid.InstrumentalLibrary.java
com.intervigil.micdroid.MicApplication.java
com.intervigil.micdroid.Mic.java
com.intervigil.micdroid.Preferences.java
com.intervigil.micdroid.RecordingLibrary.java
com.intervigil.micdroid.RecordingPlayer.java
com.intervigil.micdroid.SeekableMediaPlayer.java
com.intervigil.micdroid.StartupDialog.java
com.intervigil.micdroid.Timer.java
com.intervigil.micdroid.helper.AdHelper.java
com.intervigil.micdroid.helper.ApplicationHelper.java
com.intervigil.micdroid.helper.AudioHelper.java
com.intervigil.micdroid.helper.DialogHelper.java
com.intervigil.micdroid.helper.HeadsetHelper.java
com.intervigil.micdroid.helper.MediaStoreHelper.java
com.intervigil.micdroid.helper.PreferenceHelper.java
com.intervigil.micdroid.helper.RecordingOptionsHelper.java
com.intervigil.micdroid.helper.UpdateHelper.java
com.intervigil.micdroid.interfaces.DependentTask.java
com.intervigil.micdroid.interfaces.Recorder.java
com.intervigil.micdroid.model.Recording.java
com.intervigil.micdroid.recorder.JNIRecorder.java
com.intervigil.micdroid.recorder.SimpleRecorder.java
com.intervigil.micdroid.recorder.SipdroidRecorder.java
org.openintents.intents.FileManagerIntents.java