1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera; 18 19 import android.content.Context; 20 import android.media.AudioManager; 21 import android.media.SoundPool; 22 import android.util.SparseIntArray; 23 24 import com.android.camera.util.ApiHelper; 25 26 /** 27 * Loads a plays custom sounds. For playing system-standard sounds for various 28 * camera actions, please refer to {@link SoundClips}. 29 */ 30 public class SoundPlayer { 31 private final Context mAppContext; 32 private final SoundPool mSoundPool; 33 /** Keeps a mapping from sound resource ID to sound ID */ 34 private final SparseIntArray mResourceToSoundId = new SparseIntArray(); 35 private boolean mIsReleased = false; 36 37 /** 38 * Construct a new sound player. 39 */ SoundPlayer(Context appContext)40 public SoundPlayer(Context appContext) { 41 mAppContext = appContext; 42 final int audioType = getAudioTypeForSoundPool(); 43 mSoundPool = new SoundPool(1 /* max streams */, audioType, 0 /* quality */); 44 } 45 46 /** 47 * Load the sound from a resource. 48 */ loadSound(int resourceId)49 public void loadSound(int resourceId) { 50 int soundId = mSoundPool.load(mAppContext, resourceId, 1/* priority */); 51 mResourceToSoundId.put(resourceId, soundId); 52 } 53 54 /** 55 * Play the sound with the given resource. The resource has to be loaded 56 * before it can be played, otherwise an exception will be thrown. 57 */ play(int resourceId, float volume)58 public void play(int resourceId, float volume) { 59 Integer soundId = mResourceToSoundId.get(resourceId); 60 if (soundId == null) { 61 throw new IllegalStateException("Sound not loaded. Must call #loadSound first."); 62 } 63 mSoundPool.play(soundId, volume, volume, 0 /* priority */, 0 /* loop */, 1 /* rate */); 64 } 65 66 /** 67 * Unload the given sound if it's not needed anymore to release memory. 68 */ unloadSound(int resourceId)69 public void unloadSound(int resourceId) { 70 Integer soundId = mResourceToSoundId.get(resourceId); 71 if (soundId == null) { 72 throw new IllegalStateException("Sound not loaded. Must call #loadSound first."); 73 } 74 mSoundPool.unload(soundId); 75 } 76 77 /** 78 * Call this if you don't need the SoundPlayer anymore. All memory will be 79 * released and the object cannot be re-used. 80 */ release()81 public void release() { 82 mIsReleased = true; 83 mSoundPool.release(); 84 } 85 isReleased()86 public boolean isReleased() { 87 return mIsReleased; 88 } 89 getAudioTypeForSoundPool()90 private static int getAudioTypeForSoundPool() { 91 // STREAM_SYSTEM_ENFORCED is hidden API. 92 return ApiHelper.getIntFieldIfExists(AudioManager.class, 93 "STREAM_SYSTEM_ENFORCED", null, AudioManager.STREAM_RING); 94 } 95 } 96