ToneControl is the interface to enable playback of a
user-defined monotonic tone sequence.
A tone sequence is specified as a list of tone-duration pairs and
user-defined sequence blocks. The list is packaged as an
array of bytes. The setSequence method is used to
input the sequence to the ToneControl . In addition,
the tone sequence format specified below can also be used as a
file format to define tone sequences. A file containing a
tone sequence as specified must use ".jts" as the file extension.
"audio/x-tone-seq" designates the MIME type for this
format.
The syntax of a tone sequence is described in
Augmented BNF notations:
sequence = version *1tempo_definition *1resolution_definition
*block_definition 1*sequence_event
version = VERSION version_number
VERSION = byte-value
version_number = 1 ; version # 1
tempo_definition = TEMPO tempo_modifier
TEMPO = byte-value
tempo_modifier = byte-value
; multiply by 4 to get the tempo (in bpm) used
; in the sequence.
resolution_definition = RESOLUTION resolution_unit
RESOLUTION = byte-value
resolution_unit = byte-value
block_definition = BLOCK_START block_number
1*sequence_event
BLOCK_END block_number
BLOCK_START = byte-value
BLOCK_END = byte-value
block_number = byte-value
; block_number specified in BLOCK_END has to be the
; same as the one in BLOCK_START
sequence_event = tone_event / block_event /
volume_event / repeat_event
tone_event = note duration
note = byte-value ; note to be played
duration = byte-value ; duration of the note
block_event = PLAY_BLOCK block_number
PLAY_BLOCK = byte-value
block_number = byte-value
; block_number must be previously defined
; by a full block_definition
volume_event = SET_VOLUME volume
SET_VOLUME = byte-value
volume = byte-value ; new volume
repeat_event = REPEAT multiplier tone_event
REPEAT = byte-value
multiplier = byte-value
; number of times to repeat a tone
byte-value = -128 - 127
; the value of each constant and additional
; constraints on each parameter are specified below.
VERSION ,
TEMPO ,
RESOLUTION ,
BLOCK_START ,
BLOCK_END ,
PLAY_BLOCK
SET_VOLUME
REPEAT
are pre-defined constants.
Following table shows the valid range of the parameters:
Parameter |
Valid Range |
Effective Range |
Default |
tempo_modifier |
5<= tempo_modifier <= 127 |
20bpm to 508bpm |
120bpm |
resolution_unit |
1<= resolution_unit <= 127 |
1/1 note to 1/127 note |
1/64 note |
block_number |
0<= block_number <= 127 |
- |
- |
note |
0<= note <= 127 or
SILENCE |
C-1 to G9 or rest |
- |
duration |
1<= duration <= 127 |
- |
- |
volume |
0<= volume <= 100 |
0% to 100% volume |
100% |
multiplier |
2<= multiplier <= 127 |
- |
- |
The frequency
of the note can be calculated from the following formula:
SEMITONE_CONST = 17.31234049066755 = 1/(ln(2^(1/12)))
note = ln(freq/8.176)*SEMITONE_CONST
The musical note A = note 69 (0x45) = 440 Hz.
Middle C (C4) and
SILENCE are defined as constants.
The duration of each tone is measured in units of 1/resolution notes
and tempo is specified in beats/minute, where 1 beat = 1/4 note.
Because the range of positive values of byte is only 1 - 127,
the tempo is
formed by multiplying the tempo modifier by 4. Very slow tempos
are excluded so range of tempo modifiers is 5 - 127 providing an
effective range of 20 - 508 bpm.
To compute the effective duration in milliseconds for a tone,
the following formula can be used:
duration * 60 * 1000 * 4 / (resolution * tempo)
The following table lists some common durations in musical notes:
Note Length |
Duration, Resolution=64 |
Duration, Resolution=96 |
1/1 |
64 |
96 |
1/4 |
16 |
24 |
1/4 dotted |
24 |
36 |
1/8 |
8 |
12 |
1/8 triplets |
- |
8 |
4/1 |
REPEAT 4 <note> 64 |
REPEAT 4 <note> 96 |
Example
// "Mary Had A Little Lamb" has "ABAC" structure.
// Use block to repeat "A" section.
byte tempo = 30; // set tempo to 120 bpm
byte d = 8; // eighth-note
byte C4 = ToneControl.C4;;
byte D4 = (byte)(C4 + 2); // a whole step
byte E4 = (byte)(C4 + 4); // a major third
byte G4 = (byte)(C4 + 7); // a fifth
byte rest = ToneControl.SILENCE; // rest
byte[] mySequence = {
ToneControl.VERSION, 1, // version 1
ToneControl.TEMPO, tempo, // set tempo
ToneControl.BLOCK_START, 0, // start define "A" section
E4,d, D4,d, C4,d, E4,d, // content of "A" section
E4,d, E4,d, E4,d, rest,d,
ToneControl.BLOCK_END, 0, // end define "A" section
ToneControl.PLAY_BLOCK, 0, // play "A" section
D4,d, D4,d, D4,d, rest,d, // play "B" section
E4,d, G4,d, G4,d, rest,d,
ToneControl.PLAY_BLOCK, 0, // repeat "A" section
D4,d, D4,d, E4,d, D4,d, C4,d // play "C" section
};
try{
Player p = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
p.realize();
ToneControl c = (ToneControl)p.getControl("ToneControl");
c.setSequence(mySequence);
p.start();
} catch (IOException ioe) {
} catch (MediaException me) { }
|