7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 1999, 2000 Hugh Blemings & Pavel JanÃk ml.
11 Released under the terms of the GNU GPL, see file COPYING for more details.
13 This file provides support for ringtones.
16 Revision 1.1.1.1 2001/11/25 21:58:59 short
17 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
19 Revision 1.13 2001/06/28 00:28:45 pkot
20 Small docs updates (Pawel Kot)
25 #include "fbus-6110-ringtones.h"
27 /* Beats-per-Minute Encoding */
29 int BeatsPerMinute[] = {
64 int FB61_OctetAlign(unsigned char *Dest, int CurrentBit)
68 while((CurrentBit+i)%8) {
69 ClearBit(Dest, CurrentBit+i);
76 int FB61_OctetAlignNumber(int CurrentBit)
80 while((CurrentBit+i)%8) {
87 int FB61_BitPack(unsigned char *Dest, int CurrentBit, unsigned char *Source, int Bits)
92 for (i=0; i<Bits; i++)
93 if (GetBit(Source, i))
94 SetBit(Dest, CurrentBit+i);
96 ClearBit(Dest, CurrentBit+i);
98 return CurrentBit+Bits;
101 int FB61_GetTempo(int Beats) {
105 while ( i < sizeof(BeatsPerMinute)/sizeof(BeatsPerMinute[0])) {
107 if (Beats<=BeatsPerMinute[i])
115 int FB61_BitPackByte(unsigned char *Dest, int CurrentBit, unsigned char Command, int Bits) {
117 unsigned char Byte[]={Command};
119 return FB61_BitPack(Dest, CurrentBit, Byte, Bits);
124 /* This is messy but saves using the math library! */
126 int FB61_GetDuration(int number, unsigned char *spec) {
133 duration=Duration_Full; *spec=DottedNote; break;
135 duration=Duration_Full; *spec=Length_2_3; break;
137 duration=Duration_Full; *spec=NoSpecialDuration; break;
139 duration=Duration_1_2; *spec=DoubleDottedNote; break;
141 duration=Duration_1_2; *spec=DottedNote; break;
143 duration=Duration_1_2; *spec=Length_2_3; break;
145 duration=Duration_1_2; *spec=NoSpecialDuration; break;
147 duration=Duration_1_4; *spec=DoubleDottedNote; break;
149 duration=Duration_1_4; *spec=DottedNote; break;
151 duration=Duration_1_4; *spec=Length_2_3; break;
153 duration=Duration_1_4; *spec=NoSpecialDuration; break;
155 duration=Duration_1_8; *spec=DoubleDottedNote; break;
157 duration=Duration_1_8; *spec=DottedNote; break;
159 duration=Duration_1_8; *spec=Length_2_3; break;
161 duration=Duration_1_8; *spec=NoSpecialDuration; break;
163 duration=Duration_1_16; *spec=DoubleDottedNote; break;
165 duration=Duration_1_16; *spec=DottedNote; break;
167 duration=Duration_1_16; *spec=Length_2_3; break;
169 duration=Duration_1_16; *spec=NoSpecialDuration; break;
171 duration=Duration_1_32; *spec=DoubleDottedNote; break;
173 duration=Duration_1_32; *spec=DottedNote; break;
175 duration=Duration_1_32; *spec=Length_2_3; break;
177 duration=Duration_1_32; *spec=NoSpecialDuration; break;
184 int FB61_GetNote(int number) {
195 note=Note_Cis; break;
199 note=Note_Dis; break;
205 note=Note_Fis; break;
209 note=Note_Gis; break;
213 note=Note_Ais; break;
218 else note = Note_Pause;
224 int FB61_GetScale(int number) {
231 /* Ensure the scale is valid */
240 /* This function packs the ringtone from the structure, so it can be set
241 or sent via sms to another phone.
242 Function returns number of packed notes and changes maxlength to
243 number of used chars in "package" */
245 u8 FB61_PackRingtone(GSM_Ringtone *ringtone, char *package, int *maxlength)
249 unsigned char CommandLength = 0x02;
251 int oldscale=10, newscale;
252 int HowMany=0, HowLong=0, StartNote=0, EndNote=0;
254 StartBit=FB61_BitPackByte(package, StartBit, CommandLength, 8);
255 StartBit=FB61_BitPackByte(package, StartBit, RingingToneProgramming, 7);
257 /* The page 3-23 of the specs says that <command-part> is always
259 StartBit=FB61_OctetAlign(package, StartBit);
261 StartBit=FB61_BitPackByte(package, StartBit, Sound, 7);
262 StartBit=FB61_BitPackByte(package, StartBit, BasicSongType, 3);
264 /* Packing the name of the tune. */
265 StartBit=FB61_BitPackByte(package, StartBit, strlen(ringtone->name)<<4, 4);
266 StartBit=FB61_BitPack(package, StartBit, ringtone->name, 8*strlen(ringtone->name));
268 /* Info about song pattern */
269 StartBit=FB61_BitPackByte(package, StartBit, 0x01, 8); /* One song pattern */
270 StartBit=FB61_BitPackByte(package, StartBit, PatternHeaderId, 3);
271 StartBit=FB61_BitPackByte(package, StartBit, A_part, 2);
272 StartBit=FB61_BitPackByte(package, StartBit, 0, 4); /* No loop value */
274 /* Info, how long is contents for SMS */
275 HowLong=30+8*strlen(ringtone->name)+17+8+8+13;
277 /* Calculate the number of instructions in the tune.
278 Each Note contains Note and (sometimes) Scale.
279 Default Tempo and Style are instructions too. */
280 HowMany=2; /* Default Tempo and Style */
282 for(i=0; i<ringtone->NrNotes; i++) {
284 /* PC Composer 2.0.010 doesn't like, when we start ringtone from pause:
285 it displays that the format is invalid and
286 hangs, when you move mouse over place, where pause is */
287 if (FB61_GetNote(ringtone->notes[i].note)==Note_Pause && oldscale==10) {
291 /* we don't write Scale info before "Pause" note - it saves space */
292 if (FB61_GetNote(ringtone->notes[i].note)!=Note_Pause &&
293 oldscale!=(newscale=FB61_GetScale(ringtone->notes[i].note))) {
295 /* We calculate, if we have space to add next scale instruction */
296 if (((HowLong+5)/8)<=(*maxlength-1)) {
305 /* We calculate, if we have space to add next note instruction */
306 if (((HowLong+12)/8)<=(*maxlength-1)) {
315 /* If we are sure, we pack it for SMS or setting to phone, not for OTT file */
316 if (*maxlength<1000) {
317 /* Pc Composer gives this as the phone limitation */
318 if ((EndNote-StartNote)==FB61_MAX_RINGTONE_NOTES-1) break;
322 StartBit=FB61_BitPackByte(package, StartBit, HowMany, 8);
325 StartBit=FB61_BitPackByte(package, StartBit, StyleInstructionId, 3);
326 StartBit=FB61_BitPackByte(package, StartBit, ContinuousStyle, 2);
328 /* Beats per minute/tempo of the tune */
329 StartBit=FB61_BitPackByte(package, StartBit, TempoInstructionId, 3);
330 StartBit=FB61_BitPackByte(package, StartBit, FB61_GetTempo(ringtone->tempo), 5);
336 for(i=StartNote; i<(EndNote+StartNote); i++) {
338 /* we don't write Scale info before "Pause" note - it saves place */
339 if (FB61_GetNote(ringtone->notes[i].note)!=Note_Pause &&
340 oldscale!=(newscale=FB61_GetScale(ringtone->notes[i].note))) {
342 StartBit=FB61_BitPackByte(package, StartBit, ScaleInstructionId, 3);
343 StartBit=FB61_BitPackByte(package, StartBit, FB61_GetScale(ringtone->notes[i].note), 2);
347 StartBit=FB61_BitPackByte(package, StartBit, NoteInstructionId, 3);
348 StartBit=FB61_BitPackByte(package, StartBit, FB61_GetNote(ringtone->notes[i].note), 4);
349 StartBit=FB61_BitPackByte(package, StartBit, FB61_GetDuration(ringtone->notes[i].duration,&spec), 3);
350 StartBit=FB61_BitPackByte(package, StartBit, spec, 2);
353 StartBit=FB61_OctetAlign(package, StartBit);
355 StartBit=FB61_BitPackByte(package, StartBit, CommandEnd, 8);
358 if (StartBit!=FB61_OctetAlignNumber(HowLong))
359 fprintf(stdout,_("Error in PackRingtone - StartBit different to HowLong %d - %d)\n"),StartBit,FB61_OctetAlignNumber(HowLong));
362 *maxlength=StartBit/8;
364 return(EndNote+StartNote);
368 int FB61_BitUnPack(unsigned char *Dest, int CurrentBit, unsigned char *Source, int Bits)
372 for (i=0; i<Bits; i++)
373 if (GetBit(Dest, CurrentBit+i)) {
379 return CurrentBit+Bits;
382 int FB61_BitUnPackInt(unsigned char *Src, int CurrentBit, int *integer, int Bits) {
386 for (i=0; i<Bits; i++) {
387 if (GetBit(Src, CurrentBit+i)) l=l+z;
396 int FB61_OctetUnAlign(int CurrentBit)
400 while((CurrentBit+i)%8) i++;
406 /* TODO: better checking, if contents of ringtone is OK */
408 GSM_Error FB61_UnPackRingtone(GSM_Ringtone *ringtone, char *package, int maxlength)
411 int spec,duration,scale;
415 StartBit=FB61_BitUnPackInt(package,StartBit,&l,8);
418 fprintf(stdout,_("Not header\n"));
420 if (l!=0x02) return GE_SUBFORMATNOTSUPPORTED;
422 StartBit=FB61_BitUnPackInt(package,StartBit,&l,7);
424 if (l!=RingingToneProgramming)
425 fprintf(stdout,_("Not RingingToneProgramming\n"));
427 if (l!=RingingToneProgramming) return GE_SUBFORMATNOTSUPPORTED;
429 /* The page 3-23 of the specs says that <command-part> is always
431 StartBit=FB61_OctetUnAlign(StartBit);
433 StartBit=FB61_BitUnPackInt(package,StartBit,&l,7);
436 fprintf(stdout,_("Not Sound\n"));
438 if (l!=Sound) return GE_SUBFORMATNOTSUPPORTED;
440 StartBit=FB61_BitUnPackInt(package,StartBit,&l,3);
442 if (l!=BasicSongType)
443 fprintf(stdout,_("Not BasicSongType\n"));
445 if (l!=BasicSongType) return GE_SUBFORMATNOTSUPPORTED;
447 /* Getting length of the tune name */
448 StartBit=FB61_BitUnPackInt(package,StartBit,&l,4);
451 /* Unpacking the name of the tune. */
452 StartBit=FB61_BitUnPack(package, StartBit, ringtone->name, 8*l);
455 StartBit=FB61_BitUnPackInt(package,StartBit,&l,8);
456 if (l!=1) return GE_SUBFORMATNOTSUPPORTED; //we support only one song pattern
458 StartBit=FB61_BitUnPackInt(package,StartBit,&l,3);
460 if (l!=PatternHeaderId)
461 fprintf(stdout,_("Not PatternHeaderId\n"));
463 if (l!=PatternHeaderId) return GE_SUBFORMATNOTSUPPORTED;
465 StartBit+=2; //Pattern ID - we ignore it
467 StartBit=FB61_BitUnPackInt(package,StartBit,&l,4);
470 StartBit=FB61_BitUnPackInt(package, StartBit, &HowMany, 8);
475 for (i=0;i<HowMany;i++) {
477 StartBit=FB61_BitUnPackInt(package,StartBit,&q,3);
479 case VolumeInstructionId:
482 case StyleInstructionId:
483 StartBit=FB61_BitUnPackInt(package,StartBit,&l,2);
486 case TempoInstructionId:
487 StartBit=FB61_BitUnPackInt(package,StartBit,&l,5); l=l>>3;
488 ringtone->tempo=BeatsPerMinute[l];
490 case ScaleInstructionId:
491 StartBit=FB61_BitUnPackInt(package,StartBit,&scale,2);
494 case NoteInstructionId:
495 StartBit=FB61_BitUnPackInt(package,StartBit,&l,4);
498 case Note_C :ringtone->notes[ringtone->NrNotes].note=0;break;
499 case Note_Cis:ringtone->notes[ringtone->NrNotes].note=1;break;
500 case Note_D :ringtone->notes[ringtone->NrNotes].note=2;break;
501 case Note_Dis:ringtone->notes[ringtone->NrNotes].note=3;break;
502 case Note_E :ringtone->notes[ringtone->NrNotes].note=4;break;
503 case Note_F :ringtone->notes[ringtone->NrNotes].note=6;break;
504 case Note_Fis:ringtone->notes[ringtone->NrNotes].note=7;break;
505 case Note_G :ringtone->notes[ringtone->NrNotes].note=8;break;
506 case Note_Gis:ringtone->notes[ringtone->NrNotes].note=9;break;
507 case Note_A :ringtone->notes[ringtone->NrNotes].note=10;break;
508 case Note_Ais:ringtone->notes[ringtone->NrNotes].note=11;break;
509 case Note_H :ringtone->notes[ringtone->NrNotes].note=12;break;
510 default :ringtone->notes[ringtone->NrNotes].note=255;break; //Pause ?
513 if (ringtone->notes[ringtone->NrNotes].note!=255)
514 ringtone->notes[ringtone->NrNotes].note=ringtone->notes[ringtone->NrNotes].note+scale*14;
516 StartBit=FB61_BitUnPackInt(package,StartBit,&duration,3);
518 StartBit=FB61_BitUnPackInt(package,StartBit,&spec,2);
520 if (duration==Duration_Full && spec==DottedNote)
521 ringtone->notes[ringtone->NrNotes].duration=128*3/2;
522 if (duration==Duration_Full && spec==Length_2_3)
523 ringtone->notes[ringtone->NrNotes].duration=128*2/3;
524 if (duration==Duration_Full && spec==NoSpecialDuration)
525 ringtone->notes[ringtone->NrNotes].duration=128;
526 if (duration==Duration_1_2 && spec==DottedNote)
527 ringtone->notes[ringtone->NrNotes].duration=64*3/2;
528 if (duration==Duration_1_2 && spec==Length_2_3)
529 ringtone->notes[ringtone->NrNotes].duration=64*2/3;
530 if (duration==Duration_1_2 && spec==NoSpecialDuration)
531 ringtone->notes[ringtone->NrNotes].duration=64;
532 if (duration==Duration_1_4 && spec==DottedNote)
533 ringtone->notes[ringtone->NrNotes].duration=32*3/2;
534 if (duration==Duration_1_4 && spec==Length_2_3)
535 ringtone->notes[ringtone->NrNotes].duration=32*2/3;
536 if (duration==Duration_1_4 && spec==NoSpecialDuration)
537 ringtone->notes[ringtone->NrNotes].duration=32;
538 if (duration==Duration_1_8 && spec==DottedNote)
539 ringtone->notes[ringtone->NrNotes].duration=16*3/2;
540 if (duration==Duration_1_8 && spec==Length_2_3)
541 ringtone->notes[ringtone->NrNotes].duration=16*2/3;
542 if (duration==Duration_1_8 && spec==NoSpecialDuration)
543 ringtone->notes[ringtone->NrNotes].duration=16;
544 if (duration==Duration_1_16 && spec==DottedNote)
545 ringtone->notes[ringtone->NrNotes].duration=8*3/2;
546 if (duration==Duration_1_16 && spec==Length_2_3)
547 ringtone->notes[ringtone->NrNotes].duration=8*2/3;
548 if (duration==Duration_1_16 && spec==NoSpecialDuration)
549 ringtone->notes[ringtone->NrNotes].duration=8;
550 if (duration==Duration_1_32 && spec==DottedNote)
551 ringtone->notes[ringtone->NrNotes].duration=4*3/2;
552 if (duration==Duration_1_32 && spec==Length_2_3)
553 ringtone->notes[ringtone->NrNotes].duration=4*2/3;
554 if (duration==Duration_1_32 && spec==NoSpecialDuration)
555 ringtone->notes[ringtone->NrNotes].duration=4;
557 if (ringtone->NrNotes==MAX_RINGTONE_NOTES) break;
563 fprintf(stdout,_("Unsupported block\n"));
565 return GE_SUBFORMATNOTSUPPORTED;