gpt4 book ai didi

android - 复杂的声音处理(即循环时音高变化)

转载 作者:行者123 更新时间:2023-11-30 04:52:14 24 4
gpt4 key购买 nike

在阅读了一组可爱的 Java 教程并花了一段时间埋头于源代码之后,我开始对它有了感觉。对于我的下一步,我将深入研究一个功能齐全的应用程序,包括图形、声音、传感器使用、触摸响应和完整菜单。

我的宏伟想法是制作一个动画 Screwdriver ,上下滑动控件可以调节频率,而该频率决定了它返回的传感器数据。

现在我有一个半工作的音响系统,但它的设计表现非常差,我只是不乐意生产低于标准的最终产品,无论它是否是我的第一个。

问题:

  • 当用户按下控件时声音必须开始循环
  • 当用户释放控制时声音必须停止
  • 向上或向下移动控件时,音效必须相应地改变音高
  • 如果用户在退出应用程序之前没有移开手指,则必须在该设备的外壳上镀金(复活节彩蛋;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);

最佳答案

那里有一些令人困惑的地方,我认为它们只是试图将源代码放入此页面的剪切和粘贴问题,但假设您的 onTouchEvent 处理没有问题,我的随机评论是:

  • 看起来您在按住触摸时每 250 毫秒调用一次 play()。我看不到 play() 调用的循环参数,但我认为它是 -1。如果是这样,那么您将每 250 毫秒启动一个全新的循环声音(播放会为您创建的每个音频流返回一个唯一的 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 方法中使用该 ID


当然,我自己也有关于循环声音“恢复”的问题,所以请对我所说的持保留态度:-)

祝你好运!我想我应该检查时间戳。如果您在 3 年前发帖,我深表歉意:-)

关于android - 复杂的声音处理(即循环时音高变化),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2947210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com