package org.spin.gaitlib.gaitlibdemo.beat; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.SoundPool; import android.os.AsyncTask; import android.os.IBinder; import android.util.Log; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.TimerTask; public class GaitSoundService extends Service { private static final double CADENCE_THRESHOLD_MAX = 3; private static final double CADENCE_THRESHOLD_MIN = 0.2; private final GaitAnalysisServiceReceiver receiver = new GaitAnalysisServiceReceiver(); private SoundPool mSoundPool; private final Map<String, Integer> gaitSoundIds = new HashMap<String, Integer>(); private String gait = null; private float cadence = 0; private boolean isStarted = false; private boolean isClassifyingGait = false; private SoundTask soundTask; @Override public int onStartCommand(Intent intent, int flags, int startId) { isClassifyingGait = intent.getBooleanExtra(MainActivity.GAIT_CLASSIFICATION, false); return super.onStartCommand(intent, flags, startId); } @Override public void onCreate() { initSoundPool(); registerReceiver(receiver, new IntentFilter( GaitAnalysisService.GAIT_UPDATE)); soundTask = new SoundTask(); super.onCreate(); } @Override public void onDestroy() { soundTask.stopTimer(); soundTask.cancel(true); unregisterReceiver(receiver); super.onDestroy(); } private void initSoundPool() { mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0); int walkSoundID = mSoundPool.load(this, R.raw.footstep, 1); int narrowSoundID = mSoundPool.load(this, R.raw.drumroll, 1); int twofoothopSoundID = mSoundPool.load(this, R.raw.spring, 1); int penguinSoundID = mSoundPool.load(this, R.raw.chicken, 1); int liftkneesSoundID = mSoundPool.load(this, R.raw.knee, 1); int dingSoundID = mSoundPool.load(this, R.raw.ding, 1); gaitSoundIds.put("walk", walkSoundID); gaitSoundIds.put("narrow", narrowSoundID); gaitSoundIds.put("twofoothop", twofoothopSoundID); gaitSoundIds.put("penguin", penguinSoundID); gaitSoundIds.put("walksideways", penguinSoundID); gaitSoundIds.put("liftknees", liftkneesSoundID); gaitSoundIds.put("ding", dingSoundID); } private class SoundTask extends AsyncTask<URL, Integer, Long> { private final Timer timer = new Timer(); @Override protected Long doInBackground(URL... urls) { startTimer(); return Long.valueOf(0); } private void startTimer() { if (cadence < CADENCE_THRESHOLD_MIN || cadence > CADENCE_THRESHOLD_MAX) { timer.schedule(new TimerTask() { @Override public void run() { startTimer(); } }, 200); } else { final long delay = (long) (1000 / cadence); timer.schedule(new TimerTask() { @Override public void run() { playSound(); startTimer(); } }, delay); } } private void playSound() { Integer soundId = gaitSoundIds.get(gait); Log.v("SoundService", "gait = " + gait + "; sound id = " + soundId); if (soundId == null || !isClassifyingGait) { soundId = gaitSoundIds.get("ding"); } mSoundPool.play(soundId, 1, 1, 1, 0, 1f); } private void stopTimer(){ timer.cancel(); timer.purge(); } } @Override public IBinder onBind(Intent intent) { return null; } public class GaitAnalysisServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (GaitAnalysisService.GAIT_UPDATE.equals(action)) { cadence = intent.getFloatExtra(GaitAnalysisService.CADENCE, 0); gait = intent.getStringExtra(GaitAnalysisService.GAIT); if (!isStarted) { soundTask.execute(null, null, null); isStarted = true; } } } } }