复杂的声音处理(循环时的I.E.音高变化)

时间:2010-06-01 04:04:50

标签: android

大家好,我一直想学习Java一段时间(我通常会把自己保留在像C和Lua这样的语言中)但购买Android手机似乎是一个很好的开始时间。

现在经过一系列可爱的教程并花了一段时间埋在源代码中,我开始感受到它,所以我的下一步是什么?很好地利用具有图形,声音,传感器使用,触摸响应和完整菜单的全功能应用程序。

嗯,现在有一个轻微的难题,因为我可以继续使用神秘的参考我的项目或冒险告诉你应用程序是什么,但同时它会让我看起来像一个狂热的科幻书呆子,所以裸我简要介绍......

一个半工作的声波螺丝刀(哦,是的!)我的主要想法是制作一个动画螺丝刀,上下滑动控制器调制频率,频率决定它返回的传感器数据。 现在我有一个半工作的音响系统,但它的设计代表的却很差,而且不管它是我的第一个产品,我都不会乐意生产低端产品。

问题:

    当用户按下控件时
  • 声音必须开始循环
  • 当用户释放控件时声音必须停止
  • 当向上或向下移动控件时,声音效果必须相应地改变音高
  • 如果用户在退出应用程序之前没有将手指移开,则必须将装置的外壳镀金(复活节彩蛋; P)

现在我知道前3个外观是多么的单片,这就是为什么我真的很感激我能得到的任何帮助。

对不起这段代码看起来有多糟糕,但我的总体计划是创建功能组件,然后稍后改进代码,如果屋顶没有完成则不能很好地绘制墙壁。

这是我的用户输入,他设置幻灯片的东西用于控件的图形

@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;

}

而这里的那些方法最终出现在我的声音池类中,它非常混乱,但那是因为我一直在尝试大量的变体来实现这一点,你还会注意到我开始对索引进行硬编码,在让它们运行良好之前,我试图让这些方法起作用。

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<Integer, Integer> 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);
    }

}
啊哈!我差点忘了,这看起来很无效但是我省略了我的线程,现实更新它,没什么好看的只是调用:

mSonicAudio.playUpdate(1);

提前感谢,马修

1 个答案:

答案 0 :(得分:1)

在那里有一些令人困惑的问题,我认为只是剪切和粘贴问题试图将源代码放到这个页面中,但假设你的onTouchEvent处理没有问题,我的随机评论是:

  • 看起来你在按住触摸时每250毫秒调用一次play()。我看不到play()调用的循环参数,但我认为它是-1。如果是这样,那么你每250 msc发出一个全新的循环声音(播放为你创建的每个音频流返回一个唯一的streamId)。

  • 我认为您想要修改单个现有流的音高和幅度。所以我想你想要这样的东西:


int mySoundStreamId = 0;

...

onDown()
   if( mySoundStreamId == 0 ) {
     // create the one true stream
     mySoundStreamId = mySOundPool.play( initial power and freq modifiers, loop = -1 )
   } else {
     // resume the one true stream
     mySoundPool.resume( mySoundStreamId );  // note: a STREAM id is NOT a SOUND id.
   }

onUp()
   if( mySoundStreamId != 0 ) {
      // pause the one true stream
      mySoundPool.pause( mySoundStreamId )  // stop() will release all the samples you held
   }


onWiggle()
   if( mySoundStreamId != 0 ) {
      // modify parameters of the one true stream
      mySoundPool.setPitch( mySoundStreamId, newPitch );  // too lazy to look up real soundPool command
   }

onGameOver
    if( mySoundStreamId != 0 ) {
      // shut down and release the samples of the one true stream
      mySoundPool.setLoop( mySountStreamId, 0 ); // otherwise some phones will keep looping after shutdown
      mySoundPool.stop( mySoundStreamId );  // no resume possible after this, need to reload samples
      mySOundStreamId = 0;
    }

我省略了声音池本身的创建/销毁。听起来你成功地将声音数据加载到声音池中了。

请注意,LOAD会返回您传递给PLAY命令的SOUND ID 但是PLAY返回一个STREAM ID,你在大多数其他soundPool方法中使用它


当然,我对循环声音中的'恢复'有自己的问题,所以拿一点我说的话来说: - )

祝你好运!我想我应该检查一下时间戳。如果你在3年前发布了我的道歉: - )