Logo Search packages:      
Sourcecode: nas version File versions  Download package

auconvert.c

/**
 * Copyright 1993 Network Computing Devices, Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and
 * its documentation for any purpose is hereby granted without fee, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name Network Computing Devices, Inc. not be
 * used in advertising or publicity pertaining to distribution of this
 * software without specific, written prior permission.
 *
 * THIS SOFTWARE IS PROVIDED `AS-IS'.  NETWORK COMPUTING DEVICES, INC.,
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
 * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NONINFRINGEMENT.  IN NO EVENT SHALL NETWORK
 * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
 * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
 * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
 * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Greg Renda <greg@ncd.com>
 *          Network Computing Devices, Inc.
 *          350 North Bernardo Ave.
 *          Mountain View, CA  94043
 *
 * $Id: auconvert.c,v 1.3 2000/12/13 04:22:31 jon Exp $
 * $NCDId: @(#)auconvert.c,v 1.8 1994/04/07 18:09:30 greg Exp $
 */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <audio/Aos.h>        /* for string and other os stuff */
#include <audio/Afuncs.h>     /* for bcopy et. al. */
#include <audio/audiolib.h>
#include <audio/soundlib.h>

#define USAGE "\
usage: auconvert [options] [<input file>] [<output file>]\n\
where options include:\n\n\
    -file format                   file format\n\
    -data format                   data format\n\
    -rate <sample rate>            sampling rate\n\
    -comment string                comment\n\
    -raw <data format> <tracks>    input file is raw data\n\
    -volume percent|\"max\"          volume percent or \"max\" volume\n\
"

#define max(a, b) ((a) > (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? -(a) : a)

#define OPTION(_o) (!strncmp(arg, _o, strlen(_o)))
#define GETARG(_d, _s)                                            \
do                                                          \
{                                                           \
    if (--argc)                                                   \
    {                                                       \
      arg = *(++argv);                                      \
      _d = _s;                                              \
    }                                                       \
    else                                                    \
      usage();                                              \
} while(0)

static struct
{
    char           *string;
    int             value;
}
                dataFormats[] =
{
    "ulaw8", AuFormatULAW8,
    "linu8", AuFormatLinearUnsigned8,
    "lins8", AuFormatLinearSigned8,
    "lins16m", AuFormatLinearSigned16MSB,
    "linu16m", AuFormatLinearUnsigned16MSB,
    "lins16l", AuFormatLinearSigned16LSB,
    "linu16l", AuFormatLinearUnsigned16LSB,
};

static void
fatalError(message, arg)
char           *message,
               *arg;
{
    fprintf(stderr, message, arg);
    fprintf(stderr, "\n");
    exit(1);
}

static void
usage()
{
    int             i;

    fprintf(stderr, USAGE);

    fprintf(stderr, "\nFile Formats:\n\n");

    for (i = 0; i < SoundNumFileFormats; i++)
      fprintf(stderr, "%10s - %s\n", SoundFileFormatToAbbrev(i),
            SoundFileFormatToString(i));

    fprintf(stderr, "\nData Formats:\n\n");

    for (i = 0; i < sizeof(dataFormats) / sizeof(dataFormats[0]); i++)
      fprintf(stderr, "%10s - %s\n", dataFormats[i].string,
            AuFormatToString(dataFormats[i].value));

    fprintf(stderr, "\nNote that each file format may only support selected data formats\n");

    exit(1);
}

static int
convertDataFormat(s)
char           *s;
{
    int             f,
                    i;

    for (i = 0; i < sizeof(dataFormats) / sizeof(dataFormats[0]); i++)
      if (!strcasecmp(s, dataFormats[i].string))
          return dataFormats[i].value;

    usage();
}

static int
convertFileFormat(s)
char           *s;
{
    int             f;

    f = SoundAbbrevToFileFormat(s);

    if (f == -1)
      usage();

    return f;
}

static void
adjustVolume(count, data, v)
int             count;
short          *data;
float           v;
{
    while (count--)
      *data++ *= v;
}

static void
maxVolume(count, data)
int             count;
short          *data;
{
    int             n = count;
    short          *p = data,
                    m = 0;
    float           scale;

    while (n--)
    {
      m = max(m, abs(*p));
      *p++;
    }

    scale = 32767.0 / m;

    fprintf(stderr, "volume scaled by %f\n", scale);
    adjustVolume(count, data, scale);
}

static void
rateConvert(in, out, numBytes, data)
Sound           in,
                out;
int             numBytes;
char           *data;
{
    int             size = SoundBytesPerSample(out),
                    phase = 0;
    char           *last;

    if (!(last = (char *) malloc(size)))
      fatalError("Malloc error");

    while (numBytes)
    {
      while (phase >= 0)
      {
          if (!numBytes)
          {
            free(last);
            return;
          }

          phase -= SoundSampleRate(out);
          bcopy(data, last, size);
          data += size;
          numBytes -= size;
      }

      phase += SoundSampleRate(in);

      if (SoundWriteFile(last, size, out) != size)
          fatalError("Error writing output file");
    }

    free(last);
}

int
main(argc, argv)
int             argc;
char          **argv;
{
    FILE           *fp;
    char           *arg,
                   *inputFile = NULL,
                   *outputFile = NULL,
                   *comment = NULL,
                   *volume = "100",
                   *mktemp(),
                   *outName;
    int             fileFormat = -1,
                    dataFormat = -1,
                    vol,
                    rawFormat = -1,
                    rawTracks,
#if defined(HAS_MKSTEMP)
                    fd = -1, 
#endif
                    outputDataFormat;
    AuUint32        rate = 0,
                    numBytes;
    Sound           in,
                    out;
    short          *data;

    while (--argc)
    {
      arg = *(++argv);

      if (OPTION("-f"))
          GETARG(fileFormat, convertFileFormat(arg));
      else if (OPTION("-d"))
          GETARG(dataFormat, convertDataFormat(arg));
      else if (OPTION("-raw"))
      {
          GETARG(rawFormat, convertDataFormat(arg));
          GETARG(rawTracks, atoi(arg));
      }
      else if (OPTION("-rat"))
          GETARG(rate, atoi(arg));
      else if (OPTION("-c"))
          GETARG(comment, arg);
      else if (OPTION("-v"))
          GETARG(volume, arg);
      else if (OPTION("-?") || OPTION("-h"))
          usage();
      else if (inputFile)
          if (outputFile)
            usage();
          else
            outputFile = arg;
      else
          inputFile = arg;
    }

    if (!inputFile)
      inputFile = "-";

    if (rawFormat == -1)
    {
      if (!(in = SoundOpenFileForReading(inputFile)))
          fatalError("Can't open input file %s", inputFile);
    }
    else
    {
      if (fileFormat == -1)
          fatalError("You must specify a file format for raw files");

      if (!rate)
          fatalError("You must specify a sampling rate for raw files");

      if (!(fp = fopen(inputFile, "r")))
          fatalError("Can't open input file %s", inputFile);

      fseek(fp, 0, 2);
      numBytes = ftell(fp);
      rewind(fp);

      in = SoundCreate(SoundFileFormatNone, rawFormat, rawTracks, rate,
                   numBytes / rawTracks / AuSizeofFormat(rawFormat),
                   NULL);
      
      if (!in)
      {
          fprintf(stderr, "%s file format does not support %s data.\n",
                SoundFileFormatToString(fileFormat),
                AuFormatToString(rawFormat));
          exit(1);
      }
    }

    numBytes = SoundNumSamples(in) * SoundNumTracks(in) * sizeof(short);

    if (!(data = (short *) malloc(numBytes)))
      fatalError("Malloc error");

    if (rawFormat == -1)
    {
      if (SoundReadFile((char *) data, SoundNumBytes(in), in) !=
          SoundNumBytes(in))
          fatalError("Error reading input file");
    }
    else if (fread(data, 1, SoundNumBytes(in), fp) != SoundNumBytes(in))
      fatalError("Error reading input file");

    if (AuConvertDataToShort(SoundDataFormat(in), SoundNumBytes(in), data))
      fatalError("Error converting input data");

    if (!strncasecmp(volume, "max", 3))
      maxVolume(numBytes / sizeof(short), data);
    else if ((vol = atoi(volume)) != 100)
      adjustVolume(numBytes / sizeof(short), data, (float) vol / 100);

    outputDataFormat = dataFormat == -1 ? SoundDataFormat(in) : dataFormat;

    if (fileFormat == -1)
      fileFormat = SoundFileFormat(in);

    if (!SoundValidDataFormat(fileFormat, outputDataFormat))
    {
      fprintf(stderr, "%s file format does not support %s data.\n",
            SoundFileFormatToString(fileFormat),
            AuFormatToString(outputDataFormat));
      exit(1);
    }

    out = SoundCreate(fileFormat, outputDataFormat, SoundNumTracks(in),
                  rate ? rate : SoundSampleRate(in),
                  SoundUnknownNumSamples,
                  comment ? comment : SoundComment(in));

    if (!out)
      fatalError("Error creating output sound");

    if (AuConvertShortToData(outputDataFormat, numBytes, data))
      fatalError("Error converting output data");

    if (!outputFile && strcmp(inputFile, "-"))
    {
      if (!(outName = (char *) malloc(strlen(inputFile) + 7)))
          fatalError("Malloc error");

      sprintf(outName, "%sXXXXXX", inputFile);
#if defined(HAS_MKSTEMP)
      fd = mkstemp(outName);
#else
      outName = mktemp(outName);
#endif

    }
    else
      outName = outputFile;

#if defined(HAS_MKSTEMP)
    if ((-1 == fd) || (!SoundOpenFileForWriting(outName, out)))
#else
    if (!SoundOpenFileForWriting(outName, out))
#endif
      fatalError("Can't open output file %s", outName);

    numBytes = numBytes / sizeof(short) * SoundBytesPerSample(out);

    if (SoundSampleRate(in) == SoundSampleRate(out))
    {
      if (SoundWriteFile((char *) data, numBytes, out) != numBytes)
          fatalError("Error writing output file");
    }
    else
      rateConvert(in, out, numBytes, data);

    if (SoundCloseFile(out))
      fatalError("Error closing output file");

    if (!outputFile)
      {
#if defined(HAS_MKSTEMP)
      if (fd != -1)
        close(fd);
#endif
      if (rename(outName, inputFile))
        fatalError("Error renaming temp file");
      }

    exit(0);
}

Generated by  Doxygen 1.6.0   Back to index