Android - производительность MediaPlayer/SoundPool?
Я новичок в Android, и я создал 16-Step-Pattern-Sequencer. Я сделал это с MediaPlayer, но когда одновременно должно воспроизводиться более 1 звука, все замедляется:/ .. поэтому я попытался сделать то же самое с SoundPool (который помечен как устаревший), но здесь появляется тот же эффект, тоже..
Он построен следующим образом: - каждый шаг, я проверяю, установлена ли нота... если так... звук воспроизводится - 16-шаговый цикл запускается в потоке
После длительного тестирования кажется, что первый прогон (все 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:
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;
}
}
теперь ваш поток умрет с максимальной реакцией 100 мс к следующему разу, когда он доберется до начала цикла while и проверит, что seq_Status изменился на false... и я думаю, что это нормально делать это
вы могли бы сделать if перед тем, как он заснет, чтобы проверить, изменился ли seq_Status, чтобы поймать его, прежде чем он заснет, конечно