PageRenderTime 41ms CodeModel.GetById 25ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/ocr/ocrservice/src/com/googlecode/eyesfree/env/Metronome.java

http://eyes-free.googlecode.com/
Java | 210 lines | 117 code | 43 blank | 50 comment | 20 complexity | 58846b041c088f669de651c91104d31c MD5 | raw file
  1/*
  2 * Copyright (C) 2011 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.googlecode.eyesfree.env;
 18
 19import android.content.Context;
 20import android.media.AudioManager;
 21import android.media.SoundPool;
 22import android.os.SystemClock;
 23
 24/**
 25 * A metronome that uses a provided sound resource as its ticking noise.
 26 *
 27 * @author alanv@google.com (Alan Viverette)
 28 */
 29public class Metronome {
 30    private static final int DEFAULT_QUALITY = 0;
 31
 32    private static final int DEFAULT_PRIORITY = 1;
 33
 34    private static final int NO_LOOP = 0;
 35
 36    private Thread mThread;
 37
 38    private SoundPool mSoundPool;
 39
 40    private int mSoundId;
 41
 42    private int mStreamId;
 43
 44    private long mDelayMillis;
 45
 46    private float mLeftVolume;
 47
 48    private float mRightVolume;
 49
 50    private float mPitch;
 51
 52    private boolean mAlive;
 53
 54    private boolean[] mPattern;
 55
 56    private int mPatternIndex;
 57
 58    public Metronome(Context context, int resId) {
 59        mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, DEFAULT_QUALITY);
 60        mSoundId = mSoundPool.load(context, resId, DEFAULT_PRIORITY);
 61
 62        mStreamId = -1;
 63        mDelayMillis = 1000;
 64        mLeftVolume = 0.5f;
 65        mRightVolume = 0.5f;
 66        mPitch = 1.0f;
 67
 68        mPattern = new boolean[] { true };
 69        mPatternIndex = 0;
 70    }
 71
 72    /**
 73     * Starts metronome playback. Does nothing if called again before stop().
 74     */
 75    public synchronized void start() {
 76        if (mThread != null) {
 77            return;
 78        }
 79
 80        mAlive = true;
 81
 82        mThread = new Thread() {
 83            @Override
 84            public void run() {
 85                runAsync();
 86            }
 87        };
 88        mThread.start();
 89    }
 90
 91    private void runAsync() {
 92        long timeElapsed = 0;
 93        long timeLeft;
 94        long time = SystemClock.elapsedRealtime();
 95
 96        while (mAlive) {
 97            timeLeft = mDelayMillis - timeElapsed;
 98
 99            if (timeLeft > 0) {
100                try {
101                    Thread.sleep(timeLeft);
102                } catch (InterruptedException e) {
103                    // Do nothing
104                }
105            }
106
107            timeElapsed += (SystemClock.elapsedRealtime() - time);
108            time = SystemClock.elapsedRealtime();
109
110            if (timeElapsed >= mDelayMillis) {
111                timeElapsed = 0;
112
113                int streamId = -1;
114
115                // Play the sound only if we're supposed to play at this pattern
116                // index
117                if (mPattern[mPatternIndex]) {
118                    streamId = mSoundPool.play(
119                            mSoundId, mLeftVolume, mRightVolume, DEFAULT_PRIORITY, NO_LOOP, mPitch);
120                }
121
122                if (mStreamId >= 0) {
123                    mSoundPool.stop(mStreamId);
124                }
125
126                mStreamId = streamId;
127
128                // Move to next pattern index, looping around if necessary
129                mPatternIndex++;
130                if (mPatternIndex >= mPattern.length) {
131                    mPatternIndex %= mPattern.length;
132                }
133            }
134        }
135    }
136
137    /**
138     * Stops metronome playback. You may call start() after this to resume
139     * playback. Does nothing if called again before start().
140     */
141    public synchronized void stop() {
142        mAlive = false;
143
144        if (mThread != null) {
145            mThread.interrupt();
146            mThread = null;
147        }
148    }
149
150    /**
151     * Sets the delay in milliseconds between metronome clicks.
152     *
153     * @param delayMillis
154     */
155    public void setDelay(long delayMillis) {
156        if (delayMillis <= 10) {
157            delayMillis = 10;
158        }
159
160        mDelayMillis = delayMillis;
161
162        if (mThread != null) {
163            mThread.interrupt();
164        }
165    }
166
167    /**
168     * Sets the volume (within the range of 0.0 to 1.0) of the left and right
169     * channels.
170     *
171     * @param leftChannel
172     * @param rightChannel
173     */
174    public void setVolume(float leftChannel, float rightChannel) {
175        if (leftChannel < 0.0f) {
176            leftChannel = 0.0f;
177        } else if (leftChannel > 1.0f) {
178            leftChannel = 1.0f;
179        }
180
181        if (rightChannel < 0.0f) {
182            rightChannel = 0.0f;
183        } else if (rightChannel > 1.0f) {
184            rightChannel = 1.0f;
185        }
186
187        mLeftVolume = leftChannel;
188        mRightVolume = rightChannel;
189    }
190
191    /**
192     * Sets the relative pitch of the metronome by changing the playback rate. A
193     * pitch of 1.0 is normal, while a pitch of 2.0 plays twice as quickly and a
194     * pitch of 0.5 plays half as quickly.
195     *
196     * @param pitch
197     */
198    public void setPitch(float pitch) {
199        if (pitch < 0.001f) {
200            pitch = 0.001f;
201        }
202
203        mPitch = pitch;
204    }
205
206    public void setPattern(boolean[] pattern) {
207        mPattern = pattern;
208        mPatternIndex = 0;
209    }
210}