/* speed.c - change the speed of a sound file
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include <stdio.h>
#include "libst.h"

#define MYBUFSIZ 256
#define SCALE 4096
#define HALFSCALE 2048

main( argc, argv )
int argc;
char *argv[];
    {
    FILE *f;
    char mybuf[MYBUFSIZ];
    float scale;
    register long sscale, fractofill, fracleft, sc;
    double atof();
    int c, lc;

    if ( argc < 2 || argc > 3 )
	{
	fprintf( stderr, "usage:  %s <factor> [<file>]\n", argv[0] );
	exit( 1 );
	}

    scale = atof( argv[1] );
    if ( scale == 0.0 )
	{
	fprintf( stderr, "%s: scale factor required\n", argv[0] );
	exit( 1 );
	}
    scale = 1.0 / scale;
    sscale = scale * SCALE;

    if ( argc == 2 )
	f = stdin;
    else if ( argc == 3 )
	{
	f = fopen( argv[2], "r" );
	if ( f == NULL )
	    {
	    perror( argv[2] );
	    exit( 1 );
	    }
	}
    setbuffer( stdout, mybuf, MYBUFSIZ );

    fractofill = SCALE;
    sc = HALFSCALE;
    while ( (c = getc( f )) != EOF )
	{
	lc = st_ulaw_to_linear( c );
	fracleft = sscale;
	while ( fracleft >= fractofill )
	    {
	    sc += fractofill * lc;
	    sc /= SCALE;
	    LINCLIP( sc );
	    putchar( st_linear_to_ulaw( sc ) );
	    fracleft -= fractofill;
	    fractofill = SCALE;
	    }
	if ( fracleft > 0 )
	    {
	    sc += fracleft * lc;
	    fractofill -= fracleft;
	    }
	}
    if ( fractofill > 0 )
	{
	sc += fractofill * lc;
	sc /= SCALE;
	LINCLIP( sc );
	putchar( st_linear_to_ulaw( sc ) );
	}

    exit( 0 );
    }
