From 1d981414c55c088c7f411159659d3b1193c1e006 Mon Sep 17 00:00:00 2001 From: Minje Ahn Date: Wed, 13 May 2020 15:08:46 +0900 Subject: [PATCH] format IMELODY cleanup Change-Id: I581d81b7b4b7043adadbf9759535721ba39c4712 Signed-off-by: Minje Ahn --- formats/ffmpeg/mm_file_format_imelody.c | 956 +++++++++++--------------------- 1 file changed, 329 insertions(+), 627 deletions(-) diff --git a/formats/ffmpeg/mm_file_format_imelody.c b/formats/ffmpeg/mm_file_format_imelody.c index d9e4298..f5ac646 100755 --- a/formats/ffmpeg/mm_file_format_imelody.c +++ b/formats/ffmpeg/mm_file_format_imelody.c @@ -42,6 +42,14 @@ #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, @@ -80,345 +88,28 @@ static const char *g_imy_key_str[] = { "END:IMELODY", }; - -static int __is_good_imelody(unsigned char *src, unsigned int size); -static unsigned char *__get_load_memory(char *src, int *out_size); -static unsigned char __AvMIDISetVolume(char *pMelodyBuf); -static int __AvMIDISetBeat(char *pMelodyBuf); -static char __AvMIDISetStyle(char *pMelodyBuf); -static unsigned char *__AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen); -static int __get_imelody_tag(const char *uriname, tMMFileImelodyTagInfo *tags); - - -/* interface functions */ -int mmfile_format_read_stream_imy(MMFileFormatContext *formatContext); -int mmfile_format_read_frame_imy(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame); -int mmfile_format_read_tag_imy(MMFileFormatContext *formatContext); -int mmfile_format_close_imy(MMFileFormatContext *formatContext); - - - -int mmfile_format_open_imy(MMFileFormatContext *formatContext) +static bool __is_good_imelody(char *src, unsigned int size) { - int ret = 0; - - if (!formatContext) { - debug_error(DEBUG, "formatContext is NULL\n"); - return MMFILE_FORMAT_FAIL; - } - - ret = MMFileFormatIsValidIMY(NULL, formatContext->uriFileName, 0); - if (ret == 0) { - debug_error(DEBUG, "It is not imelody file\n"); - return MMFILE_FORMAT_FAIL; - } - - formatContext->ReadStream = mmfile_format_read_stream_imy; - formatContext->ReadFrame = mmfile_format_read_frame_imy; - formatContext->ReadTag = mmfile_format_read_tag_imy; - formatContext->Close = mmfile_format_close_imy; - - formatContext->videoTotalTrackNum = 0; - formatContext->audioTotalTrackNum = 1; - - formatContext->privateFormatData = NULL; - - return MMFILE_FORMAT_SUCCESS; -} - - -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]; - - int ret = 0; - - if (!formatContext) { - debug_error(DEBUG, "formatContext is NULL\n"); - return MMFILE_FORMAT_FAIL; - } - - /*convert iMelody to Midi*/ - imy = __get_load_memory(formatContext->uriFileName, &imy_size); - if (!imy) { - debug_error(DEBUG, "failed to load memory.\n"); - goto exception; - } - ret = __is_good_imelody(imy, imy_size); - if (ret != MMFILE_FORMAT_SUCCESS) { - 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->videoStreamId = -1; - formatContext->videoTotalTrackNum = 0; - formatContext->audioTotalTrackNum = info->track_num; - formatContext->nbStreams = 1; - - audioStream = g_new0(MMFileFormatStream, 1); + char *found = NULL; + int i = 0; + int num = sizeof(g_imy_key_str) / sizeof(g_imy_key_str[0]); - audioStream->streamType = MMFILE_AUDIO_STREAM; - audioStream->codecId = MM_AUDIO_CODEC_IMELODY; - audioStream->bitRate = 0; - audioStream->framePerSec = 0; - audioStream->width = 0; - audioStream->height = 0; - audioStream->nbChannel = 1; - audioStream->samplePerSec = 0; - formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream; - -#ifdef __MMFILE_TEST_MODE__ - mmfile_format_print_contents(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; -} - - -int mmfile_format_read_frame_imy(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame) -{ - return MMFILE_FORMAT_SUCCESS; -} - - - -int mmfile_format_read_tag_imy(MMFileFormatContext *formatContext) -{ - tMMFileImelodyTagInfo taginfo = {0, }; - unsigned int tag_len; - unsigned int cnv_len; - const char *locale = MMFileUtilGetLocale(); - - if (!formatContext) { - debug_error(DEBUG, "formatContext is NULL\n"); - return MMFILE_FORMAT_FAIL; - } - - __get_imelody_tag(formatContext->uriFileName, &taginfo); - - /** - * UTF8 convert - */ - if (taginfo.title) { - tag_len = strlen(taginfo.title); - cnv_len = 0; - formatContext->title = mmfile_string_convert((const char *)taginfo.title, - tag_len, - "UTF-8", - locale, - NULL, - (unsigned int *)&cnv_len); - - if (formatContext->title == NULL) { - debug_warning(DEBUG, "failed to UTF8 convert.\n"); - formatContext->title = g_strdup(taginfo.title); - } - mmfile_free(taginfo.title); - } - - if (taginfo.composer) { - tag_len = strlen(taginfo.composer); - cnv_len = 0; - formatContext->composer = mmfile_string_convert((const char *)taginfo.composer, - tag_len, - "UTF-8", - locale, - NULL, - (unsigned int *)&cnv_len); - if (formatContext->composer == NULL) { - debug_warning(DEBUG, "failed to UTF8 convert.\n"); - formatContext->composer = g_strdup(taginfo.composer); - } - mmfile_free(taginfo.composer); - } - - if (taginfo.comment) { - tag_len = strlen(taginfo.comment); - cnv_len = 0; - formatContext->comment = mmfile_string_convert((const char *)taginfo.comment, - tag_len, - "UTF-8", - locale, - NULL, - (unsigned int *)&cnv_len); - if (formatContext->comment == NULL) { - debug_warning(DEBUG, "failed to UTF8 convert.\n"); - formatContext->comment = g_strdup(taginfo.comment); - } - mmfile_free(taginfo.comment); - } - - if (taginfo.copyright) { - tag_len = strlen(taginfo.copyright); - cnv_len = 0; - formatContext->copyright = mmfile_string_convert((const char *)taginfo.copyright, - tag_len, - "UTF-8", - locale, - NULL, - (unsigned int *)&cnv_len); - if (formatContext->copyright == NULL) { - debug_warning(DEBUG, "failed to UTF8 convert.\n"); - formatContext->copyright = g_strdup(taginfo.copyright); - } - mmfile_free(taginfo.copyright); + for (i = 0; i < num; i++) { + found = g_strstr_len(src, size, g_imy_key_str[i]); + if (!found) + return false; } - return MMFILE_FORMAT_SUCCESS; -} - - -int mmfile_format_close_imy(MMFileFormatContext *formatContext) -{ - return MMFILE_FORMAT_SUCCESS; + return true; } -static int __get_imelody_tag(const char *uriname, tMMFileImelodyTagInfo *tags) +static unsigned char * __get_load_memory(const char *src, int *out_size) { -#define _MMFILE_IMY_TAG_BUFFER_LENGTH 512 -#define _MMFILE_IMY_HEADER_LENGTH 20 -#define _MMFILE_IMY_KEY_BUFFER_LENGTH 20 -#define _MMFILE_IMY_VALUE_BUFFER_LENGTH 128 - + unsigned char *buf = NULL; MMFileIOHandle *fp = NULL; - unsigned char buffer[_MMFILE_IMY_TAG_BUFFER_LENGTH] = {0, }; - long long filesize = 0; - unsigned int startoffset = 0; - unsigned int endoffset = 0, i = 0; - int readed = 0, j = 0; - char imy_key_buffer[_MMFILE_IMY_KEY_BUFFER_LENGTH] = {0, }; - unsigned int imy_key_buffer_index = 0; - char imy_value_buffer[_MMFILE_IMY_VALUE_BUFFER_LENGTH] = {0, }; - unsigned int imy_value_buffer_index = 0; - int isKeyBuffer = 1; - int isDone = 0; - - int ret = MMFILE_FORMAT_FAIL; - - if (!uriname || !tags) { - debug_error(DEBUG, "uriname or tags is NULL\n"); - return MMFILE_FORMAT_FAIL; - } - - ret = mmfile_open(&fp, uriname, MMFILE_RDONLY); - if (ret == MMFILE_UTIL_FAIL) { - debug_error(DEBUG, "open failed.\n"); - return MMFILE_FORMAT_FAIL; - } - - filesize = mmfile_get_size(fp); - if (filesize < _MMFILE_IMY_HEADER_LENGTH) { - debug_error(DEBUG, "header is too small.\n"); - ret = MMFILE_FORMAT_FAIL; - goto exit; - } - - /* set begin and end point at the file */ - startoffset = 0; - endoffset = filesize; - - i = startoffset; - isKeyBuffer = 1; - while (i < endoffset) { - mmfile_seek(fp, i, MMFILE_SEEK_SET); - readed = mmfile_read(fp, buffer, _MMFILE_IMY_TAG_BUFFER_LENGTH); - if (readed < 0) { - debug_error(DEBUG, "read error. size = %d. Maybe end of file.\n", readed); - ret = 0; - break; - } - - j = 0; - while (j < readed) { - if (*(buffer + j) == 0x3a) { - isKeyBuffer = 0; - } else if (*(buffer + j) == 0x0d) { - } else if (*(buffer + j) == 0x0a) { - isKeyBuffer = 1; - isDone = 1; - } else { - if (isKeyBuffer) { - if (imy_key_buffer_index < _MMFILE_IMY_KEY_BUFFER_LENGTH) { - imy_key_buffer[imy_key_buffer_index++] = *(buffer + j); - } - - } else { - if (imy_value_buffer_index < _MMFILE_IMY_VALUE_BUFFER_LENGTH) { - imy_value_buffer[imy_value_buffer_index++] = *(buffer + j); - } - } - } - - if (isDone) { - if (!strncmp(imy_key_buffer, "NAME", 4)) { - mmfile_free(tags->title); - tags->title = g_strdup(imy_value_buffer); - } else if (!strncmp(imy_key_buffer, "COMPOSER", 8)) { - mmfile_free(tags->composer); - tags->composer = g_strdup(imy_value_buffer); - } else if (!strncmp(imy_key_buffer, "COPYRIGHT", 9)) { - mmfile_free(tags->copyright); - tags->copyright = g_strdup(imy_value_buffer); - } - - memset(imy_key_buffer, 0x00, _MMFILE_IMY_KEY_BUFFER_LENGTH); - memset(imy_value_buffer, 0x00, _MMFILE_IMY_VALUE_BUFFER_LENGTH); - imy_key_buffer_index = 0; - imy_value_buffer_index = 0; - isDone = 0; - } - - j++; - } - - memset(buffer, 0x00, _MMFILE_IMY_TAG_BUFFER_LENGTH); - - i = i + j; - } - -exit: - mmfile_close(fp); - return ret; -} - -static unsigned char * -__get_load_memory(char *src, int *out_size) -{ - unsigned char *buf = NULL; - MMFileIOHandle *fp = NULL; - long long src_size = 0L; - int readed = 0; - int ret = 0; + long long src_size = 0L; + int readed = 0; + int ret = 0; /*open*/ ret = mmfile_open(&fp, src, MMFILE_RDONLY); @@ -454,35 +145,61 @@ failed: return NULL; } - -static int -__is_good_imelody(unsigned char *src, unsigned int size) +static unsigned char __AvMIDISetVolume(const char *pMelodyBuf) { - unsigned int i, j; - int key_len; - int is_found; - unsigned char *p; - unsigned int num = sizeof(g_imy_key_str) / sizeof(g_imy_key_str[0]); + /* 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; - for (i = 0; i < num; i++) { - key_len = strlen(g_imy_key_str[i]); - p = src; - is_found = 0; - for (j = 0; j <= size - key_len; j++, p++) { - if (memcmp(g_imy_key_str[i], p, key_len) == 0) { - is_found = 1; - break; - } - } - if (is_found) continue; - else return MMFILE_FORMAT_FAIL; + if (found && *(found + strlen(IMY_KEY_VOLUME)) == '0') + vol = 0; + + return vol; +} + +static int __AvMIDISetBeat(const char *pMelodyBuf) +{ + /* Format - BEAT:### (Optional) */ + char *found = strstr(pMelodyBuf, IMY_KEY_BEAT); + /* Default [120] */ + char *beatValue = NULL; + int bpm = 120; + int beat = 0; + + if (found) { + beatValue = g_strndup(found + strlen(IMY_KEY_BEAT), 3); + /* No need to check integer bound */ + bpm = atoi(beatValue); + + if (bpm < 25 || bpm > 900) + bpm = 120; } - return MMFILE_FORMAT_SUCCESS; + beat = 1000000 * 60 / bpm; + debug_msg(RELEASE, "beat: %d\n", beat); + + return beat; } -static void -__init_imelody_data(void) +static char __AvMIDISetStyle(const char *pMelodyBuf) +{ + /* 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; +} + +static void __init_imelody_data(void) { int idx = 0; @@ -514,8 +231,7 @@ __init_imelody_data(void) memcpy(midiData, midiHeader, MIDI_HEADER_LENGTH); } -static void -__get_imelody_duration(char style, int number) +static void __get_imelody_duration(char style, int number) { if (style == '0') { switch (Melody[number].duration) { @@ -546,9 +262,7 @@ __get_imelody_duration(char style, int number) default: break; } - } - - else if (style == '1') { + } else if (style == '1') { switch (Melody[number].duration) { case '0': noteData[number].duration_on = 192; @@ -577,9 +291,7 @@ __get_imelody_duration(char style, int number) default: break; } - } - - else { + } else { switch (Melody[number].duration) { case '0': noteData[number].duration_on = 96; @@ -653,8 +365,7 @@ __get_imelody_duration(char style, int number) } } -static void -__get_imelody_melody(int number, int octaveValue) +static void __get_imelody_melody(int number, int octaveValue) { if (Melody[number].flat_sharp == '#') { switch (Melody[number].note) { @@ -676,9 +387,7 @@ __get_imelody_melody(int number, int octaveValue) default: break; } - } - - else if (Melody[number].flat_sharp == '&') { + } else if (Melody[number].flat_sharp == '&') { switch (Melody[number].note) { case 'd': noteData[number].note = octaveValue + 1; @@ -698,9 +407,7 @@ __get_imelody_melody(int number, int octaveValue) default: break; } - } - - else { + } else { switch (Melody[number].note) { case 'c': noteData[number].note = octaveValue; @@ -729,8 +436,7 @@ __get_imelody_melody(int number, int octaveValue) } } -static void -__get_imelody_reset(int number) +static void __get_imelody_reset(int number) { if (Melody[number].rest >= '0' && Melody[number].rest <= '5') { switch (Melody[number].rest) { @@ -786,8 +492,7 @@ __get_imelody_reset(int number) } } -static void -__get_imelody_notetotal(int number) +static void __get_imelody_notetotal(int number) { char noteBase[6]; @@ -811,10 +516,10 @@ __get_imelody_notetotal(int number) noteTotal[6 * number + 5] = MIDI_LIMIT; } -static unsigned char * -__AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) +static unsigned char * __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) { - char *pStart; + /* Duration measures the length of one play. So no need extract REPEAT keyword */ + char *pStart = pMelodyBuf; char *pMelodyStart; int octaveCount; int octaveValue; @@ -826,18 +531,13 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) int tempoData[3]; int tempoValue; int trackSize; - int repeat = 0; int repeatCount = 0; __init_imelody_data(); - pStart = pMelodyBuf; - - midiData[49] = __AvMIDISetVolume(pMelodyBuf); - - pMelodyBuf = pStart; - - tempoValue = __AvMIDISetBeat(pMelodyBuf); + midiData[49] = __AvMIDISetVolume(pStart); + tempoValue = __AvMIDISetBeat(pStart); + style = __AvMIDISetStyle(pStart); for (number = 0; tempoValue != 0; number++) { tempoData[0] = tempoValue % 16; @@ -851,86 +551,65 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) midiData[42 - number] = tempoData[2]; } - pMelodyBuf = pStart; + /* Find MELODY */ + pStart = strstr(pMelodyBuf, IMY_KEY_MELODY) + strlen(IMY_KEY_MELODY); - while (!(*pMelodyBuf == '@' || (*pMelodyBuf == 'E' && *(pMelodyBuf + 2) == 'D'))) - pMelodyBuf++; - - pMelodyBuf++; - - if (*pMelodyBuf >= '1' && *pMelodyBuf <= '9') { - repeat = *pMelodyBuf - '0'; - pMelodyBuf++; - - } - - repeat = 0; - - pMelodyBuf = pStart; - - pMelodyBuf = pMelodyBuf + 42; - - while (!(*pMelodyBuf == 'M' && *(pMelodyBuf + 5) == 'Y' && *(pMelodyBuf + 6) == ':')) /*2007-02-28 AVMS_Sound:k2bogus - UMTS200073205;imy play, [MELODY:] extract fix */ - pMelodyBuf++; - - pMelodyBuf = pMelodyBuf + 6; - - pMelodyStart = pMelodyBuf; + /*Melody start point */ + pMelodyStart = pStart; /**@note if newline detected, stop reading * why? mobileBAE player stopped at newline. * 2009/08/12 */ - while (!((*pMelodyBuf == 'E' && *(pMelodyBuf + 2) == 'D') || (*pMelodyBuf == '\n'))) { + 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; } - pMelodyBuf++; + pStart++; - if (*pMelodyBuf == '*') { - pMelodyBuf++; + if (*pStart == '*') { + pStart++; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '8') - octave[noteCount] = *pMelodyBuf; + if (*pStart >= '0' && *pStart <= '8') + octave[noteCount] = *pStart; } - if (*pMelodyBuf == '#' || *pMelodyBuf == '&') - Melody[noteCount].flat_sharp = *pMelodyBuf; + if (*pStart == '#' || *pStart == '&') + Melody[noteCount].flat_sharp = *pStart; - if (*pMelodyBuf == 'r') { - pMelodyBuf++; + if (*pStart == 'r') { + pStart++; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '5') { - Melody[noteCount].rest = *pMelodyBuf; - pMelodyBuf++; + if (*pStart >= '0' && *pStart <= '5') { + Melody[noteCount].rest = *pStart; + pStart++; - if (*pMelodyBuf == '.' || *pMelodyBuf == ':' || *pMelodyBuf == ';') - Melody[noteCount].rest_specifier = *pMelodyBuf; + if (*pStart == '.' || *pStart == ':' || *pStart == ';') + Melody[noteCount].rest_specifier = *pStart; } } - if (*pMelodyBuf == 'V') { - pMelodyBuf++; + if (*pStart == 'V') { + pStart++; - if (*pMelodyBuf == '+' || *pMelodyBuf == '-') - Melody[noteCount].vol = *pMelodyBuf; + if (*pStart == '+' || *pStart == '-') + Melody[noteCount].vol = *pStart; } - if (*pMelodyBuf >= 'a' && *pMelodyBuf <= 'g') { - Melody[noteCount].note = *pMelodyBuf; - pMelodyBuf++; + if (*pStart >= 'a' && *pStart <= 'g') { + Melody[noteCount].note = *pStart; + pStart++; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '5') { - Melody[noteCount].duration = *pMelodyBuf; - pMelodyBuf++; - - if (*pMelodyBuf == '.' || *pMelodyBuf == ':' || *pMelodyBuf == ';') - Melody[noteCount].duration_specifier = *pMelodyBuf; + if (*pStart >= '0' && *pStart <= '5') { + Melody[noteCount].duration = *pStart; + pStart++; + if (*pStart == '.' || *pStart == ':' || *pStart == ';') + Melody[noteCount].duration_specifier = *pStart; else - pMelodyBuf--; + pStart--; noteCount++; } @@ -954,9 +633,7 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) __get_imelody_melody(number, octaveValue); } - pMelodyBuf = pMelodyStart; - - style = __AvMIDISetStyle(pMelodyBuf); + pStart = pMelodyStart; for (number = 0; number < noteCount; number++) __get_imelody_duration(style, number); @@ -1053,7 +730,7 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) for (number = 0; number < 6 * noteCount; number++) midiData[52 + number] = noteTotal[number]; - for (number = 6 * noteCount; number < 6 * noteCount * (repeat + 1); number++) { + for (number = 6 * noteCount; number < 6 * noteCount; number++) { noteTotal[number] = noteTotal[repeatCount]; midiData[52 + number] = noteTotal[number]; repeatCount++; @@ -1062,67 +739,67 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) repeatCount = 0; } - for (number = 1; number < 6 * noteCount * (repeat + 1); number = number + 6) { + for (number = 1; number < 6 * noteCount; number = number + 6) { if (midiData[52 + number] > MIDI_LIMIT) midiData[52 + number] = MIDI_LIMIT; } - pMelodyBuf = pMelodyStart; + pStart = pMelodyStart; count = noteCount; - if (*pMelodyBuf != 'E' && *pMelodyBuf != ':') { - pMelodyBuf--; + if (*pStart != 'E' && *pStart != ':') { + pStart--; - while (*pMelodyBuf != 'E') { + while (*pStart != 'E') { if (noteCount >= AV_MIDI_NOTE_MAX) { debug_warning(DEBUG, "__AvConvertIMelody2MIDI : noteCount>=AV_MIDI_NOTE_MAX\n"); break; } - pMelodyBuf++; + pStart++; - if (*pMelodyBuf == '*') { - pMelodyBuf++; + if (*pStart == '*') { + pStart++; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '8') - octave[noteCount] = *pMelodyBuf; + if (*pStart >= '0' && *pStart <= '8') + octave[noteCount] = *pStart; } - if (*pMelodyBuf == '#' || *pMelodyBuf == '&') - Melody[noteCount].flat_sharp = *pMelodyBuf; + if (*pStart == '#' || *pStart == '&') + Melody[noteCount].flat_sharp = *pStart; - if (*pMelodyBuf == 'r') { - pMelodyBuf++; + if (*pStart == 'r') { + pStart++; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '5') { - Melody[noteCount].rest = *pMelodyBuf; - pMelodyBuf++; + if (*pStart >= '0' && *pStart <= '5') { + Melody[noteCount].rest = *pStart; + pStart++; - if (*pMelodyBuf == '.' || *pMelodyBuf == ':' || *pMelodyBuf == ';') - Melody[noteCount].rest_specifier = *pMelodyBuf; + if (*pStart == '.' || *pStart == ':' || *pStart == ';') + Melody[noteCount].rest_specifier = *pStart; } } - if (*pMelodyBuf == 'V') { - pMelodyBuf++; + if (*pStart == 'V') { + pStart++; - if (*pMelodyBuf == '+' || *pMelodyBuf == '-') - Melody[noteCount].vol = *pMelodyBuf; + if (*pStart == '+' || *pStart == '-') + Melody[noteCount].vol = *pStart; } - if (*pMelodyBuf >= 'a' && *pMelodyBuf <= 'g') { - Melody[noteCount].note = *pMelodyBuf; - pMelodyBuf++; + if (*pStart >= 'a' && *pStart <= 'g') { + Melody[noteCount].note = *pStart; + pStart++; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '5') { - Melody[noteCount].duration = *pMelodyBuf; - pMelodyBuf++; + if (*pStart >= '0' && *pStart <= '5') { + Melody[noteCount].duration = *pStart; + pStart++; - if (*pMelodyBuf == '.' || *pMelodyBuf == ':' || *pMelodyBuf == ';') - Melody[noteCount].duration_specifier = *pMelodyBuf; + if (*pStart == '.' || *pStart == ':' || *pStart == ';') + Melody[noteCount].duration_specifier = *pStart; else - pMelodyBuf--; + pStart--; noteCount++; } @@ -1149,27 +826,27 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) if (Melody[count].rest >= '0' && Melody[count].rest <= '5') { switch (Melody[count].rest) { case '0': - midiData[52 + (6 * count * (repeat + 1) - 1)] += 192; + midiData[52 + (6 * count - 1)] += 192; restSpec[count] = 192; break; case '1': - midiData[52 + (6 * count * (repeat + 1) - 1)] += 96; + midiData[52 + (6 * count - 1)] += 96; restSpec[count] = 96; break; case '2': - midiData[52 + (6 * count * (repeat + 1) - 1)] += 48; + midiData[52 + (6 * count - 1)] += 48; restSpec[count] = 48; break; case '3': - midiData[52 + (6 * count * (repeat + 1) - 1)] += 24; + midiData[52 + (6 * count - 1)] += 24; restSpec[count] = 24; break; case '4': - midiData[52 + (6 * count * (repeat + 1) - 1)] += 12; + midiData[52 + (6 * count - 1)] += 12; restSpec[count] = 12; break; case '5': - midiData[52 + (6 * count * (repeat + 1) - 1)] += 6; + midiData[52 + (6 * count - 1)] += 6; restSpec[count] = 6; break; default: @@ -1179,31 +856,31 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) if (Melody[count].rest_specifier != '%') { switch (Melody[count].rest_specifier) { case '.': - midiData[52 + (6 * count * (repeat + 1) - 1)] += (restSpec[count] / 2); + midiData[52 + (6 * count - 1)] += (restSpec[count] / 2); break; case ':': - midiData[52 + (6 * count * (repeat + 1) - 1)] += restSpec[count]; + midiData[52 + (6 * count - 1)] += restSpec[count]; break; case ';': - midiData[52 + (6 * count * (repeat + 1) - 1)] -= (restSpec[count] / 3); + midiData[52 + (6 * count - 1)] -= (restSpec[count] / 3); break; default: break; } } - if (midiData[52 + (6 * count * (repeat + 1) - 1)] > MIDI_LIMIT) - midiData[52 + (6 * count * (repeat + 1) - 1)] = MIDI_LIMIT; + if (midiData[52 + (6 * count - 1)] > MIDI_LIMIT) + midiData[52 + (6 * count - 1)] = MIDI_LIMIT; if (Melody[count].rest == '0') - midiData[52 + (6 * count * (repeat + 1) - 1)] = MIDI_LIMIT; + 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 * (repeat + 1) - 5)]; + noteTotal[6 * count + 1] = midiData[52 + (6 * count - 5)]; if (Melody[count].vol == '+') noteTotal[6 * count + 1] = noteTotal[6 * count + 1] + VOL_INTERVAL; @@ -1240,201 +917,226 @@ __AvConvertIMelody2MIDI(char *pMelodyBuf, unsigned int *pBufLen) numberCount = 6 * count; - for (number = 6 * count * (repeat + 1); number < 6 * (count * (repeat + 1) + (noteCount - count)); number++) { + for (number = 6 * count; number < 6 * (count + (noteCount - count)); number++) { midiData[52 + number] = noteTotal[numberCount]; numberCount++; } } - noteTotal[6 * (count * (repeat + 1) + (noteCount - count))] = 0; /*0x00 */ - noteTotal[6 * (count * (repeat + 1) + (noteCount - count)) + 1] = MIDI_MAX; /*0xff */ - noteTotal[6 * (count * (repeat + 1) + (noteCount - count)) + 2] = 47; /*0x2f */ - noteTotal[6 * (count * (repeat + 1) + (noteCount - count)) + 3] = 0; /*0x00 */ + 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 * (repeat + 1) + (noteCount - count)); number <= 6 * (count * (repeat + 1) + (noteCount - count)) + 3; number++) + for (number = 6 * (count + (noteCount - count)); number <= 6 * (count + (noteCount - count)) + 3; number++) midiData[51 + number] = noteTotal[number]; - trackSize = (6 * (count * (repeat + 1) + (noteCount - count)) + 56) - 22 - 1 ; + trackSize = (6 * (count + (noteCount - count)) + 56) - 22 - 1 ; midiData[20] = (trackSize & 0xff00) >> 8; midiData[21] = (trackSize & 0x00ff); - *pBufLen = 6 * (count * (repeat + 1) + (noteCount - count)) + 56 - 1; + *pBufLen = 6 * (count + (noteCount - count)) + 56 - 1; return g_memdup(midiData, *pBufLen); } -static unsigned char -__AvMIDISetVolume(char *pMelodyBuf) +static int __get_imelody_tag(const char *uriname, tMMFileImelodyTagInfo *tags) { - unsigned char midiVol; + unsigned char *imy = NULL; + int filesize = 0; + gchar **taglist = NULL; + guint len = 0, i; - pMelodyBuf = pMelodyBuf + 42; + if (!uriname || !tags) { + debug_error(DEBUG, "uriname or tags is NULL\n"); + return MMFILE_FORMAT_FAIL; + } - while (!((*pMelodyBuf == 'V' && (*(pMelodyBuf + 1) < 'a' || *(pMelodyBuf + 1) > 'z')) || (*pMelodyBuf == 'M' && *(pMelodyBuf + 5) == 'Y' && *(pMelodyBuf + 6) == ':'))) /*2007-02-28 AVMS_Sound:k2bogus - UMTS200073205;imy play, [MELODY:] extract fix */ - pMelodyBuf++; + imy = __get_load_memory(uriname, &filesize); + if (filesize <= 0) { + mmfile_free(imy); + return MMFILE_FORMAT_FAIL; + } - if (*pMelodyBuf != 'V') - midiVol = AV_MIDI_VOL_MAX; + taglist = g_strsplit((char *)imy, "\n", -1); + len = g_strv_length(taglist); + + for (i = 0; i < len; i++) { + if (g_str_has_prefix(taglist[i], IMY_KEY_NAME)) { + mmfile_free(tags->title); + tags->title = g_strdup(taglist[i] + strlen(IMY_KEY_NAME)); + } else if (g_str_has_prefix(taglist[i], IMY_KEY_COMPOSER)) { + mmfile_free(tags->composer); + tags->composer = g_strdup(taglist[i] + strlen(IMY_KEY_COMPOSER)); + } else if (g_str_has_prefix(taglist[i], IMY_KEY_COPYRIGHT)) { + mmfile_free(tags->copyright); + tags->copyright = g_strdup(taglist[i] + strlen(IMY_KEY_COPYRIGHT)); + } + } - else { - pMelodyBuf = pMelodyBuf + 5; + return MMFILE_FORMAT_SUCCESS; +} - if (*pMelodyBuf == 'E') - pMelodyBuf = pMelodyBuf + 3; - else - pMelodyBuf = pMelodyBuf - 4; +/* interface functions */ +int mmfile_format_read_stream_imy(MMFileFormatContext *formatContext); +int mmfile_format_read_frame_imy(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame); +int mmfile_format_read_tag_imy(MMFileFormatContext *formatContext); +int mmfile_format_close_imy(MMFileFormatContext *formatContext); - if (*pMelodyBuf == '1') { - pMelodyBuf++; - switch (*pMelodyBuf) { - case '0': - midiVol = AV_MIDI_VOL_MAX; - break; - case '1': - midiVol = AV_MIDI_VOL_MAX; - break; - case '2': - midiVol = AV_MIDI_VOL_MAX; - break; - case '3': - midiVol = AV_MIDI_VOL_MAX; - break; - case '4': - midiVol = AV_MIDI_VOL_MAX; - break; - case '5': - midiVol = AV_MIDI_VOL_MAX; - break; - default: - midiVol = AV_MIDI_VOL_MAX; - break; - } - } +int mmfile_format_open_imy(MMFileFormatContext *formatContext) +{ + mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL); + mm_file_retvm_if_fails(DEBUG, MMFileFormatIsValidIMY(NULL, formatContext->uriFileName, 0), MMFILE_FORMAT_FAIL); - else - switch (*pMelodyBuf) { - case '0': - midiVol = 0; - break; - case '2': - midiVol = AV_MIDI_VOL_MAX; - break; - case '3': - midiVol = AV_MIDI_VOL_MAX; - break; - case '4': - midiVol = AV_MIDI_VOL_MAX; - break; - case '5': - midiVol = AV_MIDI_VOL_MAX; - break; - case '6': - midiVol = AV_MIDI_VOL_MAX; - break; - case '7': - midiVol = AV_MIDI_VOL_MAX; - break; - case '8': - midiVol = AV_MIDI_VOL_MAX; - break; - case '9': - midiVol = AV_MIDI_VOL_MAX; - break; - default: - midiVol = AV_MIDI_VOL_MAX; - break; - } - } + formatContext->ReadStream = mmfile_format_read_stream_imy; + formatContext->ReadFrame = mmfile_format_read_frame_imy; + formatContext->ReadTag = mmfile_format_read_tag_imy; + formatContext->Close = mmfile_format_close_imy; - return midiVol; -} + formatContext->videoTotalTrackNum = 0; + formatContext->audioTotalTrackNum = 1; -static int -__AvMIDISetBeat(char *pMelodyBuf) -{ - int bpmValue[4] = {0}; - int beatValue; + formatContext->privateFormatData = NULL; - pMelodyBuf = pMelodyBuf + 42; + return MMFILE_FORMAT_SUCCESS; +} - while (!((*pMelodyBuf == 'B' && (*(pMelodyBuf + 1) < 'a' || *(pMelodyBuf + 1) > 'z')) || (*pMelodyBuf == 'M' && *(pMelodyBuf + 5) == 'Y' && *(pMelodyBuf + 6) == ':'))) /*2007-02-28 AVMS_Sound:k2bogus - UMTS200073205;imy play, [MELODY:] extract fix */ - pMelodyBuf++; - if (*pMelodyBuf != 'B') - bpmValue[3] = 120; +int mmfile_format_read_stream_imy(MMFileFormatContext *formatContext) +{ + MIDI_INFO_SIMPLE *info = NULL; + MMFileFormatStream *audioStream = NULL; - else { - pMelodyBuf = pMelodyBuf + 4; + unsigned char *imy = NULL; + int imy_size = 0; + unsigned char *midi = NULL; + unsigned int midi_size = 0; + char src2[MMFILE_URI_MAX_LEN]; - if (*pMelodyBuf == ':') { - pMelodyBuf++; + mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL); - if (*pMelodyBuf >= '1' && *pMelodyBuf <= '9') { - bpmValue[0] = *pMelodyBuf - '0'; - pMelodyBuf++; + /*convert iMelody to Midi*/ + imy = __get_load_memory(formatContext->uriFileName, &imy_size); + if (!imy) { + debug_error(DEBUG, "failed to load memory.\n"); + goto exception; + } - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '9') { - bpmValue[1] = *pMelodyBuf - '0'; - pMelodyBuf++; + if (!__is_good_imelody((char *)imy, imy_size)) { + 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; + } - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '9') { - bpmValue[2] = *pMelodyBuf - '0'; + /*make uri*/ + memset(src2, 0x00, MMFILE_URI_MAX_LEN); + snprintf(src2, sizeof(src2), "%s%u:%u", MMFILE_MEM_URI, (unsigned int)midi, midi_size); - bpmValue[0] = bpmValue[0] * 100; - bpmValue[1] = bpmValue[1] * 10; - pMelodyBuf++; - } + /*get infomation*/ + info = mmfile_format_get_midi_infomation(src2); - else - bpmValue[0] = bpmValue[0] * 10; - } - } + formatContext->duration = info->duration; + formatContext->videoStreamId = -1; + formatContext->videoTotalTrackNum = 0; + formatContext->audioTotalTrackNum = info->track_num; + formatContext->nbStreams = 1; - bpmValue[3] = bpmValue[0] + bpmValue[1] + bpmValue[2]; - } - } + audioStream = g_new0(MMFileFormatStream, 1); - if (bpmValue[3] < 25 || bpmValue[3] > 900) - bpmValue[3] = 120; + audioStream->streamType = MMFILE_AUDIO_STREAM; + audioStream->codecId = MM_AUDIO_CODEC_IMELODY; + audioStream->bitRate = 0; + audioStream->framePerSec = 0; + audioStream->width = 0; + audioStream->height = 0; + audioStream->nbChannel = 1; + audioStream->samplePerSec = 0; + formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream; - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '9') - bpmValue[3] = 120; +#ifdef __MMFILE_TEST_MODE__ + mmfile_format_print_contents(formatContext); +#endif - beatValue = 1000000 * 60 / bpmValue[3]; + mmfile_free(imy); + mmfile_free(midi); + mmfile_format_free_midi_infomation(info); + return MMFILE_FORMAT_SUCCESS; - debug_msg(RELEASE, "beat: %d = 1000000 * 60 / %d\n", beatValue, bpmValue[3]); +exception: + mmfile_free(imy); + mmfile_free(midi); + mmfile_format_free_midi_infomation(info); + mmfile_free(audioStream); + return MMFILE_FORMAT_FAIL; +} - return beatValue; + +int mmfile_format_read_frame_imy(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame) +{ + return MMFILE_FORMAT_SUCCESS; } -static char -__AvMIDISetStyle(char *pMelodyBuf) +int mmfile_format_read_tag_imy(MMFileFormatContext *formatContext) { - char styleValue = '0'; + tMMFileImelodyTagInfo taginfo = {0, }; + unsigned int tag_len; + unsigned int cnv_len; + const char *locale = MMFileUtilGetLocale(); - while (*pMelodyBuf != 'S') - pMelodyBuf--; + mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL); - pMelodyBuf++; + __get_imelody_tag(formatContext->uriFileName, &taginfo); - if (*pMelodyBuf >= '0' && *pMelodyBuf <= '2') - pMelodyBuf++; + /** + * UTF8 convert + */ + if (taginfo.title) { + tag_len = strlen(taginfo.title); + cnv_len = 0; + formatContext->title = mmfile_string_convert(taginfo.title, tag_len, "UTF-8", locale, NULL, &cnv_len); + + if (formatContext->title == NULL) { + debug_warning(DEBUG, "failed to UTF8 convert.\n"); + formatContext->title = g_strdup(taginfo.title); + } + mmfile_free(taginfo.title); + } - if (*pMelodyBuf != '.') { - pMelodyBuf--; - styleValue = *pMelodyBuf; + if (taginfo.composer) { + tag_len = strlen(taginfo.composer); + cnv_len = 0; + formatContext->composer = mmfile_string_convert(taginfo.composer, tag_len, "UTF-8", locale, NULL, &cnv_len); + if (formatContext->composer == NULL) { + debug_warning(DEBUG, "failed to UTF8 convert.\n"); + formatContext->composer = g_strdup(taginfo.composer); + } + mmfile_free(taginfo.composer); } - if (styleValue < '0' || styleValue > '2') { - debug_warning(DEBUG, "unknown style. use default(S0)\n"); - styleValue = '0'; + if (taginfo.copyright) { + tag_len = strlen(taginfo.copyright); + cnv_len = 0; + formatContext->copyright = mmfile_string_convert(taginfo.copyright, tag_len, "UTF-8", locale, NULL, &cnv_len); + if (formatContext->copyright == NULL) { + debug_warning(DEBUG, "failed to UTF8 convert.\n"); + formatContext->copyright = g_strdup(taginfo.copyright); + } + mmfile_free(taginfo.copyright); } - debug_msg(RELEASE, "style: '%c'\n", styleValue); + return MMFILE_FORMAT_SUCCESS; +} - return styleValue; +int mmfile_format_close_imy(MMFileFormatContext *formatContext) +{ + return MMFILE_FORMAT_SUCCESS; } + -- 2.7.4