DRUID Development Docs: snd.c

Gadget Sourcecode: snd.c

/*
 * Justice Unlimited Gadget Sound Conversion Utility
 *
 * Copyrigh (C) 2004, Nathan (Acorn) Pooley
 *
 *
 *
 */

/*
 *
 *@DOC@ create sound parameters
 *
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

double cycle_per_sec = 8192.0;

void usage(char *err)
{
    if (err) {
        fprintf(stderr,"ERROR: %s\n",err);
    }
    fprintf(stderr,"usage: snd <period> <duration>\n");
    fprintf(stderr,"  <period>     is in cycles (int)\n");
    fprintf(stderr,"  <duration>   is in seconds (float)\n");
    exit(1);
}

typedef int (*duration_func)(int period, int d1, int d2);

int duration_n(int period, int d1, int d2)
{
    int a = period * (d1-1) + 11;
    return a * d2;
}

int duration_6(int period, int d1, int d2)
{
    int a = period * (d1-1) + 12;
    return a * d2;
}

int duration_5(int period, int d1, int d2)
{
    int a = period * (d1-1) + 15;
    return a * d2;
}

int duration_4(int period, int d1, int d2)
{
    int a = period * (d1-1) + 12;
    return a * d2;
}

int duration_3(int period, int d1, int d2)
{
    int a = 6 * (d1-1) + 12;
    return a * d2;
}

int duration_2(int period, int d1, int d2)
{
    int a = 17 * (d1-1) + 25;
    return a * d2;
}

int duration_1(int period, int d1, int d2)
{
    int a = 19 * (d1-1) + 55;
    return a * d2;
}

int snd_calc(int period, double duration, int print)
{
    int iduration;
    int actual_period;
    int actual_iduration;
    int val,d1=-1,d2=-1;
    int f;
    duration_func func;

    if (period < 1) period = 1;

    if (duration > 0.75) {
        fprintf(stderr,"WARNING: truncating duration to 3/4 sec\n");
        duration = 0.75;
    }
    iduration = (int)(duration * cycle_per_sec);

    val = (int)(((period - 4) / 3) + 0.5);
    if (val < 1) val = 1;
    if (val > 256) val = 256;

    actual_period = (val * 3) + 4;

    f = 'N';
    func = duration_n;

    switch(period) {
        case 1:
            f = '1';
            val = 0;
            actual_period = period;
            func          = duration_1;
            break;
        case 2:
            f = '2';
            val = 0;
            actual_period = period;
            func          = duration_2;
            break;
        case 3:
            f = '3';
            val = 0;
            actual_period = period;
            func          = duration_3;
            break;
        case 4:
            f = '4';
            val = 0;
            actual_period = period;
            func          = duration_4;
            break;
        case 5:
            f = '5';
            val = 0;
            actual_period = period;
            func          = duration_5;
            break;
        case 6:
            f = '6';
            val = 0;
            actual_period = period;
            func          = duration_6;
            break;
        default:
            break;
    }

    if (iduration <= 0) {
        d1 = 1;
        d2 = 1;
        actual_iduration = 11;
    } else {
        int td1,td2;
        int err = -1;
        for (td1 = 256; td1 >= 1; td1--) {
            //int tidur_a = 11 + ((td1 - 1) * actual_period);
            for (td2 = 1; td2 <= 256; td2++) {
                int tiduration, terr;
                //tiduration = tidur_a * td2;
                tiduration = func(actual_period, td1, td2);
                terr = tiduration - iduration;
                if (terr < 0) terr = -terr;

                if (err < 0 || terr < err) {
                    err = terr;
                    d1 = td1;
                    d2 = td2;
                    actual_iduration = tiduration;
                }
                if (tiduration > iduration) break;
            }
        }
    }

    if (val == 256) val = 0;
    if (d1  == 256) d1  = 0;
    if (d2  == 256) d2  = 0;

    if (print) {
#if 0
        printf("  val = %d\n",val);
        printf("  d1  = %d\n",d1);
        printf("  d2  = %d\n",d2);
        printf("  period   = %d cyc\n",actual_period);
        printf("  duration = %5.3f sec\n",
            (double)actual_iduration/cycle_per_sec);
#else
        printf("  f=%c val=0x%02x d1=0x%02x d2=0x%02x  "
                "freq=%4d Hz  period=%d cyc  dura=%5.3f sec\n",
            f,
            val,
            d1,
            d2,
            (int)(cycle_per_sec/(2*actual_period)),
            actual_period,
            (double)actual_iduration/cycle_per_sec);
#endif
    }

    return actual_period;
}

int main(int argc, char *argv[])
{
    int period = 3;
    double duration = 0.5;
    int iduration;
    int actual_period;
    int actual_iduration;
    int val,d1=-1,d2=-1;


    if (argc == 3) {
        period = (int) strtod(argv[1], 0);
        if (period < 1) period = 1;

        duration = strtod(argv[2], 0);
        if (duration > 0.75) {
            fprintf(stderr,"WARNING: truncating duration to 3/4 sec\n");
            duration = 0.75;
        }

        snd_calc(period, duration, 1);
    } else if (argc == 1) {
        int i;
        int last_period = -1;
        for (i=1; i<1000; i++) {
            int period = snd_calc(i, 0.5, 0);
            if (period != last_period) {
                last_period = snd_calc(i, 0.5, 1);
            }
            if (period > 85) break; // 50 Hz
        }

        for (i=1; i<7; i++) {
            printf(" period=%d cyc  freq=%4d Hz\n",
                i,
               (int)(cycle_per_sec/(2*i)));
        }
    } else {
        usage("Wrong number of arguments");
    }

}

This file Copyright (C) 2004 by Nathan (Acorn) Pooley
Go to DRUID Development page
Go to DRUID page
Go to JU Gadgets page
Go to Justice Unlimited homepage
Go to Acorn's personal webpage
Contact Acorn
See comments from others
Post your own comments
File created by do_doc at Wed Aug 4 18:08:30 2004