ee.ioc.phon.android.speak.Utils.java Source code

Java tutorial

Introduction

Here is the source code for ee.ioc.phon.android.speak.Utils.java

Source

/*
 * Copyright 2011-2014, Institute of Cybernetics at Tallinn University of Technology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ee.ioc.phon.android.speak;

import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import org.apache.commons.io.FileUtils;

/**
 * <p>Some useful static methods.</p>
 *
 * @author Kaarel Kaljurand
 */
public class Utils {

    private Utils() {
    }

    public static PendingIntent getPendingIntent(Bundle extras) {
        Parcelable extraResultsPendingIntentAsParceable = extras
                .getParcelable(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT);
        if (extraResultsPendingIntentAsParceable != null) {
            //PendingIntent.readPendingIntentOrNullFromParcel(mExtraResultsPendingIntent);
            if (extraResultsPendingIntentAsParceable instanceof PendingIntent) {
                return (PendingIntent) extraResultsPendingIntentAsParceable;
            }
        }
        return null;
    }

    /**
     * TODO: should we immediately return null if id = 0?
     */
    public static String idToValue(Context context, Uri contentUri, String columnId, String columnUrl, long id) {
        String value = null;
        Cursor c = context.getContentResolver().query(contentUri, new String[] { columnUrl }, columnId + "= ?",
                new String[] { String.valueOf(id) }, null);

        if (c.moveToFirst()) {
            value = c.getString(0);
        }
        c.close();
        return value;
    }

    /**
     * <p>Pretty-prints an integer value which expresses a size
     * of some data.</p>
     */
    public static String getSizeAsString(int size) {
        if (size > FileUtils.ONE_MB) {
            return String.format("%.1fMB", (float) size / FileUtils.ONE_MB);
        }

        if (size > FileUtils.ONE_KB) {
            return String.format("%.1fkB", (float) size / FileUtils.ONE_KB);
        }
        return size + "b";
    }

    /**
     * <p>Returns a bitmap that visualizes the given waveform (byte array),
     * i.e. a sequence of 16-bit integers.</p>
     *
     * TODO: show to high/low points in other color
     * TODO: show end pause data with another color
     */
    public static Bitmap drawWaveform(byte[] waveBuffer, int w, int h, int start, int end) {
        final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        final Canvas c = new Canvas(b);
        final Paint paint = new Paint();
        paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA
        paint.setAntiAlias(true);
        paint.setStrokeWidth(0);

        final Paint redPaint = new Paint();
        redPaint.setColor(0xFF000080);
        redPaint.setAntiAlias(true);
        redPaint.setStrokeWidth(0);

        final ShortBuffer buf = ByteBuffer.wrap(waveBuffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
        buf.position(0);

        final int numSamples = waveBuffer.length / 2;
        //final int delay = (SAMPLING_RATE * 100 / 1000);
        final int delay = 0;
        int endIndex = end / 2 + delay;
        if (end == 0 || endIndex >= numSamples) {
            endIndex = numSamples;
        }
        int index = start / 2 - delay;
        if (index < 0) {
            index = 0;
        }
        final int size = endIndex - index;
        int numSamplePerPixel = 32;
        int delta = size / (numSamplePerPixel * w);
        if (delta == 0) {
            numSamplePerPixel = size / w;
            delta = 1;
        }

        final float scale = 3.5f / 65536.0f;
        // do one less column to make sure we won't read past
        // the buffer.
        try {
            for (int i = 0; i < w - 1; i++) {
                final float x = i;
                for (int j = 0; j < numSamplePerPixel; j++) {
                    final short s = buf.get(index);
                    final float y = (h / 2) - (s * h * scale);
                    if (s > Short.MAX_VALUE - 10 || s < Short.MIN_VALUE + 10) {
                        // TODO: make it work
                        c.drawPoint(x, y, redPaint);
                    } else {
                        c.drawPoint(x, y, paint);
                    }
                    index += delta;
                }
            }
        } catch (IndexOutOfBoundsException e) {
            // this can happen, but we don't care
        }

        return b;
    }

    static Bitmap bytesToBitmap(byte[] byteBuffer, int w, int h, int startPosition, int endPosition) {
        final ShortBuffer waveBuffer = ByteBuffer.wrap(byteBuffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
        final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        final Canvas c = new Canvas(b);
        final Paint paint = new Paint();
        paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setAlpha(80);

        final PathEffect effect = new CornerPathEffect(3);
        paint.setPathEffect(effect);

        final int numSamples = waveBuffer.remaining();
        int endIndex;
        if (endPosition == 0) {
            endIndex = numSamples;
        } else {
            endIndex = Math.min(endPosition, numSamples);
        }

        int startIndex = startPosition - 2000; // include 250ms before speech
        if (startIndex < 0) {
            startIndex = 0;
        }
        final int numSamplePerWave = 200; // 8KHz 25ms = 200 samples
        final float scale = 10.0f / 65536.0f;

        final int count = (endIndex - startIndex) / numSamplePerWave;
        final float deltaX = 1.0f * w / count;
        int yMax = h / 2;
        Path path = new Path();
        c.translate(0, yMax);
        float x = 0;
        path.moveTo(x, 0);
        for (int i = 0; i < count; i++) {
            final int avabs = getAverageAbs(waveBuffer, startIndex, i, numSamplePerWave);
            int sign = ((i & 01) == 0) ? -1 : 1;
            final float y = Math.min(yMax, avabs * h * scale) * sign;
            path.lineTo(x, y);
            x += deltaX;
            path.lineTo(x, y);
        }
        if (deltaX > 4) {
            paint.setStrokeWidth(2);
        } else {
            paint.setStrokeWidth(Math.max(0, (int) (deltaX - .05)));
        }
        c.drawPath(path, paint);
        return b;
    }

    /**
     * @return an average abs of the specified buffer.
     */
    private static int getAverageAbs(ShortBuffer buffer, int start, int i, int npw) {
        int from = start + i * npw;
        int end = from + npw;
        int total = 0;
        for (int x = from; x < end; x++) {
            total += Math.abs(buffer.get(x));
        }
        return total / npw;
    }

    public static AlertDialog getYesNoDialog(Context context, String confirmationMessage, final Executable ex) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage(confirmationMessage).setCancelable(false)
                .setPositiveButton(context.getString(R.string.buttonYes), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        ex.execute();
                    }
                }).setNegativeButton(context.getString(R.string.buttonNo), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
        return builder.create();
    }

    public static AlertDialog getTextEntryDialog(Context context, String title, String initialText,
            final ExecutableString ex) {
        final View textEntryView = LayoutInflater.from(context).inflate(R.layout.alert_dialog_text_entry, null);
        final EditText et = (EditText) textEntryView.findViewById(R.id.url_edit);
        et.setText(initialText);
        return new AlertDialog.Builder(context).setTitle(title).setView(textEntryView)
                .setPositiveButton(R.string.buttonOk, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        ex.execute(et.getText().toString());
                    }
                }).setNegativeButton(R.string.buttonCancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        dialog.cancel();
                    }
                }).create();
    }

    public static String getVersionName(Context c) {
        PackageInfo info = getPackageInfo(c);
        if (info == null) {
            return "?.?.?";
        }
        return info.versionName;
    }

    public static Intent getAppIntent(Context c, String packageName) {
        PackageManager pm = c.getPackageManager();
        return pm.getLaunchIntentForPackage(packageName);
    }

    private static PackageInfo getPackageInfo(Context c) {
        PackageManager manager = c.getPackageManager();
        try {
            return manager.getPackageInfo(c.getPackageName(), 0);
        } catch (NameNotFoundException e) {
            Log.e("Couldn't find package information in PackageManager: " + e);
        }
        return null;
    }

    public static String chooseValue(String firstChoice, String secondChoice) {
        if (firstChoice == null) {
            return secondChoice;
        }
        return firstChoice;
    }

    public static String chooseValue(String firstChoice, String secondChoice, String thirdChoice) {
        String choice = chooseValue(firstChoice, secondChoice);
        if (choice == null) {
            return thirdChoice;
        }
        return choice;
    }

    public static String getUniqueId(SharedPreferences settings) {
        String id = settings.getString("id", null);
        if (id == null) {
            id = UUID.randomUUID().toString();
            SharedPreferences.Editor editor = settings.edit();
            editor.putString("id", id);
            editor.commit();
        }
        return id;
    }

    public static List<String> ppBundle(Bundle bundle) {
        return ppBundle("/", bundle);
    }

    private static List<String> ppBundle(String bundleName, Bundle bundle) {
        List<String> strings = new ArrayList<String>();
        for (String key : bundle.keySet()) {
            Object value = bundle.get(key);
            String name = bundleName + key;
            if (value instanceof Bundle) {
                strings.addAll(ppBundle(name + "/", (Bundle) value));
            } else {
                if (value instanceof Object[]) {
                    strings.add(name + ": " + Arrays.toString((Object[]) value));
                } else if (value instanceof float[]) {
                    strings.add(name + ": " + Arrays.toString((float[]) value));
                } else {
                    strings.add(name + ": " + value);
                }
            }
        }
        return strings;
    }

    /**
     * <p>Traverses the given bundle looking for the given key. The search also
     * looks into embedded bundles and thus differs from {@code Bundle.get(String)}.
     * Returns the first found entry as an object. If the given bundle does not
     * contain the given key then returns {@code null}.</p>
     *
     * @param bundle bundle (e.g. intent extras)
     * @param key key of a bundle entry (possibly in an embedded bundle)
     * @return first matching key's value
     */
    public static Object getBundleValue(Bundle bundle, String key) {
        for (String k : bundle.keySet()) {
            Object value = bundle.get(k);
            if (value instanceof Bundle) {
                Object deepValue = getBundleValue((Bundle) value, key);
                if (deepValue != null) {
                    return deepValue;
                }
            } else if (key.equals(k)) {
                return value;
            }
        }
        return null;
    }

    public static String makeUserAgentComment(String tag, String versionName, String caller) {
        return tag + "/" + versionName + "; " + Build.MANUFACTURER + "/" + Build.DEVICE + "/" + Build.DISPLAY + "; "
                + caller;
    }

    public static String getPrefString(SharedPreferences prefs, Resources res, int key, int defaultValue) {
        return prefs.getString(res.getString(key), res.getString(defaultValue));
    }

    public static String getPrefString(SharedPreferences prefs, Resources res, int key) {
        return prefs.getString(res.getString(key), null);
    }

    public static boolean getPrefBoolean(SharedPreferences prefs, Resources res, int key, int defaultValue) {
        return prefs.getBoolean(res.getString(key), res.getBoolean(defaultValue));
    }
}