am_imelody.cc
来自「Motorola synergy audio component」· CC 代码 · 共 983 行 · 第 1/2 页
CC
983 行
}
/* DESCRIPTION:
Converts the iMelody defined octave to AM octave value
INPUTS:
pitch, pointer to the found pitch
OUTPUTS:
AM octave value
IMPORTANT NOTES:
*/
UINT8
AM_iMelody::GetOctave (UINT8* pitch)
{
UINT8 octave = DEFAULT_OCATVE;
UINT8* ptr = NULL;
UINT8* local_pitch = pitch;
/* if octave_ptr > pitch, we need to search upward for an octave; */
if (octave_ptr > pitch)
{
ptr = GetVerboseOctave(local_pitch);
if (octaveMethod == EFFICIENT_OCTAVE)
{
while (ptr == NULL && local_pitch > body)
{
while (!IsAPitch(*(--local_pitch)) && local_pitch > body);
ptr = GetVerboseOctave(local_pitch);
}
}
if (ptr == NULL && octaveMethod == VERBOSE_OCTAVE)
{
octave_ptr = pitch;
}
else
{
octave_ptr = ptr;
}
}
/* if octave_ptr < body, we assume no more octaves left in the data; */
/* if octave_ptr is in range body-pitch, *octave_ptr is the octave; */
if (octave_ptr > body && octave_ptr < pitch)
{
octave = *octave_ptr - '0';
}
return octave;
}
/* DESCRIPTION:
Gets the value of the corresponding fields that are
in the iMelody header
INPUTS:
start, begginning of the data to be searched for the field
fieldMaker, a character string, serves as the marker of the
field to be searched for in the header.
defaultValue, the default value of the field, in case there
is not such field specified in the header.
end, end of the data to be searched for the field
OUTPUTS:
the field value
IMPORTANT NOTES:
None
*/
UINT16
AM_iMelody::GetFieldDecimalValue(UINT8* start, const UINT8 fieldMaker[], UINT8 defaultValue, UINT8* end)
{
UINT8* fieldPtr = SearchField (start, fieldMaker, end);
UINT16 fieldValue = defaultValue;
// found this field...
if (fieldPtr < end)
{
fieldValue = 0;
while (fieldPtr != NULL && *fieldPtr >= '0' && *fieldPtr <= '9')
{
fieldValue = fieldValue * 10 + (*fieldPtr - '0');
fieldPtr = NextNonLfcrASCII(end, fieldPtr, 1);
}
}
return fieldValue;
}
/* DESCRIPTION:
Gets the tune characters (tempo, volume, iMelody defined style, etc)
from header fields
INPUTS:
inputStream - the input iMelody string. If it is NULL, will use the setting stored.
OUTPUTS:
None
IMPORTANT NOTES:
None
*/
void
AM_iMelody::GetTuneInfoFromHeader(UINT8* inputStream)
{
if ( inputStream != NULL )
{
SetInput(inputStream);
}
tail = head;
/* The data the DL Feature DB writes into ends with a NULL. */
while (*tail != NULL)
{
tail++;
}
octave_ptr = tail;
/* Get the body pointer pointing to the melody body field */
body = SearchField (head, (UINT8*)IMELODY_MARKER_melody, tail);
// Oops, no body field. Treat the entire string as body...
if (body == tail)
{
body = head;
}
/* Get needed info from iMelody head fields */
TuneCharacters[STYLE] = GetFieldDecimalValue(head, IMELODY_MARKER_style, DEFAULT_STYLE, body);
TuneCharacters[VOLUME] = GetFieldDecimalValue(head, IMELODY_MARKER_volume, DEFAULT_VOLUME, body);
UINT16 beats = GetFieldDecimalValue(head, IMELODY_MARKER_beat, DEFAULT_BEAT, body);
if ( beats == 0 )
{
beats = DEFAULT_BEAT;
}
TuneCharacters[TEMPO] = BEAT_TEMPO_PRODUCT / beats;
}
/* DESCRIPTION:
Gets the next charater that is not LF or CR.
INPUTS:
boundary, the boundary for searching
Ptr, pointer to the current character in the array
increment, the increment for searching
OUTPUTS:
the to the found character; or NULL if not found;
IMPORTANT NOTES:
None
*/
UINT8*
AM_iMelody::NextNonLfcrASCII(UINT8* boundary, UINT8* Ptr, INT8 increment)
{
UINT8* found = NULL;
while (((boundary - Ptr) / increment) >= 1 && found == NULL)
{
Ptr += increment;
if (*Ptr != '\r' && *Ptr != '\n')
{
found = Ptr;
}
}
return (found);
}
/* DESCRIPTION:
pack the notes and beats passed in to the imelody buffer.
If imelody_buffer is empty, this function will pack notes_string, beats and use
default value for other fields as follows,
BEGIN:IMELODY
VERSION:1.2
FORMAT:CLASS1.0
BEAT:120
MELODY:XXXXXXXXXXXX input of notes_buffer XXXXXXXXXXXXXXXXXXXX
END:IMELODY
If imelody_buffer is not empty, this function will pack notes_string, beats and
keep the oringinal value for other fields.
INPUTS:
imelody_buffer - Input/Output imelody buffer
imelody_buffer_size - Output imelody buffer size
notes_string - notes string passed in
beats - beats passed in
OUTPUTS:
None
IMPORTANT NOTES:
imelody_buffer must not be NULL and must be initialized to be a NULL terminated string.
*/
void
AM_iMelody::TunePack( UINT8 * imelody_buffer,
UINT16 imelody_buffer_size,
UINT8 * notes_string,
UINT16 beats)
{
UINT8 * packing_ptr, * end;
UINT16 packed_len;
BOOL beat_in_header = FALSE;
if ( * imelody_buffer != NULL )
{
end = imelody_buffer;
/* search the end of the string in the imelody_buffer */
while (*end != NULL)
{
end ++;
}
packing_ptr = SearchField (imelody_buffer, IMELODY_MARKER_melody, end);
if ( packing_ptr != end )
{
// There is header in imelody_buffer
packing_ptr -= sizeof(IMELODY_MARKER_melody) - 1;
UINT8 * field_ptr;
field_ptr = SearchField (imelody_buffer, IMELODY_MARKER_beat, packing_ptr);
if ( field_ptr != packing_ptr )
{
// There is "BEAT:" field in the header
beat_in_header = TRUE;
}
}
if ( beats == 0 )
{
beats = GetFieldDecimalValue( imelody_buffer,
IMELODY_MARKER_beat,
DEFAULT_BEAT,
end);
}
}
if ( * imelody_buffer == NULL || packing_ptr == end)
{
// There isn't header information, copy the default header in
strncpy( (char *)imelody_buffer,
(char *)IMELODY_MARKER_default_header,
imelody_buffer_size);
packing_ptr = imelody_buffer + sizeof(IMELODY_MARKER_default_header) - 1;
}
// 6 is enough to hold "65535"
UINT8 number_buffer[6];
UINT8 * num_str = NULL;
UINT8 num_len;
UINT8 beats_string_len = 0;
if ( beat_in_header == FALSE && beats != 0 && beats != DEFAULT_BEAT )
{
// beats is not default value, need to pack beats
num_str = num_2_str( beats, number_buffer, sizeof(number_buffer));
num_len = strlen((char *) num_str);
beats_string_len = sizeof(IMELODY_MARKER_beat) - 1 + // "BEAT:"
num_len + // number of beats
1; // "\n"
}
INT16 notes_len = strlen((char *) notes_string);
/* The first line of notes has a IMELODY_MARKER_melody */
UINT8 line_len_max = IMELODY_MAX_TEXT_LEN - ( sizeof (IMELODY_MARKER_melody) - 1 );
UINT8 line_num = notes_len < line_len_max ?
1 : 1 + ( notes_len - line_len_max + IMELODY_MAX_TEXT_LEN - 1 ) / IMELODY_MAX_TEXT_LEN;
packed_len = packing_ptr - imelody_buffer + // header
beats_string_len + // "BEAT:", beats number and "\n"
sizeof(IMELODY_MARKER_melody) - 1 + // "MELODY:"
notes_len + // notes
line_num - 1 + // " " ahead each line of notes except 1st line
line_num + // "\n" at the end of each line of notes
sizeof(IMELODY_MARKER_endimelody) - 1 + // "END:IMELODY"
1 + 1; // "\n" and NULL
if ( packed_len > imelody_buffer_size )
{
// Don't pack if there isn't enough buffer.
return;
}
if ( num_str != NULL )
{
/* Pack IMELODY_MARKER_beat */
strcpy( (char *) packing_ptr, (char *) IMELODY_MARKER_beat);
packing_ptr += sizeof(IMELODY_MARKER_beat) - 1;
/* Pack beats number */
strncpy( (char *) packing_ptr, (char *) num_str, num_len);
packing_ptr += num_len;
* packing_ptr++ = '\n';
}
/* Pack IMELODY_MARKER_melody */
strcpy( (char *) packing_ptr, (char *) IMELODY_MARKER_melody);
packing_ptr += sizeof(IMELODY_MARKER_melody) - 1;
/* Start packing Notes */
UINT8 line_len;
BOOL not_first_line = FALSE;
while ( notes_len > 0 )
{
if ( not_first_line )
{
line_len_max = IMELODY_MAX_TEXT_LEN - 1;
/* Pack a space at the beginning of the line according to the
* iMelody specification.
*/
* packing_ptr++ = ' ';
}
line_len = notes_len < line_len_max ? notes_len : line_len_max;
memcpy( packing_ptr, notes_string, line_len);
packing_ptr += line_len;
notes_string += line_len;
/* The notes passed in by editor doesn't have any line folding,
* so pack line folding here.
*/
* packing_ptr++ = '\n';
notes_len -= line_len;
not_first_line = TRUE;
}
/* Pack IMELODY_MARKER_endimelody */
strcpy( (char *) packing_ptr, (char *) IMELODY_MARKER_endimelody);
packing_ptr += sizeof(IMELODY_MARKER_endimelody) - 1;
* packing_ptr++ = '\n';
* packing_ptr = NULL;
}
/* DESCRIPTION:
This function converts a UINT16 number to a string.
INPUTS:
num - the input number
str_buf_size - the output string buffer size
OUTPUTS:
str_buf - the output string buffer
RETURN:
the number string pointer
IMPORTANT NOTES:
The caller must allocate enough buffer for str_buf
*/
UINT8 *
AM_iMelody::num_2_str( UINT16 num, UINT8 * str_buf, UINT8 str_buf_size)
{
UINT8 * num_str = str_buf + str_buf_size - 1;
* num_str = NULL;
do
{
num_str --;
* num_str = num % 10 + '0';
num = num / 10;
} while (num);
return num_str;
}
/* DESCRIPTION:
Unpack the notes and beats passed
INPUTS:
imelody_string - Input imelody buffer
notes_buffer_size - Output imelody buffer size
OUTPUTS:
notes_buffer - Output notes buffer
beats - Output beats
IMPORTANT NOTES:
None
*/
void
AM_iMelody::TuneUnpack( UINT8 * imelody_string,
UINT8 * notes_buffer,
UINT16 notes_buffer_size,
UINT16 * beats)
{
UINT8 * unpacking_start, * notes_start, * notes_end;
UINT8 * end = imelody_string;
/* search the end of the string in the imelody_string */
while (*end != NULL)
{
end ++;
}
/* read beat */
* beats = GetFieldDecimalValue( imelody_string,
IMELODY_MARKER_beat,
DEFAULT_BEAT,
end );
if ( * beats == 0 )
{
* beats = DEFAULT_BEAT;
}
/* find the start point of the notes */
unpacking_start = SearchField (imelody_string, IMELODY_MARKER_melody, end);
if ( unpacking_start != end )
{
notes_start = unpacking_start;
}
else
{
/*
* There is no "MELODY:" field. Although this is a mandatory, we still
* want to work well for some bad iMelody files downloaded
*/
const UINT8 * header_fields[] =
{
IMELODY_MARKER_begin,
IMELODY_MARKER_version,
IMELODY_MARKER_format,
IMELODY_MARKER_name,
IMELODY_MARKER_composer,
IMELODY_MARKER_beat,
IMELODY_MARKER_style,
IMELODY_MARKER_volume
};
notes_start = imelody_string;
for ( UINT8 i = 0; i < sizeof(header_fields) / sizeof (UINT8 *); i ++ )
{
unpacking_start = SearchField (imelody_string, header_fields[i], end);
if ( unpacking_start != end )
{
notes_start = notes_start > unpacking_start ? notes_start : unpacking_start;
}
}
if ( notes_start != imelody_string )
{
// A header field is found. Bypass this header line.
while ( *notes_start != '\n' && notes_start < end )
{
notes_start++;
}
}
}
/* find the end point of the notes */
notes_end = SearchField ( imelody_string, IMELODY_MARKER_end, end);
if ( notes_end != end )
{
notes_end -= sizeof(IMELODY_MARKER_end) - 1 + 1; // move before "\nEND:"
}
/* Copy the notes and take off all the non-notes characters */
while ( * notes_start != NULL && notes_start <= notes_end )
{
if ( * notes_start != ' ' &&
* notes_start != '\r' &&
* notes_start != '\n' &&
* notes_start != '\t'
)
{
* notes_buffer = * notes_start;
notes_buffer ++;
}
notes_start ++;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?