Use getopt to handle options in makehrtf

This commit is contained in:
Chris Robinson 2017-08-20 04:30:53 -07:00
parent 051828344e
commit 55643d6370
5 changed files with 260 additions and 72 deletions

View File

@ -652,6 +652,8 @@ int main()
ENDIF()
ENDIF()
CHECK_SYMBOL_EXISTS(getopt unistd.h HAVE_GETOPT)
# Check for a 64-bit type
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
IF(NOT HAVE_STDINT_H)
@ -1395,6 +1397,9 @@ IF(ALSOFT_UTILS)
TARGET_LINK_LIBRARIES(openal-info OpenAL)
ADD_EXECUTABLE(makehrtf utils/makehrtf.c)
IF(NOT HAVE_GETOPT)
SET_PROPERTY(TARGET makehrtf APPEND PROPERTY SOURCE utils/getopt.c)
ENDIF()
SET_PROPERTY(TARGET makehrtf APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS})
IF(HAVE_LIBM)
TARGET_LINK_LIBRARIES(makehrtf m)

View File

@ -20,6 +20,9 @@
/* Define if we have the _aligned_malloc function */
#cmakedefine HAVE__ALIGNED_MALLOC
/* Define if we have the getopt function */
#cmakedefine HAVE_GETOPT
/* Define if we have SSE CPU extensions */
#cmakedefine HAVE_SSE
#cmakedefine HAVE_SSE2

137
utils/getopt.c Normal file
View File

@ -0,0 +1,137 @@
/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* Get program name in Windows
*/
const char * _getprogname(void);
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(int nargc, char * const nargv[], const char *ostr)
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
place = nargv[optind];
if (optind >= nargc || *place++ != '-') {
/* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
optopt = *place++;
if (optopt == '-' && *place == 0) {
/* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
if (optopt == 0) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
place = EMSG;
if (strchr(ostr, '-') == NULL)
return (-1);
optopt = '-';
}
} else
optopt = *place++;
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", _getprogname(),
optopt);
return (BADCH);
}
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (*place == 0)
++optind;
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*place)
optarg = place;
else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
_getprogname(), optopt);
return (BADCH);
}
place = EMSG;
++optind;
}
return (optopt); /* return option letter */
}
const char * _getprogname() {
char *pgmptr = NULL;
_get_pgmptr(&pgmptr);
return strrchr(pgmptr,'\\')+1;
}

26
utils/getopt.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef GETOPT_H
#define GETOPT_H
#ifndef _WIN32
#include <unistd.h>
#else /* _WIN32 */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern char *optarg;
extern int optind, opterr, optopt, optreset;
int getopt(int nargc, char * const nargv[], const char *ostr);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !_WIN32 */
#endif /* !GETOPT_H */

View File

@ -71,6 +71,11 @@
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#ifdef HAVE_GETOPT
#include <unistd.h>
#else
#include "getopt.h"
#endif
// Rely (if naively) on OpenAL's header for the types used for serialization.
#include "AL/al.h"
@ -2911,26 +2916,26 @@ static void PrintHelp(const char *argv0, FILE *ofile)
fprintf(ofile, " Defaults output to: ./oalsoft_hrtf_%%r.mhr\n");
fprintf(ofile, " -h, --help Displays this help information.\n\n");
fprintf(ofile, "Options:\n");
fprintf(ofile, " -r=<rate> Change the data set sample rate to the specified value and\n");
fprintf(ofile, " -r <rate> Change the data set sample rate to the specified value and\n");
fprintf(ofile, " resample the HRIRs accordingly.\n");
fprintf(ofile, " -f=<points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE);
fprintf(ofile, " -e={on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
fprintf(ofile, " -s={on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
fprintf(ofile, " -l={<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n");
fprintf(ofile, " -f <points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE);
fprintf(ofile, " -e {on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
fprintf(ofile, " -s {on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
fprintf(ofile, " -l {<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n");
fprintf(ofile, " average (default: %.2f).\n", DEFAULT_LIMIT);
fprintf(ofile, " -w=<points> Specify the size of the truncation window that's applied\n");
fprintf(ofile, " -w <points> Specify the size of the truncation window that's applied\n");
fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
fprintf(ofile, " -d={dataset| Specify the model used for calculating the head-delay timing\n");
fprintf(ofile, " -d {dataset| Specify the model used for calculating the head-delay timing\n");
fprintf(ofile, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
fprintf(ofile, " -c=<size> Use a customized head radius measured ear-to-ear in meters.\n");
fprintf(ofile, " -i=<filename> Specify an HRIR definition file to use (defaults to stdin).\n");
fprintf(ofile, " -o=<filename> Specify an output file. Overrides command-selected default.\n");
fprintf(ofile, " -c <size> Use a customized head radius measured ear-to-ear in meters.\n");
fprintf(ofile, " -i <filename> Specify an HRIR definition file to use (defaults to stdin).\n");
fprintf(ofile, " -o <filename> Specify an output file. Overrides command-selected default.\n");
fprintf(ofile, " Use of '%%r' will be substituted with the data set sample rate.\n");
}
#ifdef _WIN32
#define main my_main
int main(int argc, const char *argv[]);
int main(int argc, char *argv[]);
static char **arglist;
static void cleanup_arglist(void)
@ -2950,12 +2955,12 @@ int wmain(int argc, const wchar_t *wargv[])
for(i = 0;i < argc;i++)
arglist[i] = ToUTF8(wargv[i]);
return main(argc, (const char**)arglist);
return main(argc, arglist);
}
#endif
// Standard command line dispatch.
int main(int argc, const char *argv[])
int main(int argc, char *argv[])
{
const char *inName = NULL, *outName = NULL;
OutputFormatT outFormat;
@ -2967,13 +2972,13 @@ int main(int argc, const char *argv[])
uint truncSize;
double radius;
double limit;
int argi;
int opt;
if(argc < 2 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)
{
fprintf(stdout, "HRTF Processing and Composition Utility\n\n");
PrintHelp(argv[0], stdout);
return 0;
exit(EXIT_SUCCESS);
}
if(strcmp(argv[1], "--make-mhr") == 0 || strcmp(argv[1], "-m") == 0)
@ -2985,7 +2990,7 @@ int main(int argc, const char *argv[])
{
fprintf(stderr, "Error: Invalid command '%s'.\n\n", argv[1]);
PrintHelp(argv[0], stderr);
return -1;
exit(EXIT_FAILURE);
}
outRate = 0;
@ -2998,112 +3003,124 @@ int main(int argc, const char *argv[])
radius = DEFAULT_CUSTOM_RADIUS;
experimental = 0;
argi = 2;
while(argi < argc)
optind = 2;
while((opt=getopt(argc, argv, "r:f:e:s:k:w:d:c:e:i:o:xh")) != -1)
{
if(strncmp(argv[argi], "-r=", 3) == 0)
switch(opt)
{
outRate = strtoul(&argv[argi][3], &end, 10);
case 'r':
outRate = strtoul(optarg, &end, 10);
if(end[0] != '\0' || outRate < MIN_RATE || outRate > MAX_RATE)
{
fprintf(stderr, "Error: Expected a value from %u to %u for '-r'.\n", MIN_RATE, MAX_RATE);
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-f=", 3) == 0)
{
fftSize = strtoul(&argv[argi][3], &end, 10);
break;
case 'f':
fftSize = strtoul(optarg, &end, 10);
if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MIN_FFTSIZE || fftSize > MAX_FFTSIZE)
{
fprintf(stderr, "Error: Expected a power-of-two value from %u to %u for '-f'.\n", MIN_FFTSIZE, MAX_FFTSIZE);
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-e=", 3) == 0)
{
if(strcmp(&argv[argi][3], "on") == 0)
break;
case 'e':
if(strcmp(optarg, "on") == 0)
equalize = 1;
else if(strcmp(&argv[argi][3], "off") == 0)
else if(strcmp(optarg, "off") == 0)
equalize = 0;
else
{
fprintf(stderr, "Error: Expected 'on' or 'off' for '-e'.\n");
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-s=", 3) == 0)
{
if(strcmp(&argv[argi][3], "on") == 0)
break;
case 's':
if(strcmp(optarg, "on") == 0)
surface = 1;
else if(strcmp(&argv[argi][3], "off") == 0)
else if(strcmp(optarg, "off") == 0)
surface = 0;
else
{
fprintf(stderr, "Error: Expected 'on' or 'off' for '-s'.\n");
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-l=", 3) == 0)
{
if(strcmp(&argv[argi][3], "none") == 0)
break;
case 'l':
if(strcmp(optarg, "none") == 0)
limit = 0.0;
else
{
limit = strtod(&argv[argi] [3], &end);
limit = strtod(optarg, &end);
if(end[0] != '\0' || limit < MIN_LIMIT || limit > MAX_LIMIT)
{
fprintf(stderr, "Error: Expected 'none' or a value from %.2f to %.2f for '-l'.\n", MIN_LIMIT, MAX_LIMIT);
return -1;
exit(EXIT_FAILURE);
}
}
}
else if(strncmp(argv[argi], "-w=", 3) == 0)
{
truncSize = strtoul(&argv[argi][3], &end, 10);
break;
case 'w':
truncSize = strtoul(optarg, &end, 10);
if(end[0] != '\0' || truncSize < MIN_TRUNCSIZE || truncSize > MAX_TRUNCSIZE || (truncSize%MOD_TRUNCSIZE))
{
fprintf(stderr, "Error: Expected a value from %u to %u in multiples of %u for '-w'.\n", MIN_TRUNCSIZE, MAX_TRUNCSIZE, MOD_TRUNCSIZE);
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-d=", 3) == 0)
{
if(strcmp(&argv[argi][3], "dataset") == 0)
break;
case 'd':
if(strcmp(optarg, "dataset") == 0)
model = HM_DATASET;
else if(strcmp(&argv[argi][3], "sphere") == 0)
else if(strcmp(optarg, "sphere") == 0)
model = HM_SPHERE;
else
{
fprintf(stderr, "Error: Expected 'dataset' or 'sphere' for '-d'.\n");
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-c=", 3) == 0)
{
radius = strtod(&argv[argi][3], &end);
break;
case 'c':
radius = strtod(optarg, &end);
if(end[0] != '\0' || radius < MIN_CUSTOM_RADIUS || radius > MAX_CUSTOM_RADIUS)
{
fprintf(stderr, "Error: Expected a value from %.2f to %.2f for '-c'.\n", MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS);
return -1;
exit(EXIT_FAILURE);
}
}
else if(strncmp(argv[argi], "-i=", 3) == 0)
inName = &argv[argi][3];
else if(strncmp(argv[argi], "-o=", 3) == 0)
outName = &argv[argi][3];
else if(strcmp(argv[argi], "--experimental") == 0)
break;
case 'i':
inName = optarg;
break;
case 'o':
outName = optarg;
break;
case 'x':
experimental = 1;
else
{
fprintf(stderr, "Error: Invalid option '%s'.\n", argv[argi]);
return -1;
break;
case 'h':
PrintHelp(argv[0], stdout);
exit(EXIT_SUCCESS);
default: /* '?' */
PrintHelp(argv[0], stderr);
exit(EXIT_FAILURE);
}
argi++;
}
if(!ProcessDefinition(inName, outRate, fftSize, equalize, surface, limit,
truncSize, model, radius, outFormat, experimental,
outName))
return -1;
fprintf(stdout, "Operation completed.\n");
return 0;
return EXIT_SUCCESS;
}