1/*
2 * Copyright (C) 2008-2009 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.inputmethod.voice;
18
19import android.graphics.Bitmap;
20import android.graphics.Canvas;
21import android.graphics.Paint;
22
23import java.io.ByteArrayOutputStream;
24import java.nio.ByteBuffer;
25import java.nio.ByteOrder;
26import java.nio.ShortBuffer;
27
28/**
29 * Utility class to draw a waveform into a bitmap, given a byte array
30 * that represents the waveform as a sequence of 16-bit integers.
31 * Adapted from RecognitionActivity.java.
32 */
33public class WaveformImage {
34    private static final int SAMPLING_RATE = 8000;
35
36    private WaveformImage() {}
37
38    public static Bitmap drawWaveform(
39        ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) {
40        final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
41        final Canvas c = new Canvas(b);
42        final Paint paint = new Paint();
43        paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA
44        paint.setAntiAlias(true);
45        paint.setStrokeWidth(0);
46
47        final ShortBuffer buf = ByteBuffer
48            .wrap(waveBuffer.toByteArray())
49            .order(ByteOrder.nativeOrder())
50            .asShortBuffer();
51        buf.position(0);
52
53        final int numSamples = waveBuffer.size() / 2;
54        final int delay = (SAMPLING_RATE * 100 / 1000);
55        int endIndex = end / 2 + delay;
56        if (end == 0 || endIndex >= numSamples) {
57            endIndex = numSamples;
58        }
59        int index = start / 2 - delay;
60        if (index < 0) {
61            index = 0;
62        }
63        final int size = endIndex - index;
64        int numSamplePerPixel = 32;
65        int delta = size / (numSamplePerPixel * w);
66        if (delta == 0) {
67            numSamplePerPixel = size / w;
68            delta = 1;
69        }
70
71        final float scale = 3.5f / 65536.0f;
72        // do one less column to make sure we won't read past
73        // the buffer.
74        try {
75            for (int i = 0; i < w - 1 ; i++) {
76                final float x = i;
77                for (int j = 0; j < numSamplePerPixel; j++) {
78                    final short s = buf.get(index);
79                    final float y = (h / 2) - (s * h * scale);
80                    c.drawPoint(x, y, paint);
81                    index += delta;
82                }
83            }
84        } catch (IndexOutOfBoundsException e) {
85            // this can happen, but we don't care
86        }
87
88        return b;
89    }
90}
91