【问题标题】:Change the playback rate of a track in real time on Android在 Android 上实时更改曲目的播放速率
【发布时间】:2011-02-14 15:08:04
【问题描述】:

我想知道是否有人知道实时更改曲目播放速率的库。我的想法是加载曲目并将其播放速率更改为一半或两倍。首先,我尝试了 MusicPlayer,但根本不可能,然后我尝试了 SoundPool。问题是使用 SoundPool 加载曲目后,我无法更改速率。这是我正在使用的代码(概念证明):

float j = 1;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button b = (Button)findViewById(R.id.Button01);
    b.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            j = (float) (j +.5);

        }
    });

    AssetFileDescriptor afd;
    try {

        SoundPool sp = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);

        afd = getAssets().openFd("wav/sample.wav");
        int id = sp.load(afd, 1);
        sp.play(id, 1, 1, 1, 0, j);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

当我按下按钮时,播放速率应该会增加,但不会发生。知道如何实时更改费率吗?

提前致谢。

【问题讨论】:

    标签: android signal-processing playback sampling


    【解决方案1】:

    您调用 sp.play 一次,在调用该函数时 j 的值被复制到该函数中。

    之后改变 j 不会改变函数中 j 的值(这称为传值)

    之后要更改播放速率,您需要在按钮单击侦听器中调用 sp.setRate(StreamID,j)。

    请注意,StreamID 是由 sp.play 函数返回的,因此请将其作为变量存储在类中。

    这段代码应该可以工作(我没有测试过):

    float j = 1.0f;
    SoundPool sp = null;
    int sID = 0;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        Button b = (Button)findViewById(R.id.Button01);
        b.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                j = (float) (j +.5f);
                sp.setRate(sID,j);
    
            }
        });
    
        AssetFileDescriptor afd;
        try {
    
            sp = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
    
            afd = getAssets().openFd("wav/sample.wav");
            int id = sp.load(afd, 1);
            sID = sp.play(id, 1, 1, 1, 0, j);
    
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    虽然它可能会在按下几个按钮后崩溃,但 SoundPool 仅支持从 0.5 到 2.0 的速率。您应该添加检查以确保 j 保持在这些范围内。

    【讨论】:

    • 嗨,马克!谢谢你的回答,我试过了,你是对的。现在我有另一个问题,也许你也知道如何解决:当我运行程序时,有时我会得到这个错误:ERROR/AudioCache(31): Heap size overflow! req size: 1058400, max size: 1048576 。我的想法是加载大小为加载文件大小两倍(至少)的歌曲,所以我认为我不能为此使用 SoundPool。你怎么看?谢谢
    • TBH SoundPool 是一个有问题的 **** 您将遇到的错误之一是每个声音池最多应该有 1MB 的声音数据与之关联,无论是在 1 个文件中或 10. 它真的是为播放小音效而设计的。谷歌搜索 SoundPool 错误会出现更多,如果你使用它,你必须小心。如果您需要处理更大的音轨,我建议您构建自己的声音引擎并将原始样本转储到 AudioTrack 实例。
    • 我忘了说,1MB 的限制是原始文件的大小,所以你可以将你的 wav 文件压缩成 ogg,也许可以绕过 SoundPool 的限制
    • 感谢您的信息,马克。你是对的,SoundPool 不适合我想做的事情。所以,我一直在网上搜索,最后我找到了 gdx 项目:code.google.com/p/libgdx。它有我需要的一切。谢谢
    猜你喜欢
    • 2023-03-25
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    相关资源
    最近更新 更多