Update: orig2001_12_04_22_45 -> orig2001_12_14_20_46
[gnokii.git] / common / fbus-6110-ringtones.c
1 /*
2
3   $Id$
4
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13   This file provides support for ringtones.
14
15   $Log$
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
18
19   Revision 1.13  2001/06/28 00:28:45  pkot
20   Small docs updates (Pawel Kot)
21
22
23 */
24
25 #include "fbus-6110-ringtones.h"
26
27 /* Beats-per-Minute Encoding */
28
29 int BeatsPerMinute[] = {
30   25,
31   28,
32   31,
33   35,
34   40,
35   45,
36   50,
37   56,
38   63,
39   70,
40   80,
41   90,
42   100,
43   112,
44   125,
45   140,
46   160,
47   180,
48   200,
49   225,
50   250,
51   285,
52   320,
53   355,
54   400,
55   450,
56   500,
57   565,
58   635,
59   715,
60   800,
61   900
62 };
63
64 int FB61_OctetAlign(unsigned char *Dest, int CurrentBit)
65 {
66   int i=0;
67
68   while((CurrentBit+i)%8) {
69     ClearBit(Dest, CurrentBit+i);
70     i++;
71   }
72
73   return CurrentBit+i;
74 }
75
76 int FB61_OctetAlignNumber(int CurrentBit)
77 {
78   int i=0;
79
80   while((CurrentBit+i)%8) {
81     i++;
82   }
83
84   return CurrentBit+i;
85 }
86
87 int FB61_BitPack(unsigned char *Dest, int CurrentBit, unsigned char *Source, int Bits)
88 {
89
90   int i;
91
92   for (i=0; i<Bits; i++)
93     if (GetBit(Source, i))
94       SetBit(Dest, CurrentBit+i);
95     else
96       ClearBit(Dest, CurrentBit+i);
97
98   return CurrentBit+Bits;
99 }
100
101 int FB61_GetTempo(int Beats) {
102
103   int i=0;
104
105   while ( i < sizeof(BeatsPerMinute)/sizeof(BeatsPerMinute[0])) {
106
107     if (Beats<=BeatsPerMinute[i])
108       break;
109     i++;
110   }
111
112   return i<<3;
113 }    
114
115 int FB61_BitPackByte(unsigned char *Dest, int CurrentBit, unsigned char Command, int Bits) {
116
117   unsigned char Byte[]={Command};
118
119   return FB61_BitPack(Dest, CurrentBit, Byte, Bits);
120 }
121
122
123
124 /* This is messy but saves using the math library! */
125
126 int FB61_GetDuration(int number, unsigned char *spec) {
127
128   int duration=0;
129
130   switch (number) {
131
132   case 128*3/2:
133     duration=Duration_Full; *spec=DottedNote; break;  
134   case 128*2/3:
135     duration=Duration_Full; *spec=Length_2_3; break;  
136   case 128:
137     duration=Duration_Full; *spec=NoSpecialDuration; break;  
138   case 64*9/4:
139     duration=Duration_1_2; *spec=DoubleDottedNote; break;    
140   case 64*3/2:
141     duration=Duration_1_2; *spec=DottedNote; break;  
142   case 64*2/3:
143     duration=Duration_1_2; *spec=Length_2_3; break;  
144   case 64:
145     duration=Duration_1_2; *spec=NoSpecialDuration; break;  
146   case 32*9/4:
147     duration=Duration_1_4; *spec=DoubleDottedNote; break;    
148   case 32*3/2:
149     duration=Duration_1_4; *spec=DottedNote; break;  
150   case 32*2/3:
151     duration=Duration_1_4; *spec=Length_2_3; break;  
152   case 32:
153     duration=Duration_1_4; *spec=NoSpecialDuration; break;  
154   case 16*9/4:
155     duration=Duration_1_8; *spec=DoubleDottedNote; break;    
156   case 16*3/2:
157     duration=Duration_1_8; *spec=DottedNote; break;  
158   case 16*2/3:
159     duration=Duration_1_8; *spec=Length_2_3; break;  
160   case 16:
161     duration=Duration_1_8; *spec=NoSpecialDuration; break;  
162   case 8*9/4:
163     duration=Duration_1_16; *spec=DoubleDottedNote; break;    
164   case 8*3/2:
165     duration=Duration_1_16; *spec=DottedNote; break;  
166   case 8*2/3:
167     duration=Duration_1_16; *spec=Length_2_3; break;  
168   case 8:
169     duration=Duration_1_16; *spec=NoSpecialDuration; break;  
170   case 4*9/4:
171     duration=Duration_1_32; *spec=DoubleDottedNote; break;    
172   case 4*3/2:
173     duration=Duration_1_32; *spec=DottedNote; break;  
174   case 4*2/3:
175     duration=Duration_1_32; *spec=Length_2_3; break;  
176   case 4:
177     duration=Duration_1_32; *spec=NoSpecialDuration; break;  
178   }
179
180   return duration;
181 }
182
183
184 int FB61_GetNote(int number) {
185   
186   int note=0;
187  
188   if (number!=255) {
189     note=number%14;
190     switch (note) {
191
192     case 0:
193       note=Note_C; break;
194     case 1:
195       note=Note_Cis; break;
196     case 2:
197       note=Note_D; break;
198     case 3:
199       note=Note_Dis; break;
200     case 4:
201       note=Note_E; break;
202     case 6:
203       note=Note_F; break;
204     case 7:
205       note=Note_Fis; break;
206     case 8:
207       note=Note_G; break;
208     case 9:
209       note=Note_Gis; break;
210     case 10:
211       note=Note_A; break;
212     case 11:
213       note=Note_Ais; break;
214     case 12:
215       note=Note_H; break;
216     }
217   }
218   else note = Note_Pause;
219
220   return note;
221
222 }
223
224 int FB61_GetScale(int number) {
225
226   int scale=-1;
227
228   if (number!=255) {
229     scale=number/14;
230
231     /* Ensure the scale is valid */
232     scale%=4;
233
234     scale=scale<<6;
235   }
236   return scale;
237 }
238
239
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" */
244
245 u8 FB61_PackRingtone(GSM_Ringtone *ringtone, char *package, int *maxlength)
246 {
247   int StartBit=0;
248   int i;
249   unsigned char CommandLength = 0x02;
250   unsigned char spec;
251   int oldscale=10, newscale;
252   int HowMany=0, HowLong=0, StartNote=0, EndNote=0;
253
254   StartBit=FB61_BitPackByte(package, StartBit, CommandLength, 8);
255   StartBit=FB61_BitPackByte(package, StartBit, RingingToneProgramming, 7);
256
257   /* The page 3-23 of the specs says that <command-part> is always
258      octet-aligned. */
259   StartBit=FB61_OctetAlign(package, StartBit);
260
261   StartBit=FB61_BitPackByte(package, StartBit, Sound, 7);
262   StartBit=FB61_BitPackByte(package, StartBit, BasicSongType, 3);
263
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));
267
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 */
273
274   /* Info, how long is contents for SMS */
275   HowLong=30+8*strlen(ringtone->name)+17+8+8+13;
276   
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 */
281
282   for(i=0; i<ringtone->NrNotes; i++) {
283
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) {
288       StartNote++;
289     } else {
290       
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))) {
294
295         /* We calculate, if we have space to add next scale instruction */
296         if (((HowLong+5)/8)<=(*maxlength-1)) {
297           oldscale=newscale;
298           HowMany++;
299           HowLong+=5;
300         } else {
301           break;
302         }
303       }
304     
305       /* We calculate, if we have space to add next note instruction */
306       if (((HowLong+12)/8)<=(*maxlength-1)) {
307         HowMany++;
308         EndNote++;
309         HowLong+=12;
310       } else {
311         break;
312       }
313     }
314
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;
319     }
320   }
321
322   StartBit=FB61_BitPackByte(package, StartBit, HowMany, 8);
323
324   /* Style */
325   StartBit=FB61_BitPackByte(package, StartBit, StyleInstructionId, 3);
326   StartBit=FB61_BitPackByte(package, StartBit, ContinuousStyle, 2);
327
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);
331
332   /* Default scale */
333   oldscale=10;
334
335   /* Notes packing */
336   for(i=StartNote; i<(EndNote+StartNote); i++) {
337     
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))) {
341       oldscale=newscale;
342       StartBit=FB61_BitPackByte(package, StartBit, ScaleInstructionId, 3);
343       StartBit=FB61_BitPackByte(package, StartBit, FB61_GetScale(ringtone->notes[i].note), 2);
344     }
345
346     /* Note */
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);
351   }
352
353   StartBit=FB61_OctetAlign(package, StartBit);
354
355   StartBit=FB61_BitPackByte(package, StartBit, CommandEnd, 8);
356   
357 #ifdef DEBUG
358   if (StartBit!=FB61_OctetAlignNumber(HowLong))
359     fprintf(stdout,_("Error in PackRingtone - StartBit different to HowLong %d - %d)\n"),StartBit,FB61_OctetAlignNumber(HowLong));
360 #endif
361
362   *maxlength=StartBit/8;  
363
364   return(EndNote+StartNote);
365 }
366
367
368 int FB61_BitUnPack(unsigned char *Dest, int CurrentBit, unsigned char *Source, int Bits)
369 {
370   int i;
371
372   for (i=0; i<Bits; i++)
373     if (GetBit(Dest, CurrentBit+i)) {
374       SetBit(Source, i);
375     } else {
376       ClearBit(Source, i);
377     }
378
379   return CurrentBit+Bits;
380 }
381
382 int FB61_BitUnPackInt(unsigned char *Src, int CurrentBit, int *integer, int Bits) {
383
384   int l=0,z=128,i;
385
386   for (i=0; i<Bits; i++) {
387     if (GetBit(Src, CurrentBit+i)) l=l+z;
388     z=z/2;
389   }
390
391   *integer=l;
392   
393   return CurrentBit+i;
394 }
395
396 int FB61_OctetUnAlign(int CurrentBit)
397 {
398   int i=0;
399
400   while((CurrentBit+i)%8) i++;
401
402   return CurrentBit+i;
403 }
404
405
406 /* TODO: better checking, if contents of ringtone is OK */
407
408 GSM_Error FB61_UnPackRingtone(GSM_Ringtone *ringtone, char *package, int maxlength)
409 {
410   int StartBit=0;
411   int spec,duration,scale;
412   int HowMany;
413   int l,q,i;
414
415   StartBit=FB61_BitUnPackInt(package,StartBit,&l,8);
416 #ifdef DEBUG
417   if (l!=0x02)
418     fprintf(stdout,_("Not header\n"));  
419 #endif
420   if (l!=0x02) return GE_SUBFORMATNOTSUPPORTED;
421
422   StartBit=FB61_BitUnPackInt(package,StartBit,&l,7);    
423 #ifdef DEBUG
424   if (l!=RingingToneProgramming)
425     fprintf(stdout,_("Not RingingToneProgramming\n"));  
426 #endif
427   if (l!=RingingToneProgramming) return GE_SUBFORMATNOTSUPPORTED;
428     
429   /* The page 3-23 of the specs says that <command-part> is always
430      octet-aligned. */
431   StartBit=FB61_OctetUnAlign(StartBit);
432
433   StartBit=FB61_BitUnPackInt(package,StartBit,&l,7);    
434 #ifdef DEBUG
435   if (l!=Sound)
436     fprintf(stdout,_("Not Sound\n"));  
437 #endif
438   if (l!=Sound) return GE_SUBFORMATNOTSUPPORTED;
439
440   StartBit=FB61_BitUnPackInt(package,StartBit,&l,3);    
441 #ifdef DEBUG
442   if (l!=BasicSongType)
443     fprintf(stdout,_("Not BasicSongType\n"));  
444 #endif
445   if (l!=BasicSongType) return GE_SUBFORMATNOTSUPPORTED;
446
447   /* Getting length of the tune name */
448   StartBit=FB61_BitUnPackInt(package,StartBit,&l,4);
449   l=l>>4;
450
451   /* Unpacking the name of the tune. */
452   StartBit=FB61_BitUnPack(package, StartBit, ringtone->name, 8*l);
453   ringtone->name[l]=0;
454
455   StartBit=FB61_BitUnPackInt(package,StartBit,&l,8);    
456   if (l!=1) return GE_SUBFORMATNOTSUPPORTED; //we support only one song pattern
457
458   StartBit=FB61_BitUnPackInt(package,StartBit,&l,3);          
459 #ifdef DEBUG
460   if (l!=PatternHeaderId)
461     fprintf(stdout,_("Not PatternHeaderId\n"));
462 #endif
463   if (l!=PatternHeaderId) return GE_SUBFORMATNOTSUPPORTED;
464
465   StartBit+=2; //Pattern ID - we ignore it
466
467   StartBit=FB61_BitUnPackInt(package,StartBit,&l,4);          
468     
469   HowMany=0;
470   StartBit=FB61_BitUnPackInt(package, StartBit, &HowMany, 8);
471
472   scale=0;
473   ringtone->NrNotes=0;
474     
475   for (i=0;i<HowMany;i++) {
476
477     StartBit=FB61_BitUnPackInt(package,StartBit,&q,3);              
478     switch (q) {
479       case VolumeInstructionId:
480         StartBit+=4;
481         break;
482       case StyleInstructionId:
483         StartBit=FB61_BitUnPackInt(package,StartBit,&l,2);              
484         l=l>>3;
485         break;
486       case TempoInstructionId:
487         StartBit=FB61_BitUnPackInt(package,StartBit,&l,5);                              l=l>>3;
488         ringtone->tempo=BeatsPerMinute[l];
489         break;
490       case ScaleInstructionId:
491         StartBit=FB61_BitUnPackInt(package,StartBit,&scale,2);
492         scale=scale>>6;
493         break;
494       case NoteInstructionId:
495         StartBit=FB61_BitUnPackInt(package,StartBit,&l,4);    
496
497         switch (l) {
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 ?
511         }
512       
513         if (ringtone->notes[ringtone->NrNotes].note!=255)
514           ringtone->notes[ringtone->NrNotes].note=ringtone->notes[ringtone->NrNotes].note+scale*14;
515
516         StartBit=FB61_BitUnPackInt(package,StartBit,&duration,3);    
517
518         StartBit=FB61_BitUnPackInt(package,StartBit,&spec,2);    
519
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;
556
557         if (ringtone->NrNotes==MAX_RINGTONE_NOTES) break;
558         
559         ringtone->NrNotes++;
560         break;
561       default:
562 #ifdef DEBUG
563     fprintf(stdout,_("Unsupported block\n"));  
564 #endif
565         return GE_SUBFORMATNOTSUPPORTED;
566     } 
567   }
568
569   return GE_NONE;
570 }
571