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 + -
显示快捷键?