Add an option to make HRTFs with a custom head radius
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
# This is a makehrtf HRIR definition file. It is used to define the layout
|
||||
# and source data to be processed into an OpenAL Soft compatible HRTF.
|
||||
#
|
||||
# This definition is used to transform the left ear HRIRs from a dataset
|
||||
# This definition is used to transform the left ear HRIRs from a data set
|
||||
# used in several papers and articles by Fumitada Itakura, Kazuya Takeda,
|
||||
# Mikio Ikeda, Shoji Kajita, and Takanori Nishino.
|
||||
#
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
# and source data to be processed into an OpenAL Soft compatible HRTF.
|
||||
#
|
||||
# This definition is used to transform an average of the left and right ear
|
||||
# HRIRs from any raw dataset from the IRCAM/AKG Listen HRTF database.
|
||||
# HRIRs from any raw data set from the IRCAM/AKG Listen HRTF database.
|
||||
#
|
||||
# The datasets are available free of charge from:
|
||||
# The data sets are available free of charge from:
|
||||
#
|
||||
# http://recherche.ircam.fr/equipes/salles/listen/index.html
|
||||
#
|
||||
@@ -32,7 +32,7 @@ distance = 1.95
|
||||
# The IRCAM source azimuth is counter-clockwise, so it needs to be flipped.
|
||||
# Left and right ear HRIRs (from the respective WAVE channels) are averaged.
|
||||
|
||||
# Repalce all occurrences of IRC_#### for the desired subject (1005 was used
|
||||
# Replace all occurrences of IRC_#### for the desired subject (1005 was used
|
||||
# in this demonstration).
|
||||
|
||||
[ 3, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav"
|
||||
|
||||
+12
-8
@@ -5,17 +5,17 @@
|
||||
# of KEMAR HRIRs provided by Bill Gardner <billg@media.mit.edu> and Keith
|
||||
# Martin <kdm@media.mit.edu> of MIT Media Laboratory.
|
||||
#
|
||||
# The data (full.tar.Z or full.zip) is available from:
|
||||
# The data (full.zip) is available from:
|
||||
#
|
||||
# http://sound.media.mit.edu/resources/KEMAR.html
|
||||
#
|
||||
# It is copyright 1994 by MIT Media Laboratory, and provided free of charge
|
||||
# It is copyrighted 1994 by MIT Media Laboratory, and provided free of charge
|
||||
# with no restrictions on use so long as the authors (above) are cited.
|
||||
#
|
||||
# This definition is used to generate the internal HRTF table used by OpenAL
|
||||
# Soft.
|
||||
|
||||
# The following are the dataset metrics. They must always be specified at
|
||||
# The following are the data set metrics. They must always be specified at
|
||||
# start of a definition file, but their order is not important.
|
||||
|
||||
# Sampling rate of the HRIR data (in hertz).
|
||||
@@ -28,17 +28,21 @@ rate = 44100
|
||||
points = 512
|
||||
|
||||
# A list of the number of azimuths measured for each elevation. There must
|
||||
# be at least 5 elevations covering the 180 degrees for the dataset to be
|
||||
# be at least 5 elevations covering the 180 degrees for the data set to be
|
||||
# viable.
|
||||
azimuths = 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1
|
||||
|
||||
# The approximate radius (measured ear-to-ear) of the listener's head (in
|
||||
# meters). This does not have to match the dataset, since makehrtf uses a
|
||||
# spherical model to reconstruct the propagation delay.
|
||||
# The radius of the listener's head (measured ear-to-ear in meters). The
|
||||
# makehrtf utility uses this value to rescale measured propagation delays
|
||||
# when a custom head radius is specified on the command line. It is also
|
||||
# used as the default radius when the spherical model is used to calculate an
|
||||
# approximate set of delays. This should match the data set as close as
|
||||
# possible for accurate rescaling when using the measured delays (the
|
||||
# default). At the moment, radius rescaling does not adjust HRIR coupling.
|
||||
radius = 0.09
|
||||
|
||||
# The distance between the source and the listener (in meters). This does
|
||||
# have to match the dataset, but it's effect is minimal at the moment due to
|
||||
# have to match the data set, but it's effect is minimal at the moment due to
|
||||
# the coupled nature of OpenAL Soft's HRTF model.
|
||||
distance = 1.4
|
||||
|
||||
|
||||
+23
-9
@@ -2,7 +2,7 @@
|
||||
* HRTF utility for producing and demonstrating the process of creating an
|
||||
* OpenAL Soft compatible HRIR data set.
|
||||
*
|
||||
* Copyright (C) 2011-2013 Christopher Fitzgerald
|
||||
* Copyright (C) 2011-2014 Christopher Fitzgerald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -58,7 +58,7 @@
|
||||
* 1999
|
||||
*/
|
||||
|
||||
/* Needed for 64-bit unsigned integer. */
|
||||
// Needed for 64-bit unsigned integer.
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -153,6 +153,10 @@
|
||||
#define MIN_TRUNCSIZE (8)
|
||||
#define MAX_TRUNCSIZE (128)
|
||||
|
||||
// The limits to the custom head radius on the command line.
|
||||
#define MIN_CUSTOM_RADIUS (0.05)
|
||||
#define MAX_CUSTOM_RADIUS (0.15)
|
||||
|
||||
// The truncation window size must be a multiple of the below value to allow
|
||||
// for vectorized convolution.
|
||||
#define MOD_TRUNCSIZE (8)
|
||||
@@ -163,6 +167,7 @@
|
||||
#define DEFAULT_LIMIT (24.0)
|
||||
#define DEFAULT_TRUNCSIZE (32)
|
||||
#define DEFAULT_HEAD_MODEL (HM_DATASET)
|
||||
#define DEFAULT_CUSTOM_RADIUS (0.0)
|
||||
|
||||
// The four-character-codes for RIFF/RIFX WAVE file chunks.
|
||||
#define FOURCC_RIFF (0x46464952) // 'RIFF'
|
||||
@@ -2016,7 +2021,7 @@ static double CalcLTD (const double ev, const double az, const double rad, const
|
||||
|
||||
// Calculate the effective head-related time delays for each minimum-phase
|
||||
// HRIR.
|
||||
static void CalculateHrtds (const HeadModelT model, HrirDataT * hData) {
|
||||
static void CalculateHrtds (const HeadModelT model, const double radius, HrirDataT * hData) {
|
||||
double minHrtd, maxHrtd;
|
||||
uint e, a, j;
|
||||
double t;
|
||||
@@ -2027,13 +2032,13 @@ static void CalculateHrtds (const HeadModelT model, HrirDataT * hData) {
|
||||
for (a = 0; a < hData -> mAzCount [e]; a ++) {
|
||||
j = hData -> mEvOffset [e] + a;
|
||||
if (model == HM_DATASET) {
|
||||
t = hData -> mHrtds [j];
|
||||
t = hData -> mHrtds [j] * radius / hData -> mRadius;
|
||||
} else {
|
||||
t = CalcLTD ((-90.0 + (e * 180.0 / (hData -> mEvCount - 1))) * M_PI / 180.0,
|
||||
(a * 360.0 / hData -> mAzCount [e]) * M_PI / 180.0,
|
||||
hData -> mRadius, hData -> mDistance);
|
||||
hData -> mHrtds [j] = t;
|
||||
radius, hData -> mDistance);
|
||||
}
|
||||
hData -> mHrtds [j] = t;
|
||||
maxHrtd = fmax (t, maxHrtd);
|
||||
minHrtd = fmin (t, minHrtd);
|
||||
}
|
||||
@@ -2506,7 +2511,7 @@ static int ProcessSources (const HeadModelT model, TokenReaderT * tr, HrirDataT
|
||||
* resulting data set as desired. If the input name is NULL it will read
|
||||
* from standard input.
|
||||
*/
|
||||
static int ProcessDefinition (const char * inName, const uint outRate, const uint fftSize, const int equalize, const int surface, const double limit, const uint truncSize, const HeadModelT model, const OutputFormatT outFormat, const char * outName) {
|
||||
static int ProcessDefinition (const char * inName, const uint outRate, const uint fftSize, const int equalize, const int surface, const double limit, const uint truncSize, const HeadModelT model, const double radius, const OutputFormatT outFormat, const char * outName) {
|
||||
FILE * fp = NULL;
|
||||
TokenReaderT tr;
|
||||
HrirDataT hData;
|
||||
@@ -2572,7 +2577,7 @@ static int ProcessDefinition (const char * inName, const uint outRate, const uin
|
||||
fprintf (stdout, "Normalizing final HRIRs...\n");
|
||||
NormalizeHrirs (& hData);
|
||||
fprintf (stdout, "Calculating impulse delays...\n");
|
||||
CalculateHrtds (model, & hData);
|
||||
CalculateHrtds (model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData . mRadius, & hData);
|
||||
snprintf (rateStr, 8, "%u", hData . mIrRate);
|
||||
StrSubst (outName, "%r", rateStr, MAX_PATH_LEN, expName);
|
||||
switch (outFormat) {
|
||||
@@ -2604,6 +2609,7 @@ int main (const int argc, const char * argv []) {
|
||||
double limit;
|
||||
uint truncSize;
|
||||
HeadModelT model;
|
||||
double radius;
|
||||
char * end = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
@@ -2632,6 +2638,7 @@ int main (const int argc, const char * argv []) {
|
||||
fprintf (stdout, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
|
||||
fprintf (stdout, " -d={dataset| Specify the model used for calculating the head-delay timing\n");
|
||||
fprintf (stdout, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
|
||||
fprintf (stdout, " -c=<size> Use a customized head radius measured ear-to-ear in meters.\n");
|
||||
fprintf (stdout, " -i=<filename> Specify an HRIR definition file to use (defaults to stdin).\n");
|
||||
fprintf (stdout, " -o=<filename> Specify an output file. Overrides command-selected default.\n");
|
||||
fprintf (stdout, " Use of '%%r' will be substituted with the data set sample rate.\n");
|
||||
@@ -2661,6 +2668,7 @@ int main (const int argc, const char * argv []) {
|
||||
limit = DEFAULT_LIMIT;
|
||||
truncSize = DEFAULT_TRUNCSIZE;
|
||||
model = DEFAULT_HEAD_MODEL;
|
||||
radius = DEFAULT_CUSTOM_RADIUS;
|
||||
while (argi < argc) {
|
||||
if (strncmp (argv [argi], "-r=", 3) == 0) {
|
||||
outRate = strtoul (& argv [argi] [3], & end, 10);
|
||||
@@ -2717,6 +2725,12 @@ int main (const int argc, const char * argv []) {
|
||||
fprintf (stderr, "Error: Expected 'dataset' or 'sphere' for '-d'.\n");
|
||||
return (-1);
|
||||
}
|
||||
} else if (strncmp (argv [argi], "-c=", 3) == 0) {
|
||||
radius = strtod (& argv [argi] [3], & 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);
|
||||
}
|
||||
} else if (strncmp (argv [argi], "-i=", 3) == 0) {
|
||||
inName = & argv [argi] [3];
|
||||
} else if (strncmp (argv [argi], "-o=", 3) == 0) {
|
||||
@@ -2727,7 +2741,7 @@ int main (const int argc, const char * argv []) {
|
||||
}
|
||||
argi ++;
|
||||
}
|
||||
if (! ProcessDefinition (inName, outRate, fftSize, equalize, surface, limit, truncSize, model, outFormat, outName))
|
||||
if (! ProcessDefinition (inName, outRate, fftSize, equalize, surface, limit, truncSize, model, radius, outFormat, outName))
|
||||
return (-1);
|
||||
fprintf (stdout, "Operation completed.\n");
|
||||
return (0);
|
||||
|
||||
Reference in New Issue
Block a user