SoundPool.java revision f6e43bf29084760b39257b2273e0f04c2815fdc5
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.media;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AndroidRuntimeException;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetFileDescriptor;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Handler;
30f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Looper;
31f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Message;
32f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
33cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks/**
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The SoundPool class manages and plays audio resources for applications.
35cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
36cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>A SoundPool is a collection of samples that can be loaded into memory
37cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * from a resource inside the APK or from a file in the file system. The
38cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * SoundPool library uses the MediaPlayer service to decode the audio
39cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * into a raw 16-bit PCM mono or stereo stream. This allows applications
40cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * to ship with compressed streams without having to suffer the CPU load
41cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * and latency of decompressing during playback.</p>
42cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
43cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>In addition to low-latency playback, SoundPool can also manage the number
44cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * of audio streams being rendered at once. When the SoundPool object is
45cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * constructed, the maxStreams parameter sets the maximum number of streams
46cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * that can be played at a time from this single SoundPool. SoundPool tracks
47cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the number of active streams. If the maximum number of streams is exceeded,
48cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * SoundPool will automatically stop a previously playing stream based first
49cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * on priority and then by age within that priority. Limiting the maximum
50cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * number of streams helps to cap CPU loading and reducing the likelihood that
51cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * audio mixing will impact visuals or UI performance.</p>
52cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
536cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>Sounds can be looped by setting a non-zero loop value. A value of -1
546cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * causes the sound to loop forever. In this case, the application must
556cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * explicitly call the stop() function to stop the sound. Any other non-zero
566cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * value will cause the sound to repeat the specified number of times, e.g.
576cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * a value of 3 causes the sound to play a total of 4 times.</p>
586cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
596cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>The playback rate can also be changed. A playback rate of 1.0 causes
606cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the sound to play at its original frequency (resampled, if necessary,
616cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * to the hardware output frequency). A playback rate of 2.0 causes the
626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * sound to play at twice its original frequency, and a playback rate of
636cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * 0.5 causes it to play at half its original frequency. The playback
646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * rate range is 0.5 to 2.0.</p>
656cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
66cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Priority runs low to high, i.e. higher numbers are higher priority.
67cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * Priority is used when a call to play() would cause the number of active
68cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * streams to exceed the value established by the maxStreams parameter when
69cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the SoundPool was created. In this case, the stream allocator will stop
70cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the lowest priority stream. If there are multiple streams with the same
71cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * low priority, it will choose the oldest stream to stop. In the case
72cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * where the priority of the new stream is lower than all the active
73cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * streams, the new sound will not play and the play() function will return
74cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * a streamID of zero.</p>
75cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
76cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Let's examine a typical use case: A game consists of several levels of
77cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * play. For each level, there is a set of unique sounds that are used only
78cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * by that level. In this case, the game logic should create a new SoundPool
79cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * object when the first level is loaded. The level data itself might contain
80cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the list of sounds to be used by this level. The loading logic iterates
81cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * through the list of sounds calling the appropriate SoundPool.load()
82cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * function. This should typically be done early in the process to allow time
83cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * for decompressing the audio to raw PCM format before they are needed for
84cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * playback.</p>
85cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
86cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Once the sounds are loaded and play has started, the application can
87cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * trigger sounds by calling SoundPool.play(). Playing streams can be
88cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * paused or resumed, and the application can also alter the pitch by
89cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * adjusting the playback rate in real-time for doppler or synthesis
90cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * effects.</p>
91cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
926cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>Note that since streams can be stopped due to resource constraints, the
936cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * streamID is a reference to a particular instance of a stream. If the stream
946cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * is stopped to allow a higher priority stream to play, the stream is no
956cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * longer be valid. However, the application is allowed to call methods on
966cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the streamID without error. This may help simplify program logic since
976cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the application need not concern itself with the stream lifecycle.</p>
986cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
99cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>In our example, when the player has completed the level, the game
100cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * logic should call SoundPool.release() to release all the native resources
101cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * in use and then set the SoundPool reference to null. If the player starts
102cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * another level, a new SoundPool is created, sounds are loaded, and play
103cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * resumes.</p>
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SoundPool
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { System.loadLibrary("soundpool"); }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String TAG = "SoundPool";
110f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private final static boolean DEBUG = false;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeContext; // accessed by native methods
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
114f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private EventHandler mEventHandler;
115f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private OnLoadCompleteListener mOnLoadCompleteListener;
116f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
117f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private final Object mLock;
118f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
119f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    // SoundPool messages
120f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    //
121f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    // must match SoundPool.h
122f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private static final int SAMPLE_LOADED = 1;
123f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
124cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
125cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * Constructor. Constructs a SoundPool object with the following
126cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * characteristics:
127cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
128cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param maxStreams the maximum number of simultaneous streams for this
129cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   SoundPool object
130cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamType the audio stream type as described in AudioManager
131cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   For example, game applications will normally use
132cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   {@link AudioManager#STREAM_MUSIC}.
133cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param srcQuality the sample-rate converter quality. Currently has no
134cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   effect. Use 0 for the default.
135cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a SoundPool object, or null if creation failed
136cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SoundPool(int maxStreams, int streamType, int srcQuality) {
138f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
139f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        // do native setup
140f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if (native_setup(new WeakReference(this), maxStreams, streamType, srcQuality) != 0) {
141f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            throw new RuntimeException("Native setup failed");
142f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
143f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        mLock = new Object();
144f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
145f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        // setup message handler
146f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        Looper looper;
147f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if ((looper = Looper.myLooper()) != null) {
148f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mEventHandler = new EventHandler(this, looper);
149f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        } else if ((looper = Looper.getMainLooper()) != null) {
150f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mEventHandler = new EventHandler(this, looper);
151f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        } else {
152f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mEventHandler = null;
153f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
154f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
157cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
1586cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from the specified path.
1596cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
160cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param path the path to the audio file
1616cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
1626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
163cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
164cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(String path, int priority)
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // pass network streams to player
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (path.startsWith("http:"))
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return _load(path, priority);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // try local path
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int id = 0;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File f = new File(path);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f != null) {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (fd != null) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    id = _load(fd.getFileDescriptor(), 0, f.length(), priority);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fd.close();
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
182d282ac8610f72d964105efefe41120a5340f1ce0Marco Nelissen        } catch (java.io.IOException e) {
183f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            Log.e(TAG, "error loading " + path);
184d282ac8610f72d964105efefe41120a5340f1ce0Marco Nelissen        }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return id;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
188cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
1896cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from the specified APK resource.
190cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
1916cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Note that the extension is dropped. For example, if you want to load
192cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * a sound from the raw resource file "explosion.mp3", you would specify
193cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * "R.raw.explosion" as the resource ID. Note that this means you cannot
194cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * have both an "explosion.wav" and an "explosion.mp3" in the res/raw
1956cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * directory.
196cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
197cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param context the application context
198cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param resId the resource ID
1996cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2006cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
201cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
202cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(Context context, int resId, int priority) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int id = 0;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (afd != null) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id = _load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), priority);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                afd.close();
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (java.io.IOException ex) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "close failed:", ex);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return id;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
217cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2186cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from an asset file descriptor.
219cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
220cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param afd an asset file descriptor
2216cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2226cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
223cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
224cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(AssetFileDescriptor afd, int priority) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (afd != null) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long len = afd.getLength();
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (len < 0) {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new AndroidRuntimeException("no length for fd");
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return _load(afd.getFileDescriptor(), afd.getStartOffset(), len, priority);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
237cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2386cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from a FileDescriptor.
239cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2406cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * This version is useful if you store multiple sounds in a single
241cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * binary. The offset specifies the offset from the start of the file
2426cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * and the length specifies the length of the sound within the file.
243cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
244cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param fd a FileDescriptor object
245cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param offset offset to the start of the sound
246cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param length length of the sound
2476cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2486cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
249cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
250cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(FileDescriptor fd, long offset, long length, int priority) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return _load(fd, offset, length, priority);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int _load(String uri, int priority);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int _load(FileDescriptor fd, long offset, long length, int priority);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2606cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Unload a sound from a sound ID.
261cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Unloads the sound specified by the soundID. This is the value
263cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * returned by the load() function. Returns true if the sound is
2646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * successfully unloaded, false if the sound was already unloaded.
265cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
266cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param soundID a soundID returned by the load() function
267cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return true if just unloaded, false if previously unloaded
268cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final boolean unload(int soundID);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
271cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2726cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Play a sound from a sound ID.
273cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2746cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Play the sound specified by the soundID. This is the value
275cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * returned by the load() function. Returns a non-zero streamID
276cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * if successful, zero if it fails. The streamID can be used to
277cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * further control playback. Note that calling play() may cause
278cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * another sound to stop playing if the maximum number of active
2796cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * streams is exceeded. A loop value of -1 means loop forever,
2806cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * a value of 0 means don't loop, other values indicate the
2816cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * number of repeats, e.g. a value of 1 plays the audio twice.
2826cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * The playback rate allows the application to vary the playback
2836cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * rate (pitch) of the sound. A value of 1.0 means play back at
2846cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * the original frequency. A value of 2.0 means play back twice
2856cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * as fast, and a value of 0.5 means playback at half speed.
286cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
287cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param soundID a soundID returned by the load() function
2886cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param leftVolume left volume value (range = 0.0 to 1.0)
2896cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rightVolume right volume value (range = 0.0 to 1.0)
2906cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority stream priority (0 = lowest priority)
2916cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param loop loop mode (0 = no loop, -1 = loop forever)
2926cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
293cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return non-zero streamID if successful, zero if failed
294cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final int play(int soundID, float leftVolume, float rightVolume,
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int priority, int loop, float rate);
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
298cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2996cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Pause a playback stream.
300cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3016cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Pause the stream specified by the streamID. This is the
302cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * value returned by the play() function. If the stream is
303cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * playing, it will be paused. If the stream is not playing
304cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * (e.g. is stopped or was previously paused), calling this
3056cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * function will have no effect.
306cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
307cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
308cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void pause(int streamID);
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
311cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3126cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Resume a playback stream.
313cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3146cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Resume the stream specified by the streamID. This
315cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is the value returned by the play() function. If the stream
316cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is paused, this will resume playback. If the stream was not
3176cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * previously paused, calling this function will have no effect.
318cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
319cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
320cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void resume(int streamID);
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
323cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3246cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Stop a playback stream.
325cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3266cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Stop the stream specified by the streamID. This
327cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is the value returned by the play() function. If the stream
328cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is playing, it will be stopped. It also releases any native
329cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * resources associated with this stream. If the stream is not
3306cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * playing, it will have no effect.
331cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
332cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
333cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void stop(int streamID);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
336cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3376cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Set stream volume.
338cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3396cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Sets the volume on the stream specified by the streamID.
340cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * This is the value returned by the play() function. The
341cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * value must be in the range of 0.0 to 1.0. If the stream does
3426cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * not exist, it will have no effect.
343cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
344cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
345cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param leftVolume left volume value (range = 0.0 to 1.0)
346cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param rightVolume right volume value (range = 0.0 to 1.0)
347cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setVolume(int streamID,
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float leftVolume, float rightVolume);
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
351cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3526cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change stream priority.
353cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3546cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change the priority of the stream specified by the streamID.
355cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * This is the value returned by the play() function. Affects the
3566cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * order in which streams are re-used to play new sounds. If the
3576cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * stream does not exist, it will have no effect.
358cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
359cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
360cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setPriority(int streamID, int priority);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
363cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Set loop mode.
365cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3666cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change the loop mode. A loop value of -1 means loop forever,
3676cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * a value of 0 means don't loop, other values indicate the
3686cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * number of repeats, e.g. a value of 1 plays the audio twice.
3696cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * If the stream does not exist, it will have no effect.
370cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
371cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
3726cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param loop loop mode (0 = no loop, -1 = loop forever)
373cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setLoop(int streamID, int loop);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3766cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks    /**
3776cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change playback rate.
3786cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
3796cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * The playback rate allows the application to vary the playback
3806cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * rate (pitch) of the sound. A value of 1.0 means playback at
3816cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * the original frequency. A value of 2.0 means playback twice
3826cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * as fast, and a value of 0.5 means playback at half speed.
3836cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * If the stream does not exist, it will have no effect.
3846cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
3856cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param streamID a streamID returned by the play() function
3866cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
3876cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     */
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setRate(int streamID, float rate);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3906cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks    /**
391f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * Interface definition for a callback to be invoked when all the
392f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * sounds are loaded.
393f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     *
394f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * @hide
395f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     */
396f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    public interface OnLoadCompleteListener
397f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
398f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        /**
399f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * Called when a sound has completed loading.
400f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         *
401f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param soundPool SoundPool object from the load() method
402f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param soundPool the sample ID of the sound loaded.
403f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param status the status of the load operation (0 = success)
404f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         */
405f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public void onLoadComplete(SoundPool soundPool, int sampleId, int status);
406f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
407f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
408f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    /**
409f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * Sets the callback hook for the OnLoadCompleteListener.
410f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     *
411f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * @hide
412f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     */
413f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    public void setOnLoadCompleteListener(OnLoadCompleteListener listener)
414f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
415f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        synchronized(mLock) {
416f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mOnLoadCompleteListener = listener;
417f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
418f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
419f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
420f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private class EventHandler extends Handler
421f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
422f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        private SoundPool mSoundPool;
423f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
424f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public EventHandler(SoundPool soundPool, Looper looper) {
425f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            super(looper);
426f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mSoundPool = soundPool;
427f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
428f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
429f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        @Override
430f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public void handleMessage(Message msg) {
431f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            switch(msg.what) {
432f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            case SAMPLE_LOADED:
433f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
434f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                synchronized(mLock) {
435f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                    if (mOnLoadCompleteListener != null) {
436f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                        mOnLoadCompleteListener.onLoadComplete(mSoundPool, msg.arg1, msg.arg2);
437f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                    }
438f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                }
439f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                break;
440f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            default:
441f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                Log.e(TAG, "Unknown message type " + msg.what);
442f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                return;
443f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            }
444f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
445f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
446f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
447f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    // post event from native code to message handler
448f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private static void postEventFromNative(Object weakRef, int msg, int arg1, int arg2, Object obj)
449f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
450f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        SoundPool soundPool = (SoundPool)((WeakReference)weakRef).get();
451f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if (soundPool == null)
452f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            return;
453f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
454f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if (soundPool.mEventHandler != null) {
455f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            Message m = soundPool.mEventHandler.obtainMessage(msg, arg1, arg2, obj);
456f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            soundPool.mEventHandler.sendMessage(m);
457f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
458f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
459f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
460f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    /**
4616cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Release the SoundPool resources.
4626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
4636cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Release all memory and native resources used by the SoundPool
4646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * object. The SoundPool can no longer be used and the reference
4656cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * should be set to null.
4666cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     */
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void release();
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private native final int native_setup(Object weakRef, int maxStreams, int streamType, int srcQuality);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() { release(); }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
473