Gammu internals  1.38.0
gsmring.c File Reference
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <sys/stat.h>
#include <gammu-debug.h>
#include <gammu-unicode.h>
#include "../misc/coding/coding.h"
#include "gsmring.h"
#include "../debug.h"
Include dependency graph for gsmring.c:

Go to the source code of this file.

Macros

#define chk_fwrite(data, size, count, file)   if (fwrite(data, size, count, file) != count) goto fail;
 
#define PI   3.141592654
 
#define WAV_SAMPLE_RATE   44100
 

Functions

int GSM_RingNoteGetFrequency (GSM_RingNote Note)
 
int GSM_RingNoteGetFullDuration (GSM_RingNote Note)
 
GSM_Error GSM_SaveRingtoneWav (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error savebin (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error savepuremidi (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error savemmf (FILE *file, GSM_Ringtone *ringtone)
 
GSM_Error GSM_SaveRingtoneRttl (FILE *file, GSM_Ringtone *ringtone)
 
GSM_Error GSM_SaveRingtoneIMelody (FILE *file, GSM_Ringtone *ringtone)
 
static void WriteVarLen (unsigned char *midifile, size_t *current, long value)
 
GSM_Error GSM_SaveRingtoneMidi (FILE *file, GSM_Ringtone *ringtone)
 
GSM_Error GSM_SaveRingtoneOtt (FILE *file, GSM_Ringtone *ringtone)
 
GSM_Error GSM_SaveRingtoneFile (char *FileName, GSM_Ringtone *ringtone)
 
static GSM_Error loadrttl (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error loadott (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error loadcommunicator (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error loadbin (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error loadpuremidi (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error loadmmf (FILE *file, GSM_Ringtone *ringtone)
 
static GSM_Error loadre (FILE *file, GSM_Ringtone *ringtone)
 
GSM_Error GSM_ReadRingtoneFile (char *FileName, GSM_Ringtone *ringtone)
 
int GSM_RTTLGetTempo (int Beats)
 
unsigned char GSM_EncodeNokiaRTTLRingtone (GSM_Ringtone *ringtone, unsigned char *package, size_t *maxlength)
 
GSM_Error GSM_DecodeNokiaRTTLRingtone (GSM_Ringtone *ringtone, unsigned char *package, size_t maxlength UNUSED)
 
static void RTTL2Binary (GSM_Ringtone *dest, GSM_Ringtone *src)
 
static void Binary2RTTL (GSM_Ringtone *dest, GSM_Ringtone *src)
 
GSM_Error GSM_RingtoneConvert (GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormat Format)
 
unsigned char GSM_EncodeEMSSound (GSM_Ringtone *ringtone, unsigned char *package, size_t *maxlength, GSM_RingtoneVersion version, gboolean start)
 
const unsigned char * GSM_GetRingtoneName (const GSM_AllRingtonesInfo *Info, const int ID)
 

Variables

static int SM_BeatsPerMinute []
 

Macro Definition Documentation

§ chk_fwrite

#define chk_fwrite (   data,
  size,
  count,
  file 
)    if (fwrite(data, size, count, file) != count) goto fail;

Helper define to check error code from fwrite.

Definition at line 37 of file gsmring.c.

Referenced by GSM_SaveRingtoneIMelody(), GSM_SaveRingtoneMidi(), GSM_SaveRingtoneOtt(), GSM_SaveRingtoneWav(), savebin(), savemmf(), and savepuremidi().

§ PI

#define PI   3.141592654

Definition at line 100 of file gsmring.c.

Referenced by GSM_SaveRingtoneWav().

§ WAV_SAMPLE_RATE

#define WAV_SAMPLE_RATE   44100

Definition at line 103 of file gsmring.c.

Referenced by GSM_SaveRingtoneWav().

Function Documentation

§ Binary2RTTL()

static void Binary2RTTL ( GSM_Ringtone dest,
GSM_Ringtone src 
)
static

Definition at line 1328 of file gsmring.c.

References GSM_NoteRingtone::AllNotesScale, GSM_NoteRingtone::Commands, ContinuousStyle, dbgprintf, DottedNote, DoubleDottedNote, GSM_RingNote::Duration, Duration_1_16, Duration_1_2, Duration_1_32, Duration_1_4, Duration_1_8, Duration_Full, Duration_INVALID, GSM_RingNote::DurationSpec, FALSE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, Length_2_3, GSM_Ringtone::NokiaBinary, NoSpecialDuration, GSM_RingNote::Note, GSM_RingCommand::Note, Note_A, Note_Ais, Note_C, Note_Cis, Note_D, Note_Dis, Note_E, Note_F, Note_Fis, Note_G, Note_Gis, Note_H, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_Note, GSM_RingNote::Scale, Scale_1760, Scale_3520, Scale_440, Scale_880, GSM_RingNote::Style, GSM_RingNote::Tempo, TRUE, and GSM_RingCommand::Type.

Referenced by GSM_RingtoneConvert().

1329 {
1330  size_t NrNotes = 0, i = 3, j, StartRepeat = 0, EndRepeat;
1331  int z, repeat = 0, accuracy;
1332  int Speed;
1333  unsigned char command,length=0;
1334  int NotesLen[500];
1335  GSM_RingNoteScale NotesScale[500];
1336  GSM_RingNoteNote Notes[500];
1337  int Lengths[6*4];
1338  GSM_RingNoteDurationSpec DurationSpec[6*4];
1339  GSM_RingNoteDuration Duration[6*4];
1340  gboolean foundlen;
1341  GSM_RingNote *Note;
1342 
1343  while (i<src->NokiaBinary.Length) {
1344  command = src->NokiaBinary.Frame[i];
1345  i++;
1346  if (command != 0x06 && command != 0x00 && command != 0x09) {
1347  length = src->NokiaBinary.Frame[i];
1348  i++;
1349  dbgprintf(NULL, "Block %02x %02x - ",length,command);
1350  } else dbgprintf(NULL, "Block %02x - ",command);
1351  if (command >= 114 && command <= 161) {
1352  dbgprintf(NULL, "note\n");
1353  if (command >= 114 && command <= 124) {
1354  NotesScale[NrNotes] = Scale_440; command -= 114;
1355  } else if (command >= 125 && command <= 137) {
1356  NotesScale[NrNotes] = Scale_880; command -= 126;
1357  } else if (command >= 138 && command <= 149) {
1358  NotesScale[NrNotes] = Scale_1760; command -= 138;
1359  } else if (command >= 150 && command <= 161) {
1360  NotesScale[NrNotes] = Scale_3520; command -= 150;
1361  } else {
1362  NotesScale[NrNotes] = Scale_440;
1363  }
1364  switch (command) {
1365  case 0 : Notes[NrNotes] = Note_C; break;
1366  case 1 : Notes[NrNotes] = Note_Cis; break;
1367  case 2 : Notes[NrNotes] = Note_D; break;
1368  case 3 : Notes[NrNotes] = Note_Dis; break;
1369  case 4 : Notes[NrNotes] = Note_E; break;
1370  case 5 : Notes[NrNotes] = Note_F; break;
1371  case 6 : Notes[NrNotes] = Note_Fis; break;
1372  case 7 : Notes[NrNotes] = Note_G; break;
1373  case 8 : Notes[NrNotes] = Note_Gis; break;
1374  case 9 : Notes[NrNotes] = Note_A; break;
1375  case 10 : Notes[NrNotes] = Note_Ais; break;
1376  case 11 : Notes[NrNotes] = Note_H; break;
1377  default : Notes[NrNotes] = Note_Pause; break;
1378  }
1379  if (NrNotes > 0 &&
1380  Notes[NrNotes - 1] == Notes[NrNotes] &&
1381  NotesScale[NrNotes - 1] == NotesScale[NrNotes]) {
1382  NotesLen[NrNotes - 1] += length;
1383  } else {
1384  NotesLen[NrNotes] = length;
1385  NrNotes++;
1386  }
1387  } else switch (command) {
1388  case 0x00:
1389  dbgprintf(NULL, "Unknown\n");
1390  break;
1391  case 0x05:
1392  dbgprintf(NULL, "repeat %i times\n",length);
1393  repeat = length;
1394  StartRepeat = NrNotes;
1395  break;
1396  case 0x06:
1397  dbgprintf(NULL, "end repeat\n");
1398  EndRepeat = NrNotes;
1399  for (z=0;z<repeat-1;z++) {
1400  for (j=StartRepeat;j<EndRepeat;j++) {
1401  Notes[NrNotes] = Notes[j];
1402  NotesScale[NrNotes] = NotesScale[j];
1403  NotesLen[NrNotes] = NotesLen[j];
1404  NrNotes++;
1405  dbgprintf(NULL, "Adding repeat note %i %i\n",Notes[j],NotesLen[j]);
1406  }
1407  }
1408  break;
1409  case 0x07:
1410  if (length == 0x0B) {
1411  dbgprintf(NULL, "Ringtone end\n");
1412  i = src->NokiaBinary.Length + 1;
1413  }
1414  break;
1415  case 0x09:
1416  dbgprintf(NULL, "Unknown\n");
1417  break;
1418  case 0x0A:
1419  if (length == 0x01) {
1420  dbgprintf(NULL, "Let's start our song\n");
1421  break;
1422  }
1423  if (length == 0x0A) {
1424  dbgprintf(NULL, "Ending joining note\n");
1425  break;
1426  }
1427  if (length == 0xFE) {
1428  dbgprintf(NULL, "Starting joining note\n");
1429  break;
1430  }
1431  break;
1432  case 0x40:
1433  dbgprintf(NULL, "Pause\n");
1434  Notes[NrNotes] = Note_Pause;
1435  if (NrNotes > 0 &&
1436  Notes[NrNotes - 1] == Notes[NrNotes]) {
1437  NotesLen[NrNotes - 1] += length;
1438  } else {
1439  NotesLen[NrNotes] = length;
1440  NotesScale[NrNotes] = 0;
1441  NrNotes++;
1442  }
1443  break;
1444  default:
1445  dbgprintf(NULL, "Unknown\n");
1446  }
1447  }
1448 
1449  while (NrNotes > 0 && Notes[NrNotes-1] == Note_Pause) {
1450  NrNotes--;
1451  }
1452 
1453  for (accuracy=1; accuracy<5; accuracy++) {
1454  i = 1;
1455  while (i < 1000) {
1456  Lengths[0] = 30000/i;
1457  for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2;
1458  for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2;
1459  for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4;
1460  for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3;
1461 
1462 #ifdef DEBUG
1463  dbgprintf(NULL, "Length matrix (%ld) : ", (long)i);
1464  for (j=0;j<6*4;j++) dbgprintf(NULL, "%i ",Lengths[j]);
1465  dbgprintf(NULL, "\n");
1466 #endif
1467  foundlen = FALSE;
1468 
1469  for (j=0;j<NrNotes;j++) {
1470  dbgprintf(NULL, "Comparing to %i\n",NotesLen[j]);
1471  foundlen = FALSE;
1472  for (z=0;z<6*4;z++) {
1473  if (NotesLen[j] - Lengths[z] > -accuracy &&
1474  NotesLen[j] - Lengths[z] < accuracy) {
1475  foundlen = TRUE;
1476  break;
1477  }
1478  }
1479  if (!foundlen) break;
1480  }
1481  if (foundlen) break;
1482  i++;
1483  }
1484 
1485  if (foundlen) {
1486  Speed = i;
1487  Duration[5] = Duration_1_32; Duration[4] = Duration_1_16;
1488  Duration[3] = Duration_1_8; Duration[2] = Duration_1_4;
1489  Duration[1] = Duration_1_2; Duration[0] = Duration_Full;
1490  for (i=0;i<6;i++) Duration[i] = Duration[i];
1491  for (i=0;i<6;i++) Duration[i+6] = Duration[i];
1492  for (i=0;i<6;i++) Duration[i+12] = Duration[i];
1493  for (i=0;i<6;i++) Duration[i+18] = Duration[i];
1494  for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration;
1495  for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote;
1496  for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote;
1497  for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3;
1498 
1499  for (i=0;i<NrNotes;i++) {
1500  dest->NoteTone.Commands[i].Type = RING_Note;
1501  Note = &dest->NoteTone.Commands[i].Note;
1502  Note->Note = Notes[i];
1503  Note->Tempo = Speed;
1504  Note->Style = ContinuousStyle;
1505  if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i];
1506  for (z=0;z<6*4;z++) {
1507  if (NotesLen[i] - Lengths[z] > -accuracy &&
1508  NotesLen[i] - Lengths[z] < accuracy) {
1509  Note->Duration = Duration[z];
1510  Note->DurationSpec = DurationSpec[z];
1511  /* Trick from PPM Edit */
1512  if (Note->DurationSpec == DoubleDottedNote) {
1513  switch (Note->Duration) {
1514  case Duration_INVALID: break;
1515  case Duration_Full:Note->Duration = Duration_Full;break;
1516  case Duration_1_2 :Note->Duration = Duration_Full;break;
1517  case Duration_1_4 :Note->Duration = Duration_1_2; break;
1518  case Duration_1_8 :Note->Duration = Duration_1_4; break;
1519  case Duration_1_16:Note->Duration = Duration_1_8; break;
1520  case Duration_1_32:Note->Duration = Duration_1_16;break;
1521  }
1523  }
1524  /* Here happy creation */
1525  if (Note->DurationSpec == Length_2_3) {
1527  }
1528 
1529  break;
1530  }
1531  }
1532  }
1533  dest->NoteTone.NrCommands = NrNotes;
1534  dbgprintf(NULL, "speed = %i\n",Speed);
1535  break;
1536  }
1537  }
1538 
1539  dest->NoteTone.AllNotesScale = FALSE;
1540  if (!foundlen) dest->NoteTone.NrCommands = 0;
1541 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
GSM_RingNoteDurationSpec
GSM_RingNoteDuration Duration
GSM_RingNoteNote Note
GSM_RingNoteScale Scale
GSM_RingCommandType Type
GSM_RingNoteScale
GSM_RingNoteNote
GSM_NoteRingtone NoteTone
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
GSM_RingNoteStyle Style
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
GSM_RingNoteDurationSpec DurationSpec
#define dbgprintf
Definition: debug.h:72
#define TRUE
Definition: gammu-types.h:28
GSM_RingNoteDuration
GSM_RingNote Note
gboolean AllNotesScale

§ GSM_DecodeNokiaRTTLRingtone()

GSM_Error GSM_DecodeNokiaRTTLRingtone ( GSM_Ringtone ringtone,
unsigned char *  package,
size_t maxlength  UNUSED 
)

Definition at line 1128 of file gsmring.c.

References BufferAlignNumber(), GSM_NoteRingtone::Commands, CopyUnicodeString(), dbgprintf, DecodeUnicodeSpecialNOKIAChars(), GSM_RingNote::Duration, Duration_1_32, Duration_Full, GSM_RingNote::DurationSpec, EncodeUnicode(), ERR_NONE, ERR_NOTSUPPORTED, GSM_Ringtone::Format, GetBuffer(), GetBufferInt(), GSM_MAX_RINGTONE_NOTES, Length_2_3, GSM_Ringtone::Name, NaturalStyle, NoSpecialDuration, GSM_RingNote::Note, GSM_RingCommand::Note, Note_C, Note_H, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_Note, RING_NOTETONE, GSM_RingNote::Scale, Scale_880, SM_BeatsPerMinute, SM_Command_RingingToneProgramming, SM_Command_Sound, SM_InstructionID_NoteInstructionId, SM_InstructionID_PatternHeaderId, SM_InstructionID_ScaleInstructionId, SM_InstructionID_StyleInstructionId, SM_InstructionID_TempoInstructionId, SM_InstructionID_VolumeInstructionId, SM_Song_BasicSongType, StaccatoStyle, GSM_RingNote::Style, GSM_RingNote::Tempo, GSM_RingCommand::Type, and UnicodeLength().

Referenced by GSM_DecodeMultiPartSMS(), loadcommunicator(), and loadott().

1129 {
1130  size_t StartBit=0;
1131  int l, q, i, spec, HowMany;
1132  char Buffer[100];
1133  GSM_RingNote *Note;
1134 
1135  /* Default ringtone parameters */
1136  GSM_RingNoteScale DefScale = Scale_880;
1137  GSM_RingNoteStyle DefStyle = NaturalStyle;
1138  int DefTempo = 63;
1139 
1140  ringtone->Format = RING_NOTETONE;
1141  ringtone->NoteTone.NrCommands = 0;
1142 
1143  GetBufferInt(package,&StartBit,&l,8);
1144  if (l != 0x02) {
1145  dbgprintf(NULL, "Not header\n");
1146  return ERR_NOTSUPPORTED;
1147  }
1148 
1149  GetBufferInt(package,&StartBit,&l,7);
1151  dbgprintf(NULL, "Not RingingToneProgramming\n");
1152  return ERR_NOTSUPPORTED;
1153  }
1154 
1155  /* According to specification we need have next part octet-aligned */
1156  BufferAlignNumber(&StartBit);
1157 
1158  GetBufferInt(package,&StartBit,&l,7);
1159  if (l != SM_Command_Sound) {
1160  dbgprintf(NULL, "Not Sound\n");
1161  return ERR_NOTSUPPORTED;
1162  }
1163 
1164  GetBufferInt(package,&StartBit,&l,3);
1165  if (l != SM_Song_BasicSongType) {
1166  dbgprintf(NULL, "Not BasicSongType\n");
1167  return ERR_NOTSUPPORTED;
1168  }
1169 
1170  /* Getting length of the tune name */
1171  GetBufferInt(package,&StartBit,&l,4);
1172  l=l>>4;
1173 
1174  /* Unpacking the name of the tune. */
1175  GetBuffer(package, &StartBit, Buffer, 8*l);
1176  Buffer[l]=0;
1177  EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer));
1178  DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name));
1179  CopyUnicodeString(ringtone->Name,Buffer);
1180 
1181  GetBufferInt(package,&StartBit,&l,8);
1182  dbgprintf(NULL, "Number of song patterns: %i\n",l);
1183  /* we support only one song pattern */
1184  if (l!=1) return ERR_NOTSUPPORTED;
1185 
1186  GetBufferInt(package,&StartBit,&l,3);
1188  dbgprintf(NULL, "Not PatternHeaderId\n");
1189  return ERR_NOTSUPPORTED;
1190  }
1191 
1192  /* Pattern ID - we ignore it */
1193  StartBit+=2;
1194 
1195  GetBufferInt(package,&StartBit,&l,4);
1196  l=l>>4;
1197  dbgprintf(NULL, "Loop value: %i\n",l);
1198 
1199  HowMany=0;
1200  GetBufferInt(package, &StartBit, &HowMany, 8);
1201 
1202  for (i=0;i<HowMany;i++) {
1203  GetBufferInt(package,&StartBit,&q,3);
1204  switch (q) {
1206  StartBit+=4;
1207  break;
1209  GetBufferInt(package,&StartBit,&l,2);
1210  if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l;
1211  break;
1213  GetBufferInt(package,&StartBit,&l,5);
1214  DefTempo=SM_BeatsPerMinute[l>>3];
1215  break;
1217  GetBufferInt(package,&StartBit,&l,2);
1218  DefScale=(l>>6)+4;
1219  break;
1221  Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
1222  ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
1223 
1224  GetBufferInt(package,&StartBit,&l,4);
1225  Note->Note=Note_Pause;
1226  if (l >= Note_C && l <= Note_H) Note->Note = l;
1227 
1228  GetBufferInt(package,&StartBit,&l,3);
1229  if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l;
1230 
1231  GetBufferInt(package,&StartBit,&spec,2);
1232  if (spec >= NoSpecialDuration && spec <= Length_2_3) {
1233  Note->DurationSpec = spec;
1234  }
1235 
1236  Note->Scale = DefScale;
1237  Note->Style = DefStyle;
1238  Note->Tempo = DefTempo;
1239  if (ringtone->NoteTone.NrCommands==GSM_MAX_RINGTONE_NOTES) break;
1240  ringtone->NoteTone.NrCommands++;
1241  break;
1242  default:
1243  dbgprintf(NULL, "Unsupported block %i %i\n",q,i);
1244  return ERR_NOTSUPPORTED;
1245  }
1246  }
1247  return ERR_NONE;
1248 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
#define SM_InstructionID_StyleInstructionId
Definition: gsmring.h:25
GSM_RingtoneFormat Format
#define SM_InstructionID_TempoInstructionId
Definition: gsmring.h:26
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
GSM_RingNoteDuration Duration
GSM_RingNoteNote Note
void GetBufferInt(unsigned char *Source, size_t *CurrentBit, int *integer, size_t BitsToProcess)
Definition: coding.c:1329
GSM_RingNoteScale Scale
GSM_RingCommandType Type
#define SM_InstructionID_NoteInstructionId
Definition: gsmring.h:23
GSM_RingNoteScale
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
#define SM_InstructionID_ScaleInstructionId
Definition: gsmring.h:24
GSM_NoteRingtone NoteTone
void BufferAlignNumber(size_t *CurrentBit)
Definition: coding.c:1275
static int SM_BeatsPerMinute[]
Definition: gsmring.c:972
#define SM_Command_RingingToneProgramming
Definition: gsmring.h:12
#define GSM_MAX_RINGTONE_NOTES
Definition: gammu-limits.h:225
void GetBuffer(unsigned char *Source, size_t *CurrentBit, unsigned char *Destination, size_t BitsToProcess)
Definition: coding.c:1311
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
GSM_RingNoteStyle Style
GSM_RingNoteDurationSpec DurationSpec
GSM_RingNoteStyle
void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:1401
#define dbgprintf
Definition: debug.h:72
#define SM_InstructionID_VolumeInstructionId
Definition: gsmring.h:27
GSM_RingNote Note
#define SM_InstructionID_PatternHeaderId
Definition: gsmring.h:22
#define SM_Command_Sound
Definition: gsmring.h:13
#define SM_Song_BasicSongType
Definition: gsmring.h:16

§ GSM_EncodeEMSSound()

unsigned char GSM_EncodeEMSSound ( GSM_Ringtone ringtone,
unsigned char *  package,
size_t *  maxlength,
GSM_RingtoneVersion  version,
gboolean  start 
)

Definition at line 1565 of file gsmring.c.

References GSM_NoteRingtone::Commands, ContinuousStyle, dbgprintf, DecodeUnicodeString(), DottedNote, DoubleDottedNote, GSM_RingNote::Duration, Duration_1_16, Duration_1_2, Duration_1_32, Duration_1_4, Duration_1_8, Duration_Full, GSM_RingNote::DurationSpec, FALSE, GSM_Ring_IMelody10, GSM_Ring_IMelody12, GSM_Ring_NoHeader, INVALIDStyle, Length_2_3, GSM_Ringtone::Name, NaturalStyle, GSM_RingNote::Note, GSM_RingCommand::Note, Note_A, Note_Ais, Note_C, Note_Cis, Note_D, Note_Dis, Note_E, Note_F, Note_Fis, Note_G, Note_Gis, Note_H, Note_INVALID, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_DisableLED, RING_DisableLight, RING_DisableVibra, RING_EnableLED, RING_EnableLight, RING_EnableVibra, RING_Note, GSM_RingNote::Scale, Scale_880, StaccatoStyle, GSM_RingNote::Style, GSM_RingNote::Tempo, TRUE, and GSM_RingCommand::Type.

Referenced by GSM_EncodeEMSMultiPartSMS(), and GSM_SaveRingtoneIMelody().

1566 {
1567  int i, NrNotes = 0, Len, Max = *maxlength;
1568 
1569  GSM_RingNote *Note;
1570 
1571  GSM_RingNoteScale DefNoteScale;
1572  GSM_RingNoteStyle DefNoteStyle=0;
1573  int DefNoteTempo=0;
1574 
1575  gboolean started = FALSE, end;
1576 
1577  *maxlength = 0;
1578 
1579  if (start) {
1580  if (version != GSM_Ring_NoHeader)
1581  *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10);
1582  if (version == GSM_Ring_IMelody10)
1583  *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10);
1584  if (version == GSM_Ring_IMelody12)
1585  *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10);
1586  if (version == GSM_Ring_IMelody12 || version == GSM_Ring_IMelody10)
1587  *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10);
1588  if (version == GSM_Ring_IMelody12)
1589  *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone->Name),13,10);
1590  }
1591 
1592  DefNoteScale = Scale_880; /* by iMelody definition */
1593 
1594  for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
1595  Len = *maxlength;
1596  if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
1597 
1598  Note = &ringtone->NoteTone.Commands[i].Note;
1599  if (Note->Note == Note_Pause) continue;
1600 
1601  if (version == GSM_Ring_IMelody12 && start) {
1602  /* Save the default tempo */
1603  DefNoteTempo = Note->Tempo;
1604  Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10);
1605  dbgprintf(NULL, "DefNoteTempo=%d\n",DefNoteTempo);
1606 
1607  /* Save default style */
1608  DefNoteStyle = Note->Style;
1609  switch (DefNoteStyle) {
1610  case INVALIDStyle: break;
1611  case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break;
1612  case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break;
1613  case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break;
1614  }
1615  }
1616  Len+=sprintf(package+Len,"MELODY:");
1617  if (version != GSM_Ring_NoHeader) {
1618  /* 15 = Len of END:IMELODY... */
1619  if ((Len+15) > Max) { break; }
1620  } else {
1621  if (Len > Max) { break; }
1622  }
1623  *maxlength = Len;
1624  break;
1625  }
1626 
1627  for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
1628  end = FALSE;
1629  Len = *maxlength;
1630  switch (ringtone->NoteTone.Commands[i].Type) {
1631  case RING_Note:
1632  Note = &ringtone->NoteTone.Commands[i].Note;
1633  if (!started && Note->Note != Note_Pause) started = TRUE;
1634  if (!started) break;
1635  if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
1636  Len+=sprintf(package+Len,"*%i",Note->Scale-1);
1637  }
1638  switch (Note->Note) {
1639  case Note_C :Len+=sprintf(package+Len,"c"); break;
1640  case Note_Cis :Len+=sprintf(package+Len,"#c");break;
1641  case Note_D :Len+=sprintf(package+Len,"d"); break;
1642  case Note_Dis :Len+=sprintf(package+Len,"#d");break;
1643  case Note_E :Len+=sprintf(package+Len,"e"); break;
1644  case Note_F :Len+=sprintf(package+Len,"f"); break;
1645  case Note_Fis :Len+=sprintf(package+Len,"#f");break;
1646  case Note_G :Len+=sprintf(package+Len,"g"); break;
1647  case Note_Gis :Len+=sprintf(package+Len,"#g");break;
1648  case Note_A :Len+=sprintf(package+Len,"a"); break;
1649  case Note_Ais :Len+=sprintf(package+Len,"#a");break;
1650  case Note_H :Len+=sprintf(package+Len,"b"); break;
1651  case Note_Pause :Len+=sprintf(package+Len,"r"); break;
1652  case Note_INVALID: break;
1653  }
1654  switch (Note->Duration) {
1655  case Duration_Full : package[Len++]='0'; break;
1656  case Duration_1_2 : package[Len++]='1'; break;
1657  case Duration_1_4 : package[Len++]='2'; break;
1658  case Duration_1_8 : package[Len++]='3'; break;
1659  case Duration_1_16 : package[Len++]='4'; break;
1660  case Duration_1_32 : package[Len++]='5'; break;
1661  default : break;
1662  }
1663  switch (Note->DurationSpec) {
1664  case DottedNote : package[Len++] = '.'; break;
1665  case DoubleDottedNote : package[Len++] = ':'; break;
1666  case Length_2_3 : package[Len++] = ';'; break;
1667  default : break;
1668  }
1669  if (version != 0) {
1670  /* 15 = Len of END:IMELODY... */
1671  if ((Len+15) > Max) { end = TRUE; break; }
1672  } else {
1673  if (Len > Max) { end = TRUE; break; }
1674  }
1675  *maxlength = Len;
1676  break;
1677  case RING_DisableLED:
1678  if ((Len + 6) > Max) { end = TRUE; break; }
1679  (*maxlength)+=sprintf(package+Len,"ledoff");
1680  break;
1681  case RING_EnableLED:
1682  if ((Len + 5) > Max) { end = TRUE; break; }
1683  (*maxlength)+=sprintf(package+Len,"ledon");
1684  break;
1685  case RING_DisableVibra:
1686  if ((Len + 7) > Max) { end = TRUE; break; }
1687  (*maxlength)+=sprintf(package+Len,"vibeoff");
1688  break;
1689  case RING_EnableVibra:
1690  if ((Len + 6) > Max) { end = TRUE; break; }
1691  (*maxlength)+=sprintf(package+Len,"vibeon");
1692  break;
1693  case RING_DisableLight:
1694  if ((Len + 7) > Max) { end = TRUE; break; }
1695  (*maxlength)+=sprintf(package+Len,"backoff");
1696  break;
1697  case RING_EnableLight:
1698  if ((Len + 6) > Max) { end = TRUE; break; }
1699  (*maxlength)+=sprintf(package+Len,"backon");
1700  break;
1701  default:
1702  break;
1703  }
1704  if (end) break;
1705  NrNotes ++;
1706  }
1707 
1708  if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10);
1709 
1710  return NrNotes;
1711 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
GSM_RingNoteDuration Duration
GSM_RingNoteNote Note
GSM_RingNoteScale Scale
GSM_RingCommandType Type
GSM_RingNoteScale
GSM_NoteRingtone NoteTone
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
GSM_RingNoteStyle Style
GSM_RingNoteDurationSpec DurationSpec
GSM_RingNoteStyle
#define dbgprintf
Definition: debug.h:72
#define TRUE
Definition: gammu-types.h:28
GSM_RingNote Note

§ GSM_EncodeNokiaRTTLRingtone()

unsigned char GSM_EncodeNokiaRTTLRingtone ( GSM_Ringtone ringtone,
unsigned char *  package,
size_t *  maxlength 
)

Definition at line 992 of file gsmring.c.

References AddBuffer(), AddBufferByte(), GSM_NoteRingtone::AllNotesScale, BufferAlign(), BufferAlignNumber(), GSM_NoteRingtone::Commands, DecodeUnicodeString(), GSM_RingNote::Duration, GSM_RingNote::DurationSpec, EncodeUnicodeSpecialNOKIAChars(), FALSE, GSM_RTTLGetTempo(), GSM_Ringtone::Name, GSM_RingNote::Note, GSM_RingCommand::Note, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_Note, GSM_RingNote::Scale, SM_Command_RingingToneProgramming, SM_Command_Sound, SM_CommandEnd_CommandEnd, SM_InstructionID_NoteInstructionId, SM_InstructionID_PatternHeaderId, SM_InstructionID_ScaleInstructionId, SM_InstructionID_StyleInstructionId, SM_InstructionID_TempoInstructionId, SM_PatternID_A_part, SM_Song_BasicSongType, GSM_RingNote::Style, GSM_RingNote::Tempo, TRUE, GSM_RingCommand::Type, and UnicodeLength().

Referenced by GSM_EncodeMultiPartSMS(), GSM_EncodeSMS30MultiPartSMS(), and GSM_SaveRingtoneOtt().

993 {
994  unsigned char CommandLength = 0x02;
995  unsigned char Loop = 0x15; /* Infinite */
996 
997  unsigned char Buffer[200];
998  size_t StartBit=0, OldStartBit;
999  int StartBitHowManyCommands;
1000  int HowManyCommands = 0; /* How many instructions packed */
1001  int HowManyNotes = 0;
1002  int i;
1003  size_t j;
1004  gboolean started;
1005  GSM_RingNote *Note;
1006 
1007  GSM_RingNoteScale DefScale = 255;
1008  GSM_RingNoteStyle DefStyle = 255;
1009  int DefTempo = 255;
1010 
1011  AddBufferByte(package, &StartBit, CommandLength, 8);
1012  AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7);
1013 
1014  /* According to specification we need have next part octet-aligned */
1015  BufferAlign(package, &StartBit);
1016 
1017  AddBufferByte(package, &StartBit, SM_Command_Sound, 7);
1018  AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3);
1019 
1020  /* Packing the name of the tune. */
1021  EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name));
1022  AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4);
1023  AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer));
1024 
1025  /* Packing info about song pattern */
1026  AddBufferByte(package, &StartBit, 0x01, 8); /* one pattern */
1027  AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3);
1028  AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2);
1029  AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4);
1030 
1031  /* Later here will be HowManyCommands */
1032  StartBitHowManyCommands=StartBit;
1033  StartBit = StartBit + 8;
1034 
1035  started = FALSE;
1036  for (i=0; i<ringtone->NoteTone.NrCommands; i++) {
1037  if (ringtone->NoteTone.Commands[i].Type != RING_Note) {
1038  HowManyNotes++;
1039  continue;
1040  }
1041  Note = &ringtone->NoteTone.Commands[i].Note;
1042  if (!started) {
1043  /* First note can't be Pause - it makes problems
1044  * for example with PC Composer
1045  */
1046  if (Note->Note != Note_Pause) started = TRUE;
1047  }
1048  if (!started) {
1049  HowManyNotes++;
1050  continue;
1051  }
1052  OldStartBit = StartBit;
1053  /* we don't write Scale & Style info before "Pause" note - it saves place */
1054  if (Note->Note!=Note_Pause) {
1055  if (DefScale != Note->Scale || ringtone->NoteTone.AllNotesScale) {
1056  j = StartBit+5+8;
1057  BufferAlignNumber(&j);
1058  if ((j/8)>(*maxlength)) {
1059  StartBit = OldStartBit;
1060  break;
1061  }
1062  DefScale = Note->Scale;
1063  AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3);
1064  AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2);
1065  HowManyCommands++;
1066  }
1067  if (DefStyle != Note->Style) {
1068  j = StartBit+5+8;
1069  BufferAlignNumber(&j);
1070  if ((j/8)>(*maxlength)) {
1071  StartBit = OldStartBit;
1072  break;
1073  }
1074  DefStyle = Note->Style;
1075  AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3);
1076  AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2);
1077  HowManyCommands++;
1078  }
1079  }
1080  /* Beats per minute/tempo of the tune */
1081  if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) {
1082  j = StartBit+8+8;
1083  BufferAlignNumber(&j);
1084  if ((j/8)>(*maxlength)) {
1085  StartBit = OldStartBit;
1086  break;
1087  }
1088  DefTempo=GSM_RTTLGetTempo(Note->Tempo);
1089  /* Adding beats per minute (tempo) of the tune */
1090  AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3);
1091  AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5);
1092  HowManyCommands++;
1093  }
1094  j = StartBit+12+8;
1095  BufferAlignNumber(&j);
1096  if ((j/8)>(*maxlength)) {
1097  StartBit = OldStartBit;
1098  break;
1099  }
1100  /* Note */
1101  AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3);
1102  AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4);
1103  AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3);
1104  AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2);
1105  HowManyCommands++;
1106  /* We are sure, we pack it for SMS or setting to phone, not for OTT file */
1107  if (*maxlength<1000) {
1108  /* Like Pc Composer say - before of phone limitations...*/
1109  if (HowManyNotes==130-1) break;
1110  }
1111  HowManyNotes++;
1112  }
1113 
1114  BufferAlign(package, &StartBit);
1115  AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8);
1116 
1117  OldStartBit = StartBit;
1118  StartBit = StartBitHowManyCommands;
1119  /* HowManyCommands */
1120  AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8);
1121  StartBit = OldStartBit;
1122 
1123  *maxlength=StartBit/8;
1124 
1125  return(i);
1126 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
#define SM_InstructionID_StyleInstructionId
Definition: gsmring.h:25
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
#define SM_InstructionID_TempoInstructionId
Definition: gsmring.h:26
GSM_RingNoteDuration Duration
void AddBufferByte(unsigned char *Destination, size_t *CurrentBit, unsigned char Source, size_t BitsToProcess)
Definition: coding.c:1303
GSM_RingNoteNote Note
void BufferAlign(unsigned char *Destination, size_t *CurrentBit)
Definition: coding.c:1263
GSM_RingNoteScale Scale
GSM_RingCommandType Type
#define SM_InstructionID_NoteInstructionId
Definition: gsmring.h:23
GSM_RingNoteScale
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
#define SM_InstructionID_ScaleInstructionId
Definition: gsmring.h:24
GSM_NoteRingtone NoteTone
void BufferAlignNumber(size_t *CurrentBit)
Definition: coding.c:1275
int GSM_RTTLGetTempo(int Beats)
Definition: gsmring.c:979
#define SM_CommandEnd_CommandEnd
Definition: gsmring.h:9
#define SM_Command_RingingToneProgramming
Definition: gsmring.h:12
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
GSM_RingNoteStyle Style
GSM_RingNoteDurationSpec DurationSpec
GSM_RingNoteStyle
void AddBuffer(unsigned char *Destination, size_t *CurrentBit, unsigned char *Source, size_t BitsToProcess)
Definition: coding.c:1286
void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:1367
#define TRUE
Definition: gammu-types.h:28
GSM_RingNote Note
#define SM_InstructionID_PatternHeaderId
Definition: gsmring.h:22
#define SM_Command_Sound
Definition: gsmring.h:13
#define SM_PatternID_A_part
Definition: gsmring.h:19
#define SM_Song_BasicSongType
Definition: gsmring.h:16
gboolean AllNotesScale

§ GSM_GetRingtoneName()

const unsigned char* GSM_GetRingtoneName ( const GSM_AllRingtonesInfo Info,
const int  ID 
)

Returns ringtone name, NULL if not found.

Definition at line 1713 of file gsmring.c.

References GSM_RingtoneInfo::ID, GSM_RingtoneInfo::Name, GSM_AllRingtonesInfo::Number, and GSM_AllRingtonesInfo::Ringtone.

1714 {
1715  int i;
1716 
1717  for (i = 0; i < Info->Number; i++) {
1718  if (Info->Ringtone[i].ID == ID) {
1719  return Info->Ringtone[i].Name;
1720  }
1721  }
1722 
1723  return NULL;
1724 }
GSM_RingtoneInfo * Ringtone
unsigned char Name[30 *2]

§ GSM_ReadRingtoneFile()

GSM_Error GSM_ReadRingtoneFile ( char *  FileName,
GSM_Ringtone ringtone 
)

Definition at line 874 of file gsmring.c.

References GSM_NoteRingtone::AllNotesScale, dbgprintf, EncodeUnicode(), ERR_CANTOPENFILE, ERR_FILENOTSUPPORTED, ERR_MOREMEMORY, ERR_UNKNOWN, FALSE, GSM_Ringtone::Format, GSM_MAX_RINGTONE_NAME_LENGTH, loadbin(), loadcommunicator(), loadmmf(), loadott(), loadpuremidi(), loadre(), loadrttl(), GSM_Ringtone::Name, GSM_Ringtone::NoteTone, RING_MIDI, RING_MMF, RING_NOKIABINARY, and RING_NOTETONE.

875 {
876  FILE *file;
877  unsigned char buffer[300];
878  GSM_Error error = ERR_UNKNOWN;
879  size_t readbytes;
880  char *file_only_name;
881  size_t len;
882 
883  dbgprintf(NULL, "Loading ringtone %s\n",FileName);
884  file = fopen(FileName, "rb");
885  if (file == NULL) return ERR_CANTOPENFILE;
886 
887  file_only_name = strrchr(FileName, '/');
888  if (file_only_name == NULL) {
889  file_only_name = strrchr(FileName, '\\');
890  } else {
891  file_only_name++;
892  }
893  if (file_only_name == NULL) {
894  file_only_name = FileName;
895  } else {
896  file_only_name++;
897  }
898  len = strlen(file_only_name);
899  if (len > GSM_MAX_RINGTONE_NAME_LENGTH){
900  fclose(file);
901  return ERR_MOREMEMORY;
902  }
903 
904  EncodeUnicode(ringtone->Name, file_only_name, len);
905 
906  /* Read the header of the file. */
907  readbytes = fread(buffer, 1, 4, file);
908  if (ringtone->Format == 0x00 && readbytes == 4) {
909  ringtone->Format = RING_NOTETONE;
910  if (buffer[0]==0x00 && buffer[1]==0x00 &&
911  buffer[2]==0x0C && buffer[3]==0x01) {
912  ringtone->Format = RING_NOKIABINARY;
913  }
914  if (buffer[0]==0x00 && buffer[1]==0x00 &&
915  buffer[2]==0x00) {
916  ringtone->Format = RING_NOKIABINARY;
917  }
918  if (buffer[0]==0x4D && buffer[1]==0x54 &&
919  buffer[2]==0x68 && buffer[3]==0x64) {
920  ringtone->Format = RING_MIDI;
921  }
922  if (buffer[0]==0x4D && buffer[1]==0x4D &&
923  buffer[2]==0x4D && buffer[3]==0x44) {
924  ringtone->Format = RING_MMF;
925  }
926  if (buffer[0]=='R' && buffer[1]=='I' &&
927  buffer[2]=='F' && buffer[3]=='F') {
928  dbgprintf(NULL, "RIFF is not supported for loading!\n");
929  fclose(file);
930  return ERR_FILENOTSUPPORTED;
931  }
932  }
933  rewind(file);
934  switch (ringtone->Format) {
935  case RING_NOTETONE:
936  if (buffer[0]==0x02 && buffer[1]==0x4A) {
937  error=loadott(file,ringtone);
938  } else if (buffer[0]==0xC7 && buffer[1]==0x45) {
939  error=loadcommunicator(file,ringtone);
940  } else {
941  error=loadrttl(file,ringtone);
942  }
943  ringtone->NoteTone.AllNotesScale=FALSE;
944  break;
945  case RING_NOKIABINARY:
946  if (buffer[0]==0x00 && buffer[1]==0x00 &&
947  buffer[2]==0x0C && buffer[3]==0x01) {
948  error=loadbin(file,ringtone);
949  }
950  if (buffer[0]==0x00 && buffer[1]==0x00 &&
951  buffer[2]==0x00) {
952  error=loadre(file,ringtone);
953  }
954  break;
955  case RING_MIDI:
956  error = loadpuremidi(file,ringtone);
957  break;
958  case RING_MMF:
959  error = loadmmf(file,ringtone);
960  break;
961  default:
962  error = ERR_FILENOTSUPPORTED;
963  break;
964  }
965  fclose(file);
966  return error ;
967 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:771
GSM_RingtoneFormat Format
static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:781
static GSM_Error loadmmf(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:829
static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:800
GSM_Error
Definition: gammu-error.h:23
#define GSM_MAX_RINGTONE_NAME_LENGTH
Definition: gammu-limits.h:232
GSM_NoteRingtone NoteTone
static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:537
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
#define FALSE
Definition: gammu-types.h:25
static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:853
static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:819
#define dbgprintf
Definition: debug.h:72
gboolean AllNotesScale

§ GSM_RingNoteGetFrequency()

int GSM_RingNoteGetFrequency ( GSM_RingNote  Note)

Definition at line 40 of file gsmring.c.

References GSM_RingNote::Note, Note_A, Note_Ais, Note_C, Note_Cis, Note_D, Note_Dis, Note_E, Note_F, Note_Fis, Note_G, Note_Gis, Note_H, Note_INVALID, Note_Pause, GSM_RingNote::Scale, Scale_1760, Scale_3520, Scale_440, and Scale_880.

Referenced by GSM_SaveRingtoneWav(), and PHONE_RTTLPlayOneNote().

41 {
42  int freq = 0;
43 
44  /* Values according to the software from http://iki.fi/too/sw/xring/
45  * generated with:
46  * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
47  */
48  switch (Note.Note) {
49  case Note_C : freq = 52330; break;
50  case Note_Cis: freq = 55440; break;
51  case Note_D : freq = 58730; break;
52  case Note_Dis: freq = 62230; break;
53  case Note_E : freq = 65930; break;
54  case Note_F : freq = 69850; break;
55  case Note_Fis: freq = 74000; break;
56  case Note_G : freq = 78400; break;
57  case Note_Gis: freq = 83060; break;
58  case Note_A : freq = 88000; break;
59  case Note_Ais: freq = 93230; break;
60  case Note_H : freq = 98780; break;
61  case Note_Pause: break;
62  case Note_INVALID: break;
63  }
64  if (Note.Note != Note_Pause) {
65  switch (Note.Scale) {
66  case Scale_440 : freq = freq / 2; break;
67  case Scale_880 : break;
68  case Scale_1760: freq = freq * 2; break;
69  case Scale_3520: freq = freq * 4; break;
70  default : break;
71  }
72  }
73  return freq / 100;
74 }
GSM_RingNoteNote Note
GSM_RingNoteScale Scale

§ GSM_RingNoteGetFullDuration()

int GSM_RingNoteGetFullDuration ( GSM_RingNote  Note)

Definition at line 76 of file gsmring.c.

References DottedNote, DoubleDottedNote, GSM_RingNote::Duration, Duration_1_16, Duration_1_2, Duration_1_32, Duration_1_4, Duration_1_8, Duration_Full, Duration_INVALID, GSM_RingNote::DurationSpec, DurationSpec_INVALID, Length_2_3, and NoSpecialDuration.

Referenced by GSM_SaveRingtoneMidi(), GSM_SaveRingtoneWav(), PHONE_RTTLPlayOneNote(), and RTTL2Binary().

77 {
78  int duration = 1;
79 
80  switch (Note.Duration) {
81  case Duration_Full : duration = 128; break;
82  case Duration_1_2 : duration = 64; break;
83  case Duration_1_4 : duration = 32; break;
84  case Duration_1_8 : duration = 16; break;
85  case Duration_1_16 : duration = 8; break;
86  case Duration_1_32 : duration = 4; break;
87  case Duration_INVALID: break;
88  }
89  switch (Note.DurationSpec) {
90  case NoSpecialDuration : break;
91  case DottedNote : duration = duration * 3/2; break;
92  case DoubleDottedNote : duration = duration * 9/4; break;
93  case Length_2_3 : duration = duration * 2/3; break;
94  case DurationSpec_INVALID: break;
95  }
96  return duration;
97 }
GSM_RingNoteDuration Duration
GSM_RingNoteDurationSpec DurationSpec

§ GSM_RingtoneConvert()

GSM_Error GSM_RingtoneConvert ( GSM_Ringtone dest,
GSM_Ringtone src,
GSM_RingtoneFormat  Format 
)

Definition at line 1543 of file gsmring.c.

References Binary2RTTL(), CopyUnicodeString(), ERR_NONE, ERR_NOTIMPLEMENTED, GSM_Ringtone::Format, GSM_Ringtone::Name, RING_NOKIABINARY, RING_NOTETONE, and RTTL2Binary().

1544 {
1545  dest->Format = Format;
1546  CopyUnicodeString(dest->Name,src->Name);
1547  if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) {
1548  RTTL2Binary(dest, src);
1549  return ERR_NONE;
1550  }
1551  if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) {
1552  Binary2RTTL(dest, src);
1553  return ERR_NONE;
1554  }
1555  /* The same source and target format */
1556  if (src->Format==Format) {
1557  memcpy(dest,src,sizeof(GSM_Ringtone));
1558  return ERR_NONE;
1559  }
1560  return ERR_NOTIMPLEMENTED;
1561 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
GSM_RingtoneFormat Format
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src)
Definition: gsmring.c:1250
static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src)
Definition: gsmring.c:1328

§ GSM_RTTLGetTempo()

int GSM_RTTLGetTempo ( int  Beats)

Definition at line 979 of file gsmring.c.

References SM_BeatsPerMinute.

Referenced by GSM_EncodeNokiaRTTLRingtone().

980 {
981  int i=0;
982 
983  while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
984 
985  return i<<3;
986 }
static int SM_BeatsPerMinute[]
Definition: gsmring.c:972

§ GSM_SaveRingtoneFile()

GSM_Error GSM_SaveRingtoneFile ( char *  FileName,
GSM_Ringtone ringtone 
)

Definition at line 494 of file gsmring.c.

References ERR_CANTOPENFILE, ERR_UNKNOWN, GSM_Ringtone::Format, GSM_SaveRingtoneIMelody(), GSM_SaveRingtoneMidi(), GSM_SaveRingtoneOtt(), GSM_SaveRingtoneRttl(), GSM_SaveRingtoneWav(), RING_MIDI, RING_MMF, RING_NOKIABINARY, RING_NOTETONE, savebin(), savemmf(), and savepuremidi().

495 {
496  FILE *file;
497  GSM_Error error = ERR_UNKNOWN;;
498 
499 
500  file = fopen(FileName, "wb");
501  if (file == NULL) return ERR_CANTOPENFILE;
502 
503  switch (ringtone->Format) {
504  case RING_NOTETONE:
505  if (strstr(FileName,".ott")) {
506  error = GSM_SaveRingtoneOtt(file,ringtone);
507  } else if (strstr(FileName,".rng")) {
508  error = GSM_SaveRingtoneOtt(file,ringtone);
509  } else if (strstr(FileName,".mid")) {
510  error = GSM_SaveRingtoneMidi(file,ringtone);
511  } else if (strstr(FileName,".imy")) {
512  error = GSM_SaveRingtoneIMelody(file,ringtone);
513  } else if (strstr(FileName,".ime")) {
514  error = GSM_SaveRingtoneIMelody(file,ringtone);
515  } else if (strstr(FileName,".wav")) {
516  error = GSM_SaveRingtoneWav(file,ringtone);
517  } else {
518  error = GSM_SaveRingtoneRttl(file, ringtone);
519  }
520  break;
521  case RING_NOKIABINARY:
522  error = savebin(file, ringtone);
523  break;
524  case RING_MIDI:
525  error = savepuremidi(file, ringtone);
526  break;
527  case RING_MMF:
528  error = savemmf(file, ringtone);
529  break;
530  }
531 
532  fclose(file);
533 
534  return error;
535 }
GSM_Error GSM_SaveRingtoneMidi(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:413
GSM_RingtoneFormat Format
GSM_Error
Definition: gammu-error.h:23
static GSM_Error savemmf(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:193
GSM_Error GSM_SaveRingtoneRttl(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:201
static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:169
static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:185
GSM_Error GSM_SaveRingtoneWav(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:105
GSM_Error GSM_SaveRingtoneIMelody(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:377
GSM_Error GSM_SaveRingtoneOtt(FILE *file, GSM_Ringtone *ringtone)
Definition: gsmring.c:481

§ GSM_SaveRingtoneIMelody()

GSM_Error GSM_SaveRingtoneIMelody ( FILE *  file,
GSM_Ringtone ringtone 
)

Definition at line 377 of file gsmring.c.

References chk_fwrite, ERR_NONE, ERR_WRITING_FILE, GSM_EncodeEMSSound(), GSM_Ring_IMelody12, and TRUE.

Referenced by GSM_SaveRingtoneFile().

378 {
379  char Buffer[2000];
380  size_t i=2000;
381 
382  GSM_EncodeEMSSound(ringtone, Buffer, &i, GSM_Ring_IMelody12, TRUE);
383 
384  chk_fwrite(Buffer, 1, i, file);
385  return ERR_NONE;
386 fail:
387  return ERR_WRITING_FILE;
388 }
#define TRUE
Definition: gammu-types.h:28
unsigned char GSM_EncodeEMSSound(GSM_Ringtone *ringtone, unsigned char *package, size_t *maxlength, GSM_RingtoneVersion version, gboolean start)
Definition: gsmring.c:1565
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ GSM_SaveRingtoneMidi()

GSM_Error GSM_SaveRingtoneMidi ( FILE *  file,
GSM_Ringtone ringtone 
)

Definition at line 413 of file gsmring.c.

References chk_fwrite, GSM_NoteRingtone::Commands, ERR_NONE, ERR_WRITING_FILE, FALSE, GSM_RingNoteGetFullDuration(), GSM_RingNote::Note, GSM_RingCommand::Note, Note_C, Note_H, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_Note, GSM_RingNote::Scale, GSM_RingNote::Tempo, TRUE, GSM_RingCommand::Type, and WriteVarLen().

Referenced by GSM_SaveRingtoneFile().

414 {
415  int pause_time = 0, duration, i, note=0, length = 20;
416  size_t current = 26;
417  gboolean started = FALSE;
418  GSM_RingNote *Note;
419  unsigned char midifile[3000] = {
420  0x4D, 0x54, 0x68, 0x64, /* MThd */
421  0x00, 0x00, 0x00, 0x06, /* chunk length */
422  0x00, 0x00, /* format 0 */
423  0x00, 0x01, /* one track */
424  0x00, 0x20, /* 32 per quarter note */
425  0x4D, 0x54, 0x72, 0x6B, /* MTrk */
426  0x00, 0x00, 0x00, 0x00, /* chunk length */
427  0x00, 0xFF, 0x51, 0x03, /* tempo meta event */
428  0x00, 0x00, 0x00}; /* 3 bytes for us for a quarter note */
429 
430  for (i = 0; i < ringtone->NoteTone.NrCommands; i++) {
431  if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
432  Note = &ringtone->NoteTone.Commands[i].Note;
433  if (!started) {
434  /* readmid does not read pauses at the beginning */
435  if (Note->Note != Note_Pause) {
436  /* FIXME: we need add tempo before each note or so... */
437  duration = 60000000/Note->Tempo;
438 
439  midifile[current++] = (unsigned char)(duration >> 16);
440  midifile[current++] = (unsigned char)(duration >> 8);
441  midifile[current++] = (unsigned char)duration;
442 
443  started = TRUE;
444  }
445  }
446  if (!started) continue;
447  duration = GSM_RingNoteGetFullDuration(*Note);
448  if (Note->Note == Note_Pause) {
449  pause_time += duration;
450  } else {
451  if (Note->Note >= Note_C && Note->Note <= Note_H) {
452  note = Note->Note/16 + 12 * Note->Scale - 1;
453  }
454 
455  WriteVarLen(midifile,&current,pause_time);
456  pause_time=0;
457  midifile[current++]=0x90; /* note on */
458  midifile[current++]=note;
459  midifile[current++]=0x64; /* forte */
460 
461  WriteVarLen(midifile,&current,duration);
462  midifile[current++]=0x80; /* note off */
463  midifile[current++]=note;
464  midifile[current++]=0x64;
465  }
466  }
467  }
468  midifile[current++] = 0x00;
469  midifile[current++] = 0xFF; /* track end */
470  midifile[current++] = 0x2F;
471  midifile[current++] = 0x00;
472  midifile[length++] = (current-22) >> 8;
473  midifile[length] = current-22;
474 
475  chk_fwrite(midifile,1,current,file);
476  return ERR_NONE;
477 fail:
478  return ERR_WRITING_FILE;
479 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
GSM_RingNoteNote Note
GSM_RingNoteScale Scale
GSM_RingCommandType Type
GSM_NoteRingtone NoteTone
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
Definition: gsmring.c:76
static void WriteVarLen(unsigned char *midifile, size_t *current, long value)
Definition: gsmring.c:390
#define TRUE
Definition: gammu-types.h:28
GSM_RingNote Note
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ GSM_SaveRingtoneOtt()

GSM_Error GSM_SaveRingtoneOtt ( FILE *  file,
GSM_Ringtone ringtone 
)

Definition at line 481 of file gsmring.c.

References chk_fwrite, ERR_NONE, ERR_WRITING_FILE, and GSM_EncodeNokiaRTTLRingtone().

Referenced by GSM_SaveRingtoneFile().

482 {
483  char Buffer[2000];
484  size_t i=2000;
485 
486  GSM_EncodeNokiaRTTLRingtone(ringtone, Buffer, &i);
487 
488  chk_fwrite(Buffer, 1, i, file);
489  return ERR_NONE;
490 fail:
491  return ERR_WRITING_FILE;
492 }
unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, size_t *maxlength)
Definition: gsmring.c:992
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ GSM_SaveRingtoneRttl()

GSM_Error GSM_SaveRingtoneRttl ( FILE *  file,
GSM_Ringtone ringtone 
)

Definition at line 201 of file gsmring.c.

References GSM_NoteRingtone::Commands, ContinuousStyle, dbgprintf, DecodeUnicodeString(), DottedNote, DoubleDottedNote, GSM_RingNote::Duration, Duration_1_16, Duration_1_2, Duration_1_32, Duration_1_4, Duration_1_8, Duration_Full, Duration_INVALID, GSM_RingNote::DurationSpec, ERR_NONE, FALSE, INVALIDStyle, GSM_Ringtone::Name, NaturalStyle, NoSpecialDuration, GSM_RingNote::Note, GSM_RingCommand::Note, Note_A, Note_Ais, Note_C, Note_Cis, Note_D, Note_Dis, Note_E, Note_F, Note_Fis, Note_G, Note_Gis, Note_H, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_Note, GSM_RingNote::Scale, Scale_14080, Scale_55, StaccatoStyle, GSM_RingNote::Style, GSM_RingNote::Tempo, TRUE, and GSM_RingCommand::Type.

Referenced by GSM_SaveRingtoneFile().

202 {
203  GSM_RingNoteScale DefNoteScale;
204  GSM_RingNoteDuration DefNoteDuration;
205 
206  GSM_RingNoteStyle DefNoteStyle=0;
207  int DefNoteTempo=0;
208 
209  gboolean started = FALSE, firstcomma = TRUE;
210  GSM_RingNote *Note;
211 
212  unsigned char buffer[15];
213  int i,j,k=0;
214 
215  /* Saves ringtone name */
216  fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
217 
218  /* Find the most frequently used duration */
219  for (i=0;i<6;i++) buffer[i]=0;
220  for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
221  if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
222  Note = &ringtone->NoteTone.Commands[i].Note;
223  /* some durations need 2 bytes in file, some 1 */
224  /* Typecasting to silent GCC warning, Duration is usually unsigned */
225  if ((int)Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
226  buffer[Note->Duration/32]++;
227  }
228  if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) {
229  buffer[Note->Duration/32]+=2;
230  }
231  }
232  }
233  /* Now find the most frequently used */
234  j=0;
235  for (i=0;i<6;i++) {
236  if (buffer[i]>j) {
237  k=i;
238  j=buffer[i];
239  }
240  }
241  /* Finally convert the default duration */
242  DefNoteDuration = k * 32;
243  dbgprintf(NULL, "DefNoteDuration=%d\n", DefNoteDuration);
244  switch (DefNoteDuration) {
245  case Duration_INVALID: break;
246  case Duration_Full:fprintf(file,"d=1"); break;
247  case Duration_1_2 :fprintf(file,"d=2"); break;
248  case Duration_1_4 :fprintf(file,"d=4"); break;
249  case Duration_1_8 :fprintf(file,"d=8"); break;
250  case Duration_1_16:fprintf(file,"d=16");break;
251  case Duration_1_32:fprintf(file,"d=32");break;
252  }
253 
254  /* Find the most frequently used scale */
255  for (i=0;i<9;i++) buffer[i]=0;
256  for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
257  if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
258  Note = &ringtone->NoteTone.Commands[i].Note;
259  if (Note->Note!=Note_Pause &&
260  Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) {
261  buffer[Note->Scale - 1]++;
262  }
263  }
264  }
265  j=0;
266  for (i=0;i<9;i++) {
267  if (buffer[i]>j) {
268  k = i;
269  j=buffer[i];
270  }
271  }
272  DefNoteScale = k + 1;
273  /* Save the default scale */
274  fprintf(file,",o=%i,",DefNoteScale);
275  dbgprintf(NULL, "DefNoteScale=%d\n", DefNoteScale);
276 
277  for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
278  if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
279 
280  Note = &ringtone->NoteTone.Commands[i].Note;
281 
282  /* Trick from PPM Edit */
283  if (Note->DurationSpec == DoubleDottedNote) {
284  switch (Note->Duration) {
285  case Duration_INVALID: break;
286  case Duration_Full:Note->Duration = Duration_Full;break;
287  case Duration_1_2 :Note->Duration = Duration_Full;break;
288  case Duration_1_4 :Note->Duration = Duration_1_2; break;
289  case Duration_1_8 :Note->Duration = Duration_1_4; break;
290  case Duration_1_16:Note->Duration = Duration_1_8; break;
291  case Duration_1_32:Note->Duration = Duration_1_16;break;
292  }
294  }
295 
296  if (!started) {
297  DefNoteTempo=Note->Tempo;
298  DefNoteStyle=Note->Style;
299  switch (Note->Style) {
300  case StaccatoStyle : fprintf(file,"s=S,"); break;
301  case NaturalStyle : fprintf(file,"s=N,"); break;
302  case ContinuousStyle : break;
303  case INVALIDStyle: break;
304  }
305  /* Save the default tempo */
306  fprintf(file,"b=%i:",DefNoteTempo);
307  dbgprintf(NULL, "DefNoteTempo=%d\n", DefNoteTempo);
308  started = TRUE;
309  firstcomma = TRUE;
310  }
311 
312  if (Note->Style!=DefNoteStyle) {
313  /* And a separator */
314  if (!firstcomma) fprintf(file,",");
315  firstcomma = FALSE;
316  DefNoteStyle=Note->Style;
317  switch (Note->Style) {
318  case StaccatoStyle : fprintf(file,"s=S"); break;
319  case NaturalStyle : fprintf(file,"s=N"); break;
320  case ContinuousStyle: fprintf(file,"s=C"); break;
321  case INVALIDStyle: break;
322  }
323  }
324  if (Note->Tempo!=DefNoteTempo) {
325  /* And a separator */
326  if (!firstcomma) fprintf(file,",");
327  firstcomma = FALSE;
328  DefNoteTempo=Note->Tempo;
329  fprintf(file,"b=%i",DefNoteTempo);
330  }
331  /* This note has a duration different than the default. We must save it */
332  if (Note->Duration!=DefNoteDuration) {
333  /* And a separator */
334  if (!firstcomma) fprintf(file,",");
335  firstcomma = FALSE;
336  switch (Note->Duration) {
337  case Duration_INVALID: break;
338  case Duration_Full:fprintf(file,"1"); break;
339  case Duration_1_2 :fprintf(file,"2"); break;
340  case Duration_1_4 :fprintf(file,"4"); break;
341  case Duration_1_8 :fprintf(file,"8"); break;
342  case Duration_1_16:fprintf(file,"16");break;
343  case Duration_1_32:fprintf(file,"32");break;
344  }
345  } else {
346  /* And a separator */
347  if (!firstcomma) fprintf(file,",");
348  firstcomma = FALSE;
349  }
350  /* Now save the actual note */
351  switch (Note->Note) {
352  case Note_C :fprintf(file,"c"); break;
353  case Note_Cis:fprintf(file,"c#"); break;
354  case Note_D :fprintf(file,"d"); break;
355  case Note_Dis:fprintf(file,"d#"); break;
356  case Note_E :fprintf(file,"e"); break;
357  case Note_F :fprintf(file,"f"); break;
358  case Note_Fis:fprintf(file,"f#"); break;
359  case Note_G :fprintf(file,"g"); break;
360  case Note_Gis:fprintf(file,"g#"); break;
361  case Note_A :fprintf(file,"a"); break;
362  case Note_Ais:fprintf(file,"a#"); break;
363  case Note_H :fprintf(file,"h"); break;
364  default :fprintf(file,"p"); break; /*Pause ?*/
365  }
366  switch (Note->DurationSpec) {
367  case DottedNote : fprintf(file,"."); break;
368  default : break;
369  }
370  if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
371  fprintf(file,"%i",Note->Scale);
372  }
373  }
374  return ERR_NONE;
375 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
GSM_RingNoteDuration Duration
GSM_RingNoteNote Note
GSM_RingNoteScale Scale
GSM_RingCommandType Type
GSM_RingNoteScale
GSM_NoteRingtone NoteTone
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
GSM_RingNoteStyle Style
GSM_RingNoteDurationSpec DurationSpec
GSM_RingNoteStyle
#define dbgprintf
Definition: debug.h:72
#define TRUE
Definition: gammu-types.h:28
GSM_RingNoteDuration
GSM_RingNote Note

§ GSM_SaveRingtoneWav()

GSM_Error GSM_SaveRingtoneWav ( FILE *  file,
GSM_Ringtone ringtone 
)

Definition at line 105 of file gsmring.c.

References chk_fwrite, GSM_NoteRingtone::Commands, ERR_NONE, ERR_WRITING_FILE, GSM_RingNoteGetFrequency(), GSM_RingNoteGetFullDuration(), GSM_RingCommand::Note, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, PI, RING_Note, GSM_RingCommand::Type, and WAV_SAMPLE_RATE.

Referenced by GSM_SaveRingtoneFile().

106 {
107 
108  unsigned char WAV_Header[] = {
109  'R','I','F','F',
110  0x00,0x00,0x00,0x00, /* Length */
111  'W','A','V','E'};
112  unsigned char FMT_Header[] = {'f','m','t',' ',
113  0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac,
114  0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00};
115  unsigned char DATA_Header[] = {
116  'd','a','t','a',
117  0x00,0x00,0x00,0x00}; /* Length */
118  short DATA;
119  long wavfilesize;
120  GSM_RingNote *Note;
121  int i;
122  size_t j,length=0, duration;
123  double phase=0,phase_step;
124 
125  chk_fwrite(&WAV_Header, 1, sizeof(WAV_Header), file);
126  chk_fwrite(&FMT_Header, 1, sizeof(FMT_Header), file);
127  chk_fwrite(&DATA_Header, 1, sizeof(DATA_Header), file);
128 
129  for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
130  if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
131  Note = &ringtone->NoteTone.Commands[i].Note;
132 
133  phase_step = GSM_RingNoteGetFrequency(*Note);
134  phase_step *= WAV_SAMPLE_RATE * 1.5;
135 
136  duration = GSM_RingNoteGetFullDuration(*Note);
137  duration *= WAV_SAMPLE_RATE / 70;
138 
139  for (j = 0; j < duration; j++) {
140  DATA = ((int)(sin(phase*PI) * 50000));
141  chk_fwrite(&DATA, sizeof(short), 1, file);
142  phase = phase + phase_step;
143  length++;
144  }
145  }
146  }
147 
148  wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2;
149  WAV_Header[4] = ((unsigned char)wavfilesize % 256);
150  WAV_Header[5] = ((unsigned char)wavfilesize / 256);
151  WAV_Header[6] = ((unsigned char)wavfilesize / (256*256));
152  WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
153  wavfilesize = wavfilesize - 54;
154  DATA_Header[4] = ((unsigned char)wavfilesize % 256);
155  DATA_Header[5] = ((unsigned char)wavfilesize / 256);
156  DATA_Header[6] = ((unsigned char)wavfilesize / (256*256));
157  DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
158 
159  fseek( file, 0, SEEK_SET);
160  chk_fwrite(&WAV_Header, 1, sizeof(WAV_Header), file);
161  chk_fwrite(&FMT_Header, 1, sizeof(FMT_Header), file);
162  chk_fwrite(&DATA_Header, 1, sizeof(DATA_Header), file);
163 
164  return ERR_NONE;
165 fail:
166  return ERR_WRITING_FILE;
167 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
int GSM_RingNoteGetFrequency(GSM_RingNote Note)
Definition: gsmring.c:40
#define WAV_SAMPLE_RATE
Definition: gsmring.c:103
#define PI
Definition: gsmring.c:100
GSM_RingCommandType Type
GSM_NoteRingtone NoteTone
int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
Definition: gsmring.c:76
GSM_RingNote Note
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ loadbin()

static GSM_Error loadbin ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 800 of file gsmring.c.

References dbgprintf, DecodeUnicodeString(), EncodeUnicode(), ERR_NONE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, GSM_Ringtone::Name, and GSM_Ringtone::NokiaBinary.

Referenced by GSM_ReadRingtoneFile().

801 {
802  int i;
803  unsigned char buffer[2000];
804 
805  dbgprintf(NULL, "loading binary\n");
806  ringtone->NokiaBinary.Length = fread(buffer, 1, 500, file);
807  i=5;
808  while (buffer[i]!=0x00) i++;
809  EncodeUnicode(ringtone->Name,buffer+5,i-5);
810  while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
811  i++;
812  }
813  ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
814  memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
815  dbgprintf(NULL, "Length %ld name \"%s\"\n", (long)ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
816  return ERR_NONE;
817 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
#define dbgprintf
Definition: debug.h:72

§ loadcommunicator()

static GSM_Error loadcommunicator ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 781 of file gsmring.c.

References ERR_UNKNOWN, GSM_DecodeNokiaRTTLRingtone(), and TRUE.

Referenced by GSM_ReadRingtoneFile().

782 {
783  char Buffer[4000];
784  int bytes_read,j;
785 
786  bytes_read = fread(Buffer, 1, 4000, file);
787 
788  j=0;
789  while (TRUE) {
790  if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 &&
791  Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break;
792  if (j==bytes_read-4) return ERR_UNKNOWN;
793  j++;
794  }
795  j++;
796 
797  return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, bytes_read-j);
798 }
GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, size_t maxlength UNUSED)
Definition: gsmring.c:1128
#define TRUE
Definition: gammu-types.h:28

§ loadmmf()

static GSM_Error loadmmf ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 829 of file gsmring.c.

References GSM_Ringtone::BinaryTone, GSM_BinaryTone::Buffer, dbgprintf, DecodeUnicodeString(), ERR_MOREMEMORY, ERR_NONE, GSM_BinaryTone::Length, and GSM_Ringtone::Name.

Referenced by GSM_ReadRingtoneFile().

830 {
831  struct stat st;
832  char *buffer=NULL;
833  size_t length=0,readbytes=0;
834 
835  dbgprintf(NULL, "loading smaf file\n");
836  fstat(fileno(file), &st);
837  ringtone->BinaryTone.Length = length = st.st_size;
838  ringtone->BinaryTone.Buffer = buffer = (char *)malloc(length);
839  if (buffer == NULL)
840  return ERR_MOREMEMORY;
841  readbytes = fread(buffer, 1, length, file);
842  if (readbytes != length) {
843  dbgprintf(NULL, "Could not read whole file!\n");
844  return ERR_MOREMEMORY;
845  }
846 
847  dbgprintf(NULL, "Length %ld name \"%s\"\n", (long)length,
848  DecodeUnicodeString(ringtone->Name));
849 
850  return ERR_NONE;
851 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
unsigned char * Buffer
GSM_BinaryTone BinaryTone
#define dbgprintf
Definition: debug.h:72

§ loadott()

static GSM_Error loadott ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 771 of file gsmring.c.

References GSM_DecodeNokiaRTTLRingtone().

Referenced by GSM_ReadRingtoneFile().

772 {
773  char Buffer[2000];
774  int i;
775 
776  i = fread(Buffer, 1, 2000, file);
777 
778  return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i);
779 }
GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, size_t maxlength UNUSED)
Definition: gsmring.c:1128

§ loadpuremidi()

static GSM_Error loadpuremidi ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 819 of file gsmring.c.

References dbgprintf, DecodeUnicodeString(), EncodeUnicode(), ERR_NONE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, GSM_Ringtone::Name, and GSM_Ringtone::NokiaBinary.

Referenced by GSM_ReadRingtoneFile().

820 {
821  dbgprintf(NULL, "loading midi\n");
822  EncodeUnicode(ringtone->Name,"MIDI",4);
823  ringtone->NokiaBinary.Length = fread(ringtone->NokiaBinary.Frame,
824  1, sizeof(ringtone->NokiaBinary.Frame), file);
825  dbgprintf(NULL, "Length %ld name \"%s\"\n",(long)ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
826  return ERR_NONE;
827 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
#define dbgprintf
Definition: debug.h:72

§ loadre()

static GSM_Error loadre ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 853 of file gsmring.c.

References CopyUnicodeString(), dbgprintf, DecodeUnicodeString(), EncodeUnicode(), ERR_NONE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, GSM_Ringtone::Name, GSM_Ringtone::NokiaBinary, and UnicodeLength().

Referenced by GSM_ReadRingtoneFile().

854 {
855  unsigned char buffer[2000];
856 
857  ringtone->NokiaBinary.Length = fread(buffer, 1, 500, file);
858 
859  if (buffer[18]==0x00 && buffer[21]!=0x02) {
860  /* DCT3, Unicode subformat, 62xx & 7110 */
861  CopyUnicodeString(ringtone->Name,buffer+18);
862  ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
863  memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
864  } else {
865  /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
866  EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
867  ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
868  memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
869  }
870  dbgprintf(NULL, "Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
871  return ERR_NONE;
872 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
#define dbgprintf
Definition: debug.h:72

§ loadrttl()

static GSM_Error loadrttl ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 537 of file gsmring.c.

References GSM_NoteRingtone::Commands, ContinuousStyle, dbgprintf, DottedNote, GSM_RingNote::Duration, Duration_1_16, Duration_1_2, Duration_1_32, Duration_1_4, Duration_1_8, Duration_Full, GSM_RingNote::DurationSpec, EncodeUnicode(), ERR_FILENOTSUPPORTED, ERR_NONE, GSM_MAX_RINGTONE_NOTES, GSM_Ringtone::Name, NaturalStyle, NoSpecialDuration, GSM_RingNote::Note, GSM_RingCommand::Note, Note_A, Note_Ais, Note_C, Note_Cis, Note_D, Note_Dis, Note_E, Note_F, Note_Fis, Note_G, Note_Gis, Note_H, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_DisableLED, RING_DisableLight, RING_DisableVibra, RING_EnableLED, RING_EnableLight, RING_EnableVibra, RING_Note, GSM_RingNote::Scale, Scale_1760, Scale_3520, Scale_440, Scale_880, StaccatoStyle, GSM_RingNote::Style, GSM_RingNote::Tempo, and GSM_RingCommand::Type.

Referenced by GSM_ReadRingtoneFile().

538 {
539  GSM_RingNoteScale DefNoteScale = Scale_880;
540  GSM_RingNoteDuration DefNoteDuration = Duration_1_4;
541  GSM_RingNoteStyle DefNoteStyle = NaturalStyle;
542  int DefNoteTempo = 63;
543  size_t i = 0;
544  size_t readbytes;
545 
546  char buffer[2000],Name[100];
547  GSM_RingNote *Note;
548 
549  readbytes = fread(buffer, 1, sizeof(buffer), file);
550 
551  ringtone->NoteTone.NrCommands = 0;
552 
553  /* -------------- name ---------------- */
554  while (buffer[i] != ':' && i < readbytes) {
555  if (buffer[i] == 0x00) return ERR_NONE;
556  i++;
557  }
558  if (i == 0) {
559  /* This is for RTTL ringtones without name. */
560  EncodeUnicode(ringtone->Name,"Gammu",5);
561  } else if (i >= readbytes) {
562  return ERR_FILENOTSUPPORTED;
563  } else {
564  memcpy(Name,buffer,i);
565  Name[i] = 0x00;
566  EncodeUnicode(ringtone->Name,Name,strlen(Name));
567  }
568  i++;
569 
570  /* --------- section with default ringtone settings ----------- */
571  while(1) {
572  if (i >= readbytes) {
573  return ERR_FILENOTSUPPORTED;
574  }
575  switch (buffer[i]) {
576  case ':':
577  break;
578  case 0x00:
579  return ERR_NONE;
580  case 'd': case 'D':
581  switch (atoi(buffer+i+2)) {
582  case 1: DefNoteDuration = Duration_Full; break;
583  case 2: DefNoteDuration = Duration_1_2 ; break;
584  case 4: DefNoteDuration = Duration_1_4 ; break;
585  case 8: DefNoteDuration = Duration_1_8 ; break;
586  case 16: DefNoteDuration = Duration_1_16; break;
587  case 32: DefNoteDuration = Duration_1_32; break;
588  }
589  break;
590  case 'o': case 'O':
591  switch (atoi(buffer+i+2)) {
592  case 4: DefNoteScale = Scale_440 ; break;
593  case 5: DefNoteScale = Scale_880 ; break;
594  case 6: DefNoteScale = Scale_1760; break;
595  case 7: DefNoteScale = Scale_3520; break;
596  }
597  break;
598  case 'b': case 'B':
599  DefNoteTempo=atoi(buffer+i+2);
600  dbgprintf(NULL, "Tempo = %i\n",DefNoteTempo);
601  break;
602  case 's': case 'S':
603  switch (buffer[i+1]) {
604  case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
605  case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
606  case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
607  }
608  switch (buffer[i+2]) {
609  case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
610  case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
611  case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
612  }
613  break;
614  }
615  while (buffer[i] != ':' && buffer[i] != ',') {
616  if (buffer[i] == 0x00) return ERR_NONE;
617  i++;
618  }
619  if (buffer[i] == ',') i++;
620  if (buffer[i] == ':') break;
621  }
622  dbgprintf(NULL, "DefNoteDuration=%d\n", DefNoteDuration);
623  dbgprintf(NULL, "DefNoteScale=%d\n", DefNoteScale);
624  i++;
625 
626  /* ------------------------- notes ------------------------------ */
627  while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != GSM_MAX_RINGTONE_NOTES) {
628  switch(buffer[i]) {
629  case 'z': case 'Z':
630  switch (buffer[i+1]) {
631  case 'd':
632  ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED;
633  ringtone->NoteTone.NrCommands++;
634  break;
635  case 'D':
636  ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED;
637  ringtone->NoteTone.NrCommands++;
638  break;
639  case 'v':
641  ringtone->NoteTone.NrCommands++;
642  break;
643  case 'V':
644  ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra;
645  ringtone->NoteTone.NrCommands++;
646  break;
647  case 'l':
649  ringtone->NoteTone.NrCommands++;
650  break;
651  case 'L':
652  ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight;
653  ringtone->NoteTone.NrCommands++;
654  }
655  break;
656  case 'o': case 'O':
657  switch (buffer[i+2]) {
658  case 4: DefNoteScale = Scale_440 ; break;
659  case 5: DefNoteScale = Scale_880 ; break;
660  case 6: DefNoteScale = Scale_1760; break;
661  case 7: DefNoteScale = Scale_3520; break;
662  }
663  break;
664  case 's': case 'S':
665  switch (buffer[i+1]) {
666  case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
667  case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
668  case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
669  }
670  switch (buffer[i+2]) {
671  case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
672  case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
673  case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
674  }
675  break;
676  default:
677  ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
678  Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
679  Note->Style = DefNoteStyle;
680  Note->Tempo = DefNoteTempo;
681  Note->Scale = DefNoteScale;
682  Note->Duration = DefNoteDuration;
684  Note->Note = Note_Pause;
685 
686  /* Duration */
687  switch (atoi(buffer+i)) {
688  case 1: Note->Duration = Duration_Full ; break;
689  case 2: Note->Duration = Duration_1_2 ; break;
690  case 4: Note->Duration = Duration_1_4 ; break;
691  case 8: Note->Duration = Duration_1_8 ; break;
692  case 16: Note->Duration = Duration_1_16 ; break;
693  case 32: Note->Duration = Duration_1_32 ; break;
694  }
695  /* We skip all numbers from duration specification */
696  while(isdigit((int)buffer[i])) i++;
697 
698  /* Some files can have special duration here */
699  if (buffer[i]=='.') {
700  Note->DurationSpec = DottedNote;
701  i++;
702  }
703 
704  /* Note */
705  /* B or b is not in specs, but I decided to put it, because
706  * it's in some RTTL files. It's the same to H note */
707  switch (buffer[i]) {
708  case 'A': case 'a': Note->Note = Note_A; break;
709  case 'B': case 'b': Note->Note = Note_H; break;
710  case 'C': case 'c': Note->Note = Note_C; break;
711  case 'D': case 'd': Note->Note = Note_D; break;
712  case 'E': case 'e': Note->Note = Note_E; break;
713  case 'F': case 'f': Note->Note = Note_F; break;
714  case 'G': case 'g': Note->Note = Note_G; break;
715  case 'H': case 'h': Note->Note = Note_H; break;
716  }
717  i++;
718  if (i >= readbytes) break;
719 
720  if (buffer[i]=='#') {
721  switch (Note->Note) {
722  case Note_A : Note->Note = Note_Ais; break;
723  case Note_C : Note->Note = Note_Cis; break;
724  case Note_D : Note->Note = Note_Dis; break;
725  case Note_F : Note->Note = Note_Fis; break;
726  case Note_G : Note->Note = Note_Gis; break;
727  default : break;
728  }
729  i++;
730  if (i >= readbytes) break;
731  }
732 
733  /* Some files can have special duration here */
734  if (buffer[i]=='.') {
735  Note->DurationSpec = DottedNote;
736  i++;
737  if (i >= readbytes) break;
738  }
739 
740  /* Scale */
741  if (Note->Note!=Note_Pause && isdigit((int)buffer[i])) {
742  switch (atoi(buffer+i)) {
743  case 4: Note->Scale = Scale_440 ; break;
744  case 5: Note->Scale = Scale_880 ; break;
745  case 6: Note->Scale = Scale_1760; break;
746  case 7: Note->Scale = Scale_3520; break;
747  }
748  i++;
749  if (i >= readbytes) break;
750  }
751 
752  ringtone->NoteTone.NrCommands++;
753  break;
754  }
755  if (i >= readbytes) break;
756  while (buffer[i] != ',') {
757  if (buffer[i] == 0x00) return ERR_NONE;
758  i++;
759  if (i >= readbytes) break;
760  }
761  if (i >= readbytes) break;
762  if (buffer[i] == ',') i++;
763  if (i >= readbytes) {
764  return ERR_FILENOTSUPPORTED;
765  }
766  }
767 
768  return ERR_NONE;
769 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
GSM_RingNoteDuration Duration
GSM_RingNoteNote Note
GSM_RingNoteScale Scale
GSM_RingCommandType Type
GSM_RingNoteScale
GSM_NoteRingtone NoteTone
#define GSM_MAX_RINGTONE_NOTES
Definition: gammu-limits.h:225
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
GSM_RingNoteStyle Style
GSM_RingNoteDurationSpec DurationSpec
GSM_RingNoteStyle
#define dbgprintf
Definition: debug.h:72
GSM_RingNoteDuration
GSM_RingNote Note

§ RTTL2Binary()

static void RTTL2Binary ( GSM_Ringtone dest,
GSM_Ringtone src 
)
static

Definition at line 1250 of file gsmring.c.

References GSM_NoteRingtone::Commands, GSM_NokiaBinaryRingtone::Frame, GSM_RingNoteGetFullDuration(), GSM_NokiaBinaryRingtone::Length, NaturalStyle, GSM_Ringtone::NokiaBinary, GSM_RingNote::Note, GSM_RingCommand::Note, Note_C, Note_H, Note_Pause, GSM_Ringtone::NoteTone, GSM_NoteRingtone::NrCommands, RING_Note, GSM_RingNote::Scale, Scale_1760, Scale_3520, Scale_440, Scale_880, StaccatoStyle, GSM_RingNote::Style, GSM_RingNote::Tempo, and GSM_RingCommand::Type.

Referenced by GSM_RingtoneConvert().

1251 {
1252  int current = 0, i, note, lastnote = 0, duration;
1253  GSM_RingNote *Note;
1254  unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
1255  0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
1256  0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B};
1257 
1258  strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09"); current=current+3;
1259  dest->NokiaBinary.Frame[current++]=0x00;
1260 
1261 /* This command can be used to loop, where 0xLL = 0x01 - 0x10
1262  * 0x01=loop once [...] 0x10=loop infinite
1263  * Commented now
1264 
1265  dest->NokiaBinary.Frame[current++]=0x05;
1266  dest->NokiaBinary.Frame[current++]=0xLL;
1267  */
1268  strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01"); current=current+2;
1269 
1270  for (i=0; i<src->NoteTone.NrCommands; i++) {
1271  if (src->NoteTone.Commands[i].Type != RING_Note) continue;
1272 
1273  Note = &src->NoteTone.Commands[i].Note;
1274  note = 64; /* Pause */
1275  if (Note->Note!=Note_Pause) {
1276  if (Note->Note >= Note_C && Note->Note <= Note_H) {
1277  note = 113 + Note->Note/16;
1278  }
1279  switch (Note->Scale) {
1280  case Scale_440 : break;
1281  case Scale_880 : note = note + 12; break;
1282  case Scale_1760: note = note + 24; break;
1283  case Scale_3520: note = note + 36; break;
1284  default : break;
1285  }
1286  }
1287 
1288  /* In 7110 we have 8 ms long sounds */
1289  duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256;
1290 
1291  switch (Note->Style) {
1292  case StaccatoStyle:
1293  if (duration) {
1294  /* Note needs only one sound */
1295  dest->NokiaBinary.Frame[current++] = note;
1296  dest->NokiaBinary.Frame[current++] = 1;
1297  duration--;
1298  }
1299  note = 0x40; /* The rest is pause */
1300  case NaturalStyle:
1301  if (note != 0x40 && duration) {
1302  dest->NokiaBinary.Frame[current++] = 0x40;
1303  /* There is small pause between notes */
1304  dest->NokiaBinary.Frame[current++] = 1;
1305  duration--;
1306  }
1307  default:
1308  if (note != 0x40 && note == lastnote && duration) {
1309  dest->NokiaBinary.Frame[current++] = 0x40;
1310  /* There is small pause between same notes */
1311  dest->NokiaBinary.Frame[current++] = 1;
1312  duration--;
1313  }
1314  while (duration > 125) {
1315  dest->NokiaBinary.Frame[current++] = note;
1316  dest->NokiaBinary.Frame[current++] = 125;
1317  duration -= 125;
1318  }
1319  dest->NokiaBinary.Frame[current++] = note;
1320  dest->NokiaBinary.Frame[current++] = duration;
1321  }
1322  lastnote = note;
1323  }
1324  for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i];
1325  dest->NokiaBinary.Length=current;
1326 }
GSM_RingCommand Commands[GSM_MAX_RINGTONE_NOTES]
GSM_RingNoteNote Note
GSM_RingNoteScale Scale
GSM_RingCommandType Type
GSM_NoteRingtone NoteTone
GSM_RingNoteStyle Style
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
Definition: gsmring.c:76
GSM_RingNote Note

§ savebin()

static GSM_Error savebin ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 169 of file gsmring.c.

References chk_fwrite, DecodeUnicodeString(), ERR_NONE, ERR_WRITING_FILE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, GSM_Ringtone::Name, and GSM_Ringtone::NokiaBinary.

Referenced by GSM_SaveRingtoneFile().

170 {
171  char nullchar=0x00;
172 
173  chk_fwrite(&nullchar,1,1,file);
174  chk_fwrite(&nullchar,1,1,file);
175  fprintf(file,"\x0C\x01\x2C");
176  fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
177  chk_fwrite(&nullchar,1,1,file);
178  chk_fwrite(&nullchar,1,1,file);
179  chk_fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
180  return ERR_NONE;
181 fail:
182  return ERR_WRITING_FILE;
183 }
unsigned char Name[(GSM_MAX_RINGTONE_NAME_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ savemmf()

static GSM_Error savemmf ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 193 of file gsmring.c.

References chk_fwrite, ERR_NONE, ERR_WRITING_FILE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, and GSM_Ringtone::NokiaBinary.

Referenced by GSM_SaveRingtoneFile().

194 {
195  chk_fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
196  return ERR_NONE;
197 fail:
198  return ERR_WRITING_FILE;
199 }
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ savepuremidi()

static GSM_Error savepuremidi ( FILE *  file,
GSM_Ringtone ringtone 
)
static

Definition at line 185 of file gsmring.c.

References chk_fwrite, ERR_NONE, ERR_WRITING_FILE, GSM_NokiaBinaryRingtone::Frame, GSM_NokiaBinaryRingtone::Length, and GSM_Ringtone::NokiaBinary.

Referenced by GSM_SaveRingtoneFile().

186 {
187  chk_fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
188  return ERR_NONE;
189 fail:
190  return ERR_WRITING_FILE;
191 }
GSM_NokiaBinaryRingtone NokiaBinary
unsigned char Frame[50000]
#define chk_fwrite(data, size, count, file)
Definition: gsmring.c:37

§ WriteVarLen()

static void WriteVarLen ( unsigned char *  midifile,
size_t *  current,
long  value 
)
static

Definition at line 390 of file gsmring.c.

Referenced by GSM_SaveRingtoneMidi().

391 {
392  long buffer;
393 
394  buffer = value & 0x7f;
395 
396  while (value >>= 7) {
397  buffer <<= 8;
398  buffer |= 0x80;
399  buffer += (value & 0x7f);
400  }
401 
402  while (1) {
403  midifile[(*current)++] = (unsigned char)buffer;
404  if (buffer & 0x80) {
405  buffer >>= 8;
406  } else {
407  break;
408  }
409  }
410 }

Variable Documentation

§ SM_BeatsPerMinute

int SM_BeatsPerMinute[]
static
Initial value:
= {
25, 28, 31, 35, 40, 45, 50, 56, 63, 70,
80, 90, 100, 112, 125, 140, 160, 180, 200, 225,
250, 285, 320, 355, 400, 450, 500, 565, 635, 715,
800, 900
}

Definition at line 972 of file gsmring.c.

Referenced by GSM_DecodeNokiaRTTLRingtone(), and GSM_RTTLGetTempo().