Android - MediaPlayer/SoundPool 性能?

Posted

技术标签:

【中文标题】Android - MediaPlayer/SoundPool 性能?【英文标题】:Android - MediaPlayer/SoundPool performance? 【发布时间】:2015-07-02 09:13:47 【问题描述】:

我是 android 新手,我已经构建了一个 16-Step-Pattern-Sequencer。我已经用 MediaPlayer 做到了这一点,但是当应该同时播放 1 个以上的声音时,它都会变慢:/ .. 所以我尝试了相同的 SoundPool(标记为已弃用),但这里出现了相同的效果,也是。。

它是这样构建的: - 每一步,我检查是否设置了一个音符..如果是..播放声音 - 16-Step-Loop 在一个线程中运行

经过长时间的测试,似乎第一次运行(所有 16 步)都以正常速度运行。随着第二次运行的开始,根据需要播放的声音量,一切都变慢了.. :/

我可以尝试其他解决方案吗?

编辑:

这是我的音序器的代码

初始化:

    soundPool = new SoundPool(32, AudioManager.STREAM_MUSIC, 0);
    soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() 
        @Override
        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) 
            loaded = true;
        
    );
    soundID_kick_1 = soundPool.load(this, R.raw.kick1, 1);
    soundID_kick_2 = soundPool.load(this, R.raw.kick2, 1);
    soundID_kick_3 = soundPool.load(this, R.raw.kick3, 1);
    soundID_kick_4 = soundPool.load(this, R.raw.kick4, 1);
    soundID_kick_5 = soundPool.load(this, R.raw.kick5, 1);
    soundID_kick_6 = soundPool.load(this, R.raw.kick6, 1);
    soundID_kick_7 = soundPool.load(this, R.raw.kick7, 1);
    soundID_kick_8 = soundPool.load(this, R.raw.kick8, 1);
    soundID_hh_1 = soundPool.load(this, R.raw.hh1, 2);
    soundID_hh_2 = soundPool.load(this, R.raw.hh2, 2);
    soundID_hh_3 = soundPool.load(this, R.raw.hh3, 2);
    soundID_hh_4 = soundPool.load(this, R.raw.hh4, 2);
    soundID_hh_5 = soundPool.load(this, R.raw.hh5, 2);
    soundID_hh_6 = soundPool.load(this, R.raw.hh6, 2);
    soundID_hh_7 = soundPool.load(this, R.raw.hh7, 2);
    soundID_hh_8 = soundPool.load(this, R.raw.hh8, 2);
    soundID_sd_1 = soundPool.load(this, R.raw.sd1, 3);
    soundID_sd_2 = soundPool.load(this, R.raw.sd2, 3);
    soundID_sd_3 = soundPool.load(this, R.raw.sd3, 3);
    soundID_sd_4 = soundPool.load(this, R.raw.sd4, 3);
    soundID_sd_5 = soundPool.load(this, R.raw.sd5, 3);
    soundID_sd_6 = soundPool.load(this, R.raw.sd6, 3);
    soundID_sd_7 = soundPool.load(this, R.raw.sd7, 3);
    soundID_sd_8 = soundPool.load(this, R.raw.sd8, 3);
    soundID_snd_1 = soundPool.load(this, R.raw.snd1, 4);
    soundID_snd_2 = soundPool.load(this, R.raw.snd2, 4);
    soundID_snd_3 = soundPool.load(this, R.raw.snd3, 4);
    soundID_snd_4 = soundPool.load(this, R.raw.snd4, 4);
    soundID_snd_5 = soundPool.load(this, R.raw.snd5, 4);
    soundID_snd_6 = soundPool.load(this, R.raw.snd6, 4);
    soundID_snd_7 = soundPool.load(this, R.raw.snd7, 4);
    soundID_snd_8 = soundPool.load(this, R.raw.snd8, 4);

稍后当点击 seqPlay 时,sequencer 运行:

private View.OnClickListener seqPlay = new View.OnClickListener() 
    public void onClick(View v) 
        btn_seq_play = (ImageButton)findViewById(R.id.btn_seq_play);
        Thread seq_thread = new Thread(new Runnable() 
            @Override
            public void run() 
                // Do loop while seq_status==true
                while(seq_status) 
                    for (int i = 0; i <= 15; i++)  
                        // Play Kicks if set
                        Log.i("Durchlauf Kicks" + i, "seqKick_status[i] " + seqKick_status[i]);
                        if (seqKick_status[i] != 0 && !mute_kick_status) 
                            switch (seqKick_status[i]) 
                                case 1: 
                                    soundPool.play(soundID_kick_1, volKick[i], volKick[i], 1, 0, 1f);                                       
                                    break;
                                
                                case 2: 
                                    soundPool.play(soundID_kick_2, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                                case 3: 
                                    soundPool.play(soundID_kick_3, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                                case 4: 
                                    soundPool.play(soundID_kick_4, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                                case 5: 
                                    soundPool.play(soundID_kick_5, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                                case 6: 
                                    soundPool.play(soundID_kick_6, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                                case 7: 
                                    soundPool.play(soundID_kick_7, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                                case 8: 
                                    soundPool.play(soundID_kick_8, volKick[i], volKick[i], 1, 0, 1f);
                                    break;
                                
                            
                        

                        // Play HH if set
                        Log.i("Durchlauf HH" + i, "seqHH_status[i] " + seqHH_status[i]);
                        if (seqHH_status[i] != 0 && !mute_hh_status) 
                            switch (seqHH_status[i]) 
                                case 1: 
                                    soundPool.play(soundID_hh_1, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 2: 
                                    soundPool.play(soundID_hh_2, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 3: 
                                    soundPool.play(soundID_hh_3, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 4: 
                                    soundPool.play(soundID_hh_4, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 5: 
                                    soundPool.play(soundID_hh_5, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 6: 
                                    soundPool.play(soundID_hh_6, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 7: 
                                    soundPool.play(soundID_hh_7, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                
                                case 8: 
                                    soundPool.play(soundID_hh_8, volHH[i], volHH[i], 1, 0, 1f);
                                    break;
                                

                            
                        
                        // Play SD if set
                        Log.i("Durchlauf SD" + i, "seqSD_status[i] " + seqSD_status[i]);
                        if (seqSD_status[i] != 0 && !mute_sd_status) 
                            switch (seqSD_status[i]) 
                                case 1: 
                                    soundPool.play(soundID_sd_1, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 2: 
                                    soundPool.play(soundID_sd_2, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 3: 
                                    soundPool.play(soundID_sd_3, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 4: 
                                    soundPool.play(soundID_sd_4, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 5: 
                                    soundPool.play(soundID_sd_5, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 6: 
                                    soundPool.play(soundID_sd_6, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 7: 
                                    soundPool.play(soundID_sd_7, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                                case 8: 
                                    soundPool.play(soundID_sd_8, volSD[i], volSD[i], 1, 0, 1f);
                                    break;
                                
                            
                        
                        // Play SND if set
                        Log.i("Durchlauf SND" + i, "seqSND_status[i] " + seqSND_status[i]);
                        if (seqSND_status[i] != 0 && !mute_snd_status) 
                            switch (seqSND_status[i]) 
                                case 1: 
                                    soundPool.play(soundID_snd_1, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                                case 2: 
                                    soundPool.play(soundID_snd_2, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                                case 3: 
                                    soundPool.play(soundID_snd_3, volSND[i], volSND[i], 1, 0, 1f);                                        
                                    break;
                                
                                case 4: 
                                    soundPool.play(soundID_snd_4, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                                case 5: 
                                    soundPool.play(soundID_snd_5, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                                case 6: 
                                    soundPool.play(soundID_snd_6, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                                case 7: 
                                    soundPool.play(soundID_snd_7, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                                case 8: 
                                    soundPool.play(soundID_snd_8, volSND[i], volSND[i], 1, 0, 1f);
                                    break;
                                
                            
                        

                        try 
                            Thread.sleep(100);
                         catch (InterruptedException e) 
                            e.printStackTrace();
                        
                    
                
            
        );

        // KICK-SEQ
        if(seq_status) 
            btn_seq_play.setBackgroundResource(R.drawable.play);
            seq_status = false;
            seq_thread.interrupt();
         else 
            btn_seq_play.setBackgroundResource(R.drawable.stop);
            seq_status = true;
            seq_thread.start();
        
    
;

【问题讨论】:

【参考方案1】:

取决于音频文件的长度。 长音乐文件不太大以至于可以保存在内存中,适合媒体播放器。 0.02-5秒的短音:soundprool

还有用于流文件的 Audiotrack,但实现起来有点复杂。

试试这个......或者向我们展示代码的关键部分,也许你搞砸了,或者喜欢从主线程中进行调用或类似的事情

编辑:我的代码建议:

private View.OnClickListener seqPlay = new View.OnClickListener() 
public void onClick(View v) 
    btn_seq_play = (ImageButton)findViewById(R.id.btn_seq_play);
    if(!seq_Status)
    
        Thread seq_thread = new Thread(new Runnable() 
        @Override
        public void run() 
            // Do loop while seq_status==true
            ...
        

        btn_seq_play.setBackgroundResource(R.drawable.stop);
        seq_Thread.start();
        
    else
        btn_seq_play.setBackgroundResource(R.drawable.play);


    seq_Status=!seq_Status;

    

现在你的线程将在下次他到达 while 循环的开头并检查 seq_Status 是否已更改为 false 时以 100 毫秒的最大反应死亡......我认为这样做是可以的

你可以在他睡觉之前做一个 if 来检查 seq_Status 是否已经改变,以便在它睡觉之前捕捉它

【讨论】:

您好,来自柏林; ) 你能提供你的隔音的初始化吗?你告诉他使用多少最大流量。 Hey Ilja :) .. 我对上面的线程进行了初始化.. 共有 32 个样本可以设置为 4 个音序器轨道(每个 8 个样本) 好的,我看到没有错误代码...除了您认为您的声音已加载是理所当然的,但好吧,此时这并不重要,只要您确定每个声音都已加载...我通常为每个声音设置一个布尔值,如果声音已正确加载,但没关系,如果您播放与媒体播放器不同的是未加载的声音,则声音池不介意...。贬值仅从 Android L 开始所以不要介意(谷歌得到了使用生成器而不是构造函数的想法)....尽管如此我没有解决您的问题的代码到目前为止看起来不错 一件事....当您加载声音时...在文档中是否说优先级标志(最后一个参数)应该设置为 1 以便将来可兼容并且它没有效果atm 还是感谢您查看我的问题和我的代码 ;)

以上是关于Android - MediaPlayer/SoundPool 性能?的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)

【Android笔记】android Toast

图解Android - Android核心机制

Android游戏开发大全的目录