<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Toni Westbrook dot Com &#187; Blackberry</title>
	<atom:link href="http://www.toniwestbrook.com/archives/category/blackberry/feed" rel="self" type="application/rss+xml" />
	<link>http://www.toniwestbrook.com</link>
	<description>Sharing Software Development Knowledge With You</description>
	<lastBuildDate>Mon, 12 Sep 2011 03:35:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Blackberry Minecraft Chat Client</title>
		<link>http://www.toniwestbrook.com/archives/457</link>
		<comments>http://www.toniwestbrook.com/archives/457#comments</comments>
		<pubDate>Sun, 13 Mar 2011 23:03:02 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=457</guid>
		<description><![CDATA[First off, if you haven&#8217;t tried Minecraft yet, it is a ridiculously addictive game in which you, the player, dig tunnels, collect materials, craft items, and build up the world around you. You explore underground caverns, build houses, castles, farms, etc. It&#8217;s a ton of fun (and definitely a good way to waste hours of [...]]]></description>
			<content:encoded><![CDATA[<p>First off, if you haven&#8217;t tried Minecraft yet, it is a ridiculously addictive game in which you, the player, dig tunnels, collect materials, craft items, and build up the world around you.  You explore underground caverns, build houses, castles, farms, etc.  It&#8217;s a ton of fun (and definitely a good way to waste hours of your life).  If you haven&#8217;t seen it before, <a href="http://www.minecraft.net">check it out</a>.</p>
<p>I run a Minecraft server for a few friends of mine, and even if I wasn&#8217;t in the game, I wanted to be able to chat with them and run server comands on the go.  So I wrote a VERY quick and extremely dirty (and buggy) Minecraft chat client for the Blackberry that will connect to a server, and let you chat and run commands.  </p>
<p>BerryCraft Chat:</p>
<p><a href="http://www.toniwestbrook.com/wp-content/uploads/2011/03/BerryCraftChat.jpg"><img src="http://www.toniwestbrook.com/wp-content/uploads/2011/03/BerryCraftChat.jpg" alt="" title="BerryCraftChat" style ="width:100%" /></a></p>
<p>It has a few limitations &#8211; specifically that it will only connect to a server that has minecraft.net authentication turned off.  It wouldn&#8217;t be too difficult to insert this functionality into it, but I banged this out in a couple days and don&#8217;t really have time to put any polish on it.</p>
<p>I don&#8217;t see a huge interest in it, but if you do happen to try a copy, or would like the source to build something bigger/better, shoot me a message or comment, and I&#8217;ll send it over.  Works on any blackberry.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/457/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Good First Week for Galactic Blast!</title>
		<link>http://www.toniwestbrook.com/archives/437</link>
		<comments>http://www.toniwestbrook.com/archives/437#comments</comments>
		<pubDate>Fri, 14 Jan 2011 00:42:04 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=437</guid>
		<description><![CDATA[I tweeted this as well, but I just wanted to thank everyone who has been supportive of both the Blackberry Game Development Tutorial, as well as our commercial release of Galactic Blast! &#8211; over the first week, we sold over 100 copies! It&#8217;s a great feeling to know people are out there enjoying your game. [...]]]></description>
			<content:encoded><![CDATA[<p>I tweeted this as well, but I just wanted to thank everyone who has been supportive of both the <a href="http://www.toniwestbrook.com/archives/69">Blackberry Game Development Tutorial</a>, as well as our commercial release of Galactic Blast! &#8211; over the first week, we sold over 100 copies!  It&#8217;s a great feeling to know people are out there enjoying your game.  </p>
<p>Thanks again everyone!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/437/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Galactic Blast Released on App World!</title>
		<link>http://www.toniwestbrook.com/archives/432</link>
		<comments>http://www.toniwestbrook.com/archives/432#comments</comments>
		<pubDate>Fri, 07 Jan 2011 02:24:43 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=432</guid>
		<description><![CDATA[I&#8217;m very excited to say Galactic Blast is now officially available for purchase from App World!! Pick it up now and save the galaxy, right from your Blackberry! And for all the aspiring developers out there, don&#8217;t forget to check out the tutorial to make games just like this one.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m very excited to say Galactic Blast is now officially available for purchase from <a href="http://appworld.blackberry.com/webstore/content/22534?lang=en">App World</a>!!</p>
<p><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb9.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb9.png" alt="" title="Boss 4" width="480" height="360" class="size-full wp-image-420" /></a></p>
<p>Pick it up now and save the galaxy, right from your Blackberry!  </p>
<p>And for all the aspiring developers out there, don&#8217;t forget to check out <a href="http://www.toniwestbrook.com/archives/69">the tutorial</a> to make games just like this one.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/432/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Screenshots of Our Upcoming Blackberry Game!</title>
		<link>http://www.toniwestbrook.com/archives/419</link>
		<comments>http://www.toniwestbrook.com/archives/419#comments</comments>
		<pubDate>Fri, 24 Dec 2010 05:21:51 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=419</guid>
		<description><![CDATA[Well &#8211; I&#8217;m very excited. If you&#8217;ve been following the Twitter feed at all, you know that I&#8217;ve been working at a breakneck pace trying to get Galactic Blast completed. You might recognize the title from the demo game featured in our tutorial on creating a Blackberry game. The commercial release of Galactic Blast is [...]]]></description>
			<content:encoded><![CDATA[<p>Well &#8211; I&#8217;m very excited.  If you&#8217;ve been following the Twitter feed at all, you know that I&#8217;ve been working at a breakneck pace trying to get Galactic Blast completed.  You might recognize the title from the demo game featured in <a href="http://www.toniwestbrook.com/archives/69">our tutorial on creating a Blackberry game</a>.  The commercial release of Galactic Blast is built off a very similar framework to what&#8217;s featured in the demo, only with a LOT of extra stuff added &#8211; pre-rendered 3d graphics, bonus rounds, weapon upgrades, etc.  </p>
<p>So without further ado, screenshots!</p>
<div id="attachment_420" class="wp-caption aligncenter" style="width: 490px"><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb9.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb9.png" alt="" title="Boss 4" width="480" height="360" class="size-full wp-image-420" /></a><p class="wp-caption-text">The Gamma-3 base - the final boss.</p></div>
<div id="attachment_423" class="wp-caption aligncenter" style="width: 490px"><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb8.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb8.png" alt="" title="Boss 3" width="480" height="360" class="size-full wp-image-423" /></a><p class="wp-caption-text">The demolition controller destroys the derelict ships in decommissioned shipyard A-3. In this case, however, he's trying to destroy you! Third boss in the game.</p></div>
<div id="attachment_424" class="wp-caption aligncenter" style="width: 490px"><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb5.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb5.png" alt="" title="Nebula" width="480" height="360" class="size-full wp-image-424" /></a><p class="wp-caption-text">The Sutoran Nebula is home to the Phoraxian Shadow Fleet. They hide within the clouds of the nebula to make detection more difficult.</p></div>
<div id="attachment_425" class="wp-caption aligncenter" style="width: 490px"><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb10.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb10.png" alt="" title="Bonus" width="480" height="360" class="size-full wp-image-425" /></a><p class="wp-caption-text">Every 5 waves your SR-13 kicks it into hyperdrive, and you enter the bonus round. Pass through as many rings as possible for maximum points!</p></div>
<div id="attachment_426" class="wp-caption aligncenter" style="width: 490px"><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb1.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb1.png" alt="" title="Menu" width="480" height="360" class="size-full wp-image-426" /></a><p class="wp-caption-text">Main menu. Start/Resume game, Instructions, View High Scores, Change settings (Sound/Music/Vibration, etc), and Quit.</p></div>
<div id="attachment_427" class="wp-caption aligncenter" style="width: 490px"><a href="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb11.png"><img src="http://www.toniwestbrook.com/wp-content/uploads/2010/12/gb11.png" alt="" title="Title" width="480" height="360" class="size-full wp-image-427" /></a><p class="wp-caption-text">Title Screen</p></div>
<p>I just submitted the application to RIM for approval on App World, so hopefully it checks out and it will be available for download soon!  More to come&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/419/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Unfortunate News for a Realtime Blackberry Mixer</title>
		<link>http://www.toniwestbrook.com/archives/408</link>
		<comments>http://www.toniwestbrook.com/archives/408#comments</comments>
		<pubDate>Wed, 24 Nov 2010 00:37:30 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=408</guid>
		<description><![CDATA[Overview Sometimes I&#8217;m not sure if it&#8217;s a good thing or a bad one, but I have the kind of personality that when I get involved trying to solve a problem, I can&#8217;t stop until it&#8217;s solved. This works out well as eventually the issue at hand is fixed, but it also has the side [...]]]></description>
			<content:encoded><![CDATA[<p><b>Overview</b></p>
<p>Sometimes I&#8217;m not sure if it&#8217;s a good thing or a bad one, but I have the kind of personality that when I get involved trying to solve a problem, I can&#8217;t stop until it&#8217;s solved.  This works out well as eventually the issue at hand is fixed, but it also has the side effect that I forsake pretty much everything else until I can resolve things.  When I can&#8217;t find a solution, or there isn&#8217;t a good one, it drives me nuts.</p>
<p>And unfortunately, I&#8217;m in that irritated mindset now.  If you read my post on <a href="http://www.toniwestbrook.com/archives/267">Mixing Two or More Sounds Together on the Blackberry</a>, you saw the video I posted of a software sound mixer I had written.  While the mixer did indeed work, the problem was I had only tested one scenario &#8211; where the user has chosen to start mixing all the sounds together at the same time.  This use case is no problem.</p>
<p><b>The Ongoing Problem</b></p>
<p>The use case that&#8217;s an issue (and honestly the whole point of a realtime mixer), is where you start playing one sound, and then mix another one in at an arbitrary time later.  The reason why this is an issue is fairly easily explained (and unfortunately not apparent to me until I had written most of the code).</p>
<p>As you know if you&#8217;re a Blackberry developer, all user code is written in Java &#8211; the BB runs a JVM where all the software runs &#8211; that&#8217;s how the phone is designed.  This creates a layer of abstraction, where the user doesn&#8217;t have direct access to the hardware, and where the code runs relatively slow (compared to native instructions).  Because of this, RIM provided mappings from the javax package&#8217;s Player class to the Blackberry sound hardware. </p>
<p><b>The Problem of Buffers and Fetching</b></p>
<p>Player does a number of things &#8211; but the core of it retrieves data from a sound stream (a wav file in our case), massages it as necessary, and then loads the sound hardware buffers with the data.  The big problem is at the stage when Player retrieves data.  It does so in chunks of data &#8211; specifically (from my experiments and as other people on the web have reported) in 58000 byte chunks.  That means that is takes in a few seconds of sound at a time so the hardware buffers don&#8217;t underrun during playback.  You can do some tricks with blocking the stream and force it not to load in this full 58000 &#8211; and you will immediately hear the effects &#8211; choppy audio.  The 58000 byte buffer is not to be annoying &#8211; it&#8217;s necessary for smooth and clean audio.</p>
<p>And this is why we can&#8217;t do realtime mixing.  We don&#8217;t have direct access to the hardware buffers, we only have access to the buffer streams we can feed to Player.  And if Player demands a few seconds of audio at each read, we cannot insert a sound into the few seconds that we feed to it after the fact.</p>
<p><b>An Example of the Problem</b></p>
<p>I have two sounds.  Drums.wav which is a 20 second wav, and flute.wav which is a 5 second wave.  I would like to play drums over and over again, and then immediately mix the flute in when the user presses the &#8216;F&#8217; button.</p>
<p>Player immediately reads in, let&#8217;s say 5 seconds of drum.wav.  Then at second 3, the user presses the &#8216;F&#8217; button.  Our program can immediately queue in flute.wav into the input stream, but it won&#8217;t be played until second 5, since the Player already read in 5 seconds.  Even if we do some creative thread blocking, we can never guarantee a real time mix at all times.  </p>
<p><b>The Code (Could Still Be Useful in Certain Applications)</b></p>
<p>Below I have included all my work on this project. It consists of a &#8220;MixerStream&#8221;, which is meant to be a replacement to InputStream.  You feed an instantiated MixerStream object to Player, and then call the MixerStream &#8220;addStream&#8221; method to mix other audio files, in real time, into the Player.  It does work &#8211; but there will be large delays between when the sound is added, to when it is heard, due to the problem described above.</p>
<p>Note &#8211; this code is currently hardcoded to only work with one format of PCM stream right now (I put two hardcoded headers of a 44.1khz, 16bit, stereo, and a 44.1khz, 8bit, mono) &#8211; in addition to doing a very low tech way of mixing streams together.  The method &#8220;getMixedByte&#8221; is all setup for future functionality (Allowing any format of PCM, doing better mixing, preventing clipping, etc) &#8211; but I&#8217;m not up to doing any more work with this right now.  It only works as a semi-real time mixer, which I don&#8217;t think is too useful &#8211; the only place where it might be nice is if you&#8217;re developing a Blackberry audio-editing application, or something to that effect &#8211; where realtime isn&#8217;t necessary.  If you are doing this &#8211; feel free to use the code below &#8211; I&#8217;ll provide any help I can.  </p>
<p>So for now &#8211; this project is abandoned.  Frustrating, but necessary for now.  Hopefully with the new QNX based OS coming out, there will be more support for directly accessing the hardware buffers.</p>
<div style="font-size:10px">
<pre class="brush: java">
package com.synthdreams;

import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import net.rim.device.api.ui.component.Dialog;

// The MixerStream class allows us to add multiple PCM wave streams to mix together in real time
public class MixerStream extends InputStream{
   private Vector _streamVector; // All wave streams currently managed by the mixer
   int[] _headerArray;
   int _headerPos;
   int _totalRead;

   // WaveStream class is an InputWrapper stream that stores wav audio information
   private class WaveStream extends InputStream {
      private InputStream _fileStream; // The input stream containing the wav data
      private int _sampleRate; // Samplerate of the wave
      private int _bitRate; // Bitrate of the wave
      private int _channels; // Channels in the wave 

      public int getSampleRate() { return _sampleRate; }
      public int getBitRate() { return _bitRate; }
      public int getChannels() { return _channels; }

      public WaveStream(InputStream passStream) throws IOException {
         byte[] byteArray;
         String tempChunkName;
         int tempChunkSize;

         // Assign the file stream, then read in header info
         _fileStream = passStream;

         // 4 - ChunkID (RIFF)
         _fileStream.read(byteArray = new byte[4]);
         if (new String(byteArray).equals(&quot;RIFF&quot;) == false) {
            throw new IOException(&quot;Not a valid wave file (ChunkID).&quot;);
         }

         // 4 - ChunkSize
         _fileStream.read(byteArray = new byte[4]);

         // 4 - Format (WAVE)
         _fileStream.read(byteArray = new byte[4]);
         if (new String(byteArray).equals(&quot;WAVE&quot;) == false) {
            throw new IOException(&quot;Not a valid wave file (Format).&quot;);
         }

         // 4 - SubchunkID (fmt)
         _fileStream.read(byteArray = new byte[3]);
         if (new String(byteArray).equals(&quot;fmt&quot;) == false) {
            throw new IOException(&quot;Not a valid wave file (SubchunkID).&quot;);
         }
         _fileStream.read(byteArray = new byte[1]);

         // 4 - Subchunk1Size
         _fileStream.read(byteArray = new byte[4]);
         tempChunkSize = ((byteArray[3] &amp; 0xff) &lt;&lt; 24) | ((byteArray[2] &amp; 0xff) &lt;&lt; 16) | ((byteArray[1] &amp; 0xff) &lt;&lt; <img src='http://www.toniwestbrook.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | (byteArray[0] &amp; 0xff);

         // 2 - AudioFormat(1)
         _fileStream.read(byteArray = new byte[2]);
         if (byteArray[0] != 1) {
            throw new IOException(&quot;PCM Compression not supported.&quot;);
         }

         // 2 - NumChannels
         _fileStream.read(byteArray = new byte[2]);
         _channels = ((byteArray[1] &amp; 0xff) &lt;&lt; <img src='http://www.toniwestbrook.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | (byteArray[0] &amp; 0xff); 

         // 4 - Sample Rate
         _fileStream.read(byteArray = new byte[4]);
         _sampleRate = ((byteArray[3] &amp; 0xff) &lt;&lt; 24) | ((byteArray[2] &amp; 0xff) &lt;&lt; 16) | ((byteArray[1] &amp; 0xff) &lt;&lt; <img src='http://www.toniwestbrook.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | (byteArray[0] &amp; 0xff);

         // 6 - Byte Rate, Block Align
         _fileStream.read(byteArray = new byte[6]);

         // 2 - Bitrate
         _fileStream.read(byteArray = new byte[2]);
         _bitRate = ((byteArray[1] &amp; 0xff) &lt;&lt; <img src='http://www.toniwestbrook.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | (byteArray[0] &amp; 0xff); 

         // variable - Read in rest of chunk 1
         _fileStream.read(byteArray = new byte[tempChunkSize-16]);

         // Burn through unneeded chunks until we get to data
         tempChunkName = &quot;&quot;;
         tempChunkSize = 0;
         while (tempChunkName.equals(&quot;data&quot;) == false) {
            // Read in name and size of chunk
            _fileStream.read(byteArray = new byte[4]);
            tempChunkName = new String(byteArray);
            _fileStream.read(byteArray = new byte[4]);
            tempChunkSize = ((byteArray[3] &amp; 0xff) &lt;&lt; 24) | ((byteArray[2] &amp; 0xff) &lt;&lt; 16) | ((byteArray[1] &amp; 0xff) &lt;&lt; <img src='http://www.toniwestbrook.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | (byteArray[0] &amp; 0xff);

            // Burn through non-data chunks
            if (tempChunkName.equals(&quot;data&quot;) == false) {
               _fileStream.read(byteArray = new byte[tempChunkSize]);
            }
         }
         // End of header
      }

      public int read() throws IOException {
         return _fileStream.read();
      }
   }

   public MixerStream()  {
      _headerPos = 0;
      _totalRead = 0;

      // A constructed wav header for a 44100hz, 16bit, stereo wav of maximum length
      /*_headerArray = new byte[] {&#039;R&#039;,&#039;I&#039;,&#039;F&#039;,&#039;F&#039;, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
                                 &#039;W&#039;,&#039;A&#039;,&#039;V&#039;,&#039;E&#039;, &#039;f&#039;,&#039;m&#039;,&#039;t&#039;, 0x20, 0x10, 0x00, 0x00, 0x00,
                                 0x01, 0x00, 0x02, 0x00, 0x44, (byte)0xAC, 0x00, 0x00,
                                 0x10, (byte)0xB1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00,
                                 &#039;d&#039;,&#039;a&#039;,&#039;t&#039;,&#039;a&#039;, (byte)0xDB, (byte)0xFF, (byte)0xFF, (byte)0xFF};*/

      // A constructed wav header for a 4410hz, 8bit, mono wav of maximum length
      _headerArray = new int[] {&#039;R&#039;,&#039;I&#039;,&#039;F&#039;,&#039;F&#039;, 0xFF, 0xFF, 0xFF, 0xFF,
            &#039;W&#039;,&#039;A&#039;,&#039;V&#039;,&#039;E&#039;, &#039;f&#039;,&#039;m&#039;,&#039;t&#039;, 0x20, 0x10, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x01, 0x00, 0x44, 0xAC, 0x00, 0x00,
            0x44, 0xAC, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00,
            &#039;d&#039;,&#039;a&#039;,&#039;t&#039;,&#039;a&#039;, 0xDB, 0xFF, 0xFF, 0xFF};

      _streamVector = new Vector();
   }

   // MixerStream will first present a wav header (as documented above), then will mix data
   // from all added streams.  If there aren&#039;t any streams, it will block.
   public int read() throws IOException {
      // Increase the total count of bytes read
      _totalRead++;

      // First present header
      if (_headerPos &lt; _headerArray.length) {
         return _headerArray[_headerPos++];
      }
      else {
         // Mix any streams together
         if (_streamVector.size() &gt; 0) {
            return getMixedByte();
         }
         else {
            // If no streams are available, normally block.
            // Return 0 during the prefetch process (58000 bytes) so prefetch
            // doesn&#039;t block forever
            try {
               if (_totalRead &lt; 58001) return 0;

               synchronized(_streamVector) {
                  _streamVector.wait();
               }

               return getMixedByte();
            }
            catch (Exception e) {
               return 0;
            }
         }
      }
   }

   // This method will mix all the available streams together, keep track of current
   // playback byte position to accommodate different PCM formats, and normalize the
   // sound mixing.
   private int getMixedByte() throws IOException {
      int tempRead;
      int tempValue;

      tempValue = 0;

      // Loop through each stream
      for (int lcv = 0 ; lcv &lt; _streamVector.size() ; lcv++) {
         tempRead = ((WaveStream)_streamVector.elementAt(lcv)).read();

         // If we&#039;re at the end of the stream, remove it.  Otherwise, add it
         if (tempRead == -1) {
            _streamVector.removeElementAt(lcv--);
         }
         else {
            tempValue += tempRead;
         }
      }

      // Normalize
      if (_streamVector.size() &gt; 0) {
         tempValue /= _streamVector.size();
         return tempValue;
      }
      else {
         return 0;
      }
   }

   // Queue an audio stream to be mixed by MixerStream
   public int addStream(InputStream passStream) throws IOException {
      WaveStream tempStream;

      tempStream = new WaveStream(passStream);

      // Make sure this WaveStream is compatible with MixerStream
      // Check for sample rates
      if (tempStream.getSampleRate() != 11025 &amp;&amp; tempStream.getSampleRate() != 22050 &amp;&amp; tempStream.getSampleRate() != 44100) {
         throw new IOException(&quot;Sample rate not supported.  (11025, 22050, 44100)&quot;);
      }

      // Check for bitrates
      if (tempStream.getBitRate() != 8 &amp;&amp; tempStream.getBitRate() != 16) {
         throw new IOException(&quot;Bit rate not supported.  (8, 16)&quot;);
      }

      // Check for channels
      if (tempStream.getChannels() != 1 &amp;&amp; tempStream.getChannels() != 1) {
         throw new IOException(&quot;Number of channels not supported.  (1, 2)&quot;);
      }

      // Wave Stream checks out, let&#039;s add it to the list of streams to mix
      _streamVector.addElement(tempStream);

      try {
         // Notify the read method that there&#039;s data now if it&#039;s currently blocked
         synchronized(_streamVector) {
            _streamVector.notify();
         }
      }
      catch (Exception e) {
         Dialog.inform(&quot;Error notifying _streamVector&quot;);
      }
      return 0;
   }
}
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/408/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Blackberry &#8211; Mixing 2 or More Sounds Together (Concept Video)</title>
		<link>http://www.toniwestbrook.com/archives/267</link>
		<comments>http://www.toniwestbrook.com/archives/267#comments</comments>
		<pubDate>Thu, 02 Sep 2010 05:29:19 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=267</guid>
		<description><![CDATA[An Audio Issue One thing that I (and many others judging by forum posts) have run into is the fact that the Blackberry isn&#8217;t very good at mixing more than one sound together. You&#8217;ll be listening to music, or playing a game with music, and suddenly you&#8217;ll get a text message, and it will simply [...]]]></description>
			<content:encoded><![CDATA[<p><b> An Audio Issue </b></p>
<p>One thing that I (and many others judging by forum posts) have run into is the fact that the Blackberry isn&#8217;t very good at mixing more than one sound together.  You&#8217;ll be listening to music, or playing a game with music, and suddenly you&#8217;ll get a text message, and it will simply terminate the current sound and play the new one.  If you&#8217;ve got a friendly application, it will restart/resume the original audio, but it&#8217;s a jarring audio experience.</p>
<p>What I&#8217;m about to post won&#8217;t fix that.  However &#8211; developers also run into the issue when they want to mix sounds together in their applications and games.  Play 2 or more sound effects simultaneously and/or while music is playing.  I&#8217;ve seen official RIM developers comment that certain devices can achieve two simultaneous sounds by instantiating the Player class twice &#8211; but from what I gather, this is on GSM only phones &#8211; and still limited to two.  On CDMA devices, you&#8217;re completely out of luck.</p>
<p><b> The Cheap and Quick Workaround </b></p>
<p>In my 6 part tutorial on writing a Blackberry game, in the <a href="http://www.toniwestbrook.com/archives/75">audio article</a>, I mentioned how the Alert.startAudio method can be used for simple sound effects (tone/duration pairs) that will play simultaneously while your midi or mp3 music plays in the background.  For many applications, this is enough if you don&#8217;t need sophisticated sound effects.</p>
<p><b> The Start of a Mixer </b></p>
<p>I&#8217;m guessing that the limitation is imposed by the audio chipset/DAC inside of CDMA devices, and perhaps RIM realizes the CPU time involved in a software based audio mixer would slow the phone down too much.  However, I think the software option should be there, and developers can use it if they&#8217;d like &#8211; they might not need a large amount of CPU, or might be dealing with low quality sound files &#8211; there are a few scenarios where a software mixer would just be a nice options.</p>
<p>Tonight I sat down and wrote a quick and dirty proof of concept application showing a PCM audio mixer in action.  I loaded in 3 audio 44.1khz 8bit mono files and mixed them together in real time.  I didn&#8217;t normalize the audio at all, so its a little soft, but the code works, and could be expanded on quite a bit to make a full featured mixer. Maybe I&#8217;ll run into problems down the road that RIM already has, but it&#8217;ll be interesting nonetheless.</p>
<p>Here is the video of the test:</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/h_yWXkBOys8?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/h_yWXkBOys8?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/267/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Blackberry Programming: Increasing Video Speed Through Prerendering</title>
		<link>http://www.toniwestbrook.com/archives/249</link>
		<comments>http://www.toniwestbrook.com/archives/249#comments</comments>
		<pubDate>Sun, 29 Aug 2010 04:34:54 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/?p=249</guid>
		<description><![CDATA[A Problem of Efficiency As I finishing up the full version of Galactic Blast (screenshots on this soon, its a fully fleshed out game inspired by the demo, to be released on App World) &#8211; I ran into an issue in a strange area. The animation was smooth throughout the game, except oddly enough, on [...]]]></description>
			<content:encoded><![CDATA[<p><b> A Problem of Efficiency </b></p>
<p>As I finishing up the full version of Galactic Blast (screenshots on this soon, its a fully fleshed out game inspired by the demo, to be released on App World) &#8211; I ran into an issue in a strange area.  The animation was smooth throughout the game, except oddly enough, on the instructions screen.</p>
<p>The instructions screen in Galactic Blast includes some text describing the storyline, some text describing the keyboard controls, bitmaps showing each of the enemies and power ups with description text, and some credits at the end.  Since there&#8217;s much more than can fit on a single screen, the user can scroll up and down &#8211; nothing fancy, just your basic instructions screen.  However, the scrolling was anything but smooth.  As I debugged more, I found out that redrawing all the bitmaps and text at each scroll was simply taking too long &#8211; all the function and helper calls involved in rendering everything was just too much for the processor.  </p>
<p><b> The Solution</b></p>
<p>As I thought more about it, I realized that it would be much better to simply render one item instead of 20-30 items each time.  And since instructions are static in nature (they don&#8217;t change or animate), it was a prime candidate for prerendering all the text and bitmaps to a single, big bitmap.  However, I wanted the program to prerender the items automatically at runtime &#8211; I didn&#8217;t want to have to create the bitmap manually (which would be a huge pain anytime I needed to edit something &#8211; like adding a new line of text in).  The code below achieves this by creating a bitmap in memory and rendering all the desired text/images to it at the start of the program, and then simply displays (and scrolls) this bitmap on the instructions screen.</p>
<p><b> The Code </b></p>
<p>I&#8217;ve removed the specific text, bitmaps, and positioning from the code to make things a little clearer:</p>
<div style="font-size:10px">
<pre class="brush: java">

// _instructionsBM is the large bitmap we will be rendering all our text
// and images to.  This is the bitmap we will actually
// display on the instructions screen, thereby increasing efficiency
// since we&#039;re only redrawing one bitmap each time the
// player scrolls instead of a bunch of bitmaps.
private static Bitmap _instructionsBM;

   public static void prerenderInstructions() {
      Graphics tempGraphics;
      String objectiveString;
      Bitmap tempBitmap;
      Object castArray[][];     

      // Populate a string with the objective of the game
      objectiveString = &quot;Text describing the objective of the game  &quot;;

      // Populate an array with the enemy bitmaps, their names,
      // and how many points they are
      castArray = new Object[2][];
      castArray[0] = new Object[] { enemyBitmap1, &quot;Enemy 1&quot;, &quot;50 Points&quot; };
      castArray[1] = new Object[] { enemyBitmap2, &quot;Enemy 2&quot;, &quot;75 Points&quot; };

        // Initialize the bitmap, and then give it an alpha channel for
        // transparency, allowing the background to show through
        // behind the text and bitmaps
       _instructionsBM = new Bitmap(Bitmap.ROWWISE_16BIT_COLOR, WIDTH, HEIGHT);
       _instructionsBM.createAlpha(Bitmap.ALPHA_BITDEPTH_8BPP); 

        // Start with a blank, completely transparent image
      _instructionsBM.setARGB(new int[_instructionsBM.getWidth()*_instructionsBM.getHeight()], 0,
                                             _instructionsBM.getWidth(), 0, 0,
                                             _instructionsBM.getWidth(), _instructionsBM.getHeight());

      // The Graphics object acts a surface that drawing operations
      // can be performed on.  By calling the Graphics constructor
      // with the bitmap as an argument, all drawing operations
      // will be performed upon the bitmap itself.
      tempGraphics = new Graphics(_instructionsBM);

      // All operations to follow will be fully opaque (so pixels not
      //acted upon will stay transparent, while any text/images drawn
      // will be solid.
      tempGraphics.setGlobalAlpha(255);

      // Draw the text onto the bitmap
      tempGraphics.setColor(Color.YELLOW);
      tempGraphics.drawText(objectiveString, 5, 5);    

      // Draw enemy bitmaps onto the bitmap
      for (int lcv = 0 ; lcv &lt; castArray.length ; lcv++) {
         tempBitmap = (Bitmap) castArray[lcv][0];
         tempGraphics.drawBitmap(Utils.getDimension(5, 50+lcv*50,
                                                tempBitmap.getWidth(), tempBitmap.getHeight(), tempBitmap, 0, 0);
         tempGraphics.drawText((String) castArray[lcv][1], 100, 50+lcv*50);
         tempGraphics.drawText((String) castArray[lcv][1], 200, 50+lcv*50);
      }
   }
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/249/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blackberry Programming: Alter Bitmap Color on the Fly</title>
		<link>http://www.toniwestbrook.com/archives/169</link>
		<comments>http://www.toniwestbrook.com/archives/169#comments</comments>
		<pubDate>Sun, 21 Feb 2010 21:25:04 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/archives/169</guid>
		<description><![CDATA[While working on my current Blackberry game, I ran into a situation where I needed to change the color of of a bitmap. Specifically, I wanted to signify an object was &#8220;hit&#8221; by temporarily tinting it red &#8211; i.e. I wanted to keep the original bitmap color pattern, but wanted to increase the red portion [...]]]></description>
			<content:encoded><![CDATA[<p>While working on my current Blackberry game, I ran into a situation where I needed to change the color of of a bitmap.  Specifically, I wanted to signify an object was &#8220;hit&#8221; by temporarily tinting it red &#8211; i.e. I wanted to keep the original bitmap color pattern, but wanted to increase the red portion of all the pixels so it had a red shade to it.  </p>
<table style="width:100%;padding-bottom:30px">
<tr>
<td colspan=2 align=center>Example</td>
</tr>
<tr>
<td align=center><a href='http://www.toniwestbrook.com/wp-content/uploads/2010/02/fighter.jpg' title='Fighter - Before'><img src='http://www.toniwestbrook.com/wp-content/uploads/2010/02/fighter.jpg' alt='Fighter - Before' /></a><br />Before</td>
<td align=center><a href='http://www.toniwestbrook.com/wp-content/uploads/2010/02/fighterred.jpg' title='Fighter - After'><img src='http://www.toniwestbrook.com/wp-content/uploads/2010/02/fighterred.jpg' alt='Fighter - After' /></a></a><br />After</td>
</tr>
</table>
<p><b> ARGB Methods </b></p>
<p>Off the bat, I couldn&#8217;t find any method of directly altering the bitmap color using built in routines.  There are a few routines for altering the alpha channel of bitmaps, but nothing for the color channels.  After sifting through all the members of the Bitmap class, I came across the <a href="http://www.blackberry.com/developers/docs/4.0.2api/net/rim/device/api/system/Bitmap.html#getARGB%28int[],%20int,%20int,%20int,%20int,%20int,%20int%29">getARGB</a> method (see link for details).  This method will populate an int array with argb data, e.g. an int (4 bytes) per pixel signifying the alpha, red, green, and blue values (each value stored per byte).  And sure enough, there is a <a href="http://www.blackberry.com/developers/docs/4.0.2api/net/rim/device/api/system/Bitmap.html#setARGB%28int[],%20int,%20int,%20int,%20int,%20int,%20int%29">setARGB</a> method as well, for taking such an int array and applying it to a bitmap object.  </p>
<p><b> The Strategy </b></p>
<p>With these methods at our disposal, it now becomes a matter of populating an array with ARGB data, then altering each int in the manner desired to achieve a specific effect. In this case, increasing the value of the RED byte (2nd byte) to increase the red tint of each pixel.  However, the sky is the limit, as you could alter transparency for each pixel (alpha byte) and create a disintegration effect, average and equalize each of the color bytes to create greyscale, invert the colors, dim/brighten, etc.  However, for now, lets stick to adding a red tint.</p>
<p><b> The Code </b></p>
<div style="font-size:10px">
<pre class="brush: java">
 public static Bitmap generateHitBitmap(Bitmap passBitmap) {
      Bitmap retBitmap;  // Altered, tinted bitmap being returned
      int[] argbData; // Array holding the ARGB data
      int redData;  // The red value of a pixel

      // Create a new, empty bitmap with the same dimensions
      retBitmap = new Bitmap(passBitmap.getType(), passBitmap.getWidth(), passBitmap.getHeight());

      // Prepare the ARGB array
      argbData = new int[passBitmap.getWidth() * passBitmap.getHeight()];

      // Grab the ARGB data
      passBitmap.getARGB(argbData, 0, passBitmap.getWidth(), 0, 0, passBitmap.getWidth(), passBitmap.getHeight());

      // Loop through each pixel in the array
      for (int lcv = 0 ; lcv &lt; argbData.length ; lcv++) {
         // Get the red data by masking out the 2nd byte
         redData = (argbData[lcv] &amp; 0x00FF0000) &gt;&gt; 16;

         // Increase the red value by 80 (maximum of 255)
         redData += 80;
         if (redData &gt; 255) redData = 255;

         // Shift it back to the right place, and set it back into array
         redData = redData &lt;&lt; 16;
         argbData[lcv] = (argbData[lcv] &amp; 0xFF00FFFF) + redData;
      }

      //  Set the return Bitmap to use this altered ARGB array
      retBitmap.setARGB(argbData, 0, passBitmap.getWidth(), 0, 0, passBitmap.getWidth(), passBitmap.getHeight());

      return retBitmap;
   }
</pre>
</div>
<p>Note: There is some bitwise math going on here, and a few ways to accomplish this.  I like to isolate out the value first and work with it separately, but you may feel more comfortable working directly with the array &#8211; either works.  </p>
<p>Please feel free to share any cool effects you&#8217;ve achieved altering the ARGB data, or even constructing completely new ARGB data on the fly &#8211; I would love to see programmatically generated bitmaps! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/169/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating a Blackberry GPS Tracker</title>
		<link>http://www.toniwestbrook.com/archives/126</link>
		<comments>http://www.toniwestbrook.com/archives/126#comments</comments>
		<pubDate>Tue, 27 Jan 2009 04:22:50 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/archives/126</guid>
		<description><![CDATA[As I mentioned in my article about Creating a Blackberry Game, I love this mobile phone and writing programs for it. The device has a serious amount of untapped potential. That&#8217;s not to say the phone isn&#8217;t already a great tool for its intended purposes (I don&#8217;t think I could make it without mine these [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned in my article about <a href="http://www.toniwestbrook.com/archives/69">Creating a Blackberry Game</a>, I love this mobile phone and writing programs for it.  The device has a serious amount of untapped potential.  That&#8217;s not to say the phone isn&#8217;t already a great tool for its intended purposes (I don&#8217;t think I could make it without mine these days), but with the capabilities it has, there are a lot of creative ways it could be used for unconventional purposes.</p>
<p><b> Global Positioning System </b></p>
<p>One great feature of many modern Blackberrys is the built in GPS.  This is an awesome technology for navigation &#8211; I don&#8217;t have a GPS in the car and my phone has saved my butt on a number of occasions.  However, past that, think about the power this really gives.  We&#8217;re starting to take positioning for granted these days, but the ability to pinpoint your exact location wherever you are is amazingly powerful.  And not only for navigation &#8211; we have seen a number of very inventive programs popping up lately from trackers that pinpoint a lost/stolen phone, to photo tagging to attach a location to a picture taken.  I&#8217;ve had lots of conversations with people as well who have great ideas for unique uses of GPSes.  We&#8217;re definitely not even close to exhausting this functionality in the Blackberry.</p>
<p><b> Writing a GPS Program </b></p>
<p>When I first got my phone, I wanted to write a program to make use of the GPS.  I decided I&#8217;d write a little tracker program, basically to continually read my current coordinates and post them to a website in realtime (that&#8217;s the other amazing piece about a Blackberry, the fact that you have an Internet connection whenever in cell range).  The website would display these points on a google map, and people could see my current location and where I&#8217;d been (and how fast I was going!).  It was a fun project, amazingly easy, and worked right off the bat!</p>
<p>Below is a very quick and dirty program to get the job done.  It is not meant to be a polished product &#8211; it was a quick test, and I present it here as information on how to grab coordinates and upload them to a website.  If you decide to make your own project, you&#8217;ll want to write the code a little more cleanly and organized &#8211; but this should give some tips on how the libraries are used.  I&#8217;ve added lots of commenting to explain things as I go.</p>
<p>Also &#8211; a portion of the GPS code is grabbed from the RIM site I believe, though it was a long time ago and I&#8217;m not sure where.  No disrespect to any code I&#8217;ve copied &#8211; if you find the original source, please post it and I&#8217;ll credit it.</p>
<div style="font-size:10px">
<pre class="brush: java">

tracker.java

package com.syntheticdreams.tracker;

/* This project makes use of many standard javax libraries, especially in reading the GPS.
** The microedition package in javax contains a number of mobile device related libraries, including the
** location package, which has methods specially designed for working with coordinates and
** pulling them from a GPS.  The Blackberry supports the use of this package interfacing with its GPS (for
** providers that have not locked the phone.  Verizon has, until recently, locked the GPS of many of its models
** from use by third party applications.)  The rest of our package importing is mainly for the user interface. */
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import javax.microedition.location.*;
import javax.microedition.location.Location.*;
import javax.microedition.location.Criteria.*;
import javax.microedition.io.*;
import java.util.*;

// The UiApplication is a class designed for presenting a user interface to the user and maintaining screens on a stack.
// See Creating a Blackberry Game - Part 2 for more info (http://www.toniwestbrook.com/archives/71)
public class tracker extends UiApplication
{
    // Our main method is always called first, starts the ball rolling
    public static void main(String[] args)
    {
        // Create a new instance of the main &quot;tracker&quot; class, pushes the main screen onto the stack
        tracker trackerApp = new tracker();

        // Enter the event dispatcher to intercept key and trackball events
        trackerApp.enterEventDispatcher();
    }

    public tracker()
    {
        // See startScreen class below, our main screen where the magic takes place.  Push it onto the stack so
        // the user sees it and the instance of the class starts running and processing.
        pushScreen(new startScreen());
    }
} 

// Our only screen to be pushed on the screen stack
final class startScreen extends MainScreen
{
    // A timer that will continually poll the GPS
    Timer updateTimer = new Timer(); 

    // The specific task for our timer where the dirty work takes place
    TimerTask updateTask = new TimerTask()
    {
        // The run method is what is actually run by the timer every time it resets
        public void run()
        {
            LocationProvider lp; // LocationProvider does the actual work of reading coordinates from the GPS
            Location currentLoc; // Stores component information of our position
            Criteria cr = new Criteria(); // Settings for the GPS - we can read it at different accuracy levels
            HttpConnection httpConn;  // An HTTP socket connection class to send our results to a webserver
            String getStr; 

            // I basically set no requirements on any of the horizontal, vertical, or power consumption requirements below.
            // The distance components are set in meters if you do want to establish accuracy - the less the accuracy, the
            // quicker and more likely a successful read (I believe).
            // You can also set power consumption, between low, medium, high (or no requirement)
            // There are also a number of other settings you can tweak such as minimum response time, if altitude is required,
            // speed required, etc.  It all depends on the exact application you&#039;re writing and how specific you need the info to
            // be.  For our purposes, a rough coordinate is good enough.
            cr.setCostAllowed(true);
            cr.setHorizontalAccuracy(javax.microedition.location.Criteria.NO_REQUIREMENT);
            cr.setVerticalAccuracy(javax.microedition.location.Criteria.NO_REQUIREMENT);
            cr.setPreferredPowerConsumption(javax.microedition.location.Criteria.NO_REQUIREMENT);

            try
            {
                // Get a new instance of the location provider using the criteria we established above.
                lp = LocationProvider.getInstance(cr);

                // Now populate our location object with our current location (with a 60 second timeout)
                currentLoc = lp.getLocation(60);
            }

            // If we hit the timeout or encountered some other error, report it.
            catch(LocationException e)
            {
                Dialog.alert(&quot;Error getting coordinates&quot;);
                return;
            }

            // If reading the GPS was interrupted, report it
            catch(InterruptedException e)
            {
                Dialog.alert(&quot;GPS Interrupted!&quot;);
                return;
            }

            // If we made it here, we got a successful read.  I transmit it to a webserver via a simple querystring.
            try
            {
                // I build the querystring here
                // set the &quot;lat&quot; querystring var with the latitude from getLatitude
                getStr = &quot;lat=&quot; + currentLoc.getQualifiedCoordinates().getLatitude();

                //lon with longitude
                getStr = getStr + &quot;&amp;lon=&quot; + currentLoc.getQualifiedCoordinates().getLongitude();

                // alt with altitude
                getStr = getStr + &quot;&amp;alt=&quot; + currentLoc.getQualifiedCoordinates().getAltitude();

                // vel with speed
                getStr = getStr + &quot;&amp;vel=&quot; + currentLoc.getSpeed();

                // Now I establish an http connection the webserver running a server side script that can read the values from
                // the querystring and save them to a database.  In my case, I had a simple ASP page that wrote them to a MSSQL
                // database - this database being read by another webpage that printed said coordinates out on a google map.
                // But you could do the same with PHP, PERL, or any other server side language of your choice.
                httpConn = (javax.microedition.io.HttpConnection) javax.microedition.io.Connector.open(&quot;http://www.yourwebsitehere.com/yourpage.asp?&quot; + getStr);

                // Just an easy GET with a querystring.
                httpConn.setRequestMethod(HttpConnection.GET);

                // Set HTTP values
                httpConn.setRequestProperty(&quot;Connection&quot;,&quot;close&quot;);
                httpConn.setRequestProperty(&quot;Content-Length&quot;,&quot;0&quot;);

                // Make the request (e.g. send the data)
                httpConn.getResponseCode();

                // Close the socket
                httpConn.close();
            }

            // If there was an error contacting the webserver, post it
            catch (java.io.IOException e)
            {
                Dialog.alert(&quot;Error contacting web server&quot;);
                return;
            }
        }
    };

    // Our main screen&#039;s constructor
    public startScreen()
    {
        super();

        // Set the window&#039;s title
        LabelField title = new LabelField(&quot;GPS Tracker&quot;, LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
        setTitle(title);

        // Feel free to snazz up your program with your own messages or real time info from the GPS
        add(new RichTextField(&quot;Starting transmission...&quot;));

        // Add the update task to the update timer, running it starting in 10 milliseconds, and then every
        // 240000 milliseconds (4 minutes)
        updateTimer.scheduleAtFixedRate(updateTask, 10, 240000);
    }

    // Cleanup on close
    public boolean onClose()
    {
       Dialog.alert(&quot;Transmission Ended!&quot;);
       System.exit(0);
       return true;
    }
}
</pre>
</div>
<p>Nothing too bad &#8211; but very powerful!  I hope this helps a bit on the road to making cool GPS applications!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/126/feed</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Creating a Blackberry Game &#8211; Part 6</title>
		<link>http://www.toniwestbrook.com/archives/75</link>
		<comments>http://www.toniwestbrook.com/archives/75#comments</comments>
		<pubDate>Sun, 04 May 2008 02:51:24 +0000</pubDate>
		<dc:creator>Toni</dc:creator>
				<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://www.toniwestbrook.com/archives/75</guid>
		<description><![CDATA[Looking for part 5? Let&#8217;s Hear It! Our game is almost done &#8211; the only part left is the sound (and vibration) processing. This is a fairly simple class as well &#8211; again, most of the low level processing is done already by the Blackberry. However &#8211; you may want to play with the methods [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.toniwestbrook.com/archives/74">Looking for part 5?</a></p>
<p><strong>Let&#8217;s Hear It!</strong></p>
<p>Our game is almost done &#8211; the only part left is the sound (and vibration) processing.  This is a fairly simple class as well &#8211; again, most of the low level processing is done already by the Blackberry.  However &#8211; you may want to play with the methods in this class.  We have functionality for playing a midi file &#8211; and we could also have functionality for playing a wav file as well, but I haven&#8217;t included it.  The reason &#8211; on my 8830, the sound engine (at least the way I was using it), could only seem to mix one sound at a time, and completely stopped the other sound if a second one was played.  There may be specific methods to mix two sounds together that I did not research, or otherwise it&#8217;s a limitation/bug of the 8830.  So, if music was playing, and I then played a wav sound effect, the music would stop.  </p>
<p>I overcame this by using the Alert.startAudio method.  This takes frequency/duration pairs from an array and plays simple sounds with it.  When this method is used, it does indeed mix the audio with the midi playing in the background, so I stuck with it.  It makes for less sophisticated sound effects, but it helps us for now.  </p>
<p>Additionally, I wanted to include vibration in the game, so I included a small method for triggering this off.  Vibration is used for when spaceships explode, either yours or the enemy&#8217;s.  </p>
<p>SND.java</p>
<div style="font-size:10px">
<pre class="brush: java">
package com.synthdreams.GalacticBlast;

import net.rim.device.api.ui.component.Dialog;
import java.io.InputStream;
import java.lang.Class;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import net.rim.device.api.system.Alert;

// Sound engine
class SND {

    Player _musicPlayer; // Java media player

    SND() { }

    // Play a midi file for background music
    void playMusic(String passMusic)
    {
        try
        {
            // Set InputStream to a midi file included as resource, as specified by
            // passMusic
            InputStream in = getClass().getResourceAsStream(&quot;/&quot; + passMusic);            

            // Create a media player with mime type of audio/midi using our inputstream
            _musicPlayer = javax.microedition.media.Manager.createPlayer(in, &quot;audio/midi&quot;);

            // Ready the data and start playing it.  To loop indefinitely, we set loopcount
            // to -1.
            _musicPlayer.realize();
            _musicPlayer.prefetch();
            _musicPlayer.setLoopCount(-1);
            _musicPlayer.start();

        }
        catch (Exception e)
        {
            Dialog.alert(&quot;Error playing music&quot;);
        }
    }

    // Stop playing music
    void stopMusic()
    {
        try
        {
            // Tell player to stop playing
            _musicPlayer.stop();

        }
        catch (Exception e)
        {
            Dialog.alert(&quot;Error stopping music&quot;);
        }

        // Then release the data and close out the player
        _musicPlayer.deallocate();
        _musicPlayer.close();
    }

    // The Playsound method plays a simple combinations of tones to simulate a firing
    // noise.  This was necessary, as due to a bug or limitation of the BlackBerry 8830
    // (the phone I do my testing on), playing a WAV file stopped the midi player and
    // any other sound effects.  Player doesn&#039;t appear to mix properly (if at all).  However,
    // a midi file can be played while using the Alert objects startAudio method which
    // can play a sequence of tones, so this is what we&#039;ve done for now.
    void playSound()
    {
        // A sequence of frequencies and durations (eg 1400hz for 15ms, 1350hz for 15ms, etc)
        short[] fire = {1400, 15, 1350, 15, 1320, 20, 1300, 20, 1250, 25, 1200, 35};

        try
        {
            Alert.startAudio(fire, 100);

        }
        catch (Exception e)
        {
            Dialog.alert(&quot;Error playing sound effect.&quot;);
        }   

    }

    // Activates the phone&#039;s vibration functionality for a specific number of ms
    void vibrate(int passMilli)
    {
        Alert.startVibrate(passMilli);
    }
}
</pre>
</div>
<p>Nothing too complex at all going on here.  You may wonder what all the player initialization methods are doing &#8211; they deal mainly with making sure the sound data is available and buffered before playing.  Just call them in order and you&#8217;re good to go.</p>
<p><strong> That&#8217;s All Folks! </strong></p>
<p>At this point, you have all the basic functionality necessary for making whatever kind of Blackberry game you&#8217;d like.  Your logic may have to be much more complex, and you may have to include additional classes to accommodate everything, but the basic principles stay the same.  Also &#8211; all the classes used here are unsigned and available without a license from Research in Motion, which means you can make, play, and distribute these games for free.  </p>
<p>Feel free to comment if you have any questions, or even suggestions!  These were my own experiences and suggestions with creating a Blackberry game, but you might have your own!  Thanks for checking out this tutorial, good luck &#8211; and most importantly, have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toniwestbrook.com/archives/75/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>

