Kyocera KWS File Format Revision 2 - October 10, 2002 Written by Justin Heiner jheiner@yahoo.com http://merwin.bespin.org/t4a (Main Website-Contains RTTTL -> MIDI/KWS) http://ringtone.bespin.org (RTTTL Ringtone Website) I would like to send out greets to Ryan Sayre (http://skylab.org/~ryan), Brett Johnson, and Michael Plump. Without their initial framework specifications on the KWS format, I would not have been able to decode the rest of the format. PHONES AFFECTED: Qualcomm/Kyocera 2119, 2135, 2255, 3035, and maybe others HEADER: (Totals 6 Bytes) 1st to 4th bytes: Bit flipped length of file (32 bit) Basically, you come up with the length of the file as a 32 bit number, convert it into binary, and flip each bit (If it is a 1, make it a 0. If it is a 0 make it a 1). Then, take each hex byte and reverse it (bytes 1 2 3 4 get ordered as 4 3 2 1). Meaning, if your file length is 258, then in 32 bit hex it is 0x00000102. With the flipped bits, the hex is 0x0000FEFD. After the hex bytes are reversed, it is 0xFDFE0000. This is what you put into the first 4 bytes of the header. 5th and 6th bytes: Number of notes in the song (16 bit) Count the number of notes in the song and put it here as a 16 bit number. DO NOT flip the bits like you did in the 1st to 4th bytes. You do have to take each hex byte and reverse it (bytes 1 and 2 get ordered as 2 1). For example, if the song has 62 notes, the 16 bit hex is 0x003E. After the hex bytes are reversed, it is 0x3E00. This is what you put into the 5th and 6th header bytes. NOTE: (Totals 4 Bytes) 1st byte: Note (1 is middle c) 2nd byte: 00 = pause, 04 = note 3rd byte: 1st byte of duration. If byte 4 is equal to 0x00, then your duration is equal to the 3rd byte. For example, if byte 3 equals 0xFA and byte 4 equals 0x00, then your duration is 0xFA, or 250 milliseconds. If byte 4 does not equal 0x00, then you need to use the formula in the description of the next byte. 4th byte: 2nd byte of duration. The duration is calculated using the follwing method: Take the 4th byte and BitShift it Left 1. It is done with: myByte << 1 This will take a number like 00000011 and make it 00000110. Then take this new number and XOR it with the 3rd byte. Then tack on the old 4th byte before new number that we just made. Example: Let's say that the 3rd and 4th bytes = 0xDE 0x07 Take 0x07 (Binary 00000111) and BitShift it left. It now equals Binary 00001110. This is now our bitmask. The Binary of 0xDE is 11011110. We now do Bitmask XOR 0xDE. The equation of this looks like: 11011110 (0xDE) 00001110 (Bitmask) -------- 11010000 (New Partial Duration. Equivalent to 0xD0) We then take our original 4th byte and append it to the beginning of our new partial duration. This comes out to equal 0x07D0, which in Decimal equals 2000. If the song is 120BPM (Beats Per Minute), each QuarterNote equals 500 Milliseconds. That would mean that 2000 Milliseconds would equal a whole note. Basically, the RTTTL text for the note is: (Let's just say that the note is 1 (Middle C, or c4) MyNote:d=4,o=5,b=120:1c4 When converted from KWS to RTTTL, sometimes the notes durations are not correct if it is a fast song. Shorter notes get played quicker than they should. This is due to the conversion from milliseconds to normal note duration. I'm sure there is a way around this, but it would require a more complicated algorythm for determing the milliseconds to rtttl duration. (To encode a number INTO KWS duration, see Note ** at the end of this file) FOOTER: (Totals 4 Bytes) Same as 1st to 4th bytes of the Header ------------------------------------------------------------------------------------- Note **: (ENCODING INTO KWS DURATION FROM A REGULAR NUMBER) If the duration that you're wanting to encode into KWS duration is less than or equal to 0xFF, then all you do is put the duration in the 3rd byte and 0x00 in the 4th byte. For example, if your duratin is 250, then the encrypted duration would be 0xFA00. If the duration is MORE than 0xFF, then use this example: Let's say that your duration is 2000 milliseconds, or 0x07D0. Take the first byte (0x07) and bitshift it left by 1 byte. You now have 0x0E, which is our bitmask (or 00001110 in binary) Take the 2nd byte, D0 ( or 11010000 in binary) and appy the bitmask to it. 11010000 (0xD0) 00001110 (0x0E) -------- 11011110 (0xDE) Take your newly created 0xDE and tack on the old first byte (0x07) to the end of it and you have 0xDE07, which is your encrypted duration.