/*
 * Copyrighted as an unpublished work.
 * (c) Copyright 1991 Brian Smith
 * All rights reserved.
 *
 * Read the LICENSE file for details on distribution and use.
 *
 */

#include <sys/fcntl.h>
#include <sys/unistd.h>
#include <sys/sb.h>
#include <stdio.h>

int main(argc, argv)
int argc;
char **argv;
{
    int cmf_fd;

    if (argc != 2)
    {
        printf("usage: %s <cmf file>\n", argv[0]);
        exit(-1);
    }

    /* open cmf file */
    cmf_fd = open(argv[1], O_RDONLY);
    if (cmf_fd == -1)
    {
        printf("usage: %s <cmf file>\n", argv[0]);
        exit(-1);
    }

    /* verify that file is a cmf file */
    if (!verify_cmf(cmf_fd))
    {
        printf("file was not a cmf file\n");
        printf("usage: %s <cmf file>\n", argv[0]);
        exit(-1);
    }

    /* print out info on instruments in cmf file */
    print_instruments(cmf_fd);

    return(0);
}


/* check for "CTMF" in first four bytes of file */
int verify_cmf(fd)
int fd;
{
    char idbuf[5];

    /* get id */
    lseek(fd, 0, SEEK_SET);
    if (read(fd, idbuf, 4) != 4)
        return(FALSE);
    
    /* compare to standard id */
    idbuf[4] = (char)0;
    if (strcmp(idbuf, "CTMF") != 0)
        return(FALSE);
    
    return(TRUE);
}

int print_instruments(fd)
int fd;
{
    int offset;
    int num_instruments;
    int i;
    int j;
    unsigned char tmp_byte;
    unsigned char instrument_buf[16];

#define lobyte(X)   (((unsigned char *)&X)[0])
#define hibyte(X)   (((unsigned char *)&X)[1])

    /* get offset of instrument block */
    offset = 0;
    lseek(fd, 0x06, SEEK_SET);
    read(fd, &tmp_byte, 1);
    lobyte(offset) = tmp_byte;
    read(fd, &tmp_byte, 1);
    hibyte(offset) = tmp_byte;

    /* get number of instruments */
    num_instruments = 0;
    lseek(fd, 0x24, SEEK_SET);
    read(fd, &tmp_byte, 1);
    lobyte(num_instruments) = tmp_byte;
    read(fd, &tmp_byte, 1);
    hibyte(num_instruments) = tmp_byte;

    /* read each instrument */
    lseek(fd, offset, SEEK_SET);
    for (i=0; i< num_instruments; i++)
    {
        read(fd, instrument_buf, 16);
        printf("instrument: 0x%02x\n", i);

        for (j=0; j<16; j++)
            printf("0x%02x ", (unsigned int)instrument_buf[j]);
        printf("\n");

        /* byte 0 */
        printf("\tModulator: 0x%02x\n", (unsigned int)instrument_buf[0]);

        /* byte 1 */
        printf("\tCarrier Sound Characteristic\n");
        if (instrument_buf[1] & (1<<7))
            printf("\tPitch Vibrato: On\n");
        else
            printf("\tPitch Vibrato: Off\n");
        if (instrument_buf[1] & (1<<6))
            printf("\tAmplitude Vibrato: On\n");
        else
            printf("\tAmplitude Vibrato: Off\n");
        if (instrument_buf[1] & (1<<5))
            printf("\tSustaining Sound: On\n");
        else
            printf("\tSustaining Sound: Off\n");
        if (instrument_buf[1] & (1<<4))
            printf("\tEnvelope Scaling: On\n");
        else
            printf("\tEnvelope Scaling: Off\n");
        printf("\tFrequency Multiplier: 0x%02x\n", instrument_buf[1] & 0x0F);

        /* byte 2 */
        printf("\tModulator Level Scaling: 0x%02x\n", instrument_buf[2] >> 4);
        printf("\tModulator Output Level: 0x%02x\n", instrument_buf[2] & 0x3f);

        /* byte 3 */
        printf("\tCarrier Level Scaling: 0x%02x\n", instrument_buf[3] >> 4);
        printf("\tCarrier Output Level: 0x%02x\n", instrument_buf[3] & 0x3f);

        /* byte 4 */
        printf("\tModulator Attack Rate 0x%02x\n", instrument_buf[5] >> 4);
        printf("\tModulator Decay Rate 0x%02x\n", instrument_buf[5] & 0xF);

        /* byte 5 */
        printf("\tCarrier Attack Rate 0x%02x\n", instrument_buf[5] >> 4);
        printf("\tCarrier Decay Rate 0x%02x\n", instrument_buf[5] & 0xF);

        /* byte 6 */
        printf("\tModulator Sustain Level 0x%02x\n", instrument_buf[6] >> 4);
        printf("\tModulator Release Level 0x%02x\n", instrument_buf[6] >> 4);

        /* byte 7 */
        printf("\tCarrier Sustain Level 0x%02x\n", instrument_buf[7] >> 4);
        printf("\tCarrier Release Level 0x%02x\n", instrument_buf[7] >> 4);

        /* byte 8 */
        printf("\tModulator Wave Select 0x%02x\n", instrument_buf[8] & 0x03);

        /* byte 9 */
        printf("\tCarrier Wave Select 0x%02x\n", instrument_buf[9] & 0x03);

        /* byte A */
        printf("\tModulator FeedBack 0x%02x\n",
            (instrument_buf[0xA] >> 1) & 0x07);
    }

    return(0);
}
