tonegen.c 4.54 KB
#include <stdio.h>
#include <stdlib.h>
#include <bstring.h>
#include <assert.h>
#include <getopt.h>
#include <audiofile.h>
#include <math.h>

#define	MIN(a,b) (((a)<(b))?(a):(b))
#define	MAX(a,b) (((a)>(b))?(a):(b))

static char usage[] = "[-f frequency] [-a db attenuation] [-stereo] \
[-n <samples>] [-r sample rate] [-hex] outfile";

main(int argc, char **argv)
{
    char                *ofile = NULL;

    extern char         *optarg;
    extern int          optind;
    int                 errflg=0;
    int                 c;
    int                 asciihex=0;
    
    int                 nchannels       = 1;
    double              frequency       = 1000.0;
    double              gain            = (double)0x7fff;
    double              rate            = 44100.0;
    double              pi              = M_PI;
    double              sec             = 5.0;
    int                 bytesPerSample  = 2;
    int                 bitsPerSample   = bytesPerSample << 3;
    double              db;
    
    AFfilesetup         setup;
    AFfilehandle        file;
    FILE                *hfile;
    
    long                framesPerPass;
    int                 bytes;
    short               *buf;
    long                frames;
    double              phase;
    double              pi2_N;
    int                 i;
    long                count;
    int                 useTime = 0;
    
    while ((c = getopt(argc, argv, "hsf:t:a:n:")) != EOF) {        
        switch (c) {
            case 'h':
                asciihex = 1;
                break;
	    case 'f':
                frequency = atof(optarg);
		break;
	    case 'a':
                db = atof(optarg);
                if (db > 0)
                    db = -db;
                gain = gain * pow(10, db/10);
		break;
            case 's':
                nchannels = 2;
                break;
            case 'n':
                frames = atoi(optarg);
                break;
            case 't':
                sec = atof(optarg);
                useTime = 1;
                break;
            case '?':
                errflg++;
                break;
        }
    }

    if (errflg || optind == argc) {
        (void)fprintf(stderr, "%s %s\n", argv[0], usage);
        exit (2);
    }

    ofile = argv[optind++];
    if (optind != argc) {
	fprintf(stderr, "warning: only first file (%s) used, rest ignored\n",
	   ofile);
    }

    /*
     * open output file and initialize
     */
    if (asciihex) {
        hfile = fopen(ofile, "w");
        if (!hfile) {
            printf("error opening file %s\n", ofile);
            exit(1);
        }
    } else {
        setup = AFnewfilesetup();
        AFinitchannels(setup, AF_DEFAULT_TRACK, nchannels);
        AFinitsampfmt(setup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP,
                      bitsPerSample);
        AFinitrate(setup, AF_DEFAULT_TRACK, rate);
        AFinitcompression(setup, AF_DEFAULT_TRACK, AF_COMPRESSION_NONE);
        AFinitfilefmt(setup, AF_FILE_AIFFC);
        file = AFopenfile(ofile, "w", setup);
        if (file == AF_NULL_FILEHANDLE) {
            printf("error opening file %s\n", ofile);
            exit(1);
        }
    }
    
    framesPerPass = 512;
    bytes = (int)(framesPerPass*nchannels*bytesPerSample);
    buf = (short *)malloc(bytes);    
    if (!buf) {
        printf("memory allocation error\n");
        exit(1);
    }

    if (useTime)
        frames = (long)(sec*rate);
    
    phase = 0;
    pi2_N = 2*pi*frequency/rate;

    while (frames > 0) {
        long curFrames = MIN(frames, framesPerPass);

        if (nchannels == 1) {
            for (i = 0; i < curFrames; i++) {
                buf[i] = (short) (gain*sin(pi2_N*phase));
                if (asciihex) {
                    fprintf(hfile, "%x \n", buf[i]);
                }
                
                phase++;
            }
        } else {
            for (i = 0; i < curFrames*2; i+=2) {
                buf[i] = buf[i+1] = (short) (gain*sin(pi2_N*phase));
                if (asciihex) {
                    fprintf(hfile, "%x %x \n", buf[i], buf[i+1]);
                }
                phase++;
            }
        }

        if (asciihex) {
            count = curFrames;
        } else {
            count = AFwriteframes(file, AF_DEFAULT_TRACK, buf, curFrames);
            if (count <= 0) {
                printf("error writing file, file incomplete\n");
                exit(1);
            }
        }        

        frames -= count;
    }

    if (asciihex) {
        fclose(hfile);
    } else {
        AFfreefilesetup(setup);
        AFclosefile(file);
    }    
}