Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified
Accepted Solution

Audible feedback with an mp3 file

All,

 

I am having a bit of an issue when testing an app I created on a physical 9530. The following code:

 

public void playClick() {
	Player player; VolumeControl vc;
	try {
		InputStream is = getClass().getResourceAsStream("/" + "click.mp3"); 
		player = javax.microedition.media.Manager.createPlayer(is,"audio/mpeg");
		player.addPlayerListener(new PlayerListener() {          
          public void playerUpdate(Player player, final String event, Object eventData) {
               if (event.equals(END_OF_MEDIA)) {
                     player.close();             
               }          
          }      
    });
		player.realize();
		player.prefetch();
			
		vc = (VolumeControl) player.getControl("VolumeControl");
		if (vc != null) {
				vc.setLevel(100);
		}
				
		Control[] c = player.getControls();
		for (int i=c.length-1; i>=0; --i) {
				if (c[i] instanceof AudioPathControl) {
					AudioPathControl apc = (AudioPathControl)c[i];
					apc.setAudioPath(AudioPathControl.AUDIO_PATH_HANDSFREE);
				}
		}

		player.start();

	}
	catch(Exception e){
		System.out.println("ERR: " + e.toString());
	}
}

 

Works just fine in the 9550 simulator. I have also pulled down the standalone simulator for the 9530. In both simulators the above code works when a button is clicked. The sound plays instantly as well. I am calling playClick() within the field change listener for each button.

 

I have ptried placing the click.mp3 in the /res folder or the /src folders and it works both ways in each simulator. When I sign the code and place it on a physical 9530, the app hangs for about 5 seconds after I press the button before the button does what it is supposed to do. Although the button does its required function, there is no sound. I have coded an option to turn off the sound and when I select to turn off the sound, any button presses are instantanious and do not hang like they do when the sound is on.

 

I'm stumped. I pieced the code above from the many posts in this forum on the topic of playing sound. I have spent the past two days searching for a resolution to my specific problem with no luck. Any help or pointers in the right direction would be most appreciated. Thanks

Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified

Re: Audible feedback with an mp3 file

All, I have attached a physical 9530 to Eclipse and successfully ran the debugger. When I turn the sound on in the application and push a button I am getting the following error:

 

ERR: net.rim.device.internal.media.RimMediaException: Media unloaded while initializing

 

I have done some searching and it looks like this is an issue with the software on the physical phone and not the application itself. Is that correct? The operating system version on the 9530 that I have is:

 

v5.0.0.797 (Bundle 1348, Platform 4.2.0.359)

 

Any thoughts or suggestions would be appreciated. Thanks.

Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified

Re: Audible feedback with an mp3 file

All,

 

I seem to be making some progress now. I downgraded the device software on the phone to v5.0.0.591. I am able to get sound from any of the buttons one time. Any subsequent presses result in no sound with an error that is only seen in the debugger. The application is now responsive with sound turned on.

 

It appears the media processor is budy after the first sound is heard and that is why no additional sounds are heard. This is the code that I am using:

 

 

public void playClick() {
	Player player; VolumeControl vc;
	try {
		InputStream is = getClass().getResourceAsStream("/" + "click.mp3"); 
		player = javax.microedition.media.Manager.createPlayer(is,"audio/mp3");
		player.addPlayerListener(new PlayerListener() {          
	    public void playerUpdate(Player player, final String event, Object eventData) {
			    if (event.equals(END_OF_MEDIA)) {
					    player.close();             
      		}          
      }      
  });
	player.realize();
	player.prefetch();
				
	vc = (VolumeControl) player.getControl("VolumeControl");
	if (vc != null) {
			vc.setLevel(50);
	}
				
	Control[] c = player.getControls();
	for (int i=c.length-1; i>=0; --i) {
			if (c[i] instanceof AudioPathControl) {
					AudioPathControl apc = (AudioPathControl)c[i];
					apc.setAudioPath(AudioPathControl.AUDIO_PATH_HANDSFREE);
			}
	}

	player.start();

	} catch(Exception e){
			System.out.println("Error: " + e.toString());
	}
}

 

 

I am calling playClick() within the fieldchangelistener for each button. Here is the debug output showing the first playback at being successful and the subsequent playback as failing.

 

[STREAM] allocating big buffer [index: 0] [numStreams: 0]
[STREAM] allocating stream [index: 0] [size: 327680]
[STREAM] allocated stream [index: 0] [handle: 32002] [size: 327680]
null:_ss=32002 PID=214
MN: init0(234946816, 0, 1, 65535)=0
MN: load 2
MP: h=234946816,s=LG: +sNMD
MN: signifyNoMoreData0(234946816)=0
MP: h=234946816,s=LG: -sNMD
MP: h=234946816,s=LG: +mLod(214):41
MP: h=234946816,s=LG: -> LD
MN: getPlayableStreams0(234946816)=1
MP: h=234946816,s=LD: -mLod
MP: h=234946816,s=LD: statUpdEn true
MN: getLength0(234946816)=313
MN: getPlayableStreams0(234946816)=1
MN: isSeekable0(234946816)=1
MN: slewVolume(234946816, 50, 1)=0
MN: slewVolume(234946816, 50, 1)=0
AR: add source 13
AR: setAudioMode 32
MP: h=234946816,s=LD: +play(214):214
MN: play0(234946816) is audio, NO check for active pause
MN: play0(234946816)=0
MP: h=234946816,s=LD: -> PL
MP: h=234946816,s=PL: -play
MP: h=234946816,s=PL: volChange 50
MP: h=234946816,s=PL: volChange 50
MP: h=234946816,s=PL: mStat: 0
MP: h=234946816,s=PL: +mSeK
MP: h=234946816,s=PL: -mSeK
AUDIOMANAGER: IOException
[STREAM] releasing big buffer [index: 0] [handle: 32002]
JVM: bklt @6020718: timer
JVM: bklt[1] @6020718: idle 2
JVM: bklt @6020718: setTimer 8
[STREAM] allocating big buffer [index: 0] [numStreams: 0]
[STREAM] allocating stream [index: 0] [size: 327680]
[STREAM] allocated stream [index: 0] [handle: 32258] [size: 327680]
null:_ss=32258 PID=214
MN: init0(52332220, 0, 1, 65535)=1
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=LG: +unld(214):214
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=LG: -> UG
MN: unload0(-1)=2 pauseHandle=0
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UG: +unlC
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UG: -> UD
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UD: -unlC
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UD: -unld
[STREAM] releasing big buffer [index: 0] [handle: 32258]
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UD: +unld(214):214
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UD: -unld
net.rim.device.internal.media.MediaPlayer@571fcd6c,s=UD: LOAD ERR
Error: net.rim.device.internal.media.MediaNativesException: Native error initializing media: Media processor busy

 

What am I missing in the code I have provide above? I am listening for the sound to finish playing and then close the player and all of its connections. At least that is what I believe I am doing with my code above. Any suggestions would be appreciated. I don't necessarily need the answer, just a pointer to the right direction. Thanks.

Retired
Retired
Posts: 150
Registered: ‎10-19-2010
My Device: Not Specified
My Carrier: Rogers

Re: Audible feedback with an mp3 file

Hi TEP!

 

I have a very similar demo application that works in the same way - it invokes a playSound() method from a FieldChangeListener in a button.  It works well on my 9530 using build 5.0.0.591.  Here are some tips that should help:

 

Although I don't think it's explicitly stated, every FieldChangeListener is called from a new thread, so your code needs to be thread safe.  Try synchronizing this playClick() method on an object so that button presses happen serially with eachother instead of at the same time.  This is especially important n a 9530 since it is a CDMA device and as such only has 1 audio channel - by starting separate Players in separate threads they are essentially competing for that resource.  Also remember that the playerUpdate listener needs to be synchronized on the same object for true thread safety.

 

Not required, but noteworthy: the call to player.prefetch in your code below is the point at which the audio channel resource I emntioned will try to be acquired.  You can remove it altogether here since it will be implicitly called by the start() call later in the method, and since the volume and audio path changes don't need it, it's usually best to not grab it until needed.

 

Finally, as an optimization, instead of fetching all controls and iterating to find the AudioPathControl, you can instead get it directly (similar to how the VolumeControl is acquired) by calling:

 

AudioPathControl apc = (AudioPathControl) player.getControl("net.rim.device.api.media.control.AudioPathControl");

 

Below is the PlayerManager class I used to try this out (my apologies since it is a bit long since it works for both CDMA devices and GSM where up to 3 Players can be started at the same time). 

 

Really the only differences between your code and this code is the synchronization I mentioned.  Note that in the code below the methods are static which means they are synchronized on the .class object rather than an instance object - you can see the playerUpdate implementation synchronizes on the same .class object for thread safety.

 

Let me know if this helps!

 

 

 

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.media.control.VolumeControl;

import net.rim.device.api.system.Application;

/**
 * Manages Players in an efficient manner.
 */
public class PlayerManager implements PlayerListener {
    
    /** The current volume level. Should be a multiple of 5. */
    private static int level = 50;

    private static Player midiPlayer = null;
    
    // Other players: index corresponds to age (0 = newest)
    private static Player[] players = { null, null };

    private static final PlayerListener listener = new PlayerManager();

    private PlayerManager() {
    }

    /**
     * Start one of the three players.
     *
     * @param player
     *            the player to start
     * @param uri
     *            the uri to initialize the player with
     * @throws MediaException
     * @throws IOException
     */
    public static synchronized Player playSound( String uri ) {
        boolean midi = uri.endsWith( ".mid" );
        
        // Close existing player (oldest as applicable)
        if( midi && midiPlayer != null ) {
            midiPlayer.close();
        } else if (players[ 1 ] != null) {
            players[ 1 ].close();
        }
        
        // Create and start a new player
        Player player = startPlayer( uri );
        
        // Add new player; shuffle older players as applicable
        if( midi ) {
            midiPlayer = player;
        } else {
            players[ 1 ] = players[ 0 ];
            players[ 0 ] = player;
        }
        return player;
    }

    /**
     * Start one of the three Players.
     *
     * @param player the Player to start
     * @param uri the uri to initialize the player with
     */
    private static Player startPlayer( String uri ) {
        Player player = null;
        
        // For this demo we load from a file in this COD, so convert URI into InputStream and content type
        // A signed app can instead use MIMETypeAssociations.getMimeType(String filename)
        InputStream sound = Application.getApplication().getClass().getResourceAsStream(uri);
        String contentType = "";
        if (uri.endsWith( ".mp3" )) contentType = "audio/mp3";
        else if (uri.endsWith( ".wav" )) contentType = "audio/wav";
        else if (uri.endsWith( ".mid" )) contentType = "audio/midi";
        
        try {
            player = Manager.createPlayer( sound, contentType );
            
            player.realize();
            player.addPlayerListener( listener );
            
            // Set player volume to correct initial volume
            VolumeControl vc = (VolumeControl) player.getControl( "VolumeControl" );
            vc.setLevel( level );
            
            player.start();
        } catch( Exception e ) {
            if( player != null ) {
                player.close();
            }
            throw new RuntimeException( "Unable to start player with URI " + uri + ": " + e );
        }
        return player;
    }
    
    /**
     * Convenience method to stop all three players.
     */
    public static synchronized void stopAllSounds() {
        if (midiPlayer != null) midiPlayer.close();
        if (players[ 0 ] != null) players[ 0 ].close();
        if (players[ 1 ] != null) players[ 1 ].close();
    }

    /* (non-Javadoc)
     * @see javax.microedition.media.PlayerListener#playerUpdate(javax.microedition.media.Player, java.lang.String, java.lang.Object)
     */
    public void playerUpdate( Player player, String event, Object eventData ) {
        synchronized( PlayerManager.class ) {
            if( PlayerListener.END_OF_MEDIA.equals( event ) || PlayerListener.ERROR.equals( event ) ||
                PlayerListener.STOPPED.equals( event ) || PlayerListener.STOPPED_AT_TIME.equals( event ) ) {
                
                player.close();
                
                // Make remaining player the forward player
                if( player == players[ 0 ] ) {
                    players[ 0 ] = players[ 1 ];
                    players[ 1 ] = null;
                }
            }
        }
    }
}

Highlighted
Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified

Re: Audible feedback with an mp3 file

Since this thread has gone without any responses or suggestions I began to think that maybe there was nothing wrong with my code and it was the operating system again on the phone. I downgraded the operating system to v5.0.0.419 Platform 4.2.0.179. All sounds play back now properly with no problems.

 

I have not tested loading the newer operating systems back onto the phone to see if they were just bad loads or an actual problem with the operating sytem. I did download the stand alone simulators for the other operating system versions that I had issues with and the application ran just fine in those simulators. Does that mean there is a hardware related issue with the phone or just a fluke?

Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified

Re: Audible feedback with an mp3 file

BVP, I posted a reply to my thread thinking nobody responded. I apologize for overlooking your post. Let me look over your suggestions and implement them into my code. I wil also put back one of the other operating systems I was having trouble with to see if this resolves the sound issues. 

 

Thank you for taking the time to read my post and respond. It is greatly appreciated.

Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified

Re: Audible feedback with an mp3 file

BVP, I used your suggestions with my code and no matter what I did I still had the sound problem when running build 5.0.0.591. I switched to using the code you provided and am still faced with the same problem. It would seem sound plays once and then doesn't play anymore. It must be how I am implementing the code. When I used your code originally I put it into a method (playClick()). Here is the code I actually used:

 

 

public void playClick() {
     PlayerManager.playSound("/" + "click.mp3");
}

 

 

In the simulator, it works great but that must be because of multiple audio channels being available. On an actual phone, it plays once and stops playing. I am calling playClick() from within the FieldChangeListener of my buttons. I have six buttons and am using playClick() on each one of them. It seems to me that the PlayerListenr on both your code and my code is not listening to the END_OF_MEDIA event and closing like it should be doing. To prove my theory I implemented thread.sleep() for 250ms and then manually closed the player. Here is the code:

 

 

public void playClick() {
	PlayerManager.playSound("/" + "click.mp3");
	try {
		Thread.sleep(250);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	PlayerManager.stopAllSounds();
}

 

 

When I use the above code, I can hear sound on all of the buttons when they are pressed one right after another. If I wait for a few seconds (4 or 5) and then push a button, there is no sound but if I push another button right away, the sound comes back for all of the buttons as long as I am pushing them one right after another. To me, I am thinking that the player is just initializing the mp3 file.

 

I must be doing something incorrectly to be having this problem with sound. This is my first experience with adding sound to a program. I am still pretty green as a developer. Thanks for your time.

 

 

Retired
Retired
Posts: 150
Registered: ‎10-19-2010
My Device: Not Specified
My Carrier: Rogers

Re: Audible feedback with an mp3 file

TEP, Sorry for the delay, had a busy weekend.  Anyway I ran your code verbatim from your first post... it works fine for me on my device running the same build.  I wonder if it's the media file itself that may be the problem for you.

 

Can you try other files?  Perhaps a longer one in addition to another shorter one?  I used the "click" mp3 file at http://soundbible.com/783-Click.html which is free to download under an attribution license.  Does this work any better for you?

 

I re-looked at the debug log you posted, an IOException is happening on a read call within the file, and since I am not having trouble under what seem like identical conditions I wonder if it is the file itself causing that in this case.

 

Let me know if you see the same results with the file I linked to and we can go from there.

Thanks

Developer
Developer
Posts: 42
Registered: ‎02-17-2009
My Device: Not Specified

Re: Audible feedback with an mp3 file

BVP, no worries on taking your time getting back to me. I am appreciative of the help. Thank you for testing the code I provided on a device running the same build as I am. I swapped out the sound files to the one you suggested. Swapping the file out seems to have done the trick. I kept thinking it was the code itself and never gave a thought to the sound file as a possible cause of trouble.I guess you live and learn, right?

 

Thanks again for your time in helping me to understand a little better on how to incorporate sound into a project.