Complex sound handling (I.E. pitch change while looping)
- by Matthew
Hi everyone I've been meaning to learn Java for a while now (I usually keep myself in languages like C and Lua) but buying an android phone seems like an excellent time to start.
now after going through the lovely set of tutorials and a while spent buried in source code I'm beginning to get the feel for it so what's my next step? well to dive in with a fully featured application with graphics, sound, sensor use, touch response and a full menu.
hmm now there's a slight conundrum since i can continue to use cryptic references to my project or risk telling you what the application is but at the same time its going to make me look like a raving sci-fi nerd so bare with me for the brief...
A semi-working sonic screwdriver (oh yes!) my grand idea was to make an animated screwdriver where sliding the controls up and down modulate the frequency and that frequency dictates the sensor data it returns.
now I have a semi-working sound system but its pretty poor for what its designed to represent and I just wouldn't be happy producing a sub-par end product whether its my first or not.
the problem :
sound must begin looping when the user presses down on the control
the sound must stop when the user releases the control
when moving the control up or down the sound effect must change pitch accordingly
if the user doesn't remove there finger before backing out of the application it must plate the casing of there device with gold (Easter egg ;P)
now I'm aware of how monolithic the first 3 look and that's why I would really appreciate any help I can get.
sorry for how bad this code looks but my general plan is to create the functional components then refine the code later, no good painting the walls if the roofs not finished.
here's my user input, he set slide stuff is used in the graphics for the control
@Override
public boolean onTouchEvent(MotionEvent event)
{
//motion event for the screwdriver view
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
//make sure the users at least trying to touch the slider
if (event.getY() > SonicSlideYTop && event.getY() < SonicSlideYBottom)
{
//power setup, im using 1.5 to help out the rate on soundpool since it likes 0.5 to 1.5
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
//just goes into a method which sets a private variable in my sound pool class thing
mSonicAudio.setPower(1, SonicPower);
//this handles the slides graphics
setSlideY ( (int) event.getY() );
@Override
public boolean onTouchEvent(MotionEvent event)
{
//motion event for the screwdriver view
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
//make sure the users at least trying to touch the slider
if (event.getY() > SonicSlideYTop && event.getY() < SonicSlideYBottom)
{
//power setup, im using 1.5 to help out the rate on soundpool since it likes 0.5 to 1.5
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
//just goes into a method which sets a private variable in my sound pool class thing
mSonicAudio.setPower(1, SonicPower);
//this handles the slides graphics
setSlideY ( (int) event.getY() );
//this is from my latest attempt at loop pitch change, look for this in my soundPool class
mSonicAudio.startLoopedSound();
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE)
{
if (event.getY() > SonicSlideYTop && event.getY() < SonicSlideYBottom)
{
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
mSonicAudio.setPower(1, SonicPower);
setSlideY ( (int) event.getY() );
}
}
if(event.getAction() == MotionEvent.ACTION_UP)
{
mSonicAudio.stopLoopedSound();
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
mSonicAudio.setPower(1, SonicPower);
}
return true;
}
and here's where those methods end up in my sound pool class its horribly messy but that's because I've been trying a ton of variants to get this to work, you will also notice that I begin to hard code the index, again I was trying to get the methods to work before making them work well.
package com.mattster.sonicscrewdriver;
import java.util.HashMap;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class SoundManager
{
private float mPowerLvl = 1f;
private SoundPool mSoundPool;
private HashMap mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
private int streamVolume;
private int LoopState;
private long mLastTime;
public SoundManager()
{
}
public void initSounds(Context theContext)
{
mContext = theContext;
mSoundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
}
public void addSound(int index,int SoundID)
{
mSoundPoolMap.put(1, mSoundPool.load(mContext, SoundID, 1));
}
public void playUpdate(int index)
{
if( LoopState == 1)
{
long now = System.currentTimeMillis();
if (now > mLastTime)
{
mSoundPool.play(mSoundPoolMap.get(1), streamVolume, streamVolume, 1, 0, mPowerLvl);
mLastTime = System.currentTimeMillis() + 250;
}
}
}
public void stopLoopedSound()
{
LoopState = 0;
mSoundPool.setVolume(mSoundPoolMap.get(1), 0, 0);
mSoundPool.stop(mSoundPoolMap.get(1));
}
public void startLoopedSound()
{
LoopState = 1;
}
public void setPower(int index, float mPower)
{
mPowerLvl = mPower;
mSoundPool.setRate(mSoundPoolMap.get(1), mPowerLvl);
}
}
ah ha! I almost forgot, that looks pretty ineffective but I omitted my thread which actuality updates it, nothing fancy it just calls :
mSonicAudio.playUpdate(1);
thanks in advance, Matthew