Improve imelody related code 57/278757/14
authorminje.ahn <minje.ahn@samsung.com>
Tue, 26 Jul 2022 01:52:34 +0000 (10:52 +0900)
committerMinje ahn <minje.ahn@samsung.com>
Mon, 8 Aug 2022 23:13:10 +0000 (23:13 +0000)
Modified to calculate the duration of imelody directly without converting it to midi format.

Change-Id: Id656ebebbeb4191fbe676b35346efc44b1f055f8
Signed-off-by: minje.ahn <minje.ahn@samsung.com>
formats/ffmpeg/mm_file_format_imelody.c

index 3dab94e48f6c1b68e15b74c29a6b7da9d78360ab..5d854e90e65f4638806eace2583327ff887370c3 100755 (executable)
  *
  */
 
-#include <stdio.h>
-#include <string.h>    /*memcmp*/
-#include <stdlib.h>    /*malloc*/
-
 #include "mm_file_debug.h"
 #include "mm_file_utils.h"
 #include "mm_file_format_private.h"
 #include "mm_file_format_imelody.h"
-#include "mm_file_format_midi.h"
 
 /**
  * Define
  */
-#define AV_MIDI_COUNT_MAX              1600
-#define AV_MIDI_NOTE_MAX               256
-#define AV_MIDI_VOL_MAX                        250
-#define MIDI_LIMIT                             127
-#define MIDI_MAX                               255
-
-#define VOL_INTERVAL                   12
-
-#define MIDI_HEADER_LENGTH             52
-
-#define IMY_KEY_STYLE "STYLE:S"
 #define IMY_KEY_BEAT "BEAT:"
-#define IMY_KEY_VOLUME "VOLUME:V"
 #define IMY_KEY_NAME "NAME:"
 #define IMY_KEY_COMPOSER "COMPOSER:"
 #define IMY_KEY_COPYRIGHT "COPYRIGHT:"
 #define IMY_KEY_MELODY "MELODY:"
 
-static unsigned char midiData[AV_MIDI_COUNT_MAX] ;
-static unsigned char midiHeader[MIDI_HEADER_LENGTH] = {0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, 0x4d, 0x54,
-                                                                                                       0x72, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x58, 0x04, 0x04, 0x02, 0x18, 0x08, 0x00, 0xff,
-                                                                                                       0x59, 0x02, 0x00, 0x00, 0x00, 0xff, 0x51, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xb0,
-                                                                                                       0x07, 0x00, 0x00, 0x90
-                                                                                                       };
-
-
-static unsigned char noteTotal[AV_MIDI_COUNT_MAX];
-static char octave[AV_MIDI_NOTE_MAX];
-static int durationSpec[AV_MIDI_NOTE_MAX];
-static int restSpec[AV_MIDI_NOTE_MAX];
-
-static struct {
-       char flat_sharp;
-       char note;
-       char duration;
-       char duration_specifier;
-       char rest;
-       char rest_specifier;
-       char vol;
-} Melody[AV_MIDI_NOTE_MAX];
-
-static struct {
-       int note;
-       int duration_on;
-       int duration_off;
-} noteData[AV_MIDI_NOTE_MAX];
-
 /*imelody key string (to validatation check)*/
 static const char *g_imy_key_str[] = {
        "BEGIN:IMELODY",
@@ -145,801 +99,179 @@ failed:
        return NULL;
 }
 
-static unsigned char __AvMIDISetVolume(const char *pMelodyBuf)
-{
-       /* Format - VOLUME:V## (V0 to V15, Optional) */
-       char *found = strstr(pMelodyBuf, IMY_KEY_VOLUME);
-       /* Default [AV_MIDI_VOL_MAX] */
-       unsigned char vol = AV_MIDI_VOL_MAX;
-
-       if (found && *(found + strlen(IMY_KEY_VOLUME)) == '0')
-                       vol = 0;
-
-       return vol;
-}
-
-static int __AvMIDISetBeat(const char *pMelodyBuf)
+static int __bpm_to_tempo(const char *pMelodyBuf)
 {
        /* Format - BEAT:### (Optional) */
        char *found = strstr(pMelodyBuf, IMY_KEY_BEAT);
        /* Default [120] */
-       char *beatValue = NULL;
+       char *bpm_str = NULL;
        int bpm = 120;
-       int beat = 0;
 
        if (found) {
-               beatValue = g_strndup(found + strlen(IMY_KEY_BEAT), 3);
+               bpm_str = g_strndup(found + strlen(IMY_KEY_BEAT), 3);
                /* No need to check integer bound */
-               bpm = atoi(beatValue);
-               g_free(beatValue);
+               bpm = atoi(bpm_str);
+               g_free(bpm_str);
                if (bpm < 25 || bpm > 900)
                        bpm = 120;
        }
 
-       beat = 1000000 * 60 / bpm;
-       debug_msg(RELEASE, "beat: %d\n", beat);
-
-       return beat;
+       return 60 * 1000 / bpm;
 }
 
-static char __AvMIDISetStyle(const char *pMelodyBuf)
+static char * __remove_effect(const char *full_melody)
 {
-       /* Format - STYLE:S# (S0 to S2, Optional) */
-       char *found = strstr(pMelodyBuf, IMY_KEY_STYLE);
-       char style = '0';
-
-       if (found)
-               style = *(found + strlen(IMY_KEY_STYLE));
-
-       if (style != '0' && style != '1' && style != '2')
-               style = '0';
-
-       debug_msg(RELEASE, "style: '%c'\n", style);
-
-       return style;
-}
+       gsize i = 0;
+       GString *result = NULL;
 
-static void __init_imelody_data(void)
-{
-       int idx = 0;
-
-       for (idx = 0; idx < AV_MIDI_NOTE_MAX; idx++) {
-               restSpec[idx] = 0;
-               durationSpec[idx] = 0;
-       }
-
-       for (idx = 0; idx < AV_MIDI_NOTE_MAX; idx++)
-               octave[idx] = '%';
-
-       for (idx = 0; idx < AV_MIDI_NOTE_MAX; idx++) {
-               Melody[idx].flat_sharp = '%';
-               Melody[idx].note = '%';
-               Melody[idx].duration = '%';
-               Melody[idx].duration_specifier = '%';
-               Melody[idx].rest = '%';
-               Melody[idx].rest_specifier = '%';
-               Melody[idx].vol = '%';
-       }
-
-       for (idx = 0; idx < AV_MIDI_NOTE_MAX; idx++) {
-               noteData[idx].note = 0;
-               noteData[idx].duration_on = 0;
-               noteData[idx].duration_off = 0;
-       }
-
-       memset(midiData, 0, sizeof(midiData));
-       memcpy(midiData, midiHeader, MIDI_HEADER_LENGTH);
-}
+       if (!full_melody)
+               return NULL;
 
-static void __get_imelody_duration(char style, int number)
-{
-       if (style == '0') {
-               switch (Melody[number].duration) {
-               case '0':
-                       noteData[number].duration_on = 183;
-                       noteData[number].duration_off = 9;
-                       break;
-               case '1':
-                       noteData[number].duration_on = 91;
-                       noteData[number].duration_off = 5;
-                       break;
-               case '2':
-                       noteData[number].duration_on = 46;
-                       noteData[number].duration_off = 2;
-                       break;
-               case '3':
-                       noteData[number].duration_on = 23;
-                       noteData[number].duration_off = 1;
-                       break;
-               case '4':
-                       noteData[number].duration_on = 11;
-                       noteData[number].duration_off = 1;
-                       break;
-               case '5':
-                       noteData[number].duration_on = 5;
-                       noteData[number].duration_off = 1;
-                       break;
-               default:
-                       break;
-               }
-       } else if (style == '1') {
-               switch (Melody[number].duration) {
-               case '0':
-                       noteData[number].duration_on = 192;
-                       noteData[number].duration_off = 0;
-                       break;
-               case '1':
-                       noteData[number].duration_on = 96;
-                       noteData[number].duration_off = 0;
-                       break;
-               case '2':
-                       noteData[number].duration_on = 48;
-                       noteData[number].duration_off = 0;
-                       break;
-               case '3':
-                       noteData[number].duration_on = 24;
-                       noteData[number].duration_off = 0;
-                       break;
-               case '4':
-                       noteData[number].duration_on = 12;
-                       noteData[number].duration_off = 0;
-                       break;
-               case '5':
-                       noteData[number].duration_on = 6;
-                       noteData[number].duration_off = 0;
-                       break;
-               default:
-                       break;
-               }
-       } else {
-               switch (Melody[number].duration) {
-               case '0':
-                       noteData[number].duration_on = 96;
-                       noteData[number].duration_off = 96;
-                       break;
-               case '1':
-                       noteData[number].duration_on = 48;
-                       noteData[number].duration_off = 48;
-                       break;
-               case '2':
-                       noteData[number].duration_on = 24;
-                       noteData[number].duration_off = 24;
-                       break;
-               case '3':
-                       noteData[number].duration_on = 12;
-                       noteData[number].duration_off = 12;
-                       break;
-               case '4':
-                       noteData[number].duration_on = 6;
-                       noteData[number].duration_off = 6;
-                       break;
-               case '5':
-                       noteData[number].duration_on = 3;
-                       noteData[number].duration_off = 3;
-                       break;
-               default:
-                       break;
+       result = g_string_new(full_melody);
+
+       /*Removed unnecessary values for duration calculations.*/
+       g_string_replace(result, "ledon", "", 0);
+       g_string_replace(result, "ledoff", "", 0);
+       g_string_replace(result, "vibeon", "", 0);
+       g_string_replace(result, "vibeoff", "", 0);
+       g_string_replace(result, "backon", "", 0);
+       g_string_replace(result, "backoff", "", 0);
+       g_string_replace(result, "#", "", 0);
+       g_string_replace(result, "&", "", 0);
+       g_string_replace(result, "(", "", 0);
+       g_string_replace(result, ")", "", 0);
+
+       while (i < result->len) {
+               if (result->str[i] == 'S' || result->str[i] == 'V' || result->str[i] == '@' || result->str[i] == '*') {
+                       if ((i + 2 < result->len) && (g_ascii_digit_value(result->str[i + 2]) != -1))
+                               result = g_string_erase(result, i, 3);
+                       else
+                               result = g_string_erase(result, i, 2);
+               } else {
+                       i++;
                }
        }
+       debug_msg(RELEASE, "melody : [%s] \n", result->str);
 
-       switch (Melody[number].duration) {
-       case '0':
-               durationSpec[number] = 192;
-               break;
-       case '1':
-               durationSpec[number] = 96;
-               break;
-       case '2':
-               durationSpec[number] = 48;
-               break;
-       case '3':
-               durationSpec[number] = 24;
-               break;
-       case '4':
-               durationSpec[number] = 12;
-               break;
-       case '5':
-               durationSpec[number] = 6;
-               break;
-       default:
-               break;
-       }
-
-       if (Melody[number].duration_specifier != '%') {
-               switch (Melody[number].duration_specifier) {
-               case '.':
-                       noteData[number].duration_on += (durationSpec[number] / 2);
-                       break;
-               case ':':
-                       noteData[number].duration_on += durationSpec[number];
-                       break;
-               case ';':
-                       noteData[number].duration_on -= (durationSpec[number] / 3);
-                       break;
-               default:
-                       break;
-               }
-
-               if (noteData[number].duration_on > MIDI_MAX)
-                       noteData[number].duration_on = MIDI_LIMIT;
-       }
+       return g_string_free(result, FALSE);
 }
 
-static void __get_imelody_melody(int number, int octaveValue)
+static gchar * __get_melody(const char *buf)
 {
-       if (Melody[number].flat_sharp == '#') {
-               switch (Melody[number].note) {
-               case 'c':
-                       noteData[number].note = octaveValue + 1;
-                       break;
-               case 'd':
-                       noteData[number].note = octaveValue + 3;
-                       break;
-               case 'f':
-                       noteData[number].note = octaveValue + 6;
-                       break;
-               case 'g':
-                       noteData[number].note = octaveValue + 8;
-                       break;
-               case 'a':
-                       noteData[number].note = octaveValue + 10;
-                       break;
-               default:
-                       break;
-               }
-       } else if (Melody[number].flat_sharp == '&') {
-               switch (Melody[number].note) {
-               case 'd':
-                       noteData[number].note = octaveValue + 1;
-                       break;
-               case 'e':
-                       noteData[number].note = octaveValue + 3;
-                       break;
-               case 'g':
-                       noteData[number].note = octaveValue + 6;
-                       break;
-               case 'a':
-                       noteData[number].note = octaveValue + 8;
-                       break;
-               case 'b':
-                       noteData[number].note = octaveValue + 10;
-                       break;
-               default:
-                       break;
-               }
-       } else {
-               switch (Melody[number].note) {
-               case 'c':
-                       noteData[number].note = octaveValue;
-                       break;
-               case 'd':
-                       noteData[number].note = octaveValue + 2;
-                       break;
-               case 'e':
-                       noteData[number].note = octaveValue + 4;
-                       break;
-               case 'f':
-                       noteData[number].note = octaveValue + 5;
-                       break;
-               case 'g':
-                       noteData[number].note = octaveValue + 7;
-                       break;
-               case 'a':
-                       noteData[number].note = octaveValue + 9;
-                       break;
-               case 'b':
-                       noteData[number].note = octaveValue + 11;
-                       break;
-               default:
-                       break;
-               }
-       }
-}
+       gchar **tmp = NULL;
+       gchar *melody = NULL;
+       char *result = NULL;
 
-static void __get_imelody_reset(int number)
-{
-       if (Melody[number].rest >= '0' && Melody[number].rest <= '5') {
-               switch (Melody[number].rest) {
-               case '0':
-                       noteData[number - 1].duration_off += 192;
-                       restSpec[number] = 192;
-                       break;
-               case '1':
-                       noteData[number - 1].duration_off += 96;
-                       restSpec[number] = 96;
-                       break;
-               case '2':
-                       noteData[number - 1].duration_off += 48;
-                       restSpec[number] = 48;
-                       break;
-               case '3':
-                       noteData[number - 1].duration_off += 24;
-                       restSpec[number] = 24;
-                       break;
-               case '4':
-                       noteData[number - 1].duration_off += 12;
-                       restSpec[number] = 12;
-                       break;
-               case '5':
-                       noteData[number - 1].duration_off += 6;
-                       restSpec[number] = 6;
-                       break;
-               default:
-                       break;
-               }
+       if (!buf)
+               return NULL;
 
-               if (noteData[number - 1].duration_off > MIDI_MAX && Melody[number].rest_specifier == '%')
-                       noteData[number - 1].duration_off = MIDI_LIMIT;
-       }
+       tmp = g_strsplit(buf, IMY_KEY_MELODY, -1);
+       if (g_strv_length(tmp) == 2)
+               melody = g_strdup(tmp[1]);
 
-       if (Melody[number].rest_specifier != '%') {
-               switch (Melody[number].rest_specifier) {
-               case '.':
-                       noteData[number - 1].duration_off += (restSpec[number] / 2);
-                       break;
-               case ':':
-                       noteData[number - 1].duration_off += restSpec[number];
-                       break;
-               case ';':
-                       noteData[number - 1].duration_off -= (restSpec[number] / 3);
-                       break;
-               default:
-                       break;
-               }
+       g_strfreev(tmp);
+       tmp = NULL;
 
-               if (noteData[number - 1].duration_off > MIDI_MAX)
-                       noteData[number - 1].duration_off = MIDI_LIMIT;
+       if (melody) {
+               tmp = g_strsplit(melody, "\n", -1);
+               g_free(melody);
+               melody = NULL;
        }
-}
-
-static void __get_imelody_notetotal(int number)
-{
-       char noteBase[6];
-
-       memset(noteBase, 0, sizeof(noteBase));
-
-       noteBase[0] = noteData[number].note;
-       noteBase[2] = noteData[number].duration_on;
-       noteBase[3] = noteData[number].note;
-       noteBase[5] = noteData[number].duration_off;
 
-       noteTotal[6 * number] = noteBase[0];
-       noteTotal[6 * number + 2] = noteBase[2];
-       noteTotal[6 * number + 3] = noteBase[3];
-       noteTotal[6 * number + 5] = noteBase[5];
-       noteTotal[6 * number + 4] = 0;
+       if (tmp) {
+               melody = g_strdup(tmp[0]);
+               g_strfreev(tmp);
+       }
 
-       if (noteTotal[6 * number + 2] > MIDI_LIMIT)
-               noteTotal[6 * number + 2] = MIDI_LIMIT;
+       result = __remove_effect(melody);
+       g_free(melody);
 
-       if (noteTotal[6 * number + 5] > MIDI_LIMIT)
-               noteTotal[6 * number + 5] = MIDI_LIMIT;
+       return result;
 }
 
-static unsigned char * __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen)
+static int __calculate_duration(const char *melody, int tempo)
 {
-       /* Duration measures the length of one play. So no need extract REPEAT keyword */
-       char *pStart = pMelodyBuf;
-       char *pMelodyStart;
-       int octaveCount;
-       int octaveValue;
-       int count;
-       int noteCount = 0;
-       int number;
-       int numberCount;
-       char style = '0';
-       int tempoData[3];
-       int tempoValue;
-       int trackSize;
-       int repeatCount = 0;
-
-       __init_imelody_data();
-
-       midiData[49] = __AvMIDISetVolume(pStart);
-       tempoValue = __AvMIDISetBeat(pStart);
-       style = __AvMIDISetStyle(pStart);
-
-       for (number = 0; tempoValue != 0; number++) {
-               tempoData[0] = tempoValue % 16;
-               tempoValue = tempoValue / 16;
-
-               tempoData[1] = tempoValue % 16;
-               tempoValue = tempoValue / 16;
-
-               tempoData[2] = tempoData[0] + tempoData[1] * 16;
-
-               midiData[42 - number] = tempoData[2];
-       }
-
-       /* Find MELODY */
-       pStart = strstr(pMelodyBuf, IMY_KEY_MELODY) + strlen(IMY_KEY_MELODY);
-
-       /*Melody start point */
-       pMelodyStart = pStart;
-
-       /**@note if newline detected, stop reading
-        *       why? mobileBAE player stopped at newline.
-        *       2009/08/12
-        */
-       while (!((*pStart == 'E' && *(pStart + 2) == 'D') || (*pStart == '\n'))) {
-               if (noteCount >= AV_MIDI_NOTE_MAX) {
-                       debug_warning(DEBUG, "__AvConvertIMelody2MIDI : noteCount>=AV_MIDI_NOTE_MAX\n");
-                       break;
-               }
+       int len = 0;
+       int i = 1;
+       float sum = 0.0;
+       float duration = 0.0;
+       bool is_specifier = false;
 
-               pStart++;
+       if (!melody || tempo == 0)
+               return 0;
 
-               if (*pStart == '*') {
-                       pStart++;
-
-                       if (*pStart >= '0' && *pStart <= '8')
-                               octave[noteCount] = *pStart;
-               }
-
-               if (*pStart == '#' || *pStart == '&')
-                       Melody[noteCount].flat_sharp = *pStart;
-
-               if (*pStart == 'r') {
-                       pStart++;
-
-                       if (*pStart >= '0' && *pStart <= '5') {
-                               Melody[noteCount].rest = *pStart;
-                               pStart++;
-
-                               if (*pStart == '.' || *pStart == ':' || *pStart == ';')
-                                       Melody[noteCount].rest_specifier = *pStart;
-                       }
-               }
+       len = strlen(melody);
 
-               if (*pStart == 'V') {
-                       pStart++;
-
-                       if (*pStart == '+' || *pStart == '-')
-                               Melody[noteCount].vol = *pStart;
-               }
-
-               if (*pStart >= 'a' && *pStart <= 'g') {
-                       Melody[noteCount].note = *pStart;
-                       pStart++;
-
-                       if (*pStart >= '0' && *pStart <= '5') {
-                               Melody[noteCount].duration = *pStart;
-                               pStart++;
-
-                               if (*pStart == '.' || *pStart == ':' || *pStart == ';')
-                                       Melody[noteCount].duration_specifier = *pStart;
-                               else
-                                       pStart--;
-
-                               noteCount++;
-                       }
-               }
-       }
-
-       for (octaveCount = 1; octaveCount < noteCount; octaveCount++) {
-               if (octave[octaveCount] == '%')
-                       octave[octaveCount] = octave[octaveCount - 1];
-       }
-
-       for (number = 0; number < noteCount; number++) {
-               if (octave[0] == '%' && octave[number] == '%')
-                       octaveValue = 4;
-
-               else
-                       octaveValue = octave[number] - '0';
-
-               octaveValue = octaveValue * 12;
-
-               __get_imelody_melody(number, octaveValue);
-       }
-
-       pStart = pMelodyStart;
-
-       for (number = 0; number < noteCount; number++)
-               __get_imelody_duration(style, number);
-
-       for (number = 1; number < noteCount; number++)
-               __get_imelody_reset(number);
-
-       if (Melody[0].rest >= '0' && Melody[0].rest <= '5') {
-               switch (Melody[0].rest) {
+       while (i < len) {
+               switch(melody[i]) {
                case '0':
-                       midiData[50] += 192;
-                       restSpec[0] = 192;
+                       duration = 4;
                        break;
                case '1':
-                       midiData[50] += 96;
-                       restSpec[0] = 96;
+                       duration = 2;
                        break;
                case '2':
-                       midiData[50] += 48;
-                       restSpec[0] = 48;
+                       duration = 1;
                        break;
                case '3':
-                       midiData[50] += 24;
-                       restSpec[0] = 24;
+                       duration = 0.5;
                        break;
                case '4':
-                       midiData[50] += 12;
-                       restSpec[0] = 12;
+                       duration = 0.25;
                        break;
                case '5':
-                       midiData[50] += 6;
-                       restSpec[0] = 6;
+                       duration = 0.125;
                        break;
                default:
+                       duration = 0;
                        break;
                }
 
-               if (Melody[0].rest_specifier != '%') {
-                       switch (Melody[0].rest_specifier) {
-                       case '.':
-                               midiData[50] += (restSpec[0] / 2);
-                               break;
-                       case ':':
-                               midiData[50] += restSpec[0];
-                               break;
-                       case ';':
-                               midiData[50] -= (restSpec[0] / 3);
-                               break;
-                       default:
-                               break;
-                       }
-               }
-
-               if (midiData[50] > MIDI_LIMIT)
-                       midiData[50] = MIDI_LIMIT;
-
-               if (Melody[0].rest == '0')
-                       midiData[50] = MIDI_LIMIT;
-       }
-
-       for (number = 0; number < noteCount; number++)
-               __get_imelody_notetotal(number);
-
-       for (number = 1; number < noteCount; number++) {
-               noteTotal[1] = 84;
-
-               if (Melody[0].vol == '+')
-                       noteTotal[1] = 84 + VOL_INTERVAL;
-
-               if (Melody[0].vol == '-')
-                       noteTotal[1] = 84 - VOL_INTERVAL;
-
-               switch (Melody[number].vol) {
-               case '+':
-                       noteTotal[6 * number + 1] = noteTotal[6 * (number - 1) + 1] + VOL_INTERVAL;
-                       break;
-               case '-':
-                       noteTotal[6 * number + 1] = noteTotal[6 * (number - 1) + 1] - VOL_INTERVAL;
-                       break;
-               default:
-                       break;
+               if (i + 1 >= len)
+                       goto FINALIZE;
+
+               if (melody[i + 1] == '.') {
+                       is_specifier = true;
+                       sum += duration;
+                       duration *= 0.5;
+               } else if (melody[i + 1] == ':') {
+                       is_specifier = true;
+                       sum += duration;
+                       duration *= 0.5;
+                       sum += duration;
+                       duration *= 0.5;
+               } else if (melody[i + 1] == ';') {
+                       is_specifier = true;
+                       duration *= 2.0 / 3.0;
                }
 
-               if (noteTotal[6 * number + 1] > MIDI_LIMIT)
-                       noteTotal[6 * number + 1] = MIDI_LIMIT;
-
-               if ((noteTotal[6 * (number - 1) + 1] == 0 || noteTotal[6 * (number - 1) + 1] == 7) && Melody[number].vol == '-')
-                       noteTotal[6 * number + 1] = 0;
-
-               if (Melody[number].vol == '%')
-                       noteTotal[6 * number + 1] = noteTotal[6 * (number - 1) + 1];
-       }
-
-       for (number = 0; number < 6 * noteCount; number++)
-               midiData[52 + number] = noteTotal[number];
-
-       for (number = 6 * noteCount; number < 6 * noteCount; number++) {
-               noteTotal[number] = noteTotal[repeatCount];
-               midiData[52 + number] = noteTotal[number];
-               repeatCount++;
-
-               if (repeatCount == 6 * noteCount)
-                       repeatCount = 0;
+FINALIZE:
+               sum += duration;
+               i += (is_specifier) ? 3 : 2;
+               is_specifier = false;
        }
 
-       for (number = 1; number < 6 * noteCount; number = number + 6) {
-               if (midiData[52 + number] > MIDI_LIMIT)
-                       midiData[52 + number] = MIDI_LIMIT;
-       }
-
-       pStart = pMelodyStart;
-       count = noteCount;
-
-       if (*pStart != 'E' && *pStart != ':') {
-               pStart--;
-
-               while (*pStart != 'E') {
-                       if (noteCount >= AV_MIDI_NOTE_MAX) {
-                               debug_warning(DEBUG, "__AvConvertIMelody2MIDI : noteCount>=AV_MIDI_NOTE_MAX\n");
-                               break;
-                       }
-
-                       pStart++;
-
-                       if (*pStart == '*') {
-                               pStart++;
-
-                               if (*pStart >= '0' && *pStart <= '8')
-                                       octave[noteCount] = *pStart;
-                       }
-
-                       if (*pStart == '#' || *pStart == '&')
-                               Melody[noteCount].flat_sharp = *pStart;
-
-                       if (*pStart == 'r') {
-                               pStart++;
-
-                               if (*pStart >= '0' && *pStart <= '5') {
-                                       Melody[noteCount].rest = *pStart;
-                                       pStart++;
-
-                                       if (*pStart == '.' || *pStart == ':' || *pStart == ';')
-                                               Melody[noteCount].rest_specifier = *pStart;
-                               }
-                       }
-
-                       if (*pStart == 'V') {
-                               pStart++;
-
-                               if (*pStart == '+' || *pStart == '-')
-                                       Melody[noteCount].vol = *pStart;
-                       }
-
-                       if (*pStart >= 'a' && *pStart <= 'g') {
-                               Melody[noteCount].note = *pStart;
-                               pStart++;
-
-                               if (*pStart >= '0' && *pStart <= '5') {
-                                       Melody[noteCount].duration = *pStart;
-                                       pStart++;
-
-                                       if (*pStart == '.' || *pStart == ':' || *pStart == ';')
-                                               Melody[noteCount].duration_specifier = *pStart;
-
-                                       else
-                                               pStart--;
-
-                                       noteCount++;
-                               }
-                       }
-               }
-
-               for (octaveCount = count; octaveCount < noteCount && octaveCount < AV_MIDI_NOTE_MAX; octaveCount++) {
-                       if (octave[octaveCount] == '%')
-                               octave[octaveCount] = octave[octaveCount - 1];
-               }
-
-               for (number = count; number < noteCount && number < AV_MIDI_NOTE_MAX; number++) {
-                       octaveValue = octave[number] - '0';
-
-                       octaveValue = octaveValue * 12;
-
-                       __get_imelody_melody(number, octaveValue);
-                       __get_imelody_duration(style, number);
-               }
-
-               for (number = count + 1; number < noteCount && number < AV_MIDI_NOTE_MAX; number++)
-                       __get_imelody_reset(number);
-
-               if (Melody[count].rest >= '0' && Melody[count].rest <= '5') {
-                       switch (Melody[count].rest) {
-                       case '0':
-                               midiData[52 + (6 * count - 1)] += 192;
-                               restSpec[count] = 192;
-                               break;
-                       case '1':
-                               midiData[52 + (6 * count - 1)] += 96;
-                               restSpec[count] = 96;
-                               break;
-                       case '2':
-                               midiData[52 + (6 * count - 1)] += 48;
-                               restSpec[count] = 48;
-                               break;
-                       case '3':
-                               midiData[52 + (6 * count - 1)] += 24;
-                               restSpec[count] = 24;
-                               break;
-                       case '4':
-                               midiData[52 + (6 * count - 1)] += 12;
-                               restSpec[count] = 12;
-                               break;
-                       case '5':
-                               midiData[52 + (6 * count - 1)] += 6;
-                               restSpec[count] = 6;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       if (Melody[count].rest_specifier != '%') {
-                               switch (Melody[count].rest_specifier) {
-                               case '.':
-                                       midiData[52 + (6 * count - 1)] += (restSpec[count] / 2);
-                                       break;
-                               case ':':
-                                       midiData[52 + (6 * count - 1)] += restSpec[count];
-                                       break;
-                               case ';':
-                                       midiData[52 + (6 * count - 1)] -= (restSpec[count] / 3);
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
-
-                       if (midiData[52 + (6 * count - 1)] > MIDI_LIMIT)
-                               midiData[52 + (6 * count - 1)] = MIDI_LIMIT;
-
-                       if (Melody[count].rest == '0')
-                               midiData[52 + (6 * count - 1)] = MIDI_LIMIT;
-               }
-
-               for (number = count; number < noteCount; number++)
-                       __get_imelody_notetotal(number);
-
-               for (number = count + 1; number < noteCount; number++) {
-                       noteTotal[6 * count + 1] = midiData[52 + (6 * count - 5)];
-
-                       if (Melody[count].vol == '+')
-                               noteTotal[6 * count + 1] = noteTotal[6 * count + 1] + VOL_INTERVAL;
-
-                       if (Melody[count].vol == '-' && (noteTotal[6 * count + 1] == 0 || noteTotal[6 * count + 1] == 7))
-                               noteTotal[6 * count + 1] = 0;
-
-                       if (Melody[count].vol == '-' && noteTotal[6 * count + 1] >= 12)
-                               noteTotal[6 * count + 1] = noteTotal[6 * count + 1] - VOL_INTERVAL;
-
-                       if (noteTotal[6 * count + 1] > MIDI_LIMIT)
-                               noteTotal[6 * count + 1] = MIDI_LIMIT;
-
-                       switch (Melody[number].vol) {
-                       case '+':
-                               noteTotal[6 * number + 1] = noteTotal[6 * (number - 1) + 1] + VOL_INTERVAL;
-                               break;
-                       case '-':
-                               noteTotal[6 * number + 1] = noteTotal[6 * (number - 1) + 1] - VOL_INTERVAL;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       if (noteTotal[6 * number + 1] > MIDI_LIMIT)
-                               noteTotal[6 * number + 1] = MIDI_LIMIT;
-
-                       if ((noteTotal[6 * (number - 1) + 1] == 0 || noteTotal[6 * (number - 1) + 1] == 7) && Melody[number].vol == '-')
-                               noteTotal[6 * number + 1] = 0;
+       return (int)(sum * tempo);
+}
 
-                       if (Melody[number].vol == '%')
-                               noteTotal[6 * number + 1] = noteTotal[6 * (number - 1) + 1];
-               }
+static int __AvGetDuration(const char *pMelodyBuf)
+{
+       char *melody_part = NULL;
+       int tempo = 0;
+       int result = 0;
 
-               numberCount = 6 * count;
+       if (!pMelodyBuf)
+               return 0;
 
-               for (number = 6 * count; number < 6 * (count + (noteCount - count)); number++) {
-                       midiData[52 + number] = noteTotal[numberCount];
-                       numberCount++;
-               }
+       tempo = __bpm_to_tempo(pMelodyBuf);
+       debug_msg(RELEASE, "tempo : %d ms\n", tempo);
+       melody_part = __get_melody(pMelodyBuf);
+       if (melody_part) {
+               result = __calculate_duration(melody_part, tempo);
+               g_free(melody_part);
        }
 
-       noteTotal[6 * (count + (noteCount - count))] = 0;                               /*0x00 */
-       noteTotal[6 * (count + (noteCount - count)) + 1] = MIDI_MAX;            /*0xff */
-       noteTotal[6 * (count + (noteCount - count)) + 2] = 47;                  /*0x2f */
-       noteTotal[6 * (count + (noteCount - count)) + 3] = 0;                   /*0x00 */
-
-       for (number = 6 * (count + (noteCount - count)); number <= 6 * (count + (noteCount - count)) + 3; number++)
-               midiData[51 + number] = noteTotal[number];
-
-       trackSize = (6 * (count + (noteCount - count)) + 56) - 22 - 1 ;
-
-       midiData[20] = (trackSize & 0xff00) >> 8;
-       midiData[21] = (trackSize & 0x00ff);
-
-
-       *pBufLen = 6 * (count + (noteCount - count)) + 56 - 1;
-
-       return g_memdup2(midiData, *pBufLen);
+       return result;
 }
 
 static int __get_imelody_tag(const char *uriname, tMMFileImelodyTagInfo *tags)
@@ -1010,14 +342,10 @@ int mmfile_format_open_imy(MMFileFormatContext *formatContext)
 
 int mmfile_format_read_stream_imy(MMFileFormatContext *formatContext)
 {
-       MIDI_INFO_SIMPLE *info = NULL;
        MMFileFormatStream  *audioStream = NULL;
 
        unsigned char   *imy = NULL;
        int                             imy_size = 0;
-       unsigned char   *midi = NULL;
-       unsigned int    midi_size = 0;
-       char                    src2[MMFILE_URI_MAX_LEN];
 
        mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
 
@@ -1032,23 +360,11 @@ int mmfile_format_read_stream_imy(MMFileFormatContext *formatContext)
                debug_error(DEBUG, "it's broken file.\n");
                goto exception;
        }
-       midi = __AvConvertIMelody2MIDI((char *)imy, &midi_size);
-       if (!midi) {
-               debug_error(DEBUG, "failed to convert.");
-               goto exception;
-       }
-
-       /*make uri*/
-       memset(src2, 0x00, MMFILE_URI_MAX_LEN);
-       snprintf(src2, sizeof(src2), "%s%u:%u", MMFILE_MEM_URI, (unsigned int)midi, midi_size);
-
-       /*get infomation*/
-       info = mmfile_format_get_midi_infomation(src2);
 
-       formatContext->duration = info->duration;
+       formatContext->duration = __AvGetDuration((const char *)imy);
        formatContext->videoStreamId = -1;
        formatContext->videoTotalTrackNum = 0;
-       formatContext->audioTotalTrackNum = info->track_num;
+       formatContext->audioTotalTrackNum = 1;
        formatContext->nbStreams = 1;
 
        audioStream = g_new0(MMFileFormatStream, 1);
@@ -1068,14 +384,10 @@ int mmfile_format_read_stream_imy(MMFileFormatContext *formatContext)
 #endif
 
        mmfile_free(imy);
-       mmfile_free(midi);
-       mmfile_format_free_midi_infomation(info);
        return MMFILE_FORMAT_SUCCESS;
 
 exception:
        mmfile_free(imy);
-       mmfile_free(midi);
-       mmfile_format_free_midi_infomation(info);
        mmfile_free(audioStream);
        return MMFILE_FORMAT_FAIL;
 }
@@ -1132,5 +444,4 @@ int mmfile_format_read_tag_imy(MMFileFormatContext *formatContext)
 int mmfile_format_close_imy(MMFileFormatContext *formatContext)
 {
        return MMFILE_FORMAT_SUCCESS;
-}
-
+}
\ No newline at end of file