Radios, Cell Phones, & Java

Among other tricks, Java's Advanced Multimedia API lets you turn a mobile device (such as your cell phone) into an AM/FM radio.


June 01, 2006
URL:http://www.drdobbs.com/embedded-systems/radios-cell-phones-java/188700762

Tea is a consultant focusing on security and mobile technology. He can be contacted at [email protected].


The Advanced Multimedia Supplements (JSR-234) is a Java API that provides 30 controls for applications ranging from cameras and media postprocessing to radio tuners and advanced audio (www.jcp.org/en/jsr/detail?id=234). In this article, I focus on TunerControl—the control that lets you create applications that utilize the radios built into mobile devices such as cell phones. To that end, I present an example application called "AMMS Radio" that demonstrates turning on/off the radio, switching between stereo and mono reception, manipulating radio station presets, autodialing to radio stations, and other activities, which will be described in this article. The complete source code and related files that implement AMMS Radio are available at http://www.ddj.com/code/.

Before building any radio applications, however, you need to confirm Advanced Multimedia Supplements (AMMS) and modulation support. For AMMS support, use the system properties to verify the AMMS version and AMMS media capabilities:


System.getProperty
   ("microedition.amms.version");
System.getProperty
   ("supports.mediacapabilities");


The current version is "1.0," and the media capabilities must include "tuner" in the return list.

The application should also use tuner.modulations to check for the modulations supported by the phone:


System.getProperty
   ("tuner.modulations");


Currently, AMMS 1.0 only supports AM and FM modulations.

Once these capabilities are verified, you need to initiate TunerControl by creating a Mobile Media API (MMAPI) player for the built-in radio. You then construct the radio player by setting the player to the REALIZED state. Finally, you create the AMMS TunerControl from the radio player:


Player radioplayer =     Manager.createPlayer(
      "capture://radio");
radioplayer.realize();
tunerControl = 
   (TunerControl) radioplayer.getControl(
      "TunerControl");

Because the radio can only be started from a PREFETCHED state, use the getState() method to check the state of the radio player:


if (radioplayer.getState()==
      radioplayer.PREFETCHED)
{
   try { radioplayer.start(); 
   } catch (Exception e) {}
}


The radio player can only be in one of four states—REALIZED, PREFETCHED, STARTED, or CLOSED. When the radio is started, its state changes to STARTED. When the radio is stopped, it switches back to PREFETCHED. To stop the radio:


if (radioplayer.getState()==
      radioplayer.STARTED)
{
   try { radioplayer.stop(); 
   } catch (Exception e) {}
}


Tuner Range And Region

The minimum and maximum frequency of a modulation supported by the cell phone's radio can be retrieved using TunerControl's getMinFreq() and getMaxFreq() methods. Keep in mind that the frequency returned is in units of 100 Hertz. To convert it to MHz, divide the value by 10,000; for instance, 879,000 in 100 Hertz ~ 87.9 MHz:


int minFreq = 
   tunerControl.getMinFreq
   (TunerControl.MODULATION_FM);
int maxFreq = 
   tunerControl.getMaxFreq
   (TunerControl.MODULATION_FM);

Similarly for AM modulation:


int minFreq = 
   tunerControl.getMinFreq
   (TunerControl.MODULATION_AM);
int maxFreq = 
   tunerControl.getMaxFreq
   (TunerControl.MODULATION_AM);


Some applications may need to know which region the radio is equipped for:


if ((minFreq<=879000) && 
   (maxFreq>=1079000))
   tuningRegion= "US";
if ((minFreq<=879000) && 
   (maxFreq>=1080000))
   tuningRegion="Europe";
if ((minFreq<=760000) && 
   (maxFreq>=900000))
   tuningRegion="Japan";


Low-Signal Strength

There may be times when radio reception is substandard, such as when users go underground or between buildings. In such cases, radio reception can be hazy and the audio fuzzy. Luckily, there are parameters you can control to make the reception clearer and more audible. However, you first need to detect the signal strength. Fortunately, this information is easily obtained using TunerControl's getSignalStrength(). The signal strength indicator ranges from 0-100, with 0 being no reception and 100 being the best. For instance, to trigger corrective measures when the signal strength falls below 50 percent:


if (tunerControl
   .getSignalStrength()<50)
{
   ...
}

When the application determines that the reception is not acceptable, you can switch the stereo reception off and go to mono. This prevents the "wobbling" effect as the left and right channels drop off alternately. Do the switch using TunerControl's setStereoMode() method with the parameter TunerControl.MONO:


tunerControl.setStereoMode
   (TunerControl.MONO);

When the reception is weak, the volume tends to fade and becomes soft as well. To counteract this, you can have the application boost the volume. There are two basic approaches you can take—boosting the volume to the maximum, or incrementing it from the current volume setting. In either case, the first thing you have to do is get the MMAPI volume control of the radio player if it was not created earlier:


VolumeControl volumeControl = 
  (VolumeControl)radioplayer.
   getControl"VolumeControl");

Once you have the volume control, you can read the current volume level. This ranges from 0-100 with 100 being the loudest and 0 being mute. Thus, to increment the volume, you add a positive numeric value to the current volume level:

int currentVolume = 
   volumeControl.getLevel();
currentVolume = 
   volumeControl.setLevel
   (currentVolume + 10);

Or if we are just setting the volume to maximum:


int currentVolume = volumeControl.setLevel(100);

Combining all the previous actions, the end result is:


if (tunerControl.
   getSignalStrength()<50)
{
   tunerControl.setStereoMode
   (TunerControl.MONO);
   int currentVolume = 
   volumeControl.getLevel();
   currentVolume = 
   volumeControl.setLevel
   (currentVolume + 10);
}

Enhancing Listener Interaction

To increase listener interaction with radio stations, a quick-launch interaction shortcut can be included in radio applications. For instance, instead of having to remember a radio station's call-in number, exiting the radio application, then keying in the number to call the radio station, you can configure a phone button for automatic dialing of call-in numbers at the radio station listeners are tuned to:

if (c == CMD_CALLSTATION) 
{
   ...
if (tunerControl.getFrequency()==
   911000) platformRequest("tel:5559110"); 
   ...
}

Similarly, a shortcut for sending SMS "votes" or song requests can be incorporated using the Wireless Messaging API (WMA). This saves users from having to remember SMS codes and formats to key in, as well as SMS numbers to send messages to. In this instance, the radio application has an internal record of that information as well as the radio station's SMS message templates:


if (c == CMD_MESSAGESTATION) 
{
   ...
   if (tunerControl.getFrequency()==9
   11000)
   {
      ...
      textMessage.setPayloadText

         ("vote " + choice);
      ...
   }
   ...
}

Tuner and Station Presets

The preset stations of the mobile phone's native radio tuner application can be set using TunerControl's setPreset() method. The required attributes are the preset number, radio frequency in units of 100 Hertz, AM/FM modulation, and stereo mode for the station. For instance, to preset channel 1 for an FM stereo radio station whose frequency is 91.1 MHz (where 911,000 = 91.1 MHz × 10,000):


tunerControl.setPreset(1, 911000, 
  TunerControl.MODULATION_FM, 
    TunerControl.STEREO);


On a new mobile phone just out of the box, you can assume that none of the radio presets are configured. However, if a phone has been in use, users may have manually configured one or more of the presets. Consequently, it is a good idea to ask/confirm with users before overwriting the presets.

To tune to radio stations in the preset list, simply call TunerControl's usePreset() method with the channel number of the preset:


tunerControl.usePreset(1);


However, if some presets are not set, users may end up hearing static when they tune in to a frequency with no broadcast. To mute those channels, use TunerControl's setSquelch() method with the Boolean parameter true:


tunerControl.setSquelch(true);

Configuring Presets Automatically

A useful function that radio applications can provide is the ability to automatically configure radio tuner presets. The reasons for doing so range from autosetting for user convenience in a given location, to a sophisticated marketing mechanism for promoting affiliated radio stations as listeners roam from state to state or country to country.

To begin with, the application needs to know how many preset channels are available on the mobile phone. This number varies from five to ten or more, and can be ascertained from TunerControl's getNumberOfPresets() method:


int NumberOfPresets = 
   tunerControl.
      getNumberOfPresets();


To preset a channel, you must have the radio station's various turning and interaction information. These data can be stored offline and locally on the phone, or obtained on-line/over-the-air via a wireless data network service, such as the General Packet Radio Service (GPRS).

Online Radio Station Database

For online query of the radio station's preset data, the radio application can prompt users for their geographical location via a text entry, or provide a list of likely locations. Better yet, the radio application can directly read the user's GPS coordinates via the JSR-179 Location API (www.ddj.com/ documents/s=9938/ddj0601i/0601i.html). Both of these approaches enable a database server to determine the location of listeners and return a list of radio stations with coverage in that area. In other words, this would be like "GSM roaming," except that it is "radio station roaming." The radio application will then replace and update the static (and most likely out-of-range) radio presets with radio station names and frequencies receivable and valid for the area that listeners are currently at.

For instance, assume users have just arrived at a new area where the available radio stations are:

If it was a purely utilitarian application, the radio application could simply update the preset in a sequential manner, using radio stations it encounters as it scans the spectrum from the lowest to the highest frequency. For example, if the tuner picks up the first station at 97.0 MHz and there is an entry for 97.0 MHz on the server's list, the application will set Preset 1 to 97.0 MHz with the corresponding radio station name indicated in the list ("KAAAA"), and so on.

If the radio application was sponsored or provided by a radio-station network, the server's database list could include only affiliated radio stations. Because the radio stations on 97.0 MHz and 104.6 MHz are not affiliates of the network "KFFFF," the sponsored application skips to the next station until it finds a station with a matching frequency that is an affiliate of the radio network. On the listener's phone, the preset eventually becomes Preset 1 at 110.5 MHz and the corresponding radio station name becomes "KCCCC."

Offline Radio-Station Database

The same "radio-station roaming" idea applies in offline scenarios, too, although the storage mechanism for the radio-station data differs and is more varied. The four main approaches are:


int RadioStationFrequency = 
   tunerControl.seek
      (prevFrequency, 
      TunerControl.
      MODULATION_FM, true);



tunerControl.setPresetName
   (1, "C-ROCK");
tunerControl.
   setFrequency(911000, 
   TunerControl.MODULATION_FM);
tunerControl.setStereoMode(
   TunerControl.AUTO);
tunerControl.setPreset(1);
callinNumber[1]="555-5555";

tunerControl.setPresetName
   (2, "Tennessee FM");
tunerControl.setFrequency
   (919000, TunerControl.
    MODULATION_FM);
tunerControl.setStereoMode
   (TunerControl.AUTO);
tunerControl.setPreset(2);
callinNumber[2]="555-5556";

tuner.setPresetName
   (3, "Easy Listening");
tuner.setFrequency(1046000, 
   TunerControl.MODULATION_FM);
tuner.setStereoMode
   (TunerControl.AUTO);
tuner.setPreset(3);
callinNumber[3]="555-5557";



tunerControl.setPresetName
   (1, getAppProperty
      ("PresetName.1"));
MIDlet-1: AMMS Radio, 
   AMMSRadio.png, AMMSRadio
MIDlet-Jar-Size: 14851
MIDlet-Jar-URL: AMMSRadio.jar
MIDlet-Name: AMMSRadio
MIDlet-Vendor: Tea Vui Huang
MIDlet-Version: 1.0
Frequency.1: 911000
Frequency.2: 919000
Frequency.3: 940000
PresetName.1: All Day News
PresetName.2: Elvis Lives
PresetName.3: Sports Live
CallinNumber.1: 555-5555

CallinNumber.2: 555-5556
CallinNumber.3: 555-5557


final InputStream is = 
   getClass().getResourceAsStream
      ("/presets.csv");

AMMS Development

At this writing, there are two emulators you can use for AMMS development—the Nokia JSR-234 Reference Implementation and Nokia Prototype SDK 4.0 (www.forum .nokia.com). Both device emulators simulate the AMMS on Series 60 mobile phones. The device name is "Prototype_4_0_S60 _MIDP_Emulator," and it includes the "amms.zip" library file that is needed to compile AMMS applications.

The emulators implement AMMS 1.0 and support FM only. Its frequency range spans from 87.5 KHz to 108.0 KHz, adequately covering the European region. (One thing to note during development and testing is that the emulator does not save station presets.)

There are four audio files used to emulate radio stations. The Nokia emulators play these radio tracks in a continuous loop as long as the mobile phone radio is on and tuned in. These audio files are located in "\devices\Prototype_4_0_S60_MIDP_Emulator\tuner" for the Nokia Prototype SDK and "\jsr234-ri_10b\ri\tuner" for the Nokia JSR-234 Reference Implementation.

To use a custom radio station, an existing radio station must be replaced. To do this, create the custom radio station's audio file using one of the filenames in Table 1. Then copy the file to the respective emulator's tuner directory. Table 2 lists the recommended audio format to use for simulating radio stations.

Mode RDS Frequency Radio Station Audio File
FM Yes 91.1 MHz C-ROCK rock.wav
FM Yes 91.9 MHz Tennessee FM country.wav
FM Yes 94.0 MHz Tennessee FM country.wav
FM No 100.0 MHz noise.wav
FM No 104.6 MHz Easy Listening easylistening_and_ta.wav
FM Yes 87.9 MHz Tennessee FM country.wav

Table 1: Creating audio files for custom radio stations.

Audio Format PCM
Sample Rate 16 kHz
Audio Sample Size 16 bit
Channels 1 (Mono)

Table 2: Recommended audio format to use for simulating radio stations.

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.