[SCM] brutefir/master: Imported Upstream version 1.0m
mira-guest at users.alioth.debian.org
mira-guest at users.alioth.debian.org
Sun Feb 23 16:23:02 UTC 2014
The following commit has been merged in the master branch:
commit 8163a6ac775b9b177cbfb1f8f68ca8ab3735a576
Author: Jaromír Mikeš <mira.mikes at seznam.cz>
Date: Sun Feb 23 17:20:59 2014 +0100
Imported Upstream version 1.0m
diff --git a/CHANGES b/CHANGES
index 4dfd506..ca4eda6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+BruteFIR v1.0m November 27, 2013
+ * Fixed SSE2 bug introduced in 1.0l.
+ * Added safety_limit feature to protect speakers.
+ * Fixed a rare race condition on multi-core.
+ * More sample format fixing, removed S16_4*, changed S24_4* to
+ represent low bits in sample, so it matches ALSA formats. If
+ you used S24_4LE in earlier versions you should now use S32_LE.
+
BruteFIR v1.0l October 6, 2013
* Made the code compile well on x86-64.
* Replaced legacy assembler code with new SSE/SSE2 C code,
diff --git a/README b/README
index e47e99d..a78a68c 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
-BruteFIR v1.0l
+BruteFIR v1.0m
================================================================================
This is the source code for a generic FIR filter (convolution) engine,
@@ -13,4 +13,4 @@ web may be more up to date.
Anders Torger, torger at ludd.ltu.se
-October 2013
+November 2013
diff --git a/bfconf.c b/bfconf.c
index 743eb71..6c52582 100644
--- a/bfconf.c
+++ b/bfconf.c
@@ -203,7 +203,8 @@ modules_path: \".\"; # extra path where to find BruteFIR modules\n\
monitor_rate: false; # monitor sample rate\n\
powersave: false; # pause filtering when input is zero\n\
lock_memory: true; # try to lock memory if realtime prio is set\n\
-sdf_length: -1; # subsample filter half length in samples\n"
+sdf_length: -1; # subsample filter half length in samples\n\
+safety_limit: 20; # if non-zero max dB in output before aborting\n"
#ifdef CONVOLVER_NEEDS_CONFIGFILE
"convolver_config: \"~/.brutefir_convolver\"; # location of "
"convolver config file\n"
@@ -391,20 +392,6 @@ parse_sample_format(struct sample_format *sf,
sf->bytes = 2;
sf->sbytes = 2;
native_endian = true;
- } else if (strcasecmp(s, "S16_4LE") == 0) {
- sf->format = BF_SAMPLE_FORMAT_S16_4LE;
- sf->bytes = 4;
- sf->sbytes = 2;
- } else if (strcasecmp(s, "S16_4BE") == 0) {
- sf->format = BF_SAMPLE_FORMAT_S16_4BE;
- sf->bytes = 4;
- sf->sbytes = 2;
- little_endian = false;
- } else if (strcasecmp(s, "S16_4NE") == 0) {
- sf->format = BF_SAMPLE_FORMAT_S16_4NE;
- sf->bytes = 4;
- sf->sbytes = 2;
- native_endian = true;
} else if (strcasecmp(s, "S24_LE") == 0 || strcasecmp(s, "S24_3LE") == 0) {
sf->format = BF_SAMPLE_FORMAT_S24_LE;
sf->bytes = 3;
@@ -485,7 +472,7 @@ parse_sample_format(struct sample_format *sf,
if (sf->isfloat) {
sf->scale = 1.0;
} else {
- sf->scale = 1.0 / (double)(1 << ((sf->sbytes << 3) - 1));
+ sf->scale = 1.0 / (double)((uint64_t)1 << ((sf->sbytes << 3) - 1));
}
#ifdef __BIG_ENDIAN__
if (native_endian) {
@@ -494,9 +481,6 @@ parse_sample_format(struct sample_format *sf,
case BF_SAMPLE_FORMAT_S16_NE:
sf->format = BF_SAMPLE_FORMAT_S16_BE;
break;
- case BF_SAMPLE_FORMAT_S16_4NE:
- sf->format = BF_SAMPLE_FORMAT_S16_4LE;
- break;
case BF_SAMPLE_FORMAT_S24_NE:
sf->format = BF_SAMPLE_FORMAT_S24_BE;
break;
@@ -523,9 +507,6 @@ parse_sample_format(struct sample_format *sf,
case BF_SAMPLE_FORMAT_S16_NE:
sf->format = BF_SAMPLE_FORMAT_S16_LE;
break;
- case BF_SAMPLE_FORMAT_S16_4NE:
- sf->format = BF_SAMPLE_FORMAT_S16_4LE;
- break;
case BF_SAMPLE_FORMAT_S24_NE:
sf->format = BF_SAMPLE_FORMAT_S24_LE;
break;
@@ -1643,6 +1624,15 @@ parse_setting(char field[],
unexpected_token(EOS, token);
break;
}
+ } else if (strcmp(field, "safety_limit") == 0) {
+ field_repeat_test(repeat_bitset, 18);
+ get_token(REAL);
+ bfconf->safety_limit = pow(10.0, yylval.real / 20.0);
+ if (!isfinite(bfconf->safety_limit)) {
+ fprintf(stderr, "invalid safety_limit.\n");
+ exit(BF_EXIT_INVALID_CONFIG);
+ }
+ get_token(EOS);
} else {
parse_error("unrecognised setting name.\n");
}
@@ -1814,13 +1804,13 @@ raw_read(FILE *stream,
}
realbuf = emalloc((*totitems) * realsize);
if (realsize == 4) {
- raw2realf(realbuf, rawbuf, sf->bytes, (sf->bytes - sf->sbytes) << 3,
+ raw2realf(realbuf, rawbuf, sf->bytes,
sf->isfloat, 1, sf->swap, *totitems);
for (n_items = 0; n_items < *totitems; n_items++) {
((float *)realbuf)[n_items] *= (float)sf->scale;
}
} else {
- raw2reald(realbuf, rawbuf, sf->bytes, (sf->bytes - sf->sbytes) << 3,
+ raw2reald(realbuf, rawbuf, sf->bytes,
sf->isfloat, 1, sf->swap, *totitems);
for (n_items = 0; n_items < *totitems; n_items++) {
((double *)realbuf)[n_items] *= sf->scale;
@@ -2372,6 +2362,7 @@ bfconf_init(char filename[],
bfconf->sdf_length = -1;
bfconf->quiet = quiet;
bfconf->realsize = sizeof(float);
+ bfconf->safety_limit = 0;
if (!nodefault) {
get_defaults();
diff --git a/bfconf.h b/bfconf.h
index 8d9cfb7..7fdd9c7 100644
--- a/bfconf.h
+++ b/bfconf.h
@@ -1,5 +1,5 @@
/*
- * (c) Copyright 2001 - 2004, 2006 -- Anders Torger
+ * (c) Copyright 2001 - 2004, 2006, 2013 -- Anders Torger
*
* This program is open source. For license terms, see the LICENSE file.
*
@@ -76,6 +76,7 @@ struct bfconf {
int *subdelay[2];
int sdf_length;
double sdf_beta;
+ double safety_limit;
};
extern struct bfconf *bfconf;
diff --git a/bfio_alsa.c b/bfio_alsa.c
index 955dcab..0daa32c 100644
--- a/bfio_alsa.c
+++ b/bfio_alsa.c
@@ -110,12 +110,10 @@ set_params(snd_pcm_t *handle,
format = SND_PCM_FORMAT_S24_BE;
*sample_size = 4;
break;
- case BF_SAMPLE_FORMAT_S16_4LE:
case BF_SAMPLE_FORMAT_S32_LE:
format = SND_PCM_FORMAT_S32_LE;
*sample_size = 4;
break;
- case BF_SAMPLE_FORMAT_S16_4BE:
case BF_SAMPLE_FORMAT_S32_BE:
format = SND_PCM_FORMAT_S32_BE;
*sample_size = 4;
diff --git a/bfio_oss.c b/bfio_oss.c
index 39c61cb..ebccca3 100644
--- a/bfio_oss.c
+++ b/bfio_oss.c
@@ -83,12 +83,10 @@ set_params(int fd,
break;
#endif
#ifdef AFMT_S32_LE
- case BF_SAMPLE_FORMAT_S16_4LE:
case BF_SAMPLE_FORMAT_S24_4LE:
case BF_SAMPLE_FORMAT_S32_LE:
format = AFMT_S32_LE;
break;
- case BF_SAMPLE_FORMAT_S16_4BE:
case BF_SAMPLE_FORMAT_S24_4BE:
case BF_SAMPLE_FORMAT_S32_BE:
format = AFMT_S32_BE;
diff --git a/bfmod.h b/bfmod.h
index 0b5d004..a70b9e9 100644
--- a/bfmod.h
+++ b/bfmod.h
@@ -34,8 +34,8 @@ extern "C" {
#define BF_SAMPLE_FORMAT_S8 1
#define BF_SAMPLE_FORMAT_S16_LE 2
#define BF_SAMPLE_FORMAT_S16_BE 3
-#define BF_SAMPLE_FORMAT_S16_4LE 4
-#define BF_SAMPLE_FORMAT_S16_4BE 5
+#define BF_SAMPLE_FORMAT_S16_4LE 4 // unused since 1.0m
+#define BF_SAMPLE_FORMAT_S16_4BE 5 // unused since 1.0m
#define BF_SAMPLE_FORMAT_S24_LE 6
#define BF_SAMPLE_FORMAT_S24_BE 7
#define BF_SAMPLE_FORMAT_S24_4LE 8
@@ -51,7 +51,7 @@ extern "C" {
/* macro sample formats */
#define BF_SAMPLE_FORMAT_S16_NE 16
-#define BF_SAMPLE_FORMAT_S16_4NE 17
+#define BF_SAMPLE_FORMAT_S16_4NE 17 // unused since 1.0m
#define BF_SAMPLE_FORMAT_S24_NE 18
#define BF_SAMPLE_FORMAT_S24_4NE 19
#define BF_SAMPLE_FORMAT_S32_NE 20
diff --git a/bfrun.c b/bfrun.c
index 4f56cad..1dad9ce 100644
--- a/bfrun.c
+++ b/bfrun.c
@@ -983,13 +983,35 @@ apply_subdelay(void *realbuf,
}
static void
+synch_filter_processes(int filter_readfd,
+ int filter_writefd[],
+ int process_index)
+{
+ int n;
+ char dummydata[bfconf->n_processes - 1];
+ if (bfconf->n_processes > 1) {
+ for (n = 0; n < bfconf->n_processes; n++) {
+ if (n != process_index) {
+ dummydata[0] = 0;
+ if (!writefd(filter_writefd[n], dummydata, 1)) {
+ bf_exit(BF_EXIT_OTHER);
+ }
+ }
+ }
+ if (!readfd(filter_readfd, dummydata, bfconf->n_processes - 1)) {
+ bf_exit(BF_EXIT_OTHER);
+ }
+ }
+}
+
+static void
filter_process(struct bfaccess *bfaccess,
void *inbuf[2],
void *outbuf[2],
void *input_freqcbuf[],
void *output_freqcbuf[],
int filter_readfd,
- int filter_writefd,
+ int filter_writefd[],
int input_readfd,
int cb_input_readfd,
int output_writefd,
@@ -1101,13 +1123,7 @@ filter_process(struct bfaccess *bfaccess,
if (!readfd(input_readfd, dummydata, 1)) { /* for init */
bf_exit(BF_EXIT_OTHER);
}
- if (bfconf->n_processes > 1) {
- if (!writefd(filter_writefd, dummydata, 1) ||
- !readfd(filter_readfd, dummydata, 1))
- {
- bf_exit(BF_EXIT_OTHER);
- }
- }
+ synch_filter_processes(filter_readfd, filter_writefd, process_index);
/* allocate input delay buffers */
for (n = j = 0; n < n_procinputs; n++) {
@@ -1434,20 +1450,9 @@ filter_process(struct bfaccess *bfaccess,
tv = period_start;
events.block_start[i](bfaccess, blockcounter, &tv);
}
- if (bfconf->n_processes > 1) {
- if (!writefd(filter_writefd, dummydata, 1) ||
- !readfd(filter_readfd, dummydata, 1))
- {
- bf_exit(BF_EXIT_OTHER);
- }
- }
- } else {
- if (!readfd(filter_readfd, dummydata, 1) ||
- !writefd(filter_writefd, dummydata, 1))
- {
- bf_exit(BF_EXIT_OTHER);
- }
}
+ synch_filter_processes(filter_readfd, filter_writefd,
+ process_index);
}
/* get all shared memory data we need where mutex is important */
@@ -1554,13 +1559,7 @@ filter_process(struct bfaccess *bfaccess,
}
timestamp(&icomm->debug.f[dbg_pos].fsynch_fd.ts_call);
- if (bfconf->n_processes > 1) {
- if (!writefd(filter_writefd, dummydata, 1) ||
- !readfd(filter_readfd, dummydata, 1))
- {
- bf_exit(BF_EXIT_OTHER);
- }
- }
+ synch_filter_processes(filter_readfd, filter_writefd, process_index);
timestamp(&icomm->debug.f[dbg_pos].fsynch_fd.ts_ret);
for (n = 0; n < n_filters; n++) {
@@ -1870,13 +1869,7 @@ filter_process(struct bfaccess *bfaccess,
t[4] += t2 - t1;
timestamp(&icomm->debug.f[dbg_pos].fsynch_td.ts_call);
- if (bfconf->n_processes > 1) {
- if (!writefd(filter_writefd, dummydata, 1) ||
- !readfd(filter_readfd, dummydata, 1))
- {
- bf_exit(BF_EXIT_OTHER);
- }
- }
+ synch_filter_processes(filter_readfd, filter_writefd, process_index);
timestamp(&icomm->debug.f[dbg_pos].fsynch_td.ts_ret);
mixbuf_is_filled = false;
@@ -2141,12 +2134,13 @@ bfrun(void)
int synch_pipe[2];
int bl_input_2_filter[2];
int filter_2_bl_output[2], filter2filter_pipes[bfconf->n_processes][2];
+ int filter_writefd[bfconf->n_processes];
char dummydata[bfconf->n_processes];
void *buffers[2][2];
void *input_freqcbuf[bfconf->n_channels[IN]], *input_freqcbuf_base;
void *output_freqcbuf[bfconf->n_channels[OUT]], *output_freqcbuf_base;
int nc[2], cpos[2], channels[2][BF_MAXCHANNELS];
- int n, i, j, prev, cbufsize, physch;
+ int n, i, j, cbufsize, physch;
bool_t checkdrift, trigger;
struct bfaccess bfaccess;
pid_t pid;
@@ -2277,7 +2271,7 @@ bfrun(void)
reset_overflow[n].max = 1.0;
} else {
reset_overflow[n].max = (double)
- (1 << ((dai_buffer_format[OUT]->bf[physch].
+ ((uint64_t)1 << ((dai_buffer_format[OUT]->bf[physch].
sf.sbytes << 3) - 1)) - 1;
}
icomm->overflow[n] = reset_overflow[n];
@@ -2334,8 +2328,6 @@ bfrun(void)
switch (pid = fork()) {
case 0:
- prev = (n == 0) ? bfconf->n_processes - 1 : n - 1;
-
close(bl_output_2_bl_input[0]);
close(bl_output_2_bl_input[1]);
close(bl_input_2_filter[1]);
@@ -2343,13 +2335,12 @@ bfrun(void)
close(cb_input_2_filter[1]);
close(filter_2_cb_output[0]);
for (i = 0; i < bfconf->n_processes; i++) {
- if (i == prev) {
+ if (i == n) {
+ filter_writefd[i] = -1;
close(filter2filter_pipes[i][1]);
- } else if (i == n) {
- close(filter2filter_pipes[i][0]);
} else {
close(filter2filter_pipes[i][0]);
- close(filter2filter_pipes[i][1]);
+ filter_writefd[i] = filter2filter_pipes[i][1];
}
}
@@ -2358,8 +2349,8 @@ bfrun(void)
buffers[OUT],
input_freqcbuf,
output_freqcbuf,
- filter2filter_pipes[prev][0],
- filter2filter_pipes[n][1],
+ filter2filter_pipes[n][0],
+ filter_writefd,
bl_input_2_filter[0],
cb_input_2_filter[0],
filter_2_bl_output[1],
diff --git a/brutefir.c b/brutefir.c
index c1d4d18..c9d08cb 100644
--- a/brutefir.c
+++ b/brutefir.c
@@ -19,7 +19,7 @@
#define PRESENTATION_STRING \
"\n\
-BruteFIR v1.0l (October 2013) \
+BruteFIR v1.0m (November 2013) \
(c) Anders Torger\n\
\n"
diff --git a/brutefir.html b/brutefir.html
index 9c6850e..646808d 100644
--- a/brutefir.html
+++ b/brutefir.html
@@ -6,7 +6,7 @@
</head>
<body>
<h1>BruteFIR</h1>
-<em>last updated 2013-10-06</em>
+<em>last updated 2013-11-29</em>
<hr>
<h2>Table of contents</h2>
<ul>
@@ -67,6 +67,23 @@
<p>
<h2><a name="news">News</a></h2>
+<strong>2013-11-29</strong><br>
+There was still a typo in the last uploaded 1.0m affecting
+SSE2. Uploaded fix.
+<p>
+<strong>2013-11-28</strong><br>
+There was a typo in the last uploaded 1.0m release causing the
+S24_LE/S24_3LE formats to break for input. So if you downloaded 1.0m
+yesterday please do it again.
+<p>
+<strong>2013-11-27</strong><br>
+BruteFIR v1.0m. Fixed an SSE2 bug introduced in 1.0l. Added
+'safety_limit' feature which can be used to protect your expensive
+speakers (and sensitive ears). Also fixed a rare race condition bug
+and further synchronized sample formats with ALSA, so now S24_4LE
+means low 24 bits of 32 bit word. Thus if you used S24_4LE before you
+should use S32_LE now to get the old behavior.
+<p>
<strong>2013-10-06</strong><br>
BruteFIR v1.0l. Refreshed code to compile well on x86-64, dropped
3Dnow support and replaced the hand-coded SSE with SSE C code, and
@@ -736,8 +753,8 @@ non-portable Intel Native signalling processing library <a
href="brutefir.html#nsp">[19]</a>.
<h2><a name="download">Where can I get it?</a></h2>
-You are free to <a href="files/brutefir-1.0l.tar.gz">download version
-1.0l</a>.
+You are free to <a href="files/brutefir-1.0m.tar.gz">download version
+1.0m</a>.
<p>
The package contains the source-code, you will need a supported
platform to run it on (Linux is recommended, but FreeBSD or Solaris
@@ -1110,6 +1127,7 @@ lock_memory: <BOOLEAN: try to lock memory if realtime prio is set>;
sdf_length: <NUMBER: sub-sample delay filter half length in samples>[, <NUMBER: kaiser window beta>];
convolver_config: <STRING: file to store FFTW wisdom in>;
benchmark: <BOOLEAN: start in benchmark mode (can only be used in main config file)>;
+safety_limit: <NUMBER: if non-zero max dB in output before aborting>;
</pre>
<p>
The <tt>filter_length</tt> setting specifies how long the filters
@@ -1256,6 +1274,12 @@ response is flat up to 19 kHz, and then a soft rolloff begins which
reaches -0.20 dB at 20 kHz, which is good enough for most needs. The
next natural step, 63, keeps a flat response up to about 20500 Hz,
with -0.20 dB at 21 kHz.
+<p>
+The purpose of the <tt>safety_limit</tt> setting is to protect your
+ears and expensive speakers, it's active if set to a non-zero
+value. Every output sample is checked and if it exceeds this value (in
+dB) BruteFIR will immediately exit with an error message, before any
+sound is sent to the output.
<h3><a name="config_2">General structure syntax</a></h3>
<pre>
diff --git a/fftw_convolver.c b/fftw_convolver.c
index 308d0a8..8fc3c0e 100644
--- a/fftw_convolver.c
+++ b/fftw_convolver.c
@@ -178,11 +178,11 @@ convolver_raw2cbuf(void *rawbuf,
{
if (realsize == 4) {
raw2realf(next_cbuf, (void *)&((uint8_t *)rawbuf)[bf->byte_offset],
- bf->sf.bytes, (bf->sf.bytes - bf->sf.sbytes) << 3,
+ bf->sf.bytes,
bf->sf.isfloat, bf->sample_spacing, bf->sf.swap, n_fft2);
} else {
raw2reald(next_cbuf, (void *)&((uint8_t *)rawbuf)[bf->byte_offset],
- bf->sf.bytes, (bf->sf.bytes - bf->sf.sbytes) << 3,
+ bf->sf.bytes,
bf->sf.isfloat, bf->sample_spacing, bf->sf.swap, n_fft2);
}
if (postprocess != NULL) {
@@ -254,7 +254,8 @@ convolver_convolve_add(void *input_cbuf,
void *coeffs,
void *output_cbuf)
{
-/*
+ /*
+#define real_t double
real_t *_b = (real_t *)emallocaligned(n_fft * sizeof(real_t));
real_t *_c = (real_t *)emallocaligned(n_fft * sizeof(real_t));
real_t *_d = (real_t *)emallocaligned(n_fft * sizeof(real_t));
@@ -262,7 +263,7 @@ convolver_convolve_add(void *input_cbuf,
memcpy(_b, input_cbuf, n_fft * sizeof(real_t));
memcpy(_c, coeffs, n_fft * sizeof(real_t));
memcpy(_d, output_cbuf, n_fft * sizeof(real_t));
-*/
+ */
switch (opt_code) {
#if defined(__ARCH_IA32__) || defined(__ARCH_X86_64__)
case OPT_CODE_SSE:
@@ -272,7 +273,7 @@ convolver_convolve_add(void *input_cbuf,
#ifdef __SSE2__
case OPT_CODE_SSE2:
convolver_sse2_convolve_add(input_cbuf, coeffs, output_cbuf,
- n_fft >> 4);
+ n_fft >> 3);
break;
#endif
#endif
@@ -284,7 +285,7 @@ convolver_convolve_add(void *input_cbuf,
convolve_addd(input_cbuf, coeffs, output_cbuf);
}
}
-/*
+ /*
{
real_t d1s, d2s, err, e;
int n;
@@ -314,12 +315,15 @@ convolver_convolve_add(void *input_cbuf,
err += e;
}
}
- fprintf(stderr, "err: %.10e\n", err);
+ if (err > 0.0) {
+ fprintf(stderr, "err: %.10e\n", err);
+ }
efree(_b);
efree(_c);
efree(_d);
+#undef real_t
}
-*/
+ */
}
void
@@ -487,13 +491,11 @@ convolver_cbuf2raw(void *cbuf,
dither_preloop_real2int_hp_tpdf(dither_state, n_fft2);
real2rawf_hp_tpdf((void *)&((uint8_t *)outbuf)[bf->byte_offset],
cbuf, bf->sf.sbytes << 3, bf->sf.bytes,
- (bf->sf.bytes - bf->sf.sbytes) << 3,
bf->sf.isfloat, bf->sample_spacing,
bf->sf.swap, n_fft2, overflow, dither_state);
} else {
real2rawf_no_dither((void *)&((uint8_t *)outbuf)[bf->byte_offset],
cbuf, bf->sf.sbytes << 3, bf->sf.bytes,
- (bf->sf.bytes - bf->sf.sbytes) << 3,
bf->sf.isfloat, bf->sample_spacing,
bf->sf.swap, n_fft2, overflow);
}
@@ -502,14 +504,12 @@ convolver_cbuf2raw(void *cbuf,
dither_preloop_real2int_hp_tpdf(dither_state, n_fft2);
real2rawd_hp_tpdf((void *)&((uint8_t *)outbuf)[bf->byte_offset],
cbuf, bf->sf.sbytes << 3, bf->sf.bytes,
- (bf->sf.bytes - bf->sf.sbytes) << 3,
bf->sf.isfloat, bf->sample_spacing,
bf->sf.swap, n_fft2, overflow, dither_state);
} else {
real2rawd_no_dither((void *)&((uint8_t *)outbuf)[bf->byte_offset],
cbuf, bf->sf.sbytes << 3,
bf->sf.bytes,
- (bf->sf.bytes - bf->sf.sbytes) << 3,
bf->sf.isfloat, bf->sample_spacing,
bf->sf.swap, n_fft2, overflow);
}
diff --git a/raw2real.h b/raw2real.h
index fbbc436..09bcaa6 100644
--- a/raw2real.h
+++ b/raw2real.h
@@ -1,5 +1,5 @@
/*
- * (c) Copyright 2001 - 2004 -- Anders Torger
+ * (c) Copyright 2001 - 2004, 2013 -- Anders Torger
*
* This program is open source. For license terms, see the LICENSE file.
*
@@ -8,7 +8,6 @@ static void
RAW2REAL_NAME(void *_realbuf,
void *_rawbuf,
int bytes,
- int shift,
bool_t isfloat,
int spacing,
bool_t swap,
@@ -20,10 +19,6 @@ RAW2REAL_NAME(void *_realbuf,
realbuf = (numunion_t *)_realbuf;
rawbuf = (numunion_t *)_rawbuf;
if (isfloat) {
- if (shift != 0) {
- fprintf(stderr, "Shift must be zero for floating point formats.\n");
- bf_exit(BF_EXIT_OTHER);
- }
#if REALSIZE == 4
#define RXX r32
#define REAL_T float
@@ -98,46 +93,32 @@ RAW2REAL_NAME(void *_realbuf,
}
break;
case 2:
- if (shift == 0) {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] = (REAL_T)((int16_t)SWAP16(rawbuf->u16[i]));
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] = (REAL_T)rawbuf->i16[i];
- }
- }
- } else {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] =
- (REAL_T)((int16_t)SWAP16(rawbuf->u16[i]) >> shift);
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] = (REAL_T)(rawbuf->i16[i] >> shift);
- }
- }
- }
+ if (swap) {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ realbuf->RXX[n] = (REAL_T)((int16_t)SWAP16(rawbuf->u16[i]));
+ }
+ } else {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ realbuf->RXX[n] = (REAL_T)rawbuf->i16[i];
+ }
+ }
break;
case 3:
spacing = spacing * 3 - 3;
- shift += 8;
#ifdef __BIG_ENDIAN__
if (swap) {
for (n = i = 0; n < n_samples; n++, i += spacing) {
sample.u8[2] = rawbuf->u8[i++];
sample.u8[1] = rawbuf->u8[i++];
sample.u8[0] = rawbuf->u8[i++];
- realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> shift);
+ realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> 8);
}
} else {
for (n = i = 0; n < n_samples; n++, i += spacing) {
sample.u8[0] = rawbuf->u8[i++];
sample.u8[1] = rawbuf->u8[i++];
sample.u8[2] = rawbuf->u8[i++];
- realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> shift);
+ realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> 8);
}
}
#endif
@@ -147,41 +128,28 @@ RAW2REAL_NAME(void *_realbuf,
sample.u8[3] = rawbuf->u8[i++];
sample.u8[2] = rawbuf->u8[i++];
sample.u8[1] = rawbuf->u8[i++];
- realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> shift);
+ realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> 8);
}
} else {
for (n = i = 0; n < n_samples; n++, i += spacing) {
sample.u8[1] = rawbuf->u8[i++];
sample.u8[2] = rawbuf->u8[i++];
sample.u8[3] = rawbuf->u8[i++];
- realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> shift);
+ realbuf->RXX[n] = (REAL_T)(sample.i32[0] >> 8);
}
}
#endif
break;
case 4:
- if (shift == 0) {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] = (REAL_T)((int32_t)SWAP32(rawbuf->u32[i]));
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] = (REAL_T)rawbuf->i32[i];
- }
- }
- } else {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] =
- (REAL_T)((int32_t)SWAP32(rawbuf->u32[i]) >> shift);
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- realbuf->RXX[n] = (REAL_T)(rawbuf->i32[i] >> shift);
- }
- }
- }
+ if (swap) {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ realbuf->RXX[n] = (REAL_T)((int32_t)SWAP32(rawbuf->u32[i]));
+ }
+ } else {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ realbuf->RXX[n] = (REAL_T)rawbuf->i32[i];
+ }
+ }
break;
default:
raw2real_invalid_byte_size:
diff --git a/real2raw.h b/real2raw.h
index 5f12ef0..1c8d647 100644
--- a/real2raw.h
+++ b/real2raw.h
@@ -1,5 +1,5 @@
/*
- * (c) Copyright 2001 - 2004 -- Anders Torger
+ * (c) Copyright 2001 - 2004, 2013 -- Anders Torger
*
* This program is open source. For license terms, see the LICENSE file.
*
@@ -15,6 +15,32 @@
#error invalid REALSIZE
#endif
+#ifndef CONCAT_EVAL_
+#define CONCAT_EVAL_(a, b) a ## b
+#define CONCAT_(a, b) CONCAT_EVAL_(a, b)
+#endif
+#define REAL2RAW_SAMPLE_TEST CONCAT_(REAL2RAW_NAME, _sample_test)
+
+static inline void
+REAL2RAW_SAMPLE_TEST(REAL_T real_sample, struct bfoverflow *overflow)
+{
+ if (!isfinite(real_sample)) {
+ fprintf(stderr, "NaN or Inf values in the output! Bad output. "
+ "Aborting.\n");
+ abort();
+ }
+ if (bfconf->safety_limit != 0.0 &&
+ (real_sample < -bfconf->safety_limit * overflow->max ||
+ real_sample > bfconf->safety_limit * overflow->max))
+ {
+ fprintf(stderr, "Safety limit exceeded on output (%.2f > %.2f). "
+ "Aborting.\n",
+ 20.0 * log10(fabs(real_sample / overflow->max)),
+ 20.0 * log10(bfconf->safety_limit));
+ bf_exit(BF_EXIT_OTHER);
+ }
+}
+
#define REAL_OVERFLOW_UPDATE \
if (realbuf->RXX[n] < 0.0) { \
if (realbuf->RXX[n] < rmin) { \
@@ -37,7 +63,6 @@ REAL2RAW_NAME(void *_rawbuf,
void *_realbuf,
int bits,
int bytes,
- int shift,
bool_t isfloat,
int spacing,
bool_t swap,
@@ -59,20 +84,18 @@ REAL2RAW_NAME(void *_rawbuf,
if (isfloat) {
rmin = -overflow->max;
rmax = overflow->max;
- if (shift != 0) {
- fprintf(stderr, "Shift must be zero for floating point formats.\n");
- bf_exit(BF_EXIT_OTHER);
- }
#if REALSIZE == 4
switch (bytes) {
case 4:
if (swap) {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
rawbuf->u32[i] = SWAP32(realbuf->u32[n]);
}
} else {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
rawbuf->r32[i] = realbuf->r32[n];
}
@@ -81,12 +104,14 @@ REAL2RAW_NAME(void *_rawbuf,
case 8:
if (swap) {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
sample.r64[0] = (double)realbuf->r32[n];
rawbuf->u64[i] = SWAP64(sample.u64[0]);
}
} else {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
rawbuf->r64[i] = (double)realbuf->r32[n];
}
@@ -100,12 +125,14 @@ REAL2RAW_NAME(void *_rawbuf,
case 4:
if (swap) {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
sample.r32[0] = (float)realbuf->r64[n];
rawbuf->u32[i] = SWAP32(sample.u32[0]);
}
} else {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
rawbuf->r32[i] = (float)realbuf->r64[n];
}
@@ -114,11 +141,13 @@ REAL2RAW_NAME(void *_rawbuf,
case 8:
if (swap) {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
rawbuf->u64[i] = SWAP64(realbuf->u64[n]);
}
} else {
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
REAL_OVERFLOW_UPDATE;
rawbuf->r64[i] = realbuf->r64[n];
}
@@ -133,138 +162,85 @@ REAL2RAW_NAME(void *_rawbuf,
return;
}
- imin = -(1 << (bits - 1));
- imax = (1 << (bits - 1)) - 1;
+ imin = -((uint64_t)1 << (bits - 1));
+ imax = ((uint64_t)1 << (bits - 1)) - 1;
rmin = (REAL_T)imin;
rmax = (REAL_T)imax;
switch (bytes) {
case 1:
for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
rawbuf->i8[i] = (int8_t)REAL2INT_CALL;
}
break;
case 2:
- if (shift == 0) {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i16[0] = (int16_t)REAL2INT_CALL;
- rawbuf->u16[i] = SWAP16(sample.u16[0]);
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- rawbuf->i16[i] = (int16_t)REAL2INT_CALL;
- }
- }
- } else {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i16[0] = (int16_t)(REAL2INT_CALL << shift);
- rawbuf->u16[i] = SWAP16(sample.u16[0]);
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- rawbuf->i16[i] = (int16_t)(REAL2INT_CALL << shift);
- }
- }
- }
+ if (swap) {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ sample.i16[0] = (int16_t)REAL2INT_CALL;
+ rawbuf->u16[i] = SWAP16(sample.u16[0]);
+ }
+ } else {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ rawbuf->i16[i] = (int16_t)REAL2INT_CALL;
+ }
+ }
break;
case 3:
spacing = spacing * 3 - 3;
#ifdef __BIG_ENDIAN__
- if (shift == 0) {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL;
- rawbuf->u8[i++] = sample.u8[3];
- rawbuf->u8[i++] = sample.u8[2];
- rawbuf->u8[i++] = sample.u8[1];
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL;
- rawbuf->u8[i++] = sample.u8[1];
- rawbuf->u8[i++] = sample.u8[2];
- rawbuf->u8[i++] = sample.u8[3];
- }
- }
- } else {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL << shift;
- rawbuf->u8[i++] = sample.u8[3];
- rawbuf->u8[i++] = sample.u8[2];
- rawbuf->u8[i++] = sample.u8[1];
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL << shift;
- rawbuf->u8[i++] = sample.u8[1];
- rawbuf->u8[i++] = sample.u8[2];
- rawbuf->u8[i++] = sample.u8[3];
- }
- }
- }
+ if (swap) {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ sample.i32[0] = REAL2INT_CALL;
+ rawbuf->u8[i++] = sample.u8[3];
+ rawbuf->u8[i++] = sample.u8[2];
+ rawbuf->u8[i++] = sample.u8[1];
+ }
+ } else {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ sample.i32[0] = REAL2INT_CALL;
+ rawbuf->u8[i++] = sample.u8[1];
+ rawbuf->u8[i++] = sample.u8[2];
+ rawbuf->u8[i++] = sample.u8[3];
+ }
+ }
#endif
#ifdef __LITTLE_ENDIAN__
- if (shift == 0) {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL;
- rawbuf->u8[i++] = sample.u8[2];
- rawbuf->u8[i++] = sample.u8[1];
- rawbuf->u8[i++] = sample.u8[0];
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL;
- rawbuf->u8[i++] = sample.u8[0];
- rawbuf->u8[i++] = sample.u8[1];
- rawbuf->u8[i++] = sample.u8[2];
- }
- }
- } else {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL << shift;
- rawbuf->u8[i++] = sample.u8[2];
- rawbuf->u8[i++] = sample.u8[1];
- rawbuf->u8[i++] = sample.u8[0];
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL << shift;
- rawbuf->u8[i++] = sample.u8[0];
- rawbuf->u8[i++] = sample.u8[1];
- rawbuf->u8[i++] = sample.u8[2];
- }
- }
- }
+ if (swap) {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ sample.i32[0] = REAL2INT_CALL;
+ rawbuf->u8[i++] = sample.u8[2];
+ rawbuf->u8[i++] = sample.u8[1];
+ rawbuf->u8[i++] = sample.u8[0];
+ }
+ } else {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ sample.i32[0] = REAL2INT_CALL;
+ rawbuf->u8[i++] = sample.u8[0];
+ rawbuf->u8[i++] = sample.u8[1];
+ rawbuf->u8[i++] = sample.u8[2];
+ }
+ }
#endif
break;
case 4:
- if (shift == 0) {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL;
- rawbuf->u32[i] = SWAP32(sample.u32[0]);
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- rawbuf->i32[i] = REAL2INT_CALL;
- }
- }
- } else {
- if (swap) {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- sample.i32[0] = REAL2INT_CALL << shift;
- rawbuf->u32[i] = SWAP32(sample.u32[0]);
- }
- } else {
- for (n = i = 0; n < n_samples; n++, i += spacing) {
- rawbuf->i32[i] = REAL2INT_CALL << shift;
- }
- }
- }
+ if (swap) {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ sample.i32[0] = REAL2INT_CALL;
+ rawbuf->u32[i] = SWAP32(sample.u32[0]);
+ }
+ } else {
+ for (n = i = 0; n < n_samples; n++, i += spacing) {
+ REAL2RAW_SAMPLE_TEST(realbuf->RXX[n], overflow);
+ rawbuf->i32[i] = REAL2INT_CALL;
+ }
+ }
break;
default:
real2raw_invalid_byte_size:
--
brutefir packaging
More information about the pkg-multimedia-commits
mailing list