Verzweifel an SoundPool

  • 5 Antworten
  • Letztes Antwortdatum
H

Hikku

Neues Mitglied
0
Ich grüße euch,

Google hat mich dieses Forum finden lassen und ich erhoffe mir die nötige Hilfe zu finden.

Ich versuche eine App zu bauen, welche mir 2 Bongos als Musikinstrument simuliert. Mein Problem ist, dass jede Sounddatei mehr als nur 1x abgespielt wird. (Manchmal sogar öfter oder garnicht mehr). Falls jemand Erfahrung mit der Nutzung von SoundPool hat, so wäre ich dem jenigen sehr dankbar wenn er meinen Quelltext mal überfliegen könnte.

Die App besitzt zu einem eine Activty Klasse BongoAktivity und zu anderem die Klasse Bongo welche von einer ImageView erbt. Ich habe mich für die ImageView entschieden, da zu bestimmten Koordinaten x,y per touch jeweils ein Sound abgespielt werden soll. Ziel ist es, das Instrument so realistisch wie möglich dem Nutzer erscheinen zu lassen.

Es sei zusätzlich zu erwähnen, dass die verwendeten Soundfiles alle ins *.ogg Format konvertiert wurden und nicht länger als eine Sekunde lang sind.

Danke im voraus für jegliche Hilfe!

BongoActivity.java
Code:
package de.luh.se.musicapp.bongo;

import android.app.Activity;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
import de.luh.se.musicapp.R;

public class BongoActivity extends Activity {

    private Bongo bongo;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        
        bongo = new Bongo(this);
        
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(bongo);
        
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
        
    }
    
    @Override
    protected void onDestroy() {
        bongo.destroy();        
        super.onDestroy();
    }

}
Bongo.java
Code:
package de.luh.se.musicapp.bongo;

import de.luh.se.musicapp.R;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;

public class Bongo extends ImageView {

    //---audio tools---
    private AudioManager audioManager;
    private SoundPool soundPool;
    private int soundId = -1;

    private float x;
    private float y;
    
    private int height = this.getHeight();
    private int width = this.getWidth();
    
    boolean obereHaelfte = false;
    boolean untereHaelfte = false;
    
    private float obereBongoMitteX = width/2; 
    private float obereBongoMitteY = height/4;        
    private float untereBongoMitteX = width/2; 
    private float untereBongoMitteY = height*3/4;
    
    float temp_x = 0;
    float temp_y = 0;
    float tempRadius = 0;
    
    public Bongo(Context context) {
        super(context);

        soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        
        AssetFileDescriptor descriptor;
        AssetManager assetManager = context.getAssets();
        try {
            
            descriptor = assetManager.openFd("bong1.ogg");
            soundId = soundPool.load(descriptor, 1);
            descriptor = assetManager.openFd("bong2.ogg");
            soundId = soundPool.load(descriptor, 2);
            descriptor = assetManager.openFd("bong3.ogg");
            soundId = soundPool.load(descriptor, 3);
            descriptor = assetManager.openFd("bong4.ogg");
            soundId = soundPool.load(descriptor, 4);
            descriptor = assetManager.openFd("bong5.ogg");
            soundId = soundPool.load(descriptor, 5);
            
        } catch (Exception ex) {
            Log.d("Sound Sample", "couldn't load soundfiles");
            throw new RuntimeException(ex);
        }
        //unter res/drawable/ eine beliebiges Bild einfügen
        this.setImageResource(R.drawable.bongo);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        
        
        canvas.rotate(0, width / 2, height / 2);

        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        x = event.getX();
        y = event.getY();

        
        
        if (x > 227 && x < 625 && y > 100 && y < 500){
            
            soundPool.play(1, 1, 1, 1, 0, 1.0f);
            
        }

        if (x > 600 && x < 910 && y > 650 && y < 1130){
            
            soundPool.play(3, 1, 1, 1, 0, 1.0f);
            
        }
        
        return true;
    }
    
    public void destroy(){

        soundPool.release();
        soundPool = null;
    }

    
}
 
Gerade nicht viel Zeit den Quellcode zu überfliegen, daher nur ein Denkansatz.

Wenn du die Bongos übers drücken auf den Touchscreen abspielst und ich habe "onTouchEvent(MotionEvent event)" gefunden, dann sollte dir klar sein, dass dieses immer aufgerufen wird, wenn du drückst und wenn du den Finger bewegst. Den Finger richtig still zu halten ohne ledigliche Bewegung ist nun wirklich fast unmachbar, daher wird die Methode wohl einfach sehr, sehr schnell aufgerufen.

Denkbar wäre das Event einfach mal auf "MotionEvent.ACTION_DOWN" zu überprüfen und nur dann abzuspielen.

Vielleicht hilft es ja schon ;)
 
Ich danke dir erstmal Kane2, du hast mich weitergebracht. Soweit alles gut und die Bongosound werden gescheit abgespielt.

Nun habe ich das folgende Problem, dass ich nicht auf beiden Bongos jeweils zeitgleich einen Ton erzeugen kann, wie handhabe ich das am besten?
 
Funktioniert es denn gar nicht?

android - Playing multiple sounds using SoundManager - Stack Overflow

Vielleicht hilft dir das weiter? Ich hab mit SoundPool selber noch nie was gemacht, aber es scheint so als, ob man die Streams auch wieder killen muss usw..

So wie ich das sehe hast du aber 4 Stück und benutzt auch unterschiedliche für die jeweilige Sounddateien, daran sollte es wohl also nicht liegen.
 
Das ist der neue Quelltext der Bongo.java
Code:
package de.luh.se.musicapp.bongo;

import de.luh.se.musicapp.R;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;

public class Bongo extends ImageView {

    //---audio tools---
    private AudioManager audioManager;
    private SoundPool soundPool;
    private int soundId = -1;

    private float x;
    private float y;
    
    private float height = 1; //= this.getHeight();
    private float width = 1; //= this.getWidth();
    private float deviceHeight;
    private float deviceWidth;
    
    boolean obereHaelfte = false;
    boolean untereHaelfte = false;
    
    private float obereBongoMitteX = (float) 0.5185; 
    private float obereBongoMitteY = (float) 0.2023;        
    private float untereBongoMitteX = (float) 0.5092; 
    private float untereBongoMitteY = (float) 0.71098;
    
    public Bongo(Context context) {
        super(context);

        soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        
        AssetFileDescriptor descriptor;
        AssetManager assetManager = context.getAssets();
        try {
            
            descriptor = assetManager.openFd("bong9.ogg");
            soundId = soundPool.load(descriptor, 1);
            descriptor = assetManager.openFd("bong8.ogg");
            soundId = soundPool.load(descriptor, 2);
            descriptor = assetManager.openFd("bong7.ogg");
            soundId = soundPool.load(descriptor, 3);
            descriptor = assetManager.openFd("bong6.ogg");
            soundId = soundPool.load(descriptor, 4);
            descriptor = assetManager.openFd("bong5.ogg");
            soundId = soundPool.load(descriptor, 5);
            
        } catch (Exception ex) {
            Log.d("Sound Sample", "couldn't load soundfiles");
            throw new RuntimeException(ex);
        }

        this.setImageResource(R.drawable.bongo);
    }

    @Override
    protected void onDraw(Canvas canvas) {    
        canvas.rotate(0, width / 2, height / 2);
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        x = event.getX()/this.deviceWidth;
        y = event.getY()/this.deviceHeight;
        //Log.i("Info","x:"+x+" y:"+y);

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            
            float actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            float maxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            float volume = actualVolume / maxVolume;
            
            soundPool.play(calcRadius(this.x,this.y), volume, volume, 1, 0, 1.0f);
        }
        return true;
    }
    
    
    public void destroy(){
        soundPool.release();
        soundPool = null;
    }
    
    public int calcRadius(float px, float py){
        if(py <= height/2)
            obereHaelfte = true;
        else
            untereHaelfte = true;
            
        float radius; 
                        
        if(obereHaelfte){
            
            radius = (float) Math.sqrt(
                                Math.abs((float) obereBongoMitteX-px) * Math.abs((float) obereBongoMitteX-px)
                            +    Math.abs((float) obereBongoMitteY-py) * Math.abs((float) obereBongoMitteY-py)
                            );
            
            //Log.i("Info", Float.toString(radius));
            
            
            if(radius <= 0.32407 && radius >0.16035){
                return 1;
            }
            if(radius <= 0.16035 && radius >0){
                return 2;
            }
        }
        else{
            
            radius = (float) Math.sqrt(
                    Math.abs((float) untereBongoMitteX-px) * Math.abs((float) untereBongoMitteX-px)
                +    Math.abs((float) untereBongoMitteY-py) * Math.abs((float) untereBongoMitteY-py)
                );
            
            //Log.i("Info", Float.toString(radius));
            
            if(radius <= 0.36111 && radius >0.24074){
                return 3;
            }
            if(radius <= 0.24074 && radius >0.12037){
                return 4;
            }
            if(radius <= 0.12037 && radius >0){
                return 5;
            }
        }
            
        obereHaelfte = false;
        untereHaelfte = false;
        return 0;
    }
    
    @Override
    public void onWindowFocusChanged(boolean hasFocus){
        this.deviceWidth=this.getWidth();
        this.deviceHeight=this.getHeight();
    }
    
}

Wie gesagt, es läuft halt alles einwandfrei, nur dass die sounds nicht gleichzeitig abgespielt werden. Habe auch mal versucht für jede Bongo einen eigenen SoundPool zu erzeugen, funktioniert leider auch nicht.

So frage ich ja nur das onTouchEvent ab, wenn ich nen multiple Touch irgendwie auslesen könnte, vllt würde das ja dann gehen :confused:
 
Hy,

ich bin gerade auf deinen Thread gestoßen und denke ich kann dir weiter helfen. SoundPool kann definitv mehrere verschiedene Audiodateien gleichzeitig abspielen. In einer meiner Projekte mache ich genau das. Ich poste dir mal den Quelltext, denke das hilft dir weiter.

Code:
package com.example.playsoundtest;

import java.math.BigDecimal;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.SoundPool.OnLoadCompleteListener;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Toast;

public class MainActivity extends Activity 
{

    private SeekBar sb_finger1, sb_finger2, sb_finger3, sb_finger4, sb_finger5;
    private EditText et_finger1, et_finger2, et_finger3, et_finger4, et_finger5;
    private Button bt_finger1, bt_finger2, bt_finger3, bt_finger4, bt_finger5;
    
    private SoundPool mSoundPool;
    private int[] soundID = new int[5];
    private int[] soundIDGoOn = new int[5];
    private int[] sampleID = new int[5];
    private int[] sampleIDGoOn = new int[5];
    private boolean[] loaded = new boolean[6];
    private int index = 0;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        sb_finger1 = (SeekBar) findViewById(R.id.sb_finger1);
        et_finger1 = (EditText) findViewById(R.id.et_finger1);
        sb_finger2 = (SeekBar) findViewById(R.id.sb_finger2);
        et_finger2 = (EditText) findViewById(R.id.et_finger2);
        sb_finger3 = (SeekBar) findViewById(R.id.sb_finger3);
        et_finger3 = (EditText) findViewById(R.id.et_finger3);
        sb_finger4 = (SeekBar) findViewById(R.id.sb_finger4);
        et_finger4 = (EditText) findViewById(R.id.et_finger4);
        sb_finger5 = (SeekBar) findViewById(R.id.sb_finger5);
        et_finger5 = (EditText) findViewById(R.id.et_finger5);
        
        bt_finger1 = (Button) findViewById(R.id.play_finger1);
        bt_finger2 = (Button) findViewById(R.id.play_finger2);
        bt_finger3 = (Button) findViewById(R.id.play_finger3);
        bt_finger4 = (Button) findViewById(R.id.play_finger4);
        bt_finger5 = (Button) findViewById(R.id.play_finger5);
        
        bt_finger1.setOnTouchListener(touchListener);
        bt_finger2.setOnTouchListener(touchListener);
        bt_finger3.setOnTouchListener(touchListener);
        bt_finger4.setOnTouchListener(touchListener);
        bt_finger5.setOnTouchListener(touchListener);
        
        sb_finger1.setOnSeekBarChangeListener(sb_listener);
        sb_finger2.setOnSeekBarChangeListener(sb_listener);
        sb_finger3.setOnSeekBarChangeListener(sb_listener);
        sb_finger4.setOnSeekBarChangeListener(sb_listener);
        sb_finger5.setOnSeekBarChangeListener(sb_listener);
        
        //Initial-Werte setzen
        et_finger1.setText(""+sb_finger1.getProgress());
        et_finger2.setText(""+sb_finger2.getProgress());
        et_finger3.setText(""+sb_finger3.getProgress());
        et_finger4.setText(""+sb_finger4.getProgress());
        et_finger5.setText(""+sb_finger5.getProgress());
        
        //SoundPool-Stuff
        this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        
        mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
        mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId,
                    int status) {
                if(index < 5)
                {
                loaded[index] = true;
                sampleID[index] = sampleId;
                index++;
                }
            }
        });
        
        for(int i=0;i<soundID.length;i++)
        {
            switch(i)
            {
            case 0: soundID[i] = mSoundPool.load(this, R.raw.ton_c, 1); soundIDGoOn[0] = mSoundPool.load(this, R.raw.ton_c_goon, 1); break;
            case 1: soundID[i] = mSoundPool.load(this, R.raw.ton_d, 1); break;
            case 2: soundID[i] = mSoundPool.load(this, R.raw.ton_e, 1); break;
            case 3: soundID[i] = mSoundPool.load(this, R.raw.ton_f, 1); break;
            case 4: soundID[i] = mSoundPool.load(this, R.raw.ton_g, 1); break;
            }
            
        }
    }
    
    private boolean allLoaded()
    {
        boolean result = false;
        for(int i=0;i<4;i++)
        {
            if(loaded[i])
                result = true;
            else
                result = false;
        }
        return result;
    }
    
    private OnSeekBarChangeListener sb_listener = new OnSeekBarChangeListener() {
        
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            
            int id = seekBar.getId();
            
            AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
            float actualVolume = (float) audioManager
                    .getStreamVolume(AudioManager.STREAM_MUSIC);
            float maxVolume = (float) audioManager
                    .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            float volume = actualVolume / maxVolume;
            
            
            //Schwellwert aus den Einstellungen beziehen
            SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            int schwellwert = Integer.parseInt(sharedPrefs.getString("schwellwert", "512"));
            
            /*
             * Test-Formel!!!
             */
            int schwellwert_n = 1023 - schwellwert;
            float test_wert = seekBar.getProgress();
            test_wert /= schwellwert_n;
            
            /*
             * Test-Ende!!!
             */
            
            //(x - from_min) * (to_max - to_min) / (from_max - from_min) + to_min
            //float test = (seekBar.getProgress()-511);
            //test /= 511;
            float gerundet = Math.round(test_wert*10.0f) / 10.0f;
            switch(id)
            {
            case R.id.sb_finger1: et_finger1.setText(""+seekBar.getProgress()); 
                                  if(seekBar.getProgress() >= schwellwert)
                                  {
                                      mSoundPool.stop(sampleID[0]);
                                      sampleID[0] = mSoundPool.play(soundID[0], gerundet, gerundet, 1, -1, 1f);
                                  }
                                  else
                                  {
                                      mSoundPool.stop(sampleID[0]);
                                  }
                                  break;
            case R.id.sb_finger2: et_finger2.setText(""+seekBar.getProgress()); 
                                  if(seekBar.getProgress() >= schwellwert)
                                  {
                                      mSoundPool.stop(sampleID[1]);
                                      sampleID[1] = mSoundPool.play(soundID[1], gerundet, gerundet, 1, -1, 1f);
                                  }
                                  else
                                  {
                                      mSoundPool.stop(sampleID[1]);
                                  }
                                  break;
            case R.id.sb_finger3: et_finger3.setText(""+seekBar.getProgress()); 
                                  if(seekBar.getProgress() >= schwellwert)
                                  {
                                      mSoundPool.stop(sampleID[2]);
                                      sampleID[2] = mSoundPool.play(soundID[2], gerundet, gerundet, 1, -1, 1f);
                                  }
                                  else
                                  {
                                      mSoundPool.stop(sampleID[2]);
                                  }
                                  break;
            case R.id.sb_finger4: et_finger4.setText(""+seekBar.getProgress()); 
                                  if(seekBar.getProgress() >= schwellwert)
                                  {
                                      mSoundPool.stop(sampleID[3]);
                                      sampleID[3] = mSoundPool.play(soundID[3], gerundet, gerundet, 1, -1, 1f);
                                  }
                                  else
                                  {
                                      mSoundPool.stop(sampleID[3]);
                                  }
                                  break;
            case R.id.sb_finger5: et_finger5.setText(""+seekBar.getProgress()); 
                                  if(seekBar.getProgress() >= schwellwert)
                                  {
                                      mSoundPool.stop(sampleID[4]);
                                      sampleID[4] = mSoundPool.play(soundID[4], gerundet, gerundet, 1, -1, 1f);
                                  }
                                  else
                                  {
                                      mSoundPool.stop(sampleID[4]);
                                  }
                                  break;
            }
        }
        
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub
            
        }
        
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {
            
            
            
        }
    };
    
    private OnTouchListener touchListener = new OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event) 
        {
            if(allLoaded())
            {
                
                SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                boolean soundGoOn = sharedPrefs.getBoolean("stopSound", true);
                if(event.getAction() == MotionEvent.ACTION_DOWN)
                {
                    AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
                    float actualVolume = (float) audioManager
                            .getStreamVolume(AudioManager.STREAM_MUSIC);
                    float maxVolume = (float) audioManager
                            .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
                    float volume = actualVolume / maxVolume;
                    
                    switch(v.getId())
                    {
                    case R.id.play_finger1: sampleID[0] = mSoundPool.play(soundID[0], volume, volume, 1, -1, 1f); break;
                    case R.id.play_finger2: sampleID[1] = mSoundPool.play(soundID[1], volume, volume, 1, 0, 1f); break;
                    case R.id.play_finger3: sampleID[2] = mSoundPool.play(soundID[2], volume, volume, 1, 0, 1f); break;
                    case R.id.play_finger4: sampleID[3] = mSoundPool.play(soundID[3], volume, volume, 1, 0, 1f); break;
                    case R.id.play_finger5: sampleID[4] = mSoundPool.play(soundID[4], volume, volume, 1, 0, 1f); break;
                    }
                }
                else if(event.getAction() == MotionEvent.ACTION_UP && !soundGoOn)
                {
                    //Toast.makeText(getApplicationContext(), "Stop!", Toast.LENGTH_SHORT).show();
                    
                    
                    switch(v.getId())
                    {
                    case R.id.play_finger1: mSoundPool.stop(sampleID[0]); mSoundPool.stop(sampleIDGoOn[0]); break;
                    case R.id.play_finger2: mSoundPool.stop(sampleID[1]); break;
                    case R.id.play_finger3: mSoundPool.stop(sampleID[2]); break;
                    case R.id.play_finger4: mSoundPool.stop(sampleID[3]); break;
                    case R.id.play_finger5: mSoundPool.stop(sampleID[4]); break;
                    }
                }
            }
            else
            {
                Toast.makeText(getApplicationContext(), "Tones not loaded!", Toast.LENGTH_SHORT).show();
            }
            
            
            return false;
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        getMenuInflater().inflate(R.menu.settings, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch (item.getItemId()) 
        {
        case R.id.menu_settings: Intent i = new Intent(this, Preferences.class);
                                 startActivity(i);
                                 break;

        default:
            break;
        }
        return true;
    }
    

}

In dem Projekt wird es so gehandhabt das 5 Buttons auf dem Display sind. je nachdem welcher button gedrückt wird, wird ein Ton abgespielt. Es gibt auch die Möglichkeit einen Schwellwert anzugeben, dann kann für jeden Ton über eine Seekbar ein Wert eingestellt werden. liegt der Wert über dem definierten Schwellwert wird der Sound geloopt abgespielt. Die Buttons stehen in dem Projekt für Finger. Wir haben einen Handschuh entwickelt bei dem die Beugung der Finger gemessen wird. Im Endeffekt sollen die Seekbars in dem Projektbeispiel den beugungsgrad der Finger darstellen.
 
Zurück
Oben Unten