author | zautrix <zautrix> | 2004-08-30 20:21:20 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-08-30 20:21:20 (UTC) |
commit | 109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3 (patch) (unidiff) | |
tree | 30407f1548315b403f1ad7c55c81744413fcd14c | |
parent | 5f4867356dc4b34da20b66e9ede71e22899e4a4b (diff) | |
download | kdepimpi-109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3.zip kdepimpi-109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3.tar.gz kdepimpi-109a23b70f67552a9ce27f682bb2b1bdbb2bb4f3.tar.bz2 |
sine fix
-rw-r--r-- | gammu/emb/common/common.pro | 1 | ||||
-rw-r--r-- | gammu/emb/common/service/gsmring.c | 6 |
2 files changed, 6 insertions, 1 deletions
diff --git a/gammu/emb/common/common.pro b/gammu/emb/common/common.pro index 9342cb7..0e719ee 100644 --- a/gammu/emb/common/common.pro +++ b/gammu/emb/common/common.pro | |||
@@ -1,186 +1,187 @@ | |||
1 | ###################################################################### | 1 | ###################################################################### |
2 | # Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004 | 2 | # Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004 |
3 | ###################################################################### | 3 | ###################################################################### |
4 | 4 | ||
5 | TEMPLATE = lib | 5 | TEMPLATE = lib |
6 | DEPENDPATH += device \ | 6 | DEPENDPATH += device \ |
7 | misc \ | 7 | misc \ |
8 | phone \ | 8 | phone \ |
9 | protocol \ | 9 | protocol \ |
10 | service \ | 10 | service \ |
11 | device/bluetoth \ | 11 | device/bluetoth \ |
12 | device/irda \ | 12 | device/irda \ |
13 | device/serial \ | 13 | device/serial \ |
14 | misc/coding \ | 14 | misc/coding \ |
15 | phone/alcatel \ | 15 | phone/alcatel \ |
16 | phone/at \ | 16 | phone/at \ |
17 | phone/nokia \ | 17 | phone/nokia \ |
18 | phone/obex \ | 18 | phone/obex \ |
19 | phone/symbian \ | 19 | phone/symbian \ |
20 | protocol/alcatel \ | 20 | protocol/alcatel \ |
21 | protocol/at \ | 21 | protocol/at \ |
22 | protocol/nokia \ | 22 | protocol/nokia \ |
23 | protocol/obex \ | 23 | protocol/obex \ |
24 | protocol/symbian \ | 24 | protocol/symbian \ |
25 | service/backup \ | 25 | service/backup \ |
26 | service/sms \ | 26 | service/sms \ |
27 | phone/nokia/dct3 \ | 27 | phone/nokia/dct3 \ |
28 | phone/nokia/dct4 | 28 | phone/nokia/dct4 |
29 | INCLUDEPATH += . \ | 29 | INCLUDEPATH += . \ |
30 | misc/coding \ | 30 | misc/coding \ |
31 | misc \ | 31 | misc \ |
32 | device \ | 32 | device \ |
33 | phone/nokia/dct4 \ | 33 | phone/nokia/dct4 \ |
34 | phone/nokia/dct3 \ | 34 | phone/nokia/dct3 \ |
35 | phone/at \ | 35 | phone/at \ |
36 | phone/alcatel \ | 36 | phone/alcatel \ |
37 | phone/obex \ | 37 | phone/obex \ |
38 | phone/symbian \ | 38 | phone/symbian \ |
39 | protocol \ | 39 | protocol \ |
40 | protocol/nokia \ | 40 | protocol/nokia \ |
41 | protocol/at \ | 41 | protocol/at \ |
42 | protocol/alcatel \ | 42 | protocol/alcatel \ |
43 | protocol/obex \ | 43 | protocol/obex \ |
44 | protocol/symbian \ | 44 | protocol/symbian \ |
45 | device/serial \ | 45 | device/serial \ |
46 | device/irda \ | 46 | device/irda \ |
47 | device/bluetoth \ | 47 | device/bluetoth \ |
48 | service \ | 48 | service \ |
49 | service/sms \ | 49 | service/sms \ |
50 | service/backup \ | 50 | service/backup \ |
51 | phone/nokia \ | 51 | phone/nokia \ |
52 | phone | 52 | phone |
53 | 53 | ||
54 | # Input | 54 | # Input |
55 | HEADERS += config.h \ | 55 | HEADERS += config.h \ |
56 | gammu.h \ | 56 | gammu.h \ |
57 | gsmcomon.h \ | 57 | gsmcomon.h \ |
58 | gsmstate.h \ | 58 | gsmstate.h \ |
59 | device/devfunc.h \ | 59 | device/devfunc.h \ |
60 | misc/cfg.h \ | 60 | misc/cfg.h \ |
61 | misc/misc.h \ | 61 | misc/misc.h \ |
62 | phone/pfunc.h \ | 62 | phone/pfunc.h \ |
63 | protocol/protocol.h \ | 63 | protocol/protocol.h \ |
64 | service/gsmcal.h \ | 64 | service/gsmcal.h \ |
65 | service/gsmcall.h \ | 65 | service/gsmcall.h \ |
66 | service/gsmdata.h \ | 66 | service/gsmdata.h \ |
67 | service/gsmlogo.h \ | 67 | service/gsmlogo.h \ |
68 | service/gsmmisc.h \ | 68 | service/gsmmisc.h \ |
69 | service/gsmnet.h \ | 69 | service/gsmnet.h \ |
70 | service/gsmpbk.h \ | 70 | service/gsmpbk.h \ |
71 | service/gsmprof.h \ | 71 | service/gsmprof.h \ |
72 | service/gsmring.h \ | 72 | service/gsmring.h \ |
73 | device/bluetoth/affix.h \ | 73 | device/bluetoth/affix.h \ |
74 | device/bluetoth/blue_w32.h \ | 74 | device/bluetoth/blue_w32.h \ |
75 | device/bluetoth/bluetoth.h \ | 75 | device/bluetoth/bluetoth.h \ |
76 | device/bluetoth/bluez.h \ | 76 | device/bluetoth/bluez.h \ |
77 | device/irda/irda.h \ | 77 | device/irda/irda.h \ |
78 | device/irda/irda_unx.h \ | 78 | device/irda/irda_unx.h \ |
79 | device/irda/irda_w32.h \ | 79 | device/irda/irda_w32.h \ |
80 | device/serial/ser_djg.h \ | 80 | device/serial/ser_djg.h \ |
81 | device/serial/ser_unx.h \ | 81 | device/serial/ser_unx.h \ |
82 | device/serial/ser_w32.h \ | 82 | device/serial/ser_w32.h \ |
83 | misc/coding/coding.h \ | 83 | misc/coding/coding.h \ |
84 | misc/coding/md5.h \ | 84 | misc/coding/md5.h \ |
85 | phone/alcatel/alcatel.h \ | 85 | phone/alcatel/alcatel.h \ |
86 | phone/at/atgen.h \ | 86 | phone/at/atgen.h \ |
87 | phone/nokia/ncommon.h \ | 87 | phone/nokia/ncommon.h \ |
88 | phone/nokia/nfunc.h \ | 88 | phone/nokia/nfunc.h \ |
89 | phone/nokia/nfuncold.h \ | 89 | phone/nokia/nfuncold.h \ |
90 | phone/obex/obexgen.h \ | 90 | phone/obex/obexgen.h \ |
91 | phone/symbian/mroutgen.h \ | 91 | phone/symbian/mroutgen.h \ |
92 | protocol/alcatel/alcabus.h \ | 92 | protocol/alcatel/alcabus.h \ |
93 | protocol/at/at.h \ | 93 | protocol/at/at.h \ |
94 | protocol/nokia/fbus2.h \ | 94 | protocol/nokia/fbus2.h \ |
95 | protocol/nokia/mbus2.h \ | 95 | protocol/nokia/mbus2.h \ |
96 | protocol/nokia/phonet.h \ | 96 | protocol/nokia/phonet.h \ |
97 | protocol/obex/obex.h \ | 97 | protocol/obex/obex.h \ |
98 | protocol/symbian/mrouter.h \ | 98 | protocol/symbian/mrouter.h \ |
99 | service/backup/backgen.h \ | 99 | service/backup/backgen.h \ |
100 | service/backup/backics.h \ | 100 | service/backup/backics.h \ |
101 | service/backup/backldif.h \ | 101 | service/backup/backldif.h \ |
102 | service/backup/backlmb.h \ | 102 | service/backup/backlmb.h \ |
103 | service/backup/backtext.h \ | 103 | service/backup/backtext.h \ |
104 | service/backup/backvcf.h \ | 104 | service/backup/backvcf.h \ |
105 | service/backup/backvcs.h \ | 105 | service/backup/backvcs.h \ |
106 | service/backup/gsmback.h \ | 106 | service/backup/gsmback.h \ |
107 | service/sms/gsmems.h \ | 107 | service/sms/gsmems.h \ |
108 | service/sms/gsmmulti.h \ | 108 | service/sms/gsmmulti.h \ |
109 | service/sms/gsmsms.h \ | 109 | service/sms/gsmsms.h \ |
110 | phone/nokia/dct3/dct3comm.h \ | 110 | phone/nokia/dct3/dct3comm.h \ |
111 | phone/nokia/dct3/dct3func.h \ | 111 | phone/nokia/dct3/dct3func.h \ |
112 | phone/nokia/dct3/n6110.h \ | 112 | phone/nokia/dct3/n6110.h \ |
113 | phone/nokia/dct3/n7110.h \ | 113 | phone/nokia/dct3/n7110.h \ |
114 | phone/nokia/dct3/n9210.h \ | 114 | phone/nokia/dct3/n9210.h \ |
115 | phone/nokia/dct4/dct4func.h \ | 115 | phone/nokia/dct4/dct4func.h \ |
116 | phone/nokia/dct4/n3320.h \ | 116 | phone/nokia/dct4/n3320.h \ |
117 | phone/nokia/dct4/n3650.h \ | 117 | phone/nokia/dct4/n3650.h \ |
118 | phone/nokia/dct4/n6510.h | 118 | phone/nokia/dct4/n6510.h |
119 | SOURCES +=gsmcomon.c \ | 119 | SOURCES +=gsmcomon.c \ |
120 | gsmstate.c \ | 120 | gsmstate.c \ |
121 | misc/misc.c \ | 121 | misc/misc.c \ |
122 | misc/cfg.c \ | 122 | misc/cfg.c \ |
123 | misc/coding/coding.c \ | 123 | misc/coding/coding.c \ |
124 | misc/coding/md5.c \ | 124 | misc/coding/md5.c \ |
125 | service/sms/gsmsms.c \ | 125 | service/sms/gsmsms.c \ |
126 | service/sms/gsmems.c \ | 126 | service/sms/gsmems.c \ |
127 | service/sms/gsmmulti.c \ | 127 | service/sms/gsmmulti.c \ |
128 | service/gsmcal.c \ | 128 | service/gsmcal.c \ |
129 | service/gsmdata.c \ | 129 | service/gsmdata.c \ |
130 | service/gsmpbk.c \ | 130 | service/gsmpbk.c \ |
131 | service/gsmring.c \ | 131 | service/gsmring.c \ |
132 | service/gsmlogo.c \ | 132 | service/gsmlogo.c \ |
133 | service/gsmmisc.c \ | 133 | service/gsmmisc.c \ |
134 | service/gsmnet.c \ | 134 | service/gsmnet.c \ |
135 | service/backup/gsmback.c \ | 135 | service/backup/gsmback.c \ |
136 | service/backup/backldif.c \ | 136 | service/backup/backldif.c \ |
137 | service/backup/backlmb.c \ | 137 | service/backup/backlmb.c \ |
138 | service/backup/backtext.c \ | 138 | service/backup/backtext.c \ |
139 | service/backup/backvcs.c \ | 139 | service/backup/backvcs.c \ |
140 | service/backup/backvcf.c \ | 140 | service/backup/backvcf.c \ |
141 | service/backup/backics.c \ | 141 | service/backup/backics.c \ |
142 | device/bluetoth/affix.c \ | 142 | device/bluetoth/affix.c \ |
143 | device/bluetoth/bluez.c \ | 143 | device/bluetoth/bluez.c \ |
144 | device/bluetoth/blue_w32.c \ | 144 | device/bluetoth/blue_w32.c \ |
145 | device/bluetoth/bluetoth.c \ | 145 | device/bluetoth/bluetoth.c \ |
146 | device/serial/ser_djg.c \ | 146 | device/serial/ser_djg.c \ |
147 | device/irda/irda.c \ | 147 | device/irda/irda.c \ |
148 | device/devfunc.c \ | 148 | device/devfunc.c \ |
149 | protocol/at/at.c \ | 149 | protocol/at/at.c \ |
150 | protocol/alcatel/alcabus.c \ | 150 | protocol/alcatel/alcabus.c \ |
151 | protocol/nokia/mbus2.c \ | 151 | protocol/nokia/mbus2.c \ |
152 | protocol/nokia/fbus2.c \ | 152 | protocol/nokia/fbus2.c \ |
153 | protocol/nokia/phonet.c \ | 153 | protocol/nokia/phonet.c \ |
154 | protocol/obex/obex.c \ | 154 | protocol/obex/obex.c \ |
155 | protocol/symbian/mrouter.c \ | 155 | protocol/symbian/mrouter.c \ |
156 | phone/pfunc.c \ | 156 | phone/pfunc.c \ |
157 | phone/at/atgen.c \ | 157 | phone/at/atgen.c \ |
158 | phone/at/siemens.c \ | 158 | phone/at/siemens.c \ |
159 | phone/at/sonyeric.c \ | 159 | phone/at/sonyeric.c \ |
160 | phone/alcatel/alcatel.c \ | 160 | phone/alcatel/alcatel.c \ |
161 | phone/nokia/dct3/n6110.c \ | 161 | phone/nokia/dct3/n6110.c \ |
162 | phone/nokia/dct3/n7110.c \ | 162 | phone/nokia/dct3/n7110.c \ |
163 | phone/nokia/dct3/n9210.c \ | 163 | phone/nokia/dct3/n9210.c \ |
164 | phone/nokia/dct3/dct3func.c \ | 164 | phone/nokia/dct3/dct3func.c \ |
165 | phone/nokia/dct4/n3320.c \ | 165 | phone/nokia/dct4/n3320.c \ |
166 | phone/nokia/dct4/n3650.c \ | 166 | phone/nokia/dct4/n3650.c \ |
167 | phone/nokia/dct4/n6510.c \ | 167 | phone/nokia/dct4/n6510.c \ |
168 | phone/nokia/dct4/dct4func.c \ | 168 | phone/nokia/dct4/dct4func.c \ |
169 | phone/nokia/nauto.c \ | 169 | phone/nokia/nauto.c \ |
170 | phone/nokia/nfunc.c \ | 170 | phone/nokia/nfunc.c \ |
171 | phone/nokia/nfuncold.c \ | 171 | phone/nokia/nfuncold.c \ |
172 | phone/obex/obexgen.c \ | 172 | phone/obex/obexgen.c \ |
173 | phone/symbian/mroutgen.c | 173 | phone/symbian/mroutgen.c |
174 | 174 | ||
175 | DEFINES += DESKTOP_VERSION | ||
175 | TARGET = microgammu | 176 | TARGET = microgammu |
176 | CONFIG = warn_off release console | 177 | CONFIG = warn_off release console |
177 | DESTDIR = ../../../bin | 178 | DESTDIR = ../../../bin |
178 | OBJECTS_DIR = obj/unix | 179 | OBJECTS_DIR = obj/unix |
179 | MOC_DIR = moc/unix | 180 | MOC_DIR = moc/unix |
180 | 181 | ||
181 | unix: { | 182 | unix: { |
182 | SOURCES += device/serial/ser_unx.c | 183 | SOURCES += device/serial/ser_unx.c |
183 | } | 184 | } |
184 | win32:{ | 185 | win32:{ |
185 | SOURCES += device/serial/ser_w32.c | 186 | SOURCES += device/serial/ser_w32.c |
186 | } | 187 | } |
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c index f7f7082..7df46f1 100644 --- a/gammu/emb/common/service/gsmring.c +++ b/gammu/emb/common/service/gsmring.c | |||
@@ -1,1601 +1,1605 @@ | |||
1 | /* (c) 2001-2004 by Marcin Wiacek */ | 1 | /* (c) 2001-2004 by Marcin Wiacek */ |
2 | /* Based on some work from Ralf Thelen (7110 ringtones), | 2 | /* Based on some work from Ralf Thelen (7110 ringtones), |
3 | * Gnokii (RTTL and SM) and others | 3 | * Gnokii (RTTL and SM) and others |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <ctype.h> | 8 | #include <ctype.h> |
9 | #include <math.h> | 9 | #include <math.h> |
10 | #ifdef WIN32 | 10 | #ifdef WIN32 |
11 | # include <windows.h> | 11 | # include <windows.h> |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #include "../gsmcomon.h" | 14 | #include "../gsmcomon.h" |
15 | #include "../misc/coding/coding.h" | 15 | #include "../misc/coding/coding.h" |
16 | #include "../gsmstate.h" | 16 | #include "../gsmstate.h" |
17 | #include "gsmring.h" | 17 | #include "gsmring.h" |
18 | #include "sms/gsmsms.h" | 18 | #include "sms/gsmsms.h" |
19 | 19 | ||
20 | int GSM_RingNoteGetFrequency(GSM_RingNote Note) | 20 | int GSM_RingNoteGetFrequency(GSM_RingNote Note) |
21 | { | 21 | { |
22 | double freq=0; | 22 | double freq=0; |
23 | 23 | ||
24 | /* Values according to the software from http://iki.fi/too/sw/xring/ | 24 | /* Values according to the software from http://iki.fi/too/sw/xring/ |
25 | * generated with: | 25 | * generated with: |
26 | * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)' | 26 | * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)' |
27 | */ | 27 | */ |
28 | switch (Note.Note) { | 28 | switch (Note.Note) { |
29 | case Note_C : freq = 523.3; break; | 29 | case Note_C : freq = 523.3; break; |
30 | case Note_Cis: freq = 554.4; break; | 30 | case Note_Cis: freq = 554.4; break; |
31 | case Note_D : freq = 587.3; break; | 31 | case Note_D : freq = 587.3; break; |
32 | case Note_Dis: freq = 622.3; break; | 32 | case Note_Dis: freq = 622.3; break; |
33 | case Note_E : freq = 659.3; break; | 33 | case Note_E : freq = 659.3; break; |
34 | case Note_F : freq = 698.5; break; | 34 | case Note_F : freq = 698.5; break; |
35 | case Note_Fis: freq = 740; break; | 35 | case Note_Fis: freq = 740; break; |
36 | case Note_G : freq = 784; break; | 36 | case Note_G : freq = 784; break; |
37 | case Note_Gis: freq = 830.6; break; | 37 | case Note_Gis: freq = 830.6; break; |
38 | case Note_A : freq = 880; break; | 38 | case Note_A : freq = 880; break; |
39 | case Note_Ais: freq = 932.3; break; | 39 | case Note_Ais: freq = 932.3; break; |
40 | case Note_H : freq = 987.8; break; | 40 | case Note_H : freq = 987.8; break; |
41 | case Note_Pause: break; | 41 | case Note_Pause: break; |
42 | } | 42 | } |
43 | switch (Note.Scale) { | 43 | switch (Note.Scale) { |
44 | case Scale_440 : freq = freq / 2; break; | 44 | case Scale_440 : freq = freq / 2; break; |
45 | case Scale_880 : break; | 45 | case Scale_880 : break; |
46 | case Scale_1760: freq = freq * 2; break; | 46 | case Scale_1760: freq = freq * 2; break; |
47 | case Scale_3520: freq = freq * 4; break; | 47 | case Scale_3520: freq = freq * 4; break; |
48 | default : break; | 48 | default : break; |
49 | } | 49 | } |
50 | return (int)freq; | 50 | return (int)freq; |
51 | } | 51 | } |
52 | 52 | ||
53 | int GSM_RingNoteGetFullDuration(GSM_RingNote Note) | 53 | int GSM_RingNoteGetFullDuration(GSM_RingNote Note) |
54 | { | 54 | { |
55 | int duration = 1; | 55 | int duration = 1; |
56 | 56 | ||
57 | switch (Note.Duration) { | 57 | switch (Note.Duration) { |
58 | case Duration_Full : duration = 128; break; | 58 | case Duration_Full : duration = 128; break; |
59 | case Duration_1_2 : duration = 64; break; | 59 | case Duration_1_2 : duration = 64; break; |
60 | case Duration_1_4 : duration = 32; break; | 60 | case Duration_1_4 : duration = 32; break; |
61 | case Duration_1_8 : duration = 16; break; | 61 | case Duration_1_8 : duration = 16; break; |
62 | case Duration_1_16 : duration = 8; break; | 62 | case Duration_1_16 : duration = 8; break; |
63 | case Duration_1_32 : duration = 4; break; | 63 | case Duration_1_32 : duration = 4; break; |
64 | } | 64 | } |
65 | switch (Note.DurationSpec) { | 65 | switch (Note.DurationSpec) { |
66 | case NoSpecialDuration : break; | 66 | case NoSpecialDuration : break; |
67 | case DottedNote : duration = duration * 3/2;break; | 67 | case DottedNote : duration = duration * 3/2;break; |
68 | case DoubleDottedNote : duration = duration * 9/4;break; | 68 | case DoubleDottedNote : duration = duration * 9/4;break; |
69 | case Length_2_3 : duration = duration * 2/3;break; | 69 | case Length_2_3 : duration = duration * 2/3;break; |
70 | } | 70 | } |
71 | return duration; | 71 | return duration; |
72 | } | 72 | } |
73 | 73 | ||
74 | #ifndef PI | 74 | #ifndef PI |
75 | # define PI 3.141592654 | 75 | # define PI 3.141592654 |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | #define WAV_SAMPLE_RATE 44100 | 78 | #define WAV_SAMPLE_RATE 44100 |
79 | 79 | ||
80 | GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone) | 80 | GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone) |
81 | { | 81 | { |
82 | unsigned char WAV_Header[] = { | 82 | unsigned char WAV_Header[] = { |
83 | 'R','I','F','F', | 83 | 'R','I','F','F', |
84 | 0x00,0x00,0x00,0x00,/* Length */ | 84 | 0x00,0x00,0x00,0x00,/* Length */ |
85 | 'W','A','V','E'}; | 85 | 'W','A','V','E'}; |
86 | unsigned char FMT_Header[] = {'f','m','t',' ', | 86 | unsigned char FMT_Header[] = {'f','m','t',' ', |
87 | 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac, | 87 | 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac, |
88 | 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00}; | 88 | 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00}; |
89 | unsigned char DATA_Header[] = { | 89 | unsigned char DATA_Header[] = { |
90 | 'd','a','t','a', | 90 | 'd','a','t','a', |
91 | 0x00,0x00,0x00,0x00};/* Length */ | 91 | 0x00,0x00,0x00,0x00};/* Length */ |
92 | short DATA_Buffer[60000]; | 92 | short DATA_Buffer[60000]; |
93 | long wavfilesize; | 93 | long wavfilesize; |
94 | GSM_RingNote *Note; | 94 | GSM_RingNote *Note; |
95 | long i,j,length=0; | 95 | long i,j,length=0; |
96 | double phase=0,phase_step; | 96 | double phase=0,phase_step; |
97 | 97 | ||
98 | fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); | 98 | fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); |
99 | fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); | 99 | fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); |
100 | fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); | 100 | fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); |
101 | 101 | ||
102 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { | 102 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { |
103 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { | 103 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { |
104 | Note = &ringtone->NoteTone.Commands[i].Note; | 104 | Note = &ringtone->NoteTone.Commands[i].Note; |
105 | phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5; | 105 | phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5; |
106 | for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) { | 106 | for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) { |
107 | /*DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));*/ | 107 | #ifdef DESKTOP_VERSION |
108 | DATA_Buffer[j] = ((int)(sin(phase*PI)*50000)); | ||
109 | #else | ||
110 | // we have no sin on Zaurus | ||
108 | DATA_Buffer[j] = ((int)(0.5*50000)); | 111 | DATA_Buffer[j] = ((int)(0.5*50000)); |
112 | #endif | ||
109 | phase = phase + phase_step; | 113 | phase = phase + phase_step; |
110 | length++; | 114 | length++; |
111 | } | 115 | } |
112 | fwrite(&DATA_Buffer,sizeof(short),j,file); | 116 | fwrite(&DATA_Buffer,sizeof(short),j,file); |
113 | } | 117 | } |
114 | } | 118 | } |
115 | 119 | ||
116 | wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2; | 120 | wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2; |
117 | WAV_Header[4] = ((unsigned char)wavfilesize % 256); | 121 | WAV_Header[4] = ((unsigned char)wavfilesize % 256); |
118 | WAV_Header[5] = ((unsigned char)wavfilesize / 256); | 122 | WAV_Header[5] = ((unsigned char)wavfilesize / 256); |
119 | WAV_Header[6] = ((unsigned char)wavfilesize / (256*256)); | 123 | WAV_Header[6] = ((unsigned char)wavfilesize / (256*256)); |
120 | WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); | 124 | WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); |
121 | wavfilesize = wavfilesize - 54; | 125 | wavfilesize = wavfilesize - 54; |
122 | DATA_Header[4] = ((unsigned char)wavfilesize % 256); | 126 | DATA_Header[4] = ((unsigned char)wavfilesize % 256); |
123 | DATA_Header[5] = ((unsigned char)wavfilesize / 256); | 127 | DATA_Header[5] = ((unsigned char)wavfilesize / 256); |
124 | DATA_Header[6] = ((unsigned char)wavfilesize / (256*256)); | 128 | DATA_Header[6] = ((unsigned char)wavfilesize / (256*256)); |
125 | DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); | 129 | DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); |
126 | 130 | ||
127 | fseek( file, 0, SEEK_SET); | 131 | fseek( file, 0, SEEK_SET); |
128 | fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); | 132 | fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); |
129 | fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); | 133 | fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); |
130 | fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); | 134 | fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); |
131 | 135 | ||
132 | return ERR_NONE; | 136 | return ERR_NONE; |
133 | } | 137 | } |
134 | 138 | ||
135 | static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone) | 139 | static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone) |
136 | { | 140 | { |
137 | char nullchar=0x00; | 141 | char nullchar=0x00; |
138 | 142 | ||
139 | fwrite(&nullchar,1,1,file); | 143 | fwrite(&nullchar,1,1,file); |
140 | fwrite(&nullchar,1,1,file); | 144 | fwrite(&nullchar,1,1,file); |
141 | fprintf(file,"\x0C\x01\x2C"); | 145 | fprintf(file,"\x0C\x01\x2C"); |
142 | fprintf(file,"%s",DecodeUnicodeString(ringtone->Name)); | 146 | fprintf(file,"%s",DecodeUnicodeString(ringtone->Name)); |
143 | fwrite(&nullchar,1,1,file); | 147 | fwrite(&nullchar,1,1,file); |
144 | fwrite(&nullchar,1,1,file); | 148 | fwrite(&nullchar,1,1,file); |
145 | fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); | 149 | fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); |
146 | return ERR_NONE; | 150 | return ERR_NONE; |
147 | } | 151 | } |
148 | 152 | ||
149 | static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone) | 153 | static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone) |
150 | { | 154 | { |
151 | fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); | 155 | fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); |
152 | return ERR_NONE; | 156 | return ERR_NONE; |
153 | } | 157 | } |
154 | 158 | ||
155 | GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone) | 159 | GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone) |
156 | { | 160 | { |
157 | GSM_RingNoteScaleDefNoteScale; | 161 | GSM_RingNoteScaleDefNoteScale; |
158 | GSM_RingNoteDurationDefNoteDuration; | 162 | GSM_RingNoteDurationDefNoteDuration; |
159 | 163 | ||
160 | GSM_RingNoteStyleDefNoteStyle=0; | 164 | GSM_RingNoteStyleDefNoteStyle=0; |
161 | int DefNoteTempo=0; | 165 | int DefNoteTempo=0; |
162 | 166 | ||
163 | bool started = false, firstcomma = true; | 167 | bool started = false, firstcomma = true; |
164 | GSM_RingNote *Note; | 168 | GSM_RingNote *Note; |
165 | 169 | ||
166 | unsigned char buffer[15]; | 170 | unsigned char buffer[15]; |
167 | int i,j,k=0; | 171 | int i,j,k=0; |
168 | 172 | ||
169 | /* Saves ringtone name */ | 173 | /* Saves ringtone name */ |
170 | fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name)); | 174 | fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name)); |
171 | 175 | ||
172 | /* Find the most frequently used duration */ | 176 | /* Find the most frequently used duration */ |
173 | for (i=0;i<6;i++) buffer[i]=0; | 177 | for (i=0;i<6;i++) buffer[i]=0; |
174 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { | 178 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { |
175 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { | 179 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { |
176 | Note = &ringtone->NoteTone.Commands[i].Note; | 180 | Note = &ringtone->NoteTone.Commands[i].Note; |
177 | /* some durations need 2 bytes in file, some 1 */ | 181 | /* some durations need 2 bytes in file, some 1 */ |
178 | if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) { | 182 | if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) { |
179 | buffer[Note->Duration/32]++; | 183 | buffer[Note->Duration/32]++; |
180 | } | 184 | } |
181 | if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) { | 185 | if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) { |
182 | buffer[Note->Duration/32]+=2; | 186 | buffer[Note->Duration/32]+=2; |
183 | } | 187 | } |
184 | } | 188 | } |
185 | } | 189 | } |
186 | /* Now find the most frequently used */ | 190 | /* Now find the most frequently used */ |
187 | j=0; | 191 | j=0; |
188 | for (i=0;i<6;i++) { | 192 | for (i=0;i<6;i++) { |
189 | if (buffer[i]>j) { | 193 | if (buffer[i]>j) { |
190 | k=i; | 194 | k=i; |
191 | j=buffer[i]; | 195 | j=buffer[i]; |
192 | } | 196 | } |
193 | } | 197 | } |
194 | /* Finally convert the default duration */ | 198 | /* Finally convert the default duration */ |
195 | DefNoteDuration = k * 32; | 199 | DefNoteDuration = k * 32; |
196 | dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); | 200 | dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); |
197 | switch (DefNoteDuration) { | 201 | switch (DefNoteDuration) { |
198 | case Duration_Full:fprintf(file,"d=1"); break; | 202 | case Duration_Full:fprintf(file,"d=1"); break; |
199 | case Duration_1_2 :fprintf(file,"d=2"); break; | 203 | case Duration_1_2 :fprintf(file,"d=2"); break; |
200 | case Duration_1_4 :fprintf(file,"d=4"); break; | 204 | case Duration_1_4 :fprintf(file,"d=4"); break; |
201 | case Duration_1_8 :fprintf(file,"d=8"); break; | 205 | case Duration_1_8 :fprintf(file,"d=8"); break; |
202 | case Duration_1_16:fprintf(file,"d=16");break; | 206 | case Duration_1_16:fprintf(file,"d=16");break; |
203 | case Duration_1_32:fprintf(file,"d=32");break; | 207 | case Duration_1_32:fprintf(file,"d=32");break; |
204 | } | 208 | } |
205 | 209 | ||
206 | /* Find the most frequently used scale */ | 210 | /* Find the most frequently used scale */ |
207 | for (i=0;i<9;i++) buffer[i]=0; | 211 | for (i=0;i<9;i++) buffer[i]=0; |
208 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { | 212 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { |
209 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { | 213 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { |
210 | Note = &ringtone->NoteTone.Commands[i].Note; | 214 | Note = &ringtone->NoteTone.Commands[i].Note; |
211 | if (Note->Note!=Note_Pause && | 215 | if (Note->Note!=Note_Pause && |
212 | Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) { | 216 | Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) { |
213 | buffer[Note->Scale - 1]++; | 217 | buffer[Note->Scale - 1]++; |
214 | } | 218 | } |
215 | } | 219 | } |
216 | } | 220 | } |
217 | j=0; | 221 | j=0; |
218 | for (i=0;i<9;i++) { | 222 | for (i=0;i<9;i++) { |
219 | if (buffer[i]>j) { | 223 | if (buffer[i]>j) { |
220 | k = i; | 224 | k = i; |
221 | j=buffer[i]; | 225 | j=buffer[i]; |
222 | } | 226 | } |
223 | } | 227 | } |
224 | DefNoteScale = k + 1; | 228 | DefNoteScale = k + 1; |
225 | /* Save the default scale */ | 229 | /* Save the default scale */ |
226 | fprintf(file,",o=%i,",DefNoteScale); | 230 | fprintf(file,",o=%i,",DefNoteScale); |
227 | dbgprintf("DefNoteScale=%d\n", DefNoteScale); | 231 | dbgprintf("DefNoteScale=%d\n", DefNoteScale); |
228 | 232 | ||
229 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { | 233 | for (i=0;i<ringtone->NoteTone.NrCommands;i++) { |
230 | if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue; | 234 | if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue; |
231 | 235 | ||
232 | Note = &ringtone->NoteTone.Commands[i].Note; | 236 | Note = &ringtone->NoteTone.Commands[i].Note; |
233 | 237 | ||
234 | /* Trick from PPM Edit */ | 238 | /* Trick from PPM Edit */ |
235 | if (Note->DurationSpec == DoubleDottedNote) { | 239 | if (Note->DurationSpec == DoubleDottedNote) { |
236 | switch (Note->Duration) { | 240 | switch (Note->Duration) { |
237 | case Duration_Full:Note->Duration = Duration_Full;break; | 241 | case Duration_Full:Note->Duration = Duration_Full;break; |
238 | case Duration_1_2 :Note->Duration = Duration_Full;break; | 242 | case Duration_1_2 :Note->Duration = Duration_Full;break; |
239 | case Duration_1_4 :Note->Duration = Duration_1_2; break; | 243 | case Duration_1_4 :Note->Duration = Duration_1_2; break; |
240 | case Duration_1_8 :Note->Duration = Duration_1_4; break; | 244 | case Duration_1_8 :Note->Duration = Duration_1_4; break; |
241 | case Duration_1_16:Note->Duration = Duration_1_8; break; | 245 | case Duration_1_16:Note->Duration = Duration_1_8; break; |
242 | case Duration_1_32:Note->Duration = Duration_1_16;break; | 246 | case Duration_1_32:Note->Duration = Duration_1_16;break; |
243 | } | 247 | } |
244 | Note->DurationSpec = NoSpecialDuration; | 248 | Note->DurationSpec = NoSpecialDuration; |
245 | } | 249 | } |
246 | 250 | ||
247 | if (!started) { | 251 | if (!started) { |
248 | DefNoteTempo=Note->Tempo; | 252 | DefNoteTempo=Note->Tempo; |
249 | DefNoteStyle=Note->Style; | 253 | DefNoteStyle=Note->Style; |
250 | switch (Note->Style) { | 254 | switch (Note->Style) { |
251 | case StaccatoStyle: fprintf(file,"s=S,"); break; | 255 | case StaccatoStyle: fprintf(file,"s=S,"); break; |
252 | case NaturalStyle : fprintf(file,"s=N,"); break; | 256 | case NaturalStyle : fprintf(file,"s=N,"); break; |
253 | case ContinuousStyle : break; | 257 | case ContinuousStyle : break; |
254 | } | 258 | } |
255 | /* Save the default tempo */ | 259 | /* Save the default tempo */ |
256 | fprintf(file,"b=%i:",DefNoteTempo); | 260 | fprintf(file,"b=%i:",DefNoteTempo); |
257 | dbgprintf("DefNoteTempo=%d\n", DefNoteTempo); | 261 | dbgprintf("DefNoteTempo=%d\n", DefNoteTempo); |
258 | started = true; | 262 | started = true; |
259 | firstcomma = true; | 263 | firstcomma = true; |
260 | } | 264 | } |
261 | 265 | ||
262 | if (!started) continue; | 266 | if (!started) continue; |
263 | 267 | ||
264 | if (Note->Style!=DefNoteStyle) { | 268 | if (Note->Style!=DefNoteStyle) { |
265 | /* And a separator */ | 269 | /* And a separator */ |
266 | if (!firstcomma) fprintf(file,","); | 270 | if (!firstcomma) fprintf(file,","); |
267 | firstcomma = false; | 271 | firstcomma = false; |
268 | DefNoteStyle=Note->Style; | 272 | DefNoteStyle=Note->Style; |
269 | switch (Note->Style) { | 273 | switch (Note->Style) { |
270 | case StaccatoStyle : fprintf(file,"s=S"); break; | 274 | case StaccatoStyle : fprintf(file,"s=S"); break; |
271 | case NaturalStyle : fprintf(file,"s=N"); break; | 275 | case NaturalStyle : fprintf(file,"s=N"); break; |
272 | case ContinuousStyle: fprintf(file,"s=C"); break; | 276 | case ContinuousStyle: fprintf(file,"s=C"); break; |
273 | } | 277 | } |
274 | } | 278 | } |
275 | if (Note->Tempo!=DefNoteTempo) { | 279 | if (Note->Tempo!=DefNoteTempo) { |
276 | /* And a separator */ | 280 | /* And a separator */ |
277 | if (!firstcomma) fprintf(file,","); | 281 | if (!firstcomma) fprintf(file,","); |
278 | firstcomma = false; | 282 | firstcomma = false; |
279 | DefNoteTempo=Note->Tempo; | 283 | DefNoteTempo=Note->Tempo; |
280 | fprintf(file,"b=%i",DefNoteTempo); | 284 | fprintf(file,"b=%i",DefNoteTempo); |
281 | } | 285 | } |
282 | /* This note has a duration different than the default. We must save it */ | 286 | /* This note has a duration different than the default. We must save it */ |
283 | if (Note->Duration!=DefNoteDuration) { | 287 | if (Note->Duration!=DefNoteDuration) { |
284 | /* And a separator */ | 288 | /* And a separator */ |
285 | if (!firstcomma) fprintf(file,","); | 289 | if (!firstcomma) fprintf(file,","); |
286 | firstcomma = false; | 290 | firstcomma = false; |
287 | switch (Note->Duration) { | 291 | switch (Note->Duration) { |
288 | case Duration_Full:fprintf(file,"1"); break; | 292 | case Duration_Full:fprintf(file,"1"); break; |
289 | case Duration_1_2 :fprintf(file,"2"); break; | 293 | case Duration_1_2 :fprintf(file,"2"); break; |
290 | case Duration_1_4 :fprintf(file,"4"); break; | 294 | case Duration_1_4 :fprintf(file,"4"); break; |
291 | case Duration_1_8 :fprintf(file,"8"); break; | 295 | case Duration_1_8 :fprintf(file,"8"); break; |
292 | case Duration_1_16:fprintf(file,"16");break; | 296 | case Duration_1_16:fprintf(file,"16");break; |
293 | case Duration_1_32:fprintf(file,"32");break; | 297 | case Duration_1_32:fprintf(file,"32");break; |
294 | } | 298 | } |
295 | } else { | 299 | } else { |
296 | /* And a separator */ | 300 | /* And a separator */ |
297 | if (!firstcomma) fprintf(file,","); | 301 | if (!firstcomma) fprintf(file,","); |
298 | firstcomma = false; | 302 | firstcomma = false; |
299 | } | 303 | } |
300 | /* Now save the actual note */ | 304 | /* Now save the actual note */ |
301 | switch (Note->Note) { | 305 | switch (Note->Note) { |
302 | case Note_C :fprintf(file,"c");break; | 306 | case Note_C :fprintf(file,"c");break; |
303 | case Note_Cis:fprintf(file,"c#");break; | 307 | case Note_Cis:fprintf(file,"c#");break; |
304 | case Note_D :fprintf(file,"d");break; | 308 | case Note_D :fprintf(file,"d");break; |
305 | case Note_Dis:fprintf(file,"d#");break; | 309 | case Note_Dis:fprintf(file,"d#");break; |
306 | case Note_E :fprintf(file,"e");break; | 310 | case Note_E :fprintf(file,"e");break; |
307 | case Note_F :fprintf(file,"f");break; | 311 | case Note_F :fprintf(file,"f");break; |
308 | case Note_Fis:fprintf(file,"f#");break; | 312 | case Note_Fis:fprintf(file,"f#");break; |
309 | case Note_G :fprintf(file,"g");break; | 313 | case Note_G :fprintf(file,"g");break; |
310 | case Note_Gis:fprintf(file,"g#");break; | 314 | case Note_Gis:fprintf(file,"g#");break; |
311 | case Note_A :fprintf(file,"a");break; | 315 | case Note_A :fprintf(file,"a");break; |
312 | case Note_Ais:fprintf(file,"a#");break; | 316 | case Note_Ais:fprintf(file,"a#");break; |
313 | case Note_H :fprintf(file,"h");break; | 317 | case Note_H :fprintf(file,"h");break; |
314 | default :fprintf(file,"p");break; /*Pause ?*/ | 318 | default :fprintf(file,"p");break; /*Pause ?*/ |
315 | } | 319 | } |
316 | switch (Note->DurationSpec) { | 320 | switch (Note->DurationSpec) { |
317 | case DottedNote : fprintf(file,".");break; | 321 | case DottedNote : fprintf(file,".");break; |
318 | default : break; | 322 | default : break; |
319 | } | 323 | } |
320 | if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { | 324 | if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { |
321 | fprintf(file,"%i",Note->Scale); | 325 | fprintf(file,"%i",Note->Scale); |
322 | } | 326 | } |
323 | } | 327 | } |
324 | return ERR_NONE; | 328 | return ERR_NONE; |
325 | } | 329 | } |
326 | 330 | ||
327 | void saveimelody(FILE *file, GSM_Ringtone *ringtone) | 331 | void saveimelody(FILE *file, GSM_Ringtone *ringtone) |
328 | { | 332 | { |
329 | char Buffer[2000]; | 333 | char Buffer[2000]; |
330 | int i=2000; | 334 | int i=2000; |
331 | 335 | ||
332 | GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true); | 336 | GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true); |
333 | 337 | ||
334 | fwrite(Buffer, 1, i, file); | 338 | fwrite(Buffer, 1, i, file); |
335 | } | 339 | } |
336 | 340 | ||
337 | #ifndef ENABLE_LGPL | 341 | #ifndef ENABLE_LGPL |
338 | 342 | ||
339 | static void WriteVarLen(unsigned char* midifile, int* current, long value) | 343 | static void WriteVarLen(unsigned char* midifile, int* current, long value) |
340 | { | 344 | { |
341 | long buffer; | 345 | long buffer; |
342 | 346 | ||
343 | buffer = value & 0x7f; | 347 | buffer = value & 0x7f; |
344 | 348 | ||
345 | while (value >>= 7) { | 349 | while (value >>= 7) { |
346 | buffer <<= 8; | 350 | buffer <<= 8; |
347 | buffer |= 0x80; | 351 | buffer |= 0x80; |
348 | buffer += (value & 0x7f); | 352 | buffer += (value & 0x7f); |
349 | } | 353 | } |
350 | 354 | ||
351 | while (1) { | 355 | while (1) { |
352 | midifile[(*current)++] = (unsigned char)buffer; | 356 | midifile[(*current)++] = (unsigned char)buffer; |
353 | if (buffer & 0x80) { | 357 | if (buffer & 0x80) { |
354 | buffer >>= 8; | 358 | buffer >>= 8; |
355 | } else { | 359 | } else { |
356 | break; | 360 | break; |
357 | } | 361 | } |
358 | } | 362 | } |
359 | } | 363 | } |
360 | 364 | ||
361 | #define singlepauses | 365 | #define singlepauses |
362 | 366 | ||
363 | /* FIXME: need adding tempo before each note and scale too ? */ | 367 | /* FIXME: need adding tempo before each note and scale too ? */ |
364 | void savemid(FILE* file, GSM_Ringtone *ringtone) | 368 | void savemid(FILE* file, GSM_Ringtone *ringtone) |
365 | { | 369 | { |
366 | int pause = 0, current = 26, duration, i, note=0, length = 20; | 370 | int pause = 0, current = 26, duration, i, note=0, length = 20; |
367 | bool started = false; | 371 | bool started = false; |
368 | GSM_RingNote *Note; | 372 | GSM_RingNote *Note; |
369 | unsigned char midifile[3000] = { | 373 | unsigned char midifile[3000] = { |
370 | 0x4D, 0x54, 0x68, 0x64, // MThd | 374 | 0x4D, 0x54, 0x68, 0x64, // MThd |
371 | 0x00, 0x00, 0x00, 0x06, // chunk length | 375 | 0x00, 0x00, 0x00, 0x06, // chunk length |
372 | 0x00, 0x00, // format 0 | 376 | 0x00, 0x00, // format 0 |
373 | 0x00, 0x01, // one track | 377 | 0x00, 0x01, // one track |
374 | 0x00, 0x20, // 32 per quarter note | 378 | 0x00, 0x20, // 32 per quarter note |
375 | 0x4D, 0x54, 0x72, 0x6B, // MTrk | 379 | 0x4D, 0x54, 0x72, 0x6B, // MTrk |
376 | 0x00, 0x00, 0x00, 0x00, // chunk length | 380 | 0x00, 0x00, 0x00, 0x00, // chunk length |
377 | 0x00, 0xFF, 0x51, 0x03, // tempo meta event | 381 | 0x00, 0xFF, 0x51, 0x03, // tempo meta event |
378 | 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note | 382 | 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note |
379 | 383 | ||
380 | for (i = 0; i < ringtone->NoteTone.NrCommands; i++) { | 384 | for (i = 0; i < ringtone->NoteTone.NrCommands; i++) { |
381 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { | 385 | if (ringtone->NoteTone.Commands[i].Type == RING_Note) { |
382 | Note = &ringtone->NoteTone.Commands[i].Note; | 386 | Note = &ringtone->NoteTone.Commands[i].Note; |
383 | if (!started) { | 387 | if (!started) { |
384 | /* readmid does not read pauses at the beginning */ | 388 | /* readmid does not read pauses at the beginning */ |
385 | if (Note->Note != Note_Pause) { | 389 | if (Note->Note != Note_Pause) { |
386 | /* FIXME: we need add tempo before each note or so... */ | 390 | /* FIXME: we need add tempo before each note or so... */ |
387 | long duration=60000000/Note->Tempo; | 391 | long duration=60000000/Note->Tempo; |
388 | 392 | ||
389 | midifile[current++] = (unsigned char)(duration >> 16); | 393 | midifile[current++] = (unsigned char)(duration >> 16); |
390 | midifile[current++] = (unsigned char)(duration >> 8); | 394 | midifile[current++] = (unsigned char)(duration >> 8); |
391 | midifile[current++] = (unsigned char)duration; | 395 | midifile[current++] = (unsigned char)duration; |
392 | 396 | ||
393 | started = true; | 397 | started = true; |
394 | } | 398 | } |
395 | } | 399 | } |
396 | if (!started) continue; | 400 | if (!started) continue; |
397 | duration = GSM_RingNoteGetFullDuration(*Note); | 401 | duration = GSM_RingNoteGetFullDuration(*Note); |
398 | if (Note->Note == Note_Pause) { | 402 | if (Note->Note == Note_Pause) { |
399 | pause += duration; | 403 | pause += duration; |
400 | #ifdef singlepauses | 404 | #ifdef singlepauses |
401 | WriteVarLen(midifile,¤t,pause); | 405 | WriteVarLen(midifile,¤t,pause); |
402 | pause=0; | 406 | pause=0; |
403 | midifile[current++]=0x00; // pause | 407 | midifile[current++]=0x00; // pause |
404 | midifile[current++]=0x00; | 408 | midifile[current++]=0x00; |
405 | #endif | 409 | #endif |
406 | } else { | 410 | } else { |
407 | if (Note->Note >= Note_C && Note->Note <= Note_H) { | 411 | if (Note->Note >= Note_C && Note->Note <= Note_H) { |
408 | note = Note->Note/16 + 12 * Note->Scale - 1; | 412 | note = Note->Note/16 + 12 * Note->Scale - 1; |
409 | } | 413 | } |
410 | 414 | ||
411 | WriteVarLen(midifile,¤t,pause); | 415 | WriteVarLen(midifile,¤t,pause); |
412 | pause=0; | 416 | pause=0; |
413 | midifile[current++]=0x90; // note on | 417 | midifile[current++]=0x90; // note on |
414 | midifile[current++]=note; | 418 | midifile[current++]=note; |
415 | midifile[current++]=0x64; // forte | 419 | midifile[current++]=0x64; // forte |
416 | 420 | ||
417 | WriteVarLen(midifile,¤t,duration); | 421 | WriteVarLen(midifile,¤t,duration); |
418 | midifile[current++]=0x80; // note off | 422 | midifile[current++]=0x80; // note off |
419 | midifile[current++]=note; | 423 | midifile[current++]=note; |
420 | midifile[current++]=0x64; | 424 | midifile[current++]=0x64; |
421 | } | 425 | } |
422 | } | 426 | } |
423 | } | 427 | } |
424 | if (pause) { | 428 | if (pause) { |
425 | WriteVarLen(midifile,¤t,pause); | 429 | WriteVarLen(midifile,¤t,pause); |
426 | midifile[current++]=0x00; // pause | 430 | midifile[current++]=0x00; // pause |
427 | midifile[current++]=0x00; // | 431 | midifile[current++]=0x00; // |
428 | } | 432 | } |
429 | midifile[current++] = 0x00; | 433 | midifile[current++] = 0x00; |
430 | midifile[current++] = 0xFF; // track end | 434 | midifile[current++] = 0xFF; // track end |
431 | midifile[current++] = 0x2F; | 435 | midifile[current++] = 0x2F; |
432 | midifile[current++] = 0x00; | 436 | midifile[current++] = 0x00; |
433 | midifile[length++] = (current-22) >> 8; | 437 | midifile[length++] = (current-22) >> 8; |
434 | midifile[length++] = current-22; | 438 | midifile[length++] = current-22; |
435 | 439 | ||
436 | fwrite(midifile,1,current,file); | 440 | fwrite(midifile,1,current,file); |
437 | } | 441 | } |
438 | 442 | ||
439 | #endif | 443 | #endif |
440 | 444 | ||
441 | void saveott(FILE *file, GSM_Ringtone *ringtone) | 445 | void saveott(FILE *file, GSM_Ringtone *ringtone) |
442 | { | 446 | { |
443 | char Buffer[2000]; | 447 | char Buffer[2000]; |
444 | int i=2000; | 448 | int i=2000; |
445 | 449 | ||
446 | GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i); | 450 | GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i); |
447 | 451 | ||
448 | fwrite(Buffer, 1, i, file); | 452 | fwrite(Buffer, 1, i, file); |
449 | } | 453 | } |
450 | 454 | ||
451 | GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone) | 455 | GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone) |
452 | { | 456 | { |
453 | FILE *file; | 457 | FILE *file; |
454 | 458 | ||
455 | file = fopen(FileName, "wb"); | 459 | file = fopen(FileName, "wb"); |
456 | if (file == NULL) return ERR_CANTOPENFILE; | 460 | if (file == NULL) return ERR_CANTOPENFILE; |
457 | 461 | ||
458 | switch (ringtone->Format) { | 462 | switch (ringtone->Format) { |
459 | case RING_NOTETONE: | 463 | case RING_NOTETONE: |
460 | if (strstr(FileName,".ott")) { | 464 | if (strstr(FileName,".ott")) { |
461 | saveott(file,ringtone); | 465 | saveott(file,ringtone); |
462 | #ifndef ENABLE_LGPL | 466 | #ifndef ENABLE_LGPL |
463 | } else if (strstr(FileName,".mid")) { | 467 | } else if (strstr(FileName,".mid")) { |
464 | savemid(file,ringtone); | 468 | savemid(file,ringtone); |
465 | #endif | 469 | #endif |
466 | } else if (strstr(FileName,".rng")) { | 470 | } else if (strstr(FileName,".rng")) { |
467 | saveott(file,ringtone); | 471 | saveott(file,ringtone); |
468 | } else if (strstr(FileName,".imy")) { | 472 | } else if (strstr(FileName,".imy")) { |
469 | saveimelody(file,ringtone); | 473 | saveimelody(file,ringtone); |
470 | } else if (strstr(FileName,".ime")) { | 474 | } else if (strstr(FileName,".ime")) { |
471 | saveimelody(file,ringtone); | 475 | saveimelody(file,ringtone); |
472 | } else if (strstr(FileName,".wav")) { | 476 | } else if (strstr(FileName,".wav")) { |
473 | savewav(file,ringtone); | 477 | savewav(file,ringtone); |
474 | } else { | 478 | } else { |
475 | saverttl(file, ringtone); | 479 | saverttl(file, ringtone); |
476 | } | 480 | } |
477 | break; | 481 | break; |
478 | case RING_NOKIABINARY: | 482 | case RING_NOKIABINARY: |
479 | savebin(file, ringtone); | 483 | savebin(file, ringtone); |
480 | break; | 484 | break; |
481 | case RING_MIDI: | 485 | case RING_MIDI: |
482 | savepuremidi(file, ringtone); | 486 | savepuremidi(file, ringtone); |
483 | break; | 487 | break; |
484 | } | 488 | } |
485 | 489 | ||
486 | fclose(file); | 490 | fclose(file); |
487 | 491 | ||
488 | return ERR_NONE; | 492 | return ERR_NONE; |
489 | } | 493 | } |
490 | 494 | ||
491 | static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone) | 495 | static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone) |
492 | { | 496 | { |
493 | GSM_RingNoteScale DefNoteScale= Scale_880; | 497 | GSM_RingNoteScale DefNoteScale= Scale_880; |
494 | GSM_RingNoteDuration DefNoteDuration= Duration_1_4; | 498 | GSM_RingNoteDuration DefNoteDuration= Duration_1_4; |
495 | GSM_RingNoteStyle DefNoteStyle= NaturalStyle; | 499 | GSM_RingNoteStyle DefNoteStyle= NaturalStyle; |
496 | int DefNoteTempo= 63, i=0; | 500 | int DefNoteTempo= 63, i=0; |
497 | 501 | ||
498 | unsigned char buffer[2000],Name[100]; | 502 | unsigned char buffer[2000],Name[100]; |
499 | GSM_RingNote *Note; | 503 | GSM_RingNote *Note; |
500 | 504 | ||
501 | fread(buffer, 2000, 1, file); | 505 | fread(buffer, 2000, 1, file); |
502 | 506 | ||
503 | ringtone->NoteTone.NrCommands = 0; | 507 | ringtone->NoteTone.NrCommands = 0; |
504 | 508 | ||
505 | /* -------------- name ---------------- */ | 509 | /* -------------- name ---------------- */ |
506 | while (buffer[i] != ':') { | 510 | while (buffer[i] != ':') { |
507 | if (buffer[i] == 0x00) return ERR_NONE; | 511 | if (buffer[i] == 0x00) return ERR_NONE; |
508 | i++; | 512 | i++; |
509 | } | 513 | } |
510 | if (i == 0) { | 514 | if (i == 0) { |
511 | /* This is for RTTL ringtones without name. */ | 515 | /* This is for RTTL ringtones without name. */ |
512 | EncodeUnicode(ringtone->Name,"Gammu",5); | 516 | EncodeUnicode(ringtone->Name,"Gammu",5); |
513 | } else { | 517 | } else { |
514 | memcpy(Name,buffer,i); | 518 | memcpy(Name,buffer,i); |
515 | Name[i] = 0x00; | 519 | Name[i] = 0x00; |
516 | EncodeUnicode(ringtone->Name,Name,strlen(Name)); | 520 | EncodeUnicode(ringtone->Name,Name,strlen(Name)); |
517 | } | 521 | } |
518 | i++; | 522 | i++; |
519 | 523 | ||
520 | /* --------- section with default ringtone settings ----------- */ | 524 | /* --------- section with default ringtone settings ----------- */ |
521 | while(1) { | 525 | while(1) { |
522 | switch (buffer[i]) { | 526 | switch (buffer[i]) { |
523 | case ':': | 527 | case ':': |
524 | break; | 528 | break; |
525 | case 0x00: | 529 | case 0x00: |
526 | return ERR_NONE; | 530 | return ERR_NONE; |
527 | case 'd': case 'D': | 531 | case 'd': case 'D': |
528 | switch (atoi(buffer+i+2)) { | 532 | switch (atoi(buffer+i+2)) { |
529 | case 1: DefNoteDuration = Duration_Full; break; | 533 | case 1: DefNoteDuration = Duration_Full; break; |
530 | case 2: DefNoteDuration = Duration_1_2 ; break; | 534 | case 2: DefNoteDuration = Duration_1_2 ; break; |
531 | case 4: DefNoteDuration = Duration_1_4 ; break; | 535 | case 4: DefNoteDuration = Duration_1_4 ; break; |
532 | case 8: DefNoteDuration = Duration_1_8 ; break; | 536 | case 8: DefNoteDuration = Duration_1_8 ; break; |
533 | case 16: DefNoteDuration = Duration_1_16; break; | 537 | case 16: DefNoteDuration = Duration_1_16; break; |
534 | case 32: DefNoteDuration = Duration_1_32; break; | 538 | case 32: DefNoteDuration = Duration_1_32; break; |
535 | } | 539 | } |
536 | break; | 540 | break; |
537 | case 'o': case 'O': | 541 | case 'o': case 'O': |
538 | switch (atoi(buffer+i+2)) { | 542 | switch (atoi(buffer+i+2)) { |
539 | case 4: DefNoteScale = Scale_440 ; break; | 543 | case 4: DefNoteScale = Scale_440 ; break; |
540 | case 5: DefNoteScale = Scale_880 ; break; | 544 | case 5: DefNoteScale = Scale_880 ; break; |
541 | case 6: DefNoteScale = Scale_1760; break; | 545 | case 6: DefNoteScale = Scale_1760; break; |
542 | case 7: DefNoteScale = Scale_3520; break; | 546 | case 7: DefNoteScale = Scale_3520; break; |
543 | } | 547 | } |
544 | break; | 548 | break; |
545 | case 'b': case 'B': | 549 | case 'b': case 'B': |
546 | DefNoteTempo=atoi(buffer+i+2); | 550 | DefNoteTempo=atoi(buffer+i+2); |
547 | dbgprintf("Tempo = %i\n",DefNoteTempo); | 551 | dbgprintf("Tempo = %i\n",DefNoteTempo); |
548 | break; | 552 | break; |
549 | case 's': case 'S': | 553 | case 's': case 'S': |
550 | switch (buffer[i+1]) { | 554 | switch (buffer[i+1]) { |
551 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; | 555 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; |
552 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; | 556 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; |
553 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; | 557 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; |
554 | } | 558 | } |
555 | switch (buffer[i+2]) { | 559 | switch (buffer[i+2]) { |
556 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; | 560 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; |
557 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; | 561 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; |
558 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; | 562 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; |
559 | } | 563 | } |
560 | break; | 564 | break; |
561 | } | 565 | } |
562 | while (buffer[i] != ':' && buffer[i] != ',') { | 566 | while (buffer[i] != ':' && buffer[i] != ',') { |
563 | if (buffer[i] == 0x00) return ERR_NONE; | 567 | if (buffer[i] == 0x00) return ERR_NONE; |
564 | i++; | 568 | i++; |
565 | } | 569 | } |
566 | if (buffer[i] == ',') i++; | 570 | if (buffer[i] == ',') i++; |
567 | if (buffer[i] == ':') break; | 571 | if (buffer[i] == ':') break; |
568 | } | 572 | } |
569 | dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); | 573 | dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); |
570 | dbgprintf("DefNoteScale=%d\n", DefNoteScale); | 574 | dbgprintf("DefNoteScale=%d\n", DefNoteScale); |
571 | i++; | 575 | i++; |
572 | 576 | ||
573 | /* ------------------------- notes ------------------------------ */ | 577 | /* ------------------------- notes ------------------------------ */ |
574 | while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) { | 578 | while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) { |
575 | switch(buffer[i]) { | 579 | switch(buffer[i]) { |
576 | case 'z': case 'Z': | 580 | case 'z': case 'Z': |
577 | switch (buffer[i+1]) { | 581 | switch (buffer[i+1]) { |
578 | case 'd': | 582 | case 'd': |
579 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED; | 583 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED; |
580 | ringtone->NoteTone.NrCommands++; | 584 | ringtone->NoteTone.NrCommands++; |
581 | break; | 585 | break; |
582 | case 'D': | 586 | case 'D': |
583 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED; | 587 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED; |
584 | ringtone->NoteTone.NrCommands++; | 588 | ringtone->NoteTone.NrCommands++; |
585 | break; | 589 | break; |
586 | case 'v': | 590 | case 'v': |
587 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra; | 591 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra; |
588 | ringtone->NoteTone.NrCommands++; | 592 | ringtone->NoteTone.NrCommands++; |
589 | break; | 593 | break; |
590 | case 'V': | 594 | case 'V': |
591 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra; | 595 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra; |
592 | ringtone->NoteTone.NrCommands++; | 596 | ringtone->NoteTone.NrCommands++; |
593 | break; | 597 | break; |
594 | case 'l': | 598 | case 'l': |
595 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight; | 599 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight; |
596 | ringtone->NoteTone.NrCommands++; | 600 | ringtone->NoteTone.NrCommands++; |
597 | break; | 601 | break; |
598 | case 'L': | 602 | case 'L': |
599 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight; | 603 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight; |
600 | ringtone->NoteTone.NrCommands++; | 604 | ringtone->NoteTone.NrCommands++; |
601 | } | 605 | } |
602 | break; | 606 | break; |
603 | case 'o': case 'O': | 607 | case 'o': case 'O': |
604 | switch (buffer[i+2]) { | 608 | switch (buffer[i+2]) { |
605 | case 4: DefNoteScale = Scale_440 ; break; | 609 | case 4: DefNoteScale = Scale_440 ; break; |
606 | case 5: DefNoteScale = Scale_880 ; break; | 610 | case 5: DefNoteScale = Scale_880 ; break; |
607 | case 6: DefNoteScale = Scale_1760; break; | 611 | case 6: DefNoteScale = Scale_1760; break; |
608 | case 7: DefNoteScale = Scale_3520; break; | 612 | case 7: DefNoteScale = Scale_3520; break; |
609 | } | 613 | } |
610 | break; | 614 | break; |
611 | case 's': case 'S': | 615 | case 's': case 'S': |
612 | switch (buffer[i+1]) { | 616 | switch (buffer[i+1]) { |
613 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; | 617 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; |
614 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; | 618 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; |
615 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; | 619 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; |
616 | } | 620 | } |
617 | switch (buffer[i+2]) { | 621 | switch (buffer[i+2]) { |
618 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; | 622 | case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; |
619 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; | 623 | case 'N': case 'n': DefNoteStyle=NaturalStyle; break; |
620 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; | 624 | case 'S': case 's': DefNoteStyle=StaccatoStyle; break; |
621 | } | 625 | } |
622 | break; | 626 | break; |
623 | default: | 627 | default: |
624 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; | 628 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; |
625 | Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; | 629 | Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; |
626 | Note->Style = DefNoteStyle; | 630 | Note->Style = DefNoteStyle; |
627 | Note->Tempo = DefNoteTempo; | 631 | Note->Tempo = DefNoteTempo; |
628 | Note->Scale = DefNoteScale; | 632 | Note->Scale = DefNoteScale; |
629 | Note->Duration = DefNoteDuration; | 633 | Note->Duration = DefNoteDuration; |
630 | Note->DurationSpec = NoSpecialDuration; | 634 | Note->DurationSpec = NoSpecialDuration; |
631 | Note->Note = Note_Pause; | 635 | Note->Note = Note_Pause; |
632 | 636 | ||
633 | /* Duration */ | 637 | /* Duration */ |
634 | switch (atoi(buffer+i)) { | 638 | switch (atoi(buffer+i)) { |
635 | case 1: Note->Duration = Duration_Full ; break; | 639 | case 1: Note->Duration = Duration_Full ; break; |
636 | case 2: Note->Duration = Duration_1_2 ; break; | 640 | case 2: Note->Duration = Duration_1_2 ; break; |
637 | case 4: Note->Duration = Duration_1_4 ; break; | 641 | case 4: Note->Duration = Duration_1_4 ; break; |
638 | case 8: Note->Duration = Duration_1_8 ; break; | 642 | case 8: Note->Duration = Duration_1_8 ; break; |
639 | case 16: Note->Duration = Duration_1_16 ; break; | 643 | case 16: Note->Duration = Duration_1_16 ; break; |
640 | case 32: Note->Duration = Duration_1_32 ; break; | 644 | case 32: Note->Duration = Duration_1_32 ; break; |
641 | } | 645 | } |
642 | /* We skip all numbers from duration specification */ | 646 | /* We skip all numbers from duration specification */ |
643 | while(isdigit(buffer[i])) i++; | 647 | while(isdigit(buffer[i])) i++; |
644 | 648 | ||
645 | /* Some files can have special duration here */ | 649 | /* Some files can have special duration here */ |
646 | if (buffer[i]=='.') { | 650 | if (buffer[i]=='.') { |
647 | Note->DurationSpec = DottedNote; | 651 | Note->DurationSpec = DottedNote; |
648 | i++; | 652 | i++; |
649 | } | 653 | } |
650 | 654 | ||
651 | /* Note */ | 655 | /* Note */ |
652 | /* B or b is not in specs, but I decided to put it, because | 656 | /* B or b is not in specs, but I decided to put it, because |
653 | * it's in some RTTL files. It's the same to H note */ | 657 | * it's in some RTTL files. It's the same to H note */ |
654 | switch (buffer[i]) { | 658 | switch (buffer[i]) { |
655 | case 'A': case 'a': Note->Note = Note_A; break; | 659 | case 'A': case 'a': Note->Note = Note_A; break; |
656 | case 'B': case 'b': Note->Note = Note_H; break; | 660 | case 'B': case 'b': Note->Note = Note_H; break; |
657 | case 'C': case 'c': Note->Note = Note_C; break; | 661 | case 'C': case 'c': Note->Note = Note_C; break; |
658 | case 'D': case 'd': Note->Note = Note_D; break; | 662 | case 'D': case 'd': Note->Note = Note_D; break; |
659 | case 'E': case 'e': Note->Note = Note_E; break; | 663 | case 'E': case 'e': Note->Note = Note_E; break; |
660 | case 'F': case 'f': Note->Note = Note_F; break; | 664 | case 'F': case 'f': Note->Note = Note_F; break; |
661 | case 'G': case 'g': Note->Note = Note_G; break; | 665 | case 'G': case 'g': Note->Note = Note_G; break; |
662 | case 'H': case 'h': Note->Note = Note_H; break; | 666 | case 'H': case 'h': Note->Note = Note_H; break; |
663 | } | 667 | } |
664 | i++; | 668 | i++; |
665 | 669 | ||
666 | if (buffer[i]=='#') { | 670 | if (buffer[i]=='#') { |
667 | switch (Note->Note) { | 671 | switch (Note->Note) { |
668 | case Note_A : Note->Note = Note_Ais; break; | 672 | case Note_A : Note->Note = Note_Ais; break; |
669 | case Note_C : Note->Note = Note_Cis; break; | 673 | case Note_C : Note->Note = Note_Cis; break; |
670 | case Note_D : Note->Note = Note_Dis; break; | 674 | case Note_D : Note->Note = Note_Dis; break; |
671 | case Note_F : Note->Note = Note_Fis; break; | 675 | case Note_F : Note->Note = Note_Fis; break; |
672 | case Note_G : Note->Note = Note_Gis; break; | 676 | case Note_G : Note->Note = Note_Gis; break; |
673 | default : break; | 677 | default : break; |
674 | } | 678 | } |
675 | i++; | 679 | i++; |
676 | } | 680 | } |
677 | 681 | ||
678 | /* Some files can have special duration here */ | 682 | /* Some files can have special duration here */ |
679 | if (buffer[i]=='.') { | 683 | if (buffer[i]=='.') { |
680 | Note->DurationSpec = DottedNote; | 684 | Note->DurationSpec = DottedNote; |
681 | i++; | 685 | i++; |
682 | } | 686 | } |
683 | 687 | ||
684 | /* Scale */ | 688 | /* Scale */ |
685 | if (Note->Note!=Note_Pause && isdigit(buffer[i])) { | 689 | if (Note->Note!=Note_Pause && isdigit(buffer[i])) { |
686 | switch (atoi(buffer+i)) { | 690 | switch (atoi(buffer+i)) { |
687 | case 4: Note->Scale = Scale_440 ; break; | 691 | case 4: Note->Scale = Scale_440 ; break; |
688 | case 5: Note->Scale = Scale_880 ; break; | 692 | case 5: Note->Scale = Scale_880 ; break; |
689 | case 6: Note->Scale = Scale_1760; break; | 693 | case 6: Note->Scale = Scale_1760; break; |
690 | case 7: Note->Scale = Scale_3520; break; | 694 | case 7: Note->Scale = Scale_3520; break; |
691 | } | 695 | } |
692 | i++; | 696 | i++; |
693 | } | 697 | } |
694 | 698 | ||
695 | ringtone->NoteTone.NrCommands++; | 699 | ringtone->NoteTone.NrCommands++; |
696 | break; | 700 | break; |
697 | } | 701 | } |
698 | while (buffer[i] != ',') { | 702 | while (buffer[i] != ',') { |
699 | if (buffer[i] == 0x00) return ERR_NONE; | 703 | if (buffer[i] == 0x00) return ERR_NONE; |
700 | i++; | 704 | i++; |
701 | } | 705 | } |
702 | if (buffer[i] == ',') i++; | 706 | if (buffer[i] == ',') i++; |
703 | } | 707 | } |
704 | 708 | ||
705 | return ERR_NONE; | 709 | return ERR_NONE; |
706 | } | 710 | } |
707 | 711 | ||
708 | static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone) | 712 | static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone) |
709 | { | 713 | { |
710 | char Buffer[2000]; | 714 | char Buffer[2000]; |
711 | int i; | 715 | int i; |
712 | 716 | ||
713 | i=fread(Buffer, 1, 2000, file); | 717 | i=fread(Buffer, 1, 2000, file); |
714 | 718 | ||
715 | return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i); | 719 | return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i); |
716 | } | 720 | } |
717 | 721 | ||
718 | static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone) | 722 | static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone) |
719 | { | 723 | { |
720 | char Buffer[4000]; | 724 | char Buffer[4000]; |
721 | int i,j; | 725 | int i,j; |
722 | 726 | ||
723 | i=fread(Buffer, 1, 4000, file); | 727 | i=fread(Buffer, 1, 4000, file); |
724 | 728 | ||
725 | i=0;j=0; | 729 | i=0;j=0; |
726 | while (true) { | 730 | while (true) { |
727 | if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 && | 731 | if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 && |
728 | Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break; | 732 | Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break; |
729 | if (j==i-4) return ERR_UNKNOWN; | 733 | if (j==i-4) return ERR_UNKNOWN; |
730 | j++; | 734 | j++; |
731 | } | 735 | } |
732 | j++; | 736 | j++; |
733 | 737 | ||
734 | return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j); | 738 | return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j); |
735 | } | 739 | } |
736 | 740 | ||
737 | static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone) | 741 | static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone) |
738 | { | 742 | { |
739 | int i; | 743 | int i; |
740 | unsigned charbuffer[2000]; | 744 | unsigned charbuffer[2000]; |
741 | 745 | ||
742 | dbgprintf("loading binary\n"); | 746 | dbgprintf("loading binary\n"); |
743 | ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); | 747 | ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); |
744 | i=5; | 748 | i=5; |
745 | while (buffer[i]!=0x00) i++; | 749 | while (buffer[i]!=0x00) i++; |
746 | EncodeUnicode(ringtone->Name,buffer+5,i-5); | 750 | EncodeUnicode(ringtone->Name,buffer+5,i-5); |
747 | while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) { | 751 | while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) { |
748 | i++; | 752 | i++; |
749 | } | 753 | } |
750 | ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i; | 754 | ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i; |
751 | memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length); | 755 | memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length); |
752 | dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); | 756 | dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); |
753 | return ERR_NONE; | 757 | return ERR_NONE; |
754 | } | 758 | } |
755 | 759 | ||
756 | static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone) | 760 | static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone) |
757 | { | 761 | { |
758 | unsigned char buffer[30000]; | 762 | unsigned char buffer[30000]; |
759 | 763 | ||
760 | dbgprintf("loading midi\n"); | 764 | dbgprintf("loading midi\n"); |
761 | EncodeUnicode(ringtone->Name,"MIDI",4); | 765 | EncodeUnicode(ringtone->Name,"MIDI",4); |
762 | ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file); | 766 | ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file); |
763 | memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length); | 767 | memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length); |
764 | dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); | 768 | dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); |
765 | return ERR_NONE; | 769 | return ERR_NONE; |
766 | } | 770 | } |
767 | 771 | ||
768 | static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone) | 772 | static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone) |
769 | { | 773 | { |
770 | unsigned char buffer[2000]; | 774 | unsigned char buffer[2000]; |
771 | 775 | ||
772 | ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); | 776 | ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); |
773 | 777 | ||
774 | if (buffer[18]==0x00 && buffer[21]!=0x02) { | 778 | if (buffer[18]==0x00 && buffer[21]!=0x02) { |
775 | /* DCT3, Unicode subformat, 62xx & 7110 */ | 779 | /* DCT3, Unicode subformat, 62xx & 7110 */ |
776 | CopyUnicodeString(ringtone->Name,buffer+18); | 780 | CopyUnicodeString(ringtone->Name,buffer+18); |
777 | ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2); | 781 | ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2); |
778 | memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length); | 782 | memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length); |
779 | } else { | 783 | } else { |
780 | /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */ | 784 | /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */ |
781 | EncodeUnicode(ringtone->Name,buffer+17,buffer[16]); | 785 | EncodeUnicode(ringtone->Name,buffer+17,buffer[16]); |
782 | ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name)); | 786 | ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name)); |
783 | memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length); | 787 | memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length); |
784 | } | 788 | } |
785 | dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name)); | 789 | dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name)); |
786 | return ERR_NONE; | 790 | return ERR_NONE; |
787 | } | 791 | } |
788 | 792 | ||
789 | GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone) | 793 | GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone) |
790 | { | 794 | { |
791 | FILE *file; | 795 | FILE *file; |
792 | unsigned charbuffer[300]; | 796 | unsigned charbuffer[300]; |
793 | GSM_Errorerror = ERR_UNKNOWN; | 797 | GSM_Errorerror = ERR_UNKNOWN; |
794 | 798 | ||
795 | dbgprintf("Loading ringtone %s\n",FileName); | 799 | dbgprintf("Loading ringtone %s\n",FileName); |
796 | file = fopen(FileName, "rb"); | 800 | file = fopen(FileName, "rb"); |
797 | if (file == NULL) return ERR_CANTOPENFILE; | 801 | if (file == NULL) return ERR_CANTOPENFILE; |
798 | 802 | ||
799 | /* Read the header of the file. */ | 803 | /* Read the header of the file. */ |
800 | fread(buffer, 1, 4, file); | 804 | fread(buffer, 1, 4, file); |
801 | if (ringtone->Format == 0x00) { | 805 | if (ringtone->Format == 0x00) { |
802 | ringtone->Format = RING_NOTETONE; | 806 | ringtone->Format = RING_NOTETONE; |
803 | if (buffer[0]==0x00 && buffer[1]==0x00 && | 807 | if (buffer[0]==0x00 && buffer[1]==0x00 && |
804 | buffer[2]==0x0C && buffer[3]==0x01) { | 808 | buffer[2]==0x0C && buffer[3]==0x01) { |
805 | ringtone->Format = RING_NOKIABINARY; | 809 | ringtone->Format = RING_NOKIABINARY; |
806 | } | 810 | } |
807 | if (buffer[0]==0x00 && buffer[1]==0x00 && | 811 | if (buffer[0]==0x00 && buffer[1]==0x00 && |
808 | buffer[2]==0x00) { | 812 | buffer[2]==0x00) { |
809 | ringtone->Format = RING_NOKIABINARY; | 813 | ringtone->Format = RING_NOKIABINARY; |
810 | } | 814 | } |
811 | if (buffer[0]==0x4D && buffer[1]==0x54 && | 815 | if (buffer[0]==0x4D && buffer[1]==0x54 && |
812 | buffer[2]==0x68 && buffer[3]==0x64) { | 816 | buffer[2]==0x68 && buffer[3]==0x64) { |
813 | ringtone->Format = RING_MIDI; | 817 | ringtone->Format = RING_MIDI; |
814 | } | 818 | } |
815 | } | 819 | } |
816 | rewind(file); | 820 | rewind(file); |
817 | switch (ringtone->Format) { | 821 | switch (ringtone->Format) { |
818 | case RING_NOTETONE: | 822 | case RING_NOTETONE: |
819 | if (buffer[0]==0x02 && buffer[1]==0x4A) { | 823 | if (buffer[0]==0x02 && buffer[1]==0x4A) { |
820 | error=loadott(file,ringtone); | 824 | error=loadott(file,ringtone); |
821 | } else if (buffer[0]==0xC7 && buffer[1]==0x45) { | 825 | } else if (buffer[0]==0xC7 && buffer[1]==0x45) { |
822 | error=loadcommunicator(file,ringtone); | 826 | error=loadcommunicator(file,ringtone); |
823 | } else { | 827 | } else { |
824 | error=loadrttl(file,ringtone); | 828 | error=loadrttl(file,ringtone); |
825 | } | 829 | } |
826 | ringtone->NoteTone.AllNotesScale=false; | 830 | ringtone->NoteTone.AllNotesScale=false; |
827 | break; | 831 | break; |
828 | case RING_NOKIABINARY: | 832 | case RING_NOKIABINARY: |
829 | if (buffer[0]==0x00 && buffer[1]==0x00 && | 833 | if (buffer[0]==0x00 && buffer[1]==0x00 && |
830 | buffer[2]==0x0C && buffer[3]==0x01) { | 834 | buffer[2]==0x0C && buffer[3]==0x01) { |
831 | error=loadbin(file,ringtone); | 835 | error=loadbin(file,ringtone); |
832 | } | 836 | } |
833 | if (buffer[0]==0x00 && buffer[1]==0x00 && | 837 | if (buffer[0]==0x00 && buffer[1]==0x00 && |
834 | buffer[2]==0x00) { | 838 | buffer[2]==0x00) { |
835 | error=loadre(file,ringtone); | 839 | error=loadre(file,ringtone); |
836 | } | 840 | } |
837 | break; | 841 | break; |
838 | case RING_MIDI: | 842 | case RING_MIDI: |
839 | EncodeUnicode(ringtone->Name,FileName,strlen(FileName)); | 843 | EncodeUnicode(ringtone->Name,FileName,strlen(FileName)); |
840 | error = loadpuremidi(file,ringtone); | 844 | error = loadpuremidi(file,ringtone); |
841 | } | 845 | } |
842 | fclose(file); | 846 | fclose(file); |
843 | return(error); | 847 | return(error); |
844 | } | 848 | } |
845 | 849 | ||
846 | /* -------------------------- required with Nokia & RTTL ------------------- */ | 850 | /* -------------------------- required with Nokia & RTTL ------------------- */ |
847 | 851 | ||
848 | /* Beats per Minute like written in Smart Messaging */ | 852 | /* Beats per Minute like written in Smart Messaging */ |
849 | static int SM_BeatsPerMinute[] = { | 853 | static int SM_BeatsPerMinute[] = { |
850 | 25, 28, 31, 35, 40, 45, 50, 56, 63,70, | 854 | 25, 28, 31, 35, 40, 45, 50, 56, 63,70, |
851 | 80, 90, 100, 112, 125, 140, 160, 180, 200,225, | 855 | 80, 90, 100, 112, 125, 140, 160, 180, 200,225, |
852 | 250, 285, 320, 355, 400, 450, 500, 565, 635,715, | 856 | 250, 285, 320, 355, 400, 450, 500, 565, 635,715, |
853 | 800,900 | 857 | 800,900 |
854 | }; | 858 | }; |
855 | 859 | ||
856 | int GSM_RTTLGetTempo(int Beats) | 860 | int GSM_RTTLGetTempo(int Beats) |
857 | { | 861 | { |
858 | int i=0; | 862 | int i=0; |
859 | 863 | ||
860 | while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++; | 864 | while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++; |
861 | 865 | ||
862 | return i<<3; | 866 | return i<<3; |
863 | } | 867 | } |
864 | 868 | ||
865 | /* This function packs the ringtone from the structure "ringtone" to | 869 | /* This function packs the ringtone from the structure "ringtone" to |
866 | "package", where maxlength means length of package. | 870 | "package", where maxlength means length of package. |
867 | Function returns number of packed notes and change maxlength to | 871 | Function returns number of packed notes and change maxlength to |
868 | number of used chars in "package" */ | 872 | number of used chars in "package" */ |
869 | unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength) | 873 | unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength) |
870 | { | 874 | { |
871 | unsigned char CommandLength = 0x02; | 875 | unsigned char CommandLength = 0x02; |
872 | unsigned char Loop = 0x15;/* Infinite */ | 876 | unsigned char Loop = 0x15;/* Infinite */ |
873 | 877 | ||
874 | unsigned char Buffer[200]; | 878 | unsigned char Buffer[200]; |
875 | int StartBit=0, OldStartBit; | 879 | int StartBit=0, OldStartBit; |
876 | int StartBitHowManyCommands; | 880 | int StartBitHowManyCommands; |
877 | int HowManyCommands = 0;/* How many instructions packed */ | 881 | int HowManyCommands = 0;/* How many instructions packed */ |
878 | int HowManyNotes= 0; | 882 | int HowManyNotes= 0; |
879 | int i,j; | 883 | int i,j; |
880 | bool started; | 884 | bool started; |
881 | GSM_RingNote *Note; | 885 | GSM_RingNote *Note; |
882 | 886 | ||
883 | GSM_RingNoteScale DefScale = 255; | 887 | GSM_RingNoteScale DefScale = 255; |
884 | GSM_RingNoteStyle DefStyle = 255; | 888 | GSM_RingNoteStyle DefStyle = 255; |
885 | int DefTempo = 255; | 889 | int DefTempo = 255; |
886 | 890 | ||
887 | AddBufferByte(package, &StartBit, CommandLength, 8); | 891 | AddBufferByte(package, &StartBit, CommandLength, 8); |
888 | AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7); | 892 | AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7); |
889 | 893 | ||
890 | /* According to specification we need have next part octet-aligned */ | 894 | /* According to specification we need have next part octet-aligned */ |
891 | BufferAlign(package, &StartBit); | 895 | BufferAlign(package, &StartBit); |
892 | 896 | ||
893 | AddBufferByte(package, &StartBit, SM_Command_Sound, 7); | 897 | AddBufferByte(package, &StartBit, SM_Command_Sound, 7); |
894 | AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3); | 898 | AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3); |
895 | 899 | ||
896 | /* Packing the name of the tune. */ | 900 | /* Packing the name of the tune. */ |
897 | EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name)); | 901 | EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name)); |
898 | AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4); | 902 | AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4); |
899 | AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer)); | 903 | AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer)); |
900 | 904 | ||
901 | /* Packing info about song pattern */ | 905 | /* Packing info about song pattern */ |
902 | AddBufferByte(package, &StartBit, 0x01, 8); //one pattern | 906 | AddBufferByte(package, &StartBit, 0x01, 8); //one pattern |
903 | AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3); | 907 | AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3); |
904 | AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2); | 908 | AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2); |
905 | AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4); | 909 | AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4); |
906 | 910 | ||
907 | /* Later here will be HowManyCommands */ | 911 | /* Later here will be HowManyCommands */ |
908 | StartBitHowManyCommands=StartBit; | 912 | StartBitHowManyCommands=StartBit; |
909 | StartBit = StartBit + 8; | 913 | StartBit = StartBit + 8; |
910 | 914 | ||
911 | started = false; | 915 | started = false; |
912 | for (i=0; i<ringtone.NoteTone.NrCommands; i++) { | 916 | for (i=0; i<ringtone.NoteTone.NrCommands; i++) { |
913 | if (ringtone.NoteTone.Commands[i].Type != RING_Note) { | 917 | if (ringtone.NoteTone.Commands[i].Type != RING_Note) { |
914 | HowManyNotes++; | 918 | HowManyNotes++; |
915 | continue; | 919 | continue; |
916 | } | 920 | } |
917 | Note = &ringtone.NoteTone.Commands[i].Note; | 921 | Note = &ringtone.NoteTone.Commands[i].Note; |
918 | if (!started) { | 922 | if (!started) { |
919 | /* First note can't be Pause - it makes problems | 923 | /* First note can't be Pause - it makes problems |
920 | * for example with PC Composer | 924 | * for example with PC Composer |
921 | */ | 925 | */ |
922 | if (Note->Note != Note_Pause) started = true; | 926 | if (Note->Note != Note_Pause) started = true; |
923 | } | 927 | } |
924 | if (!started) { | 928 | if (!started) { |
925 | HowManyNotes++; | 929 | HowManyNotes++; |
926 | continue; | 930 | continue; |
927 | } | 931 | } |
928 | OldStartBit = StartBit; | 932 | OldStartBit = StartBit; |
929 | /* we don't write Scale & Style info before "Pause" note - it saves place */ | 933 | /* we don't write Scale & Style info before "Pause" note - it saves place */ |
930 | if (Note->Note!=Note_Pause) { | 934 | if (Note->Note!=Note_Pause) { |
931 | if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) { | 935 | if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) { |
932 | j = StartBit+5+8; | 936 | j = StartBit+5+8; |
933 | BufferAlignNumber(&j); | 937 | BufferAlignNumber(&j); |
934 | if ((j/8)>(*maxlength)) { | 938 | if ((j/8)>(*maxlength)) { |
935 | StartBit = OldStartBit; | 939 | StartBit = OldStartBit; |
936 | break; | 940 | break; |
937 | } | 941 | } |
938 | DefScale = Note->Scale; | 942 | DefScale = Note->Scale; |
939 | AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3); | 943 | AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3); |
940 | AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2); | 944 | AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2); |
941 | HowManyCommands++; | 945 | HowManyCommands++; |
942 | } | 946 | } |
943 | if (DefStyle != Note->Style) { | 947 | if (DefStyle != Note->Style) { |
944 | j = StartBit+5+8; | 948 | j = StartBit+5+8; |
945 | BufferAlignNumber(&j); | 949 | BufferAlignNumber(&j); |
946 | if ((j/8)>(*maxlength)) { | 950 | if ((j/8)>(*maxlength)) { |
947 | StartBit = OldStartBit; | 951 | StartBit = OldStartBit; |
948 | break; | 952 | break; |
949 | } | 953 | } |
950 | DefStyle = Note->Style; | 954 | DefStyle = Note->Style; |
951 | AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3); | 955 | AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3); |
952 | AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2); | 956 | AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2); |
953 | HowManyCommands++; | 957 | HowManyCommands++; |
954 | } | 958 | } |
955 | } | 959 | } |
956 | /* Beats per minute/tempo of the tune */ | 960 | /* Beats per minute/tempo of the tune */ |
957 | if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) { | 961 | if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) { |
958 | j = StartBit+8+8; | 962 | j = StartBit+8+8; |
959 | BufferAlignNumber(&j); | 963 | BufferAlignNumber(&j); |
960 | if ((j/8)>(*maxlength)) { | 964 | if ((j/8)>(*maxlength)) { |
961 | StartBit = OldStartBit; | 965 | StartBit = OldStartBit; |
962 | break; | 966 | break; |
963 | } | 967 | } |
964 | DefTempo=GSM_RTTLGetTempo(Note->Tempo); | 968 | DefTempo=GSM_RTTLGetTempo(Note->Tempo); |
965 | /* Adding beats per minute (tempo) of the tune */ | 969 | /* Adding beats per minute (tempo) of the tune */ |
966 | AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3); | 970 | AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3); |
967 | AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5); | 971 | AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5); |
968 | HowManyCommands++; | 972 | HowManyCommands++; |
969 | } | 973 | } |
970 | j = StartBit+12+8; | 974 | j = StartBit+12+8; |
971 | BufferAlignNumber(&j); | 975 | BufferAlignNumber(&j); |
972 | if ((j/8)>(*maxlength)) { | 976 | if ((j/8)>(*maxlength)) { |
973 | StartBit = OldStartBit; | 977 | StartBit = OldStartBit; |
974 | break; | 978 | break; |
975 | } | 979 | } |
976 | /* Note */ | 980 | /* Note */ |
977 | AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3); | 981 | AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3); |
978 | AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4); | 982 | AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4); |
979 | AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3); | 983 | AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3); |
980 | AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2); | 984 | AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2); |
981 | HowManyCommands++; | 985 | HowManyCommands++; |
982 | /* We are sure, we pack it for SMS or setting to phone, not for OTT file */ | 986 | /* We are sure, we pack it for SMS or setting to phone, not for OTT file */ |
983 | if (*maxlength<1000) { | 987 | if (*maxlength<1000) { |
984 | /* Like Pc Composer say - before of phone limitations...*/ | 988 | /* Like Pc Composer say - before of phone limitations...*/ |
985 | if (HowManyNotes==130-1) break; | 989 | if (HowManyNotes==130-1) break; |
986 | } | 990 | } |
987 | HowManyNotes++; | 991 | HowManyNotes++; |
988 | } | 992 | } |
989 | 993 | ||
990 | BufferAlign(package, &StartBit); | 994 | BufferAlign(package, &StartBit); |
991 | AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8); | 995 | AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8); |
992 | 996 | ||
993 | OldStartBit = StartBit; | 997 | OldStartBit = StartBit; |
994 | StartBit = StartBitHowManyCommands; | 998 | StartBit = StartBitHowManyCommands; |
995 | /* HowManyCommands */ | 999 | /* HowManyCommands */ |
996 | AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8); | 1000 | AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8); |
997 | StartBit = OldStartBit; | 1001 | StartBit = OldStartBit; |
998 | 1002 | ||
999 | *maxlength=StartBit/8; | 1003 | *maxlength=StartBit/8; |
1000 | 1004 | ||
1001 | return(i); | 1005 | return(i); |
1002 | } | 1006 | } |
1003 | 1007 | ||
1004 | GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength) | 1008 | GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength) |
1005 | { | 1009 | { |
1006 | int StartBit=0, HowMany, l, q, i, spec; | 1010 | int StartBit=0, HowMany, l, q, i, spec; |
1007 | char Buffer[100]; | 1011 | char Buffer[100]; |
1008 | GSM_RingNote *Note; | 1012 | GSM_RingNote *Note; |
1009 | 1013 | ||
1010 | /* Default ringtone parameters */ | 1014 | /* Default ringtone parameters */ |
1011 | GSM_RingNoteScale DefScale= Scale_880; | 1015 | GSM_RingNoteScale DefScale= Scale_880; |
1012 | GSM_RingNoteStyle DefStyle = NaturalStyle; | 1016 | GSM_RingNoteStyle DefStyle = NaturalStyle; |
1013 | int DefTempo= 63; | 1017 | int DefTempo= 63; |
1014 | 1018 | ||
1015 | ringtone->Format = RING_NOTETONE; | 1019 | ringtone->Format = RING_NOTETONE; |
1016 | ringtone->NoteTone.NrCommands = 0; | 1020 | ringtone->NoteTone.NrCommands = 0; |
1017 | 1021 | ||
1018 | GetBufferInt(package,&StartBit,&l,8); | 1022 | GetBufferInt(package,&StartBit,&l,8); |
1019 | if (l!=0x02) { | 1023 | if (l!=0x02) { |
1020 | dbgprintf("Not header\n"); | 1024 | dbgprintf("Not header\n"); |
1021 | return ERR_NOTSUPPORTED; | 1025 | return ERR_NOTSUPPORTED; |
1022 | } | 1026 | } |
1023 | 1027 | ||
1024 | GetBufferInt(package,&StartBit,&l,7); | 1028 | GetBufferInt(package,&StartBit,&l,7); |
1025 | if (l!=SM_Command_RingingToneProgramming) { | 1029 | if (l!=SM_Command_RingingToneProgramming) { |
1026 | dbgprintf("Not RingingToneProgramming\n"); | 1030 | dbgprintf("Not RingingToneProgramming\n"); |
1027 | return ERR_NOTSUPPORTED; | 1031 | return ERR_NOTSUPPORTED; |
1028 | } | 1032 | } |
1029 | 1033 | ||
1030 | /* According to specification we need have next part octet-aligned */ | 1034 | /* According to specification we need have next part octet-aligned */ |
1031 | BufferAlignNumber(&StartBit); | 1035 | BufferAlignNumber(&StartBit); |
1032 | 1036 | ||
1033 | GetBufferInt(package,&StartBit,&l,7); | 1037 | GetBufferInt(package,&StartBit,&l,7); |
1034 | if (l!=SM_Command_Sound) { | 1038 | if (l!=SM_Command_Sound) { |
1035 | dbgprintf("Not Sound\n"); | 1039 | dbgprintf("Not Sound\n"); |
1036 | return ERR_NOTSUPPORTED; | 1040 | return ERR_NOTSUPPORTED; |
1037 | } | 1041 | } |
1038 | 1042 | ||
1039 | GetBufferInt(package,&StartBit,&l,3); | 1043 | GetBufferInt(package,&StartBit,&l,3); |
1040 | if (l!=SM_Song_BasicSongType) { | 1044 | if (l!=SM_Song_BasicSongType) { |
1041 | dbgprintf("Not BasicSongType\n"); | 1045 | dbgprintf("Not BasicSongType\n"); |
1042 | return ERR_NOTSUPPORTED; | 1046 | return ERR_NOTSUPPORTED; |
1043 | } | 1047 | } |
1044 | 1048 | ||
1045 | /* Getting length of the tune name */ | 1049 | /* Getting length of the tune name */ |
1046 | GetBufferInt(package,&StartBit,&l,4); | 1050 | GetBufferInt(package,&StartBit,&l,4); |
1047 | l=l>>4; | 1051 | l=l>>4; |
1048 | 1052 | ||
1049 | /* Unpacking the name of the tune. */ | 1053 | /* Unpacking the name of the tune. */ |
1050 | GetBuffer(package, &StartBit, Buffer, 8*l); | 1054 | GetBuffer(package, &StartBit, Buffer, 8*l); |
1051 | Buffer[l]=0; | 1055 | Buffer[l]=0; |
1052 | EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer)); | 1056 | EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer)); |
1053 | DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name)); | 1057 | DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name)); |
1054 | CopyUnicodeString(ringtone->Name,Buffer); | 1058 | CopyUnicodeString(ringtone->Name,Buffer); |
1055 | 1059 | ||
1056 | GetBufferInt(package,&StartBit,&l,8); | 1060 | GetBufferInt(package,&StartBit,&l,8); |
1057 | dbgprintf("Number of song patterns: %i\n",l); | 1061 | dbgprintf("Number of song patterns: %i\n",l); |
1058 | /* we support only one song pattern */ | 1062 | /* we support only one song pattern */ |
1059 | if (l!=1) return ERR_NOTSUPPORTED; | 1063 | if (l!=1) return ERR_NOTSUPPORTED; |
1060 | 1064 | ||
1061 | GetBufferInt(package,&StartBit,&l,3); | 1065 | GetBufferInt(package,&StartBit,&l,3); |
1062 | if (l!=SM_InstructionID_PatternHeaderId) { | 1066 | if (l!=SM_InstructionID_PatternHeaderId) { |
1063 | dbgprintf("Not PatternHeaderId\n"); | 1067 | dbgprintf("Not PatternHeaderId\n"); |
1064 | return ERR_NOTSUPPORTED; | 1068 | return ERR_NOTSUPPORTED; |
1065 | } | 1069 | } |
1066 | 1070 | ||
1067 | /* Pattern ID - we ignore it */ | 1071 | /* Pattern ID - we ignore it */ |
1068 | StartBit+=2; | 1072 | StartBit+=2; |
1069 | 1073 | ||
1070 | GetBufferInt(package,&StartBit,&l,4); | 1074 | GetBufferInt(package,&StartBit,&l,4); |
1071 | l=l>>4; | 1075 | l=l>>4; |
1072 | dbgprintf("Loop value: %i\n",l); | 1076 | dbgprintf("Loop value: %i\n",l); |
1073 | 1077 | ||
1074 | HowMany=0; | 1078 | HowMany=0; |
1075 | GetBufferInt(package, &StartBit, &HowMany, 8); | 1079 | GetBufferInt(package, &StartBit, &HowMany, 8); |
1076 | 1080 | ||
1077 | for (i=0;i<HowMany;i++) { | 1081 | for (i=0;i<HowMany;i++) { |
1078 | GetBufferInt(package,&StartBit,&q,3); | 1082 | GetBufferInt(package,&StartBit,&q,3); |
1079 | switch (q) { | 1083 | switch (q) { |
1080 | case SM_InstructionID_VolumeInstructionId: | 1084 | case SM_InstructionID_VolumeInstructionId: |
1081 | StartBit+=4; | 1085 | StartBit+=4; |
1082 | break; | 1086 | break; |
1083 | case SM_InstructionID_StyleInstructionId: | 1087 | case SM_InstructionID_StyleInstructionId: |
1084 | GetBufferInt(package,&StartBit,&l,2); | 1088 | GetBufferInt(package,&StartBit,&l,2); |
1085 | if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l; | 1089 | if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l; |
1086 | break; | 1090 | break; |
1087 | case SM_InstructionID_TempoInstructionId: | 1091 | case SM_InstructionID_TempoInstructionId: |
1088 | GetBufferInt(package,&StartBit,&l,5); | 1092 | GetBufferInt(package,&StartBit,&l,5); |
1089 | DefTempo=SM_BeatsPerMinute[l>>3]; | 1093 | DefTempo=SM_BeatsPerMinute[l>>3]; |
1090 | break; | 1094 | break; |
1091 | case SM_InstructionID_ScaleInstructionId: | 1095 | case SM_InstructionID_ScaleInstructionId: |
1092 | GetBufferInt(package,&StartBit,&l,2); | 1096 | GetBufferInt(package,&StartBit,&l,2); |
1093 | DefScale=(l>>6)+4; | 1097 | DefScale=(l>>6)+4; |
1094 | break; | 1098 | break; |
1095 | case SM_InstructionID_NoteInstructionId: | 1099 | case SM_InstructionID_NoteInstructionId: |
1096 | Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; | 1100 | Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; |
1097 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; | 1101 | ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; |
1098 | 1102 | ||
1099 | GetBufferInt(package,&StartBit,&l,4); | 1103 | GetBufferInt(package,&StartBit,&l,4); |
1100 | Note->Note=Note_Pause; | 1104 | Note->Note=Note_Pause; |
1101 | if (l >= Note_C && l <= Note_H) Note->Note = l; | 1105 | if (l >= Note_C && l <= Note_H) Note->Note = l; |
1102 | 1106 | ||
1103 | GetBufferInt(package,&StartBit,&l,3); | 1107 | GetBufferInt(package,&StartBit,&l,3); |
1104 | if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l; | 1108 | if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l; |
1105 | 1109 | ||
1106 | GetBufferInt(package,&StartBit,&spec,2); | 1110 | GetBufferInt(package,&StartBit,&spec,2); |
1107 | if (spec >= NoSpecialDuration && spec <= Length_2_3) { | 1111 | if (spec >= NoSpecialDuration && spec <= Length_2_3) { |
1108 | Note->DurationSpec = spec; | 1112 | Note->DurationSpec = spec; |
1109 | } | 1113 | } |
1110 | 1114 | ||
1111 | Note->Scale = DefScale; | 1115 | Note->Scale = DefScale; |
1112 | Note->Style = DefStyle; | 1116 | Note->Style = DefStyle; |
1113 | Note->Tempo = DefTempo; | 1117 | Note->Tempo = DefTempo; |
1114 | if (ringtone->NoteTone.NrCommands==MAX_RINGTONE_NOTES) break; | 1118 | if (ringtone->NoteTone.NrCommands==MAX_RINGTONE_NOTES) break; |
1115 | ringtone->NoteTone.NrCommands++; | 1119 | ringtone->NoteTone.NrCommands++; |
1116 | break; | 1120 | break; |
1117 | default: | 1121 | default: |
1118 | dbgprintf("Unsupported block %i %i\n",q,i); | 1122 | dbgprintf("Unsupported block %i %i\n",q,i); |
1119 | return ERR_NOTSUPPORTED; | 1123 | return ERR_NOTSUPPORTED; |
1120 | } | 1124 | } |
1121 | } | 1125 | } |
1122 | return ERR_NONE; | 1126 | return ERR_NONE; |
1123 | } | 1127 | } |
1124 | 1128 | ||
1125 | static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src) | 1129 | static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src) |
1126 | { | 1130 | { |
1127 | int current = 0, i, note, lastnote = 0, duration; | 1131 | int current = 0, i, note, lastnote = 0, duration; |
1128 | GSM_RingNote *Note; | 1132 | GSM_RingNote *Note; |
1129 | unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40, | 1133 | unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40, |
1130 | 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE, | 1134 | 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE, |
1131 | 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B}; | 1135 | 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B}; |
1132 | 1136 | ||
1133 | strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09");current=current+3; | 1137 | strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09");current=current+3; |
1134 | dest->NokiaBinary.Frame[current++]=0x00; | 1138 | dest->NokiaBinary.Frame[current++]=0x00; |
1135 | 1139 | ||
1136 | /*This command can be used to loop, where 0xLL = 0x01 - 0x10 | 1140 | /*This command can be used to loop, where 0xLL = 0x01 - 0x10 |
1137 | *0x01=loop once [...] 0x10=loop infinite | 1141 | *0x01=loop once [...] 0x10=loop infinite |
1138 | *Commented now | 1142 | *Commented now |
1139 | 1143 | ||
1140 | dest->NokiaBinary.Frame[current++]=0x05; | 1144 | dest->NokiaBinary.Frame[current++]=0x05; |
1141 | dest->NokiaBinary.Frame[current++]=0xLL; | 1145 | dest->NokiaBinary.Frame[current++]=0xLL; |
1142 | */ | 1146 | */ |
1143 | strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01");current=current+2; | 1147 | strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01");current=current+2; |
1144 | 1148 | ||
1145 | for (i=0; i<src->NoteTone.NrCommands; i++) { | 1149 | for (i=0; i<src->NoteTone.NrCommands; i++) { |
1146 | if (src->NoteTone.Commands[i].Type != RING_Note) continue; | 1150 | if (src->NoteTone.Commands[i].Type != RING_Note) continue; |
1147 | 1151 | ||
1148 | Note = &src->NoteTone.Commands[i].Note; | 1152 | Note = &src->NoteTone.Commands[i].Note; |
1149 | note = 64; /* Pause */ | 1153 | note = 64; /* Pause */ |
1150 | if (Note->Note!=Note_Pause) { | 1154 | if (Note->Note!=Note_Pause) { |
1151 | if (Note->Note >= Note_C && Note->Note <= Note_H) { | 1155 | if (Note->Note >= Note_C && Note->Note <= Note_H) { |
1152 | note = 113 + Note->Note/16; | 1156 | note = 113 + Note->Note/16; |
1153 | } | 1157 | } |
1154 | switch (Note->Scale) { | 1158 | switch (Note->Scale) { |
1155 | case Scale_440 : break; | 1159 | case Scale_440 : break; |
1156 | case Scale_880 : note = note + 12; break; | 1160 | case Scale_880 : note = note + 12; break; |
1157 | case Scale_1760: note = note + 24;break; | 1161 | case Scale_1760: note = note + 24;break; |
1158 | case Scale_3520: note = note + 36; break; | 1162 | case Scale_3520: note = note + 36; break; |
1159 | default : break; | 1163 | default : break; |
1160 | } | 1164 | } |
1161 | } | 1165 | } |
1162 | 1166 | ||
1163 | /* In 7110 we have 8 ms long sounds */ | 1167 | /* In 7110 we have 8 ms long sounds */ |
1164 | duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256; | 1168 | duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256; |
1165 | 1169 | ||
1166 | switch (Note->Style) { | 1170 | switch (Note->Style) { |
1167 | case StaccatoStyle: | 1171 | case StaccatoStyle: |
1168 | if (duration) { | 1172 | if (duration) { |
1169 | /* Note needs only one sound */ | 1173 | /* Note needs only one sound */ |
1170 | dest->NokiaBinary.Frame[current++] = note; | 1174 | dest->NokiaBinary.Frame[current++] = note; |
1171 | dest->NokiaBinary.Frame[current++] = 1; | 1175 | dest->NokiaBinary.Frame[current++] = 1; |
1172 | duration--; | 1176 | duration--; |
1173 | } | 1177 | } |
1174 | note = 0x40; /* The rest is pause */ | 1178 | note = 0x40; /* The rest is pause */ |
1175 | case NaturalStyle: | 1179 | case NaturalStyle: |
1176 | if (note != 0x40 && duration) { | 1180 | if (note != 0x40 && duration) { |
1177 | dest->NokiaBinary.Frame[current++] = 0x40; | 1181 | dest->NokiaBinary.Frame[current++] = 0x40; |
1178 | /* There is small pause between notes */ | 1182 | /* There is small pause between notes */ |
1179 | dest->NokiaBinary.Frame[current++] = 1; | 1183 | dest->NokiaBinary.Frame[current++] = 1; |
1180 | duration--; | 1184 | duration--; |
1181 | } | 1185 | } |
1182 | default: | 1186 | default: |
1183 | if (note != 0x40 && note == lastnote && duration) { | 1187 | if (note != 0x40 && note == lastnote && duration) { |
1184 | dest->NokiaBinary.Frame[current++] = 0x40; | 1188 | dest->NokiaBinary.Frame[current++] = 0x40; |
1185 | /* There is small pause between same notes */ | 1189 | /* There is small pause between same notes */ |
1186 | dest->NokiaBinary.Frame[current++] = 1; | 1190 | dest->NokiaBinary.Frame[current++] = 1; |
1187 | duration--; | 1191 | duration--; |
1188 | } | 1192 | } |
1189 | while (duration > 125) { | 1193 | while (duration > 125) { |
1190 | dest->NokiaBinary.Frame[current++] = note; | 1194 | dest->NokiaBinary.Frame[current++] = note; |
1191 | dest->NokiaBinary.Frame[current++] = 125; | 1195 | dest->NokiaBinary.Frame[current++] = 125; |
1192 | duration -= 125; | 1196 | duration -= 125; |
1193 | } | 1197 | } |
1194 | dest->NokiaBinary.Frame[current++] = note; | 1198 | dest->NokiaBinary.Frame[current++] = note; |
1195 | dest->NokiaBinary.Frame[current++] = duration; | 1199 | dest->NokiaBinary.Frame[current++] = duration; |
1196 | } | 1200 | } |
1197 | lastnote = note; | 1201 | lastnote = note; |
1198 | } | 1202 | } |
1199 | for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i]; | 1203 | for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i]; |
1200 | dest->NokiaBinary.Length=current; | 1204 | dest->NokiaBinary.Length=current; |
1201 | } | 1205 | } |
1202 | 1206 | ||
1203 | static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src) | 1207 | static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src) |
1204 | { | 1208 | { |
1205 | int i = 3, j, z, NrNotes = 0, repeat = 0, accuracy; | 1209 | int i = 3, j, z, NrNotes = 0, repeat = 0, accuracy; |
1206 | int StartRepeat = 0, EndRepeat, Speed; | 1210 | int StartRepeat = 0, EndRepeat, Speed; |
1207 | unsigned char command,length=0; | 1211 | unsigned char command,length=0; |
1208 | int NotesLen[500]; | 1212 | int NotesLen[500]; |
1209 | GSM_RingNoteScale NotesScale[500]; | 1213 | GSM_RingNoteScale NotesScale[500]; |
1210 | GSM_RingNoteNote Notes[500]; | 1214 | GSM_RingNoteNote Notes[500]; |
1211 | int Lengths[6*4]; | 1215 | int Lengths[6*4]; |
1212 | GSM_RingNoteDurationSpec DurationSpec[6*4]; | 1216 | GSM_RingNoteDurationSpec DurationSpec[6*4]; |
1213 | GSM_RingNoteDuration Duration[6*4]; | 1217 | GSM_RingNoteDuration Duration[6*4]; |
1214 | bool foundlen; | 1218 | bool foundlen; |
1215 | GSM_RingNote *Note; | 1219 | GSM_RingNote *Note; |
1216 | 1220 | ||
1217 | while (i<src->NokiaBinary.Length) { | 1221 | while (i<src->NokiaBinary.Length) { |
1218 | command = src->NokiaBinary.Frame[i]; | 1222 | command = src->NokiaBinary.Frame[i]; |
1219 | i++; | 1223 | i++; |
1220 | if (command != 0x06 && command != 0x00 && command != 0x09) { | 1224 | if (command != 0x06 && command != 0x00 && command != 0x09) { |
1221 | length = src->NokiaBinary.Frame[i]; | 1225 | length = src->NokiaBinary.Frame[i]; |
1222 | i++; | 1226 | i++; |
1223 | dbgprintf("Block %02x %02x - ",length,command); | 1227 | dbgprintf("Block %02x %02x - ",length,command); |
1224 | } else dbgprintf("Block %02x - ",command); | 1228 | } else dbgprintf("Block %02x - ",command); |
1225 | if (command >= 114 && command <= 161) { | 1229 | if (command >= 114 && command <= 161) { |
1226 | dbgprintf("note\n"); | 1230 | dbgprintf("note\n"); |
1227 | if (command >= 114 && command <= 124) { | 1231 | if (command >= 114 && command <= 124) { |
1228 | NotesScale[NrNotes] = Scale_440; command -= 114; | 1232 | NotesScale[NrNotes] = Scale_440; command -= 114; |
1229 | } else if (command >= 125 && command <= 137) { | 1233 | } else if (command >= 125 && command <= 137) { |
1230 | NotesScale[NrNotes] = Scale_880; command -= 126; | 1234 | NotesScale[NrNotes] = Scale_880; command -= 126; |
1231 | } else if (command >= 138 && command <= 149) { | 1235 | } else if (command >= 138 && command <= 149) { |
1232 | NotesScale[NrNotes] = Scale_1760; command -= 138; | 1236 | NotesScale[NrNotes] = Scale_1760; command -= 138; |
1233 | } else if (command >= 150 && command <= 161) { | 1237 | } else if (command >= 150 && command <= 161) { |
1234 | NotesScale[NrNotes] = Scale_3520; command -= 150; | 1238 | NotesScale[NrNotes] = Scale_3520; command -= 150; |
1235 | } | 1239 | } |
1236 | switch (command) { | 1240 | switch (command) { |
1237 | case 0 : Notes[NrNotes] = Note_C;break; | 1241 | case 0 : Notes[NrNotes] = Note_C;break; |
1238 | case 1 : Notes[NrNotes] = Note_Cis;break; | 1242 | case 1 : Notes[NrNotes] = Note_Cis;break; |
1239 | case 2 : Notes[NrNotes] = Note_D;break; | 1243 | case 2 : Notes[NrNotes] = Note_D;break; |
1240 | case 3 : Notes[NrNotes] = Note_Dis;break; | 1244 | case 3 : Notes[NrNotes] = Note_Dis;break; |
1241 | case 4 : Notes[NrNotes] = Note_E;break; | 1245 | case 4 : Notes[NrNotes] = Note_E;break; |
1242 | case 5 : Notes[NrNotes] = Note_F;break; | 1246 | case 5 : Notes[NrNotes] = Note_F;break; |
1243 | case 6 : Notes[NrNotes] = Note_Fis;break; | 1247 | case 6 : Notes[NrNotes] = Note_Fis;break; |
1244 | case 7 : Notes[NrNotes] = Note_G;break; | 1248 | case 7 : Notes[NrNotes] = Note_G;break; |
1245 | case 8 : Notes[NrNotes] = Note_Gis;break; | 1249 | case 8 : Notes[NrNotes] = Note_Gis;break; |
1246 | case 9 : Notes[NrNotes] = Note_A;break; | 1250 | case 9 : Notes[NrNotes] = Note_A;break; |
1247 | case 10 : Notes[NrNotes] = Note_Ais;break; | 1251 | case 10 : Notes[NrNotes] = Note_Ais;break; |
1248 | case 11 : Notes[NrNotes] = Note_H;break; | 1252 | case 11 : Notes[NrNotes] = Note_H;break; |
1249 | } | 1253 | } |
1250 | if (NrNotes > 0) { | 1254 | if (NrNotes > 0) { |
1251 | if (Notes[NrNotes-1] == Notes[NrNotes] && | 1255 | if (Notes[NrNotes-1] == Notes[NrNotes] && |
1252 | NotesScale[NrNotes-1] == NotesScale[NrNotes]) { | 1256 | NotesScale[NrNotes-1] == NotesScale[NrNotes]) { |
1253 | NotesLen[NrNotes-1]+=length; | 1257 | NotesLen[NrNotes-1]+=length; |
1254 | } else { | 1258 | } else { |
1255 | NotesLen[NrNotes]=length; | 1259 | NotesLen[NrNotes]=length; |
1256 | NrNotes++; | 1260 | NrNotes++; |
1257 | } | 1261 | } |
1258 | } else { | 1262 | } else { |
1259 | NotesLen[NrNotes]=length; | 1263 | NotesLen[NrNotes]=length; |
1260 | NrNotes++; | 1264 | NrNotes++; |
1261 | } | 1265 | } |
1262 | } else switch (command) { | 1266 | } else switch (command) { |
1263 | case 0x00: | 1267 | case 0x00: |
1264 | dbgprintf("Unknown\n"); | 1268 | dbgprintf("Unknown\n"); |
1265 | break; | 1269 | break; |
1266 | case 0x05: | 1270 | case 0x05: |
1267 | dbgprintf("repeat %i times\n",length); | 1271 | dbgprintf("repeat %i times\n",length); |
1268 | repeat = length; | 1272 | repeat = length; |
1269 | StartRepeat = NrNotes; | 1273 | StartRepeat = NrNotes; |
1270 | break; | 1274 | break; |
1271 | case 0x06: | 1275 | case 0x06: |
1272 | dbgprintf("end repeat\n"); | 1276 | dbgprintf("end repeat\n"); |
1273 | EndRepeat = NrNotes; | 1277 | EndRepeat = NrNotes; |
1274 | for (z=0;z<repeat-1;z++) { | 1278 | for (z=0;z<repeat-1;z++) { |
1275 | for (j=StartRepeat;j<EndRepeat;j++) { | 1279 | for (j=StartRepeat;j<EndRepeat;j++) { |
1276 | Notes[NrNotes] = Notes[j]; | 1280 | Notes[NrNotes] = Notes[j]; |
1277 | NotesScale[NrNotes] = NotesScale[j]; | 1281 | NotesScale[NrNotes] = NotesScale[j]; |
1278 | NotesLen[NrNotes] = NotesLen[j]; | 1282 | NotesLen[NrNotes] = NotesLen[j]; |
1279 | NrNotes++; | 1283 | NrNotes++; |
1280 | dbgprintf("Adding repeat note %i %i\n",Notes[j],NotesLen[j]); | 1284 | dbgprintf("Adding repeat note %i %i\n",Notes[j],NotesLen[j]); |
1281 | } | 1285 | } |
1282 | } | 1286 | } |
1283 | break; | 1287 | break; |
1284 | case 0x07: | 1288 | case 0x07: |
1285 | if (length == 0x0B) { | 1289 | if (length == 0x0B) { |
1286 | dbgprintf("Ringtone end\n"); | 1290 | dbgprintf("Ringtone end\n"); |
1287 | i = src->NokiaBinary.Length + 1; | 1291 | i = src->NokiaBinary.Length + 1; |
1288 | } | 1292 | } |
1289 | break; | 1293 | break; |
1290 | case 0x09: | 1294 | case 0x09: |
1291 | dbgprintf("Unknown\n"); | 1295 | dbgprintf("Unknown\n"); |
1292 | break; | 1296 | break; |
1293 | case 0x0A: | 1297 | case 0x0A: |
1294 | if (length == 0x01) { | 1298 | if (length == 0x01) { |
1295 | dbgprintf("Let's start our song\n"); | 1299 | dbgprintf("Let's start our song\n"); |
1296 | break; | 1300 | break; |
1297 | } | 1301 | } |
1298 | if (length == 0x0A) { | 1302 | if (length == 0x0A) { |
1299 | dbgprintf("Ending joining note\n"); | 1303 | dbgprintf("Ending joining note\n"); |
1300 | break; | 1304 | break; |
1301 | } | 1305 | } |
1302 | if (length == 0xFE) { | 1306 | if (length == 0xFE) { |
1303 | dbgprintf("Starting joining note\n"); | 1307 | dbgprintf("Starting joining note\n"); |
1304 | break; | 1308 | break; |
1305 | } | 1309 | } |
1306 | break; | 1310 | break; |
1307 | case 0x40: | 1311 | case 0x40: |
1308 | dbgprintf("Pause\n"); | 1312 | dbgprintf("Pause\n"); |
1309 | Notes[NrNotes] = Note_Pause; | 1313 | Notes[NrNotes] = Note_Pause; |
1310 | if (NrNotes > 0) { | 1314 | if (NrNotes > 0) { |
1311 | if (Notes[NrNotes-1] == Notes[NrNotes] && | 1315 | if (Notes[NrNotes-1] == Notes[NrNotes] && |
1312 | NotesScale[NrNotes-1] == NotesScale[NrNotes]) { | 1316 | NotesScale[NrNotes-1] == NotesScale[NrNotes]) { |
1313 | NotesLen[NrNotes-1]+=length; | 1317 | NotesLen[NrNotes-1]+=length; |
1314 | } else { | 1318 | } else { |
1315 | NotesLen[NrNotes]=length; | 1319 | NotesLen[NrNotes]=length; |
1316 | NrNotes++; | 1320 | NrNotes++; |
1317 | } | 1321 | } |
1318 | } else { | 1322 | } else { |
1319 | NotesLen[NrNotes]=length; | 1323 | NotesLen[NrNotes]=length; |
1320 | NrNotes++; | 1324 | NrNotes++; |
1321 | } | 1325 | } |
1322 | break; | 1326 | break; |
1323 | default: | 1327 | default: |
1324 | dbgprintf("Unknown\n"); | 1328 | dbgprintf("Unknown\n"); |
1325 | } | 1329 | } |
1326 | } | 1330 | } |
1327 | 1331 | ||
1328 | while (NrNotes>0) { | 1332 | while (NrNotes>0) { |
1329 | if (Notes[NrNotes-1] == Note_Pause) { | 1333 | if (Notes[NrNotes-1] == Note_Pause) { |
1330 | NrNotes--; | 1334 | NrNotes--; |
1331 | } else break; | 1335 | } else break; |
1332 | } | 1336 | } |
1333 | 1337 | ||
1334 | for (accuracy=1; accuracy<5; accuracy++) { | 1338 | for (accuracy=1; accuracy<5; accuracy++) { |
1335 | i = 1; | 1339 | i = 1; |
1336 | while (i < 1000) { | 1340 | while (i < 1000) { |
1337 | Lengths[0] = 30000/i; | 1341 | Lengths[0] = 30000/i; |
1338 | for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2; | 1342 | for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2; |
1339 | for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2; | 1343 | for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2; |
1340 | for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4; | 1344 | for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4; |
1341 | for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3; | 1345 | for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3; |
1342 | 1346 | ||
1343 | #ifdef DEBUG | 1347 | #ifdef DEBUG |
1344 | dbgprintf("Length matrix (%i) : ",i); | 1348 | dbgprintf("Length matrix (%i) : ",i); |
1345 | for (j=0;j<6*4;j++) dbgprintf("%i ",Lengths[j]); | 1349 | for (j=0;j<6*4;j++) dbgprintf("%i ",Lengths[j]); |
1346 | dbgprintf("\n"); | 1350 | dbgprintf("\n"); |
1347 | #endif | 1351 | #endif |
1348 | foundlen = false; | 1352 | foundlen = false; |
1349 | 1353 | ||
1350 | for (j=0;j<NrNotes;j++) { | 1354 | for (j=0;j<NrNotes;j++) { |
1351 | dbgprintf("Comparing to %i\n",NotesLen[j]); | 1355 | dbgprintf("Comparing to %i\n",NotesLen[j]); |
1352 | foundlen = false; | 1356 | foundlen = false; |
1353 | for (z=0;z<6*4;z++) { | 1357 | for (z=0;z<6*4;z++) { |
1354 | if (NotesLen[j] - Lengths[z] > -accuracy && | 1358 | if (NotesLen[j] - Lengths[z] > -accuracy && |
1355 | NotesLen[j] - Lengths[z] < accuracy) { | 1359 | NotesLen[j] - Lengths[z] < accuracy) { |
1356 | foundlen = true; | 1360 | foundlen = true; |
1357 | break; | 1361 | break; |
1358 | } | 1362 | } |
1359 | } | 1363 | } |
1360 | if (!foundlen) break; | 1364 | if (!foundlen) break; |
1361 | } | 1365 | } |
1362 | if (foundlen) break; | 1366 | if (foundlen) break; |
1363 | i++; | 1367 | i++; |
1364 | } | 1368 | } |
1365 | 1369 | ||
1366 | if (foundlen) { | 1370 | if (foundlen) { |
1367 | Speed = i; | 1371 | Speed = i; |
1368 | Duration[5] = Duration_1_32; Duration[4] = Duration_1_16; | 1372 | Duration[5] = Duration_1_32; Duration[4] = Duration_1_16; |
1369 | Duration[3] = Duration_1_8; Duration[2] = Duration_1_4; | 1373 | Duration[3] = Duration_1_8; Duration[2] = Duration_1_4; |
1370 | Duration[1] = Duration_1_2; Duration[0] = Duration_Full; | 1374 | Duration[1] = Duration_1_2; Duration[0] = Duration_Full; |
1371 | for (i=0;i<6;i++) Duration[i] = Duration[i]; | 1375 | for (i=0;i<6;i++) Duration[i] = Duration[i]; |
1372 | for (i=0;i<6;i++) Duration[i+6] = Duration[i]; | 1376 | for (i=0;i<6;i++) Duration[i+6] = Duration[i]; |
1373 | for (i=0;i<6;i++) Duration[i+12] = Duration[i]; | 1377 | for (i=0;i<6;i++) Duration[i+12] = Duration[i]; |
1374 | for (i=0;i<6;i++) Duration[i+18] = Duration[i]; | 1378 | for (i=0;i<6;i++) Duration[i+18] = Duration[i]; |
1375 | for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration; | 1379 | for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration; |
1376 | for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote; | 1380 | for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote; |
1377 | for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote; | 1381 | for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote; |
1378 | for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3; | 1382 | for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3; |
1379 | 1383 | ||
1380 | for (i=0;i<NrNotes;i++) { | 1384 | for (i=0;i<NrNotes;i++) { |
1381 | dest->NoteTone.Commands[i].Type= RING_Note; | 1385 | dest->NoteTone.Commands[i].Type= RING_Note; |
1382 | Note = &dest->NoteTone.Commands[i].Note; | 1386 | Note = &dest->NoteTone.Commands[i].Note; |
1383 | Note->Note = Notes[i]; | 1387 | Note->Note = Notes[i]; |
1384 | Note->Tempo = Speed; | 1388 | Note->Tempo = Speed; |
1385 | Note->Style = ContinuousStyle; | 1389 | Note->Style = ContinuousStyle; |
1386 | if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i]; | 1390 | if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i]; |
1387 | for (z=0;z<6*4;z++) { | 1391 | for (z=0;z<6*4;z++) { |
1388 | if (NotesLen[i] - Lengths[z] > -accuracy && | 1392 | if (NotesLen[i] - Lengths[z] > -accuracy && |
1389 | NotesLen[i] - Lengths[z] < accuracy) { | 1393 | NotesLen[i] - Lengths[z] < accuracy) { |
1390 | Note->Duration = Duration[z]; | 1394 | Note->Duration = Duration[z]; |
1391 | Note->DurationSpec = DurationSpec[z]; | 1395 | Note->DurationSpec = DurationSpec[z]; |
1392 | /* Trick from PPM Edit */ | 1396 | /* Trick from PPM Edit */ |
1393 | if (Note->DurationSpec == DoubleDottedNote) { | 1397 | if (Note->DurationSpec == DoubleDottedNote) { |
1394 | switch (Note->Duration) { | 1398 | switch (Note->Duration) { |
1395 | case Duration_Full:Note->Duration = Duration_Full;break; | 1399 | case Duration_Full:Note->Duration = Duration_Full;break; |
1396 | case Duration_1_2 :Note->Duration = Duration_Full;break; | 1400 | case Duration_1_2 :Note->Duration = Duration_Full;break; |
1397 | case Duration_1_4 :Note->Duration = Duration_1_2; break; | 1401 | case Duration_1_4 :Note->Duration = Duration_1_2; break; |
1398 | case Duration_1_8 :Note->Duration = Duration_1_4; break; | 1402 | case Duration_1_8 :Note->Duration = Duration_1_4; break; |
1399 | case Duration_1_16:Note->Duration = Duration_1_8; break; | 1403 | case Duration_1_16:Note->Duration = Duration_1_8; break; |
1400 | case Duration_1_32:Note->Duration = Duration_1_16;break; | 1404 | case Duration_1_32:Note->Duration = Duration_1_16;break; |
1401 | } | 1405 | } |
1402 | Note->DurationSpec = NoSpecialDuration; | 1406 | Note->DurationSpec = NoSpecialDuration; |
1403 | } | 1407 | } |
1404 | /* Here happy creation */ | 1408 | /* Here happy creation */ |
1405 | if (Note->DurationSpec == Length_2_3) { | 1409 | if (Note->DurationSpec == Length_2_3) { |
1406 | Note->DurationSpec = NoSpecialDuration; | 1410 | Note->DurationSpec = NoSpecialDuration; |
1407 | } | 1411 | } |
1408 | 1412 | ||
1409 | break; | 1413 | break; |
1410 | } | 1414 | } |
1411 | } | 1415 | } |
1412 | } | 1416 | } |
1413 | dest->NoteTone.NrCommands = NrNotes; | 1417 | dest->NoteTone.NrCommands = NrNotes; |
1414 | dbgprintf("speed = %i\n",Speed); | 1418 | dbgprintf("speed = %i\n",Speed); |
1415 | break; | 1419 | break; |
1416 | } | 1420 | } |
1417 | } | 1421 | } |
1418 | 1422 | ||
1419 | if (!foundlen) dest->NoteTone.NrCommands = 0; | 1423 | if (!foundlen) dest->NoteTone.NrCommands = 0; |
1420 | } | 1424 | } |
1421 | 1425 | ||
1422 | GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat) | 1426 | GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat) |
1423 | { | 1427 | { |
1424 | dest->Format = Format; | 1428 | dest->Format = Format; |
1425 | CopyUnicodeString(dest->Name,src->Name); | 1429 | CopyUnicodeString(dest->Name,src->Name); |
1426 | if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) { | 1430 | if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) { |
1427 | RTTL2Binary(dest, src); | 1431 | RTTL2Binary(dest, src); |
1428 | return ERR_NONE; | 1432 | return ERR_NONE; |
1429 | } | 1433 | } |
1430 | if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) { | 1434 | if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) { |
1431 | Binary2RTTL(dest, src); | 1435 | Binary2RTTL(dest, src); |
1432 | return ERR_NONE; | 1436 | return ERR_NONE; |
1433 | } | 1437 | } |
1434 | /* The same source and target format */ | 1438 | /* The same source and target format */ |
1435 | if (src->Format==Format) { | 1439 | if (src->Format==Format) { |
1436 | memcpy(dest,src,sizeof(GSM_Ringtone)); | 1440 | memcpy(dest,src,sizeof(GSM_Ringtone)); |
1437 | return ERR_NONE; | 1441 | return ERR_NONE; |
1438 | } | 1442 | } |
1439 | return ERR_NOTIMPLEMENTED; | 1443 | return ERR_NOTIMPLEMENTED; |
1440 | } | 1444 | } |
1441 | 1445 | ||
1442 | /* 0 = No header and footer, 0.5 = partial header and footer, | 1446 | /* 0 = No header and footer, 0.5 = partial header and footer, |
1443 | * 1.0 = IMelody 1.0, 1.2 = IMelody 1.2 */ | 1447 | * 1.0 = IMelody 1.0, 1.2 = IMelody 1.2 */ |
1444 | unsigned char GSM_EncodeEMSSound(GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start) | 1448 | unsigned char GSM_EncodeEMSSound(GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start) |
1445 | { | 1449 | { |
1446 | int i, NrNotes = 0, Len, Max = *maxlength; | 1450 | int i, NrNotes = 0, Len, Max = *maxlength; |
1447 | 1451 | ||
1448 | GSM_RingNote *Note; | 1452 | GSM_RingNote *Note; |
1449 | 1453 | ||
1450 | GSM_RingNoteScaleDefNoteScale; | 1454 | GSM_RingNoteScaleDefNoteScale; |
1451 | GSM_RingNoteStyleDefNoteStyle=0; | 1455 | GSM_RingNoteStyleDefNoteStyle=0; |
1452 | int DefNoteTempo=0; | 1456 | int DefNoteTempo=0; |
1453 | 1457 | ||
1454 | bool started = false, end; | 1458 | bool started = false, end; |
1455 | 1459 | ||
1456 | *maxlength = 0; | 1460 | *maxlength = 0; |
1457 | 1461 | ||
1458 | if (start) { | 1462 | if (start) { |
1459 | if (version != 0) *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10); | 1463 | if (version != 0) *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10); |
1460 | if (version == 1.0) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10); | 1464 | if (version == 1.0) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10); |
1461 | if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10); | 1465 | if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10); |
1462 | if (version >= 1.0) *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10); | 1466 | if (version >= 1.0) *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10); |
1463 | if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone.Name),13,10); | 1467 | if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone.Name),13,10); |
1464 | } | 1468 | } |
1465 | 1469 | ||
1466 | DefNoteScale = Scale_880; /* by iMelody definition */ | 1470 | DefNoteScale = Scale_880; /* by iMelody definition */ |
1467 | 1471 | ||
1468 | for (i=0;i<ringtone.NoteTone.NrCommands;i++) { | 1472 | for (i=0;i<ringtone.NoteTone.NrCommands;i++) { |
1469 | Len = *maxlength; | 1473 | Len = *maxlength; |
1470 | if (ringtone.NoteTone.Commands[i].Type != RING_Note) continue; | 1474 | if (ringtone.NoteTone.Commands[i].Type != RING_Note) continue; |
1471 | 1475 | ||
1472 | Note = &ringtone.NoteTone.Commands[i].Note; | 1476 | Note = &ringtone.NoteTone.Commands[i].Note; |
1473 | if (Note->Note == Note_Pause) continue; | 1477 | if (Note->Note == Note_Pause) continue; |
1474 | 1478 | ||
1475 | if (version == 1.2 && start) { | 1479 | if (version == 1.2 && start) { |
1476 | /* Save the default tempo */ | 1480 | /* Save the default tempo */ |
1477 | DefNoteTempo = Note->Tempo; | 1481 | DefNoteTempo = Note->Tempo; |
1478 | Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10); | 1482 | Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10); |
1479 | dbgprintf("DefNoteTempo=%d\n",DefNoteTempo); | 1483 | dbgprintf("DefNoteTempo=%d\n",DefNoteTempo); |
1480 | 1484 | ||
1481 | /* Save default style */ | 1485 | /* Save default style */ |
1482 | DefNoteStyle = Note->Style; | 1486 | DefNoteStyle = Note->Style; |
1483 | switch (DefNoteStyle) { | 1487 | switch (DefNoteStyle) { |
1484 | case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break; | 1488 | case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break; |
1485 | case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break; | 1489 | case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break; |
1486 | case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break; | 1490 | case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break; |
1487 | } | 1491 | } |
1488 | } | 1492 | } |
1489 | Len+=sprintf(package+Len,"MELODY:"); | 1493 | Len+=sprintf(package+Len,"MELODY:"); |
1490 | if (version != 0) { | 1494 | if (version != 0) { |
1491 | /* 15 = Len of END:IMELODY... */ | 1495 | /* 15 = Len of END:IMELODY... */ |
1492 | if ((Len+15) > Max) { end = true; break; } | 1496 | if ((Len+15) > Max) { end = true; break; } |
1493 | } else { | 1497 | } else { |
1494 | if (Len > Max) { end = true; break; } | 1498 | if (Len > Max) { end = true; break; } |
1495 | } | 1499 | } |
1496 | *maxlength = Len; | 1500 | *maxlength = Len; |
1497 | break; | 1501 | break; |
1498 | } | 1502 | } |
1499 | 1503 | ||
1500 | for (i=0;i<ringtone.NoteTone.NrCommands;i++) { | 1504 | for (i=0;i<ringtone.NoteTone.NrCommands;i++) { |
1501 | end = false; | 1505 | end = false; |
1502 | Len = *maxlength; | 1506 | Len = *maxlength; |
1503 | switch (ringtone.NoteTone.Commands[i].Type) { | 1507 | switch (ringtone.NoteTone.Commands[i].Type) { |
1504 | case RING_Note: | 1508 | case RING_Note: |
1505 | Note = &ringtone.NoteTone.Commands[i].Note; | 1509 | Note = &ringtone.NoteTone.Commands[i].Note; |
1506 | if (!started && Note->Note != Note_Pause) started = true; | 1510 | if (!started && Note->Note != Note_Pause) started = true; |
1507 | if (!started) break; | 1511 | if (!started) break; |
1508 | if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { | 1512 | if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { |
1509 | Len+=sprintf(package+Len,"*%i",Note->Scale-1); | 1513 | Len+=sprintf(package+Len,"*%i",Note->Scale-1); |
1510 | } | 1514 | } |
1511 | switch (Note->Note) { | 1515 | switch (Note->Note) { |
1512 | case Note_C :Len+=sprintf(package+Len,"c");break; | 1516 | case Note_C :Len+=sprintf(package+Len,"c");break; |
1513 | case Note_Cis:Len+=sprintf(package+Len,"#c");break; | 1517 | case Note_Cis:Len+=sprintf(package+Len,"#c");break; |
1514 | case Note_D :Len+=sprintf(package+Len,"d");break; | 1518 | case Note_D :Len+=sprintf(package+Len,"d");break; |
1515 | case Note_Dis:Len+=sprintf(package+Len,"#d");break; | 1519 | case Note_Dis:Len+=sprintf(package+Len,"#d");break; |
1516 | case Note_E :Len+=sprintf(package+Len,"e");break; | 1520 | case Note_E :Len+=sprintf(package+Len,"e");break; |
1517 | case Note_F :Len+=sprintf(package+Len,"f");break; | 1521 | case Note_F :Len+=sprintf(package+Len,"f");break; |
1518 | case Note_Fis:Len+=sprintf(package+Len,"#f");break; | 1522 | case Note_Fis:Len+=sprintf(package+Len,"#f");break; |
1519 | case Note_G :Len+=sprintf(package+Len,"g");break; | 1523 | case Note_G :Len+=sprintf(package+Len,"g");break; |
1520 | case Note_Gis:Len+=sprintf(package+Len,"#g");break; | 1524 | case Note_Gis:Len+=sprintf(package+Len,"#g");break; |
1521 | case Note_A :Len+=sprintf(package+Len,"a");break; | 1525 | case Note_A :Len+=sprintf(package+Len,"a");break; |
1522 | case Note_Ais:Len+=sprintf(package+Len,"#a");break; | 1526 | case Note_Ais:Len+=sprintf(package+Len,"#a");break; |
1523 | case Note_H :Len+=sprintf(package+Len,"b");break; | 1527 | case Note_H :Len+=sprintf(package+Len,"b");break; |
1524 | case Note_Pause :Len+=sprintf(package+Len,"r");break; | 1528 | case Note_Pause :Len+=sprintf(package+Len,"r");break; |
1525 | } | 1529 | } |
1526 | switch (Note->Duration) { | 1530 | switch (Note->Duration) { |
1527 | case Duration_Full : package[Len++]='0';break; | 1531 | case Duration_Full : package[Len++]='0';break; |
1528 | case Duration_1_2 : package[Len++]='1';break; | 1532 | case Duration_1_2 : package[Len++]='1';break; |
1529 | case Duration_1_4 : package[Len++]='2';break; | 1533 | case Duration_1_4 : package[Len++]='2';break; |
1530 | case Duration_1_8 : package[Len++]='3';break; | 1534 | case Duration_1_8 : package[Len++]='3';break; |
1531 | case Duration_1_16 : package[Len++]='4';break; | 1535 | case Duration_1_16 : package[Len++]='4';break; |
1532 | case Duration_1_32 : package[Len++]='5';break; | 1536 | case Duration_1_32 : package[Len++]='5';break; |
1533 | default : break; | 1537 | default : break; |
1534 | } | 1538 | } |
1535 | switch (Note->DurationSpec) { | 1539 | switch (Note->DurationSpec) { |
1536 | case DottedNote : package[Len++] = '.'; break; | 1540 | case DottedNote : package[Len++] = '.'; break; |
1537 | case DoubleDottedNote: package[Len++] = ':'; break; | 1541 | case DoubleDottedNote: package[Len++] = ':'; break; |
1538 | case Length_2_3 : package[Len++] = ';'; break; | 1542 | case Length_2_3 : package[Len++] = ';'; break; |
1539 | default : break; | 1543 | default : break; |
1540 | } | 1544 | } |
1541 | if (version != 0) { | 1545 | if (version != 0) { |
1542 | /* 15 = Len of END:IMELODY... */ | 1546 | /* 15 = Len of END:IMELODY... */ |
1543 | if ((Len+15) > Max) { end = true; break; } | 1547 | if ((Len+15) > Max) { end = true; break; } |
1544 | } else { | 1548 | } else { |
1545 | if (Len > Max) { end = true; break; } | 1549 | if (Len > Max) { end = true; break; } |
1546 | } | 1550 | } |
1547 | *maxlength = Len; | 1551 | *maxlength = Len; |
1548 | break; | 1552 | break; |
1549 | case RING_DisableLED: | 1553 | case RING_DisableLED: |
1550 | if ((Len + 6) > Max) { end = true; break; } | 1554 | if ((Len + 6) > Max) { end = true; break; } |
1551 | (*maxlength)+=sprintf(package+Len,"ledoff"); | 1555 | (*maxlength)+=sprintf(package+Len,"ledoff"); |
1552 | break; | 1556 | break; |
1553 | case RING_EnableLED: | 1557 | case RING_EnableLED: |
1554 | if ((Len + 5) > Max) { end = true; break; } | 1558 | if ((Len + 5) > Max) { end = true; break; } |
1555 | (*maxlength)+=sprintf(package+Len,"ledon"); | 1559 | (*maxlength)+=sprintf(package+Len,"ledon"); |
1556 | break; | 1560 | break; |
1557 | case RING_DisableVibra: | 1561 | case RING_DisableVibra: |
1558 | if ((Len + 7) > Max) { end = true; break; } | 1562 | if ((Len + 7) > Max) { end = true; break; } |
1559 | (*maxlength)+=sprintf(package+Len,"vibeoff"); | 1563 | (*maxlength)+=sprintf(package+Len,"vibeoff"); |
1560 | break; | 1564 | break; |
1561 | case RING_EnableVibra: | 1565 | case RING_EnableVibra: |
1562 | if ((Len + 6) > Max) { end = true; break; } | 1566 | if ((Len + 6) > Max) { end = true; break; } |
1563 | (*maxlength)+=sprintf(package+Len,"vibeon"); | 1567 | (*maxlength)+=sprintf(package+Len,"vibeon"); |
1564 | break; | 1568 | break; |
1565 | case RING_DisableLight: | 1569 | case RING_DisableLight: |
1566 | if ((Len + 7) > Max) { end = true; break; } | 1570 | if ((Len + 7) > Max) { end = true; break; } |
1567 | (*maxlength)+=sprintf(package+Len,"backoff"); | 1571 | (*maxlength)+=sprintf(package+Len,"backoff"); |
1568 | break; | 1572 | break; |
1569 | case RING_EnableLight: | 1573 | case RING_EnableLight: |
1570 | if ((Len + 6) > Max) { end = true; break; } | 1574 | if ((Len + 6) > Max) { end = true; break; } |
1571 | (*maxlength)+=sprintf(package+Len,"backon"); | 1575 | (*maxlength)+=sprintf(package+Len,"backon"); |
1572 | break; | 1576 | break; |
1573 | default: | 1577 | default: |
1574 | break; | 1578 | break; |
1575 | } | 1579 | } |
1576 | if (end) break; | 1580 | if (end) break; |
1577 | NrNotes ++; | 1581 | NrNotes ++; |
1578 | } | 1582 | } |
1579 | 1583 | ||
1580 | if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10); | 1584 | if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10); |
1581 | 1585 | ||
1582 | return NrNotes; | 1586 | return NrNotes; |
1583 | } | 1587 | } |
1584 | 1588 | ||
1585 | char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID) | 1589 | char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID) |
1586 | { | 1590 | { |
1587 | int i; | 1591 | int i; |
1588 | static char ala[2]; | 1592 | static char ala[2]; |
1589 | 1593 | ||
1590 | for (i=0;i<Info->Number;i++) { | 1594 | for (i=0;i<Info->Number;i++) { |
1591 | if (Info->Ringtone[i].ID == ID) return Info->Ringtone[i].Name; | 1595 | if (Info->Ringtone[i].ID == ID) return Info->Ringtone[i].Name; |
1592 | } | 1596 | } |
1593 | 1597 | ||
1594 | ala[0] = 0; | 1598 | ala[0] = 0; |
1595 | ala[1] = 0; | 1599 | ala[1] = 0; |
1596 | return ala; | 1600 | return ala; |
1597 | } | 1601 | } |
1598 | 1602 | ||
1599 | /* How should editor hadle tabs in this file? Add editor commands here. | 1603 | /* How should editor hadle tabs in this file? Add editor commands here. |
1600 | * vim: noexpandtab sw=8 ts=8 sts=8: | 1604 | * vim: noexpandtab sw=8 ts=8 sts=8: |
1601 | */ | 1605 | */ |