/**
* @author Stay
* 通过摇晃手机的频率来改变声音的速度
*/
public class ShakeSound extends Activity implements SensorEventListener,OnClickListener {
private static final float SHAKE_THRESHOLD = 50;
通过晃动手机的频率来修改播放声音的频率。效果很给力的说。主要通过sensor来算手机摇晃的频率,摇晃的频率越高,播放声音的速度越快。
private static final String TAG = "ActivityTest";
private SensorManager manager;
private SoundManager sm;
private long curTime, lastUpdate;
private float last_x, last_y, last_z;
private float x,y,z;
private boolean isPlaying;
private int count = -2;
private float force;
private int audioCount = 0;
private float audioForce;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) this.findViewById(R.id.hello);
btn.setOnClickListener(this);
manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sm = new SoundManager(this);
sm.addSound(1, "heixiu.ogg");
}
@Override
public void onSensorChanged(SensorEvent event) {
curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 100) {
count ++ ;
if (count < 0) {
return;
}
if (count == 0) {
if (!isPlaying) {
Log.i(TAG, "sm.play(1, 0, 1.0f);");
sm.play(1, 0, 1.0f);
}
last_x = event.values[SensorManager.DATA_X];
last_y = event.values[SensorManager.DATA_Y];
last_z = event.values[SensorManager.DATA_Z];
return;
}
lastUpdate = curTime;
x = event.values[SensorManager.DATA_X];
y = event.values[SensorManager.DATA_Y];
z = event.values[SensorManager.DATA_Z];
curTime = System.currentTimeMillis();
// 每100毫秒检测一次
float deltaForce = Math.abs(x + y + z - last_x - last_y - last_z);
force = force + deltaForce;
updateAudioRate(deltaForce);
if (count >= SHAKE_THRESHOLD) {
Log.i(TAG, "unSensorListener");
// onShakeCallBack(force / count); get the score
unSensorListener();
if (isPlaying) {
sm.stop();
isPlaying = false;
}
count = - 2;
force = 0;
return;
}
last_x = x;
last_y = y;
last_z = z;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void updateAudioRate(float force) {
float rate=0;
float prvAudioRate = 1;
audioCount =audioCount+1;
audioForce=audioForce+force;
if(audioCount>3){
//from 0-50 maps to 0.6 to 2
//rate=audioForce/audioCount*0.03+0.5;
//from 0-50 maps to 1 to 1.8
rate=(float) (audioForce/audioCount*0.012+1.0);
//myAlert(rate);
prvAudioRate=prvAudioRate+(rate-prvAudioRate)/3;
sm.setRate(prvAudioRate);
Log.i(TAG, "sm.setRate=" + prvAudioRate);
audioForce=0;
audioCount=0;
//prvAudioRate=rate;
}
}
private void setSensorListener() {
Log.i(TAG, "setSensorListener");
Sensor sensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}
private void unSensorListener() {
Log.i(TAG, "unregisterListener");
manager.unregisterListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.hello:
setSensorListener();
break;
default:
break;
}
}
/**
* @author Stay
* 声音管理类
*/
public class SoundManager {
public SoundPool mSoundPool;
private HashMap mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
private int mStreamID;
static final String LOG_TAG = "SoundManager";
private boolean mSoundEnable = true;
private float mRate = 1f;
private boolean playing = false;
private int loopMode = 0;
private int mPlayIndex = -1;
public SoundManager(Context mContext) {
this.mContext = mContext;
mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap();
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int index, String audioName) {
// mSoundPoolMap.put(1, mSoundPool.load(mContext, SoundID, 1));
try {
mSoundPoolMap.put(index, mSoundPool.load(mContext.getAssets().openFd(audioName), 1));
} catch (IOException e) {
e.printStackTrace();
}
}
// loopMode=0:play once; loopMode=-1:loop mode;
public void play(int index, int loopMode, float rate) {
if (mSoundEnable) {
this.loopMode = loopMode;
mRate = checkRate(rate);
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
// float streamVolume = 0.1f;
// notes: for loop mode, the priority should be set to 0, else it can't be stopped
// mStreamID=mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, loopMode, mRate);
if (mPlayIndex < 0) {
mStreamID = mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 0, loopMode, mRate);
} else {
mStreamID = mSoundPool.play(mSoundPoolMap.get(mPlayIndex), streamVolume, streamVolume, 0, loopMode, mRate);
}
playing = true;
}
}
// added for v 1.0.1, enable changing the audio remotely
public void setPlayIndex(int index) {
mPlayIndex = index;
}
public void setRate(float rate) {
if (mSoundEnable) {
mRate = checkRate(rate);
mSoundPool.setRate(mStreamID, mRate);
}
}
private float checkRate(float rate) {
if (rate > 2f) {
return 2f;
} else if (rate < 0.5f) {
return 0.5f;
} else {
return rate;
}
}
public void stepRate(float step) {
if (mSoundEnable) {
mRate = mRate + step;
mRate = checkRate(mRate);
mSoundPool.setRate(mStreamID, mRate);
}
}
public void pause() {
if (mSoundEnable) {
mSoundPool.pause(mStreamID);
// mSoundPool.autoPause();
}
}
public void resume() {
if (mSoundEnable) {
if (false == playing) {
play(1, loopMode, mRate);
} else {
mSoundPool.resume(mStreamID);
}
}
// mSoundPool.autoResume();
}
public void stop() {
if (mSoundEnable) {
playing = false;
mSoundPool.stop(mStreamID);
}
}
public void setSound(boolean soundEnable) {
mSoundEnable = soundEnable;
}
public void release() {
if (mSoundEnable) {
playing = false;
mSoundPool.release();
}
mSoundPool.release();
mSoundPool = null;
mSoundPoolMap.clear();
mSoundPoolMap = null;
}
}