libsndfile / libsamplerate Goto Github PK
View Code? Open in Web Editor NEWAn audio Sample Rate Conversion library
Home Page: http://libsndfile.github.io/libsamplerate/
License: BSD 2-Clause "Simplified" License
An audio Sample Rate Conversion library
Home Page: http://libsndfile.github.io/libsamplerate/
License: BSD 2-Clause "Simplified" License
src_get_channels
is supposed to "Returns negative on error, positive channel count otherwise"
But the implementation directly returns an error code which is positive. See https://github.com/erikd/libsamplerate/blob/2647fd9bac5f11f24b5f1ee55806671f81520f66/src/samplerate.c#L312 and https://github.com/erikd/libsamplerate/blob/2647fd9bac5f11f24b5f1ee55806671f81520f66/src/common.h#L64
Hence src_get_channels(NULL)
returns 2 [channels]
which is wrong
As noted in title: make package_source
with cmake generates libsamplerate-0.1.1-Source.tar.gz
Notice 0.1.1
instead of current 0.1.9
. I don't know if this facility is actually meant to be used
but still.. This is with cmake-3.9.6.
Related to #68 as it requires C99 (although C99 features are already used)
C99 flexible arrays are used at some points, e.g.: https://github.com/erikd/libsamplerate/blob/2647fd9bac5f11f24b5f1ee55806671f81520f66/src/src_sinc.c#L57
At other the idiom of having a trailing float[1]
member is used: https://github.com/erikd/libsamplerate/blob/2647fd9bac5f11f24b5f1ee55806671f81520f66/src/src_linear.c#L34
A SO answer highly recommends using the C99 feature: https://stackoverflow.com/a/247040/1930508 with a comment that using float[1]
may produce incorrect code: https://lkml.org/lkml/2015/2/18/407
Furthermore to much memory is allocated (1 additional float): https://github.com/erikd/libsamplerate/blob/2647fd9bac5f11f24b5f1ee55806671f81520f66/src/src_linear.c#L174
Bottom line:
float[1]
I was considering to write a C++ wrapper for the C classes for our project to slightly ease the use.
Is there some interest to have this in the upstream project as e.g. libsamplerate.hpp with some tests? @erikd
It would be:
SRC_STATE
with copy/move operators (C++11 required)src_short_to_float_array
and friends as to_float_array
and from_float_array
As found in #65 (comment) using bit shifts on signed integers is undefined behavior. Reason for that is the difference between a "regular shift" (shr) and "arithmetic shift" (sar) where the former just shifts bits while the latter preserves the sign bit in all cases. Also there is a rounding difference for positive and negative numbers.
Examples:
-1 = b11111111
-1 shr 1 = b01111111 = 127
-1 sar 1 = b11111111 = -1
-10 sar 2 = -3
10 sar 2 = 2
This may not be a problem in practice as usually int >> value
is translated to sar
but I found 1 compiler where it is translated to shr
: https://godbolt.org/z/sj_uO6
Not sure if/how to solve this as i >> value
is meant as floor(i/2^value)
while (int)(i/2^value)
is trunc(i/2^value)
and hence cannot be "optimized" to a shift.
Is this OK:
SRC_DATA data{};
data.data_in=const_cast<float*>(buffer_in);
That is, can I be sure that the library does not touch buffer_in? If so add const
, or at least annotate that in the documentation.
I re-ran the make_filter.m Octave script with f = make_filter (8, 128, 100.3)
I am using octave-6.1.0-w64-installer.exe for Windows.
When I replaced the newly-generated coefficients into fastest_coeffs.h and recompile, I am getting far worse results than the original fastest coefficients.
I have a test .wav file with two tones (400Hz and 700Hz) sampled at 8000 samples/second. When I run this through the resampler app (using -c 2 -to 16000) I get great results with the old coefficients but the newly-generated coefficients produce significant artifacts/harmonics near the high end frequency spectrum. The ONLY thing changed is the coefficient table.
I'm assuming that changes may have been made to the octave scripts since the original fastest coefficient table was generated, and these changes may be causing this issue. Since there's no history in the repo for the octave scripts (that I can see), I can't try older octave scripts to see if I can reproduce the older coefficients.
I've attached the newly-generated coefficients from the octave scripts.
fast-new.txt
Hi Erik,
I have written a self-contained test to display the problem we are seeing in our project that uses libsamplerate to do sample rate conversions. I have attached the entire libsamplerate directory along with my changes here. Additionally, I have also written up a brief description of the issue and my test below.
I would like to understand if this is indeed a potential bug or an improper use of the library. Looking forward to your thoughts.
Thanks,
Hari
Description:
Our project code follows the model in callback_test.c (ie: setup a callback using src_callback_new() with converter = SRC_SINC_FASTEST, numChannels = 32; calls to src_callback_read() till the requested # of samples are read).
We have discovered an intermittent issue where the audio data we receive after a call to src_callback_read() contains Nan values in the output buffer at a valid index (ie: within the total read samples returned by src_callback_read()). We traced this down to the calc_output_multi() function which is called by sinc_multichan_vari_process() in src_sinc.c. Specifically, in the scenarios where the issue happens, the data_index that calc_output_multi() calculates when applying the left half of the filter evaluates to a negative value (which leads to accessing uninitialized/unowned memory).
To simplify this, I have written a short self-contained test (called filterdata_integrity_test.c) under the tests directory. This test is similar to callback_test.c, ie: it sets up a callback using src_callback_new() with converter = SRC_SINC_FASTEST, numChannels = 2 (for simplicity); calls to src_callback_read() till the requested # of samples are read). The notable differences from my test and callback_test.c are:
i) Setting the src_ratio to a different value on every callback (by calling src_set_ratio()) -> this replicates the scenario in our project when the issue occurs
ii) Adding integrity checks on the audio data that is generated in the output buffer
All of the relevant changes also have comments next to them.
Note: I have also made an un-invasive change to src/src_sinc.c at line 437 to exit(1) whenever the data_index hits a negative value in calc_output_stereo() (since this is the only way I have found to catch the issue when it happens). I hit this exit every time I run the filterdata_integrity_test.
Do you have a guide how to compile this as a fat library for all required ios architectures (x86_64, armv6, armv7, ...)?
Our current configure.ac checks gcc (and only gcc) being the compiler
when deciding whether to use Version_script or the win32 def file:
https://github.com/libsndfile/libsamplerate/blob/master/configure.ac#L265
However, the linker should be one checked. Do you think the following
is correct: @SoapGentoo, @evpobr? If it is I can make a PR for it.
diff --git a/configure.ac b/configure.ac
index 0e2117c..4691e09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -260,14 +260,13 @@ AS_IF([test "x$enable_werror" = "xyes"], [
AX_APPEND_COMPILE_FLAGS([-W -Wstrict-prototypes -Wmissing-prototypes -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wpointer-arith], [CFLAGS])
dnl ====================================================================================
-dnl GCC stuff.
+dnl Exported symbols control.
-AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [
- # OS specific tweaks.
+AS_IF([test "x$lt_cv_prog_gnu_ld" = "xyes"], [
AS_CASE([${host_os}],
[mingw*|cygwin*], [
SHLIB_VERSION_ARG="-export-symbols \$(top_srcdir)/Win32/libsamplerate-0.def"],
- [linux*|kfreebsd*-gnu*|gnu*], [
+ [*], [
SHLIB_VERSION_ARG="-Wl,--version-script=\$(top_builddir)/src/Version_script"
])
])
This is current git on OpenBSD 6.5/macppc (meaning powerpc).
Running 'make check' fails with the following:
tests/float_short_test
float_to_short_test .............................
Line 64 : out [1] == -1
*** Error 1 in /home/hans/src/libsamplerate (Makefile:1877 'check')
When compiling on linux with ALSA, I get the following errors:
audio_out.c: In function ‘audio_play’:
audio_out.c:1014:16: error: dereferencing pointer to incomplete type ‘AUDIO_OUT {aka struct AUDIO_OUT_s}’
if (audio_out->magic == ALSA_MAGIC)
^~
Debian/buster (currently "stable") ships with libsamplerate0_0.1.9-2
, which includes a dynamic library file:
/usr/lib/x86_64-linux-gnu/libsamplerate.so.0.1.8
compiling the latest and greatest libsamplerate-0.2.0 i get a file:
/usr/lib/x86_64-linux-gnu/libsamplerate.so.0.1.0
This decrements the micro release, which is plain wrong!!
the new libsamplerate also introduces a new symbol src_clone
, which would - according to semantic versioning - warrants a:
please fix this and make a bugfix release asap.
When using libsamplerate via CMake and as a submodule, all targets related to tests/examples clog up generated workspace. It should be make optional f.i. with:
option(LIBSAMPLERATE_TESTS OFF "Enable to generate test targets)
Same applies to install(...)
directives.
The config.sub and config.guess should be updated to include aarch64 in 0.1.9 since I cannot see that these files are included in the repo I guess they are copied from somewhere. When looking through my host machine I located them under /usr/share/misc and they do include aarch64.
hello,
if i'm not mistaken, last release was in 2016. Do you plan to make a new release soon ?
thank you
examples/audio_out.c
fails to build on MacOS 10.13.2,
because it includes Carbon.h
which does not exist.
Apparently, the MacOS audio subsystem has changed again
(to proactively leverage the synergy of the frameworks).
Compiling 0.1.9 says
/bin/sh ../libtool --tag=CC --mode=link /usr/bin/clang -pipe -Os -arch x86_64 -std=gnu99 -W -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wpointer-arith -pipe -no-undefined -version-info 1:8:1 -L/opt/local/lib -Wl,-headerpad_max_install_names -arch x86_64 -o libsamplerate.la -rpath /opt/local/lib samplerate.lo src_sinc.lo src_zoh.lo src_linear.lo -lm -lm
What is -version-info 1:8:1
?
It also says
libtool: link: /usr/bin/clang -dynamiclib -o .libs/libsamplerate.0.dylib .libs/samplerate.o .libs/src_sinc.o .libs/src_zoh.o .libs/src_linear.o -L/opt/local/lib -lm -Os -arch x86_64 -Wl,-headerpad_max_install_names -arch x86_64 -install_name /opt/local/lib/libsamplerate.0.dylib -compatibility_version 2 -current_version 2.8 -Wl,-single_module^M^M
What is -compatibility_version 2
?
brew install libsamplerate
curl: (7) Failed to connect to www.mega-nerd.com port 80: Operation timed out
Error: An exception occurred within a child process:
DownloadError: Failed to download resource "libsamplerate"
Download failed: http://www.mega-nerd.com/SRC/libsamplerate-0.1.9.tar.gz
https://github.com/erikd/libsamplerate/blob/master/src/samplerate.h#L86
Doc is here: http://www.mega-nerd.com/SRC/api_simple.html
Documentation doesn't mention what happens if the output buffer is not big enough to hold the samplerate-converted input buffer.
It isn't certain if this will return an error or simply fill the output buffer, correctly making a note of how many input samples have been consumed in the data structure.
It would be very helpful to have this documented, as it would save a development test-cycle.
Are you considering for libsamplerate use of hardware instructions we can find in modern processors (SIMD) / GPUs? This can greatly affect the speed of resampling.
Will this impact on library precision?
For the function src_callback_read
the documentation on what is reported on error is inconsistent.
-1
zero
but also zero when there is no more inputUsing -1
for error makes that case distinguishable from "no more input", however I guess at that point it might be a breaking change. So I guess the documentation in the header should be updated and maybe tests for the error cases added to avoid possible confusion
I'm running this on android.
Getting a build error on https://github.com/erikd/libsamplerate/blob/master/src/common.h#L148:
lrint not found in common.h
Adding #include <math.h>
fixes it.
So maybe this line should be added to common.h
?
From what I can tell these libraries aren't used at all but gets linked and are required via cmake/FindSndFile.cmake
.
I have a simple array of floats containing a sequence of numbers such as 1.0, 2.0, 3.0, ... 64.0
I want to process through libsamplerate. Surprisingly, when the ratio is set to 1.0, the first frame in the output buffer is duplicated, that is 1.0, 1.0, 2.0, 3.0, ...
instead of the expected 1.0, 2.0, 3.0, 4.0, ...
.
I'm using libsamplerate 0.1.9 on Debian Stretch, GCC 6.3.0 (64 bit arch). I'm pretty sure there is something wrong on my side, even if I have triple checked it so far. Or maybe it is the expected behavior? Full code below:
#include <samplerate.h>
#include <cstdio>
int main()
{
SRC_STATE* rsmp_state;
SRC_DATA rsmp_data;
const int IN_FRAMES = 64;
const int OUT_FRAMES = 32;
float* in = new float[IN_FRAMES];
float* out = new float[OUT_FRAMES];
for (int i = 0; i < IN_FRAMES; i++)
in[i] = (float) i + 1;
rsmp_state = src_new(SRC_LINEAR, 1, nullptr);
rsmp_data.data_in = in;
rsmp_data.input_frames = IN_FRAMES;
rsmp_data.data_out = out;
rsmp_data.output_frames = OUT_FRAMES;
rsmp_data.end_of_input = false;
rsmp_data.src_ratio = 1.0;
src_process(rsmp_state, &rsmp_data);
//for (int i = 0; i < IN_FRAMES; i++) printf("%d) %f\n", i, in[i]);
for (int i = 0; i < OUT_FRAMES; i++) printf("%d) %f\n", i, out[i]);
src_delete(rsmp_state);
delete in;
delete out;
}
From: http://www.mega-nerd.com/SRC/api_misc.html#SRC_DATA
Finally, the src_ratio field specifies the conversion ratio defined as the input sample rate divided by the output sample rate.
While it should be "output sample rate divided by input sample rate". Elsewhere in the documentation it is specified correctly:
src_ratio : Equal to output_sample_rate / input_sample_rate.
On 0.1.8:
# sndfile-resample -to 24000 -c 1 $FILE out
==13807==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7f44bc709a3c at pc 0x7f44bc6b1d6b bp 0x7fffec8f5e20 sp 0x7fffec8f5e18
READ of size 4 at 0x7f44bc709a3c thread T0
#0 0x7f44bc6b1d6a in calc_output_single /tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/src/src_sinc.c:296:48
#1 0x7f44bc6b1d6a in sinc_mono_vari_process /tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/src/src_sinc.c:400
#2 0x7f44bc6a3659 in src_process /tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/src/samplerate.c:174:11
#3 0x51369a in sample_rate_convert /tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/examples/sndfile-resample.c:221:16
#4 0x51369a in main /tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/examples/sndfile-resample.c:163
#5 0x7f44bb55278f in __libc_start_main /tmp/portage/sys-libs/glibc-2.23-r3/work/glibc-2.23/csu/../csu/libc-start.c:289
#6 0x419f88 in _init (/usr/bin/sndfile-resample+0x419f88)
0x7f44bc709a3c is located 0 bytes to the right of global variable 'slow_mid_qual_coeffs' defined in '/tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/src/mid_qual_coeffs.h:37:3' (0x7f44bc6f3ba0) of size 89756
SUMMARY: AddressSanitizer: global-buffer-overflow /tmp/portage/media-libs/libsamplerate-0.1.8-r1/work/libsamplerate-0.1.8/src/src_sinc.c:296:48 in calc_output_single
Shadow bytes around the buggy address:
0x0fe9178d92f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9178d9300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9178d9310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9178d9320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9178d9330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0fe9178d9340: 00 00 00 00 00 00 00[04]f9 f9 f9 f9 f9 f9 f9 f9
0x0fe9178d9350: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x0fe9178d9360: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x0fe9178d9370: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x0fe9178d9380: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x0fe9178d9390: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==13807==ABORTING
Reproducer:
https://github.com/asarubbo/poc/blob/master/00262-libsamplerate-globaloverflow-calc_output_single
Is that intentional? Maybe you need something like the following in CMakeLists.txt?
IF (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
MESSAGE(STATUS "Setting build type to 'Debug' as none was specified.")
SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
ENDIF ()
SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}")
MESSAGE(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
OPTION(BUILD_SHARED_LIBS "Build dynamic library" OFF)
Hello Eric.
Would you please update your http://www.mega-nerd.com/SRC/ page with reference to this github project?
Would you please update link in
http://www.mega-nerd.com/SRC/quality.html
with
https://ccrma.stanford.edu/~jos/resample/
Thanks.
When compiling on windows I get the following warning and errors:
.\examples\audio_out.c(715): warning C4133: 'return': incompatible types - from 'WIN32_AUDIO_OUT *' to 'AUDIO_OUT *'
.\examples\audio_out.c(826): error C2065: 'sample_count': undeclared identifier
.\examples\audio_out.c(827): error C2065: 'sample_count': undeclared identifier
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\cl.exe"' : return code '0x2'
I looked that the lines of code in audio_out.c and couldn't find an obvious error. I think I may be missing some header file but can't figure it out.
Hi @erikd
in order to fix the resample
collision problem in Gentoo, could you please issue a new tarball for libsamplerate?
Thanks!
Line 255 in 01284e7
Without it shared library is not compatible with Autotools build.
It'd be very helpful to know the transport delay that a given converter at a given ratio exhibits.
I'd suggest a function like:
/*
** Calculate the transport delay (number of samples that are buffered
** on average) that a given converter exhibits, when resampling at the
** specified SRC ratio.
** Returns the transport delay, measured in output samples.
*/
double src_get_delay (int converter_type, double src_ratio) ;
For the linear and ZOH converters the calculation is very easy (something along 1 + 1/src_ratio
if I recall correctly), but I'm not able to come up with an expression for the sinc converters (which are perhaps the most interesting cases, where the transport delay is significant).
I'd like to save and restore SRC_STATE, so I can rerender a resampled output incrementally. For this, I think I just need to know the size of SRC_STATE, then I can use memcpy to serialize and deserialize. So I think a new src_size method is needed. But I could use that to redo src_clone, from commit 945b993, in a generic way and get rid of those individual *_copy functions.
Any interest in a PR? Or is this already possible?
Hi Erik,
I found that src_process
throws an error when called with data_in = NULL
and input_frames = 0
.
I was calling it like that with end_of_input
set to finish a resampling process. I think it's a bit unintuitive that this doesn't work and the documentation also does not indicate that it might be forbidden.
A work-around is to set data_in
to a dummy value like (float *) 1
in the special case of finishing the resampling process with no more frames to resample.
So my suggestion is to accept data_in = NULL
when input_frames = 0
or, alternatively, mention in the API docs that data_in
must not be NULL
even when passing no input frames. I think just accepting NULL
in this case would be the better solution, though.
Here is an example program that illustrates the issue: finish-test.c.gz
Thanks,
Robert
The autoconf already requires a C99 compiler. I suggest to do the same for CMake which simplifies the code, config and removes the whole float_convert header.
It would be helpful for consumers to know the version of the library during compilation.
So I propose to define at least LIBSAMPLERATE_VERSION
in samplerate.h
.
A good way done by other projects is to have _VERSION
a string, and _VERSION_[MAJOR|MINOR|PATCH]
as 3 additional defines.
Examples: https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/version.hpp or https://github.com/esp8266/Arduino/blob/master/tools/sdk/include/version.h
Boost uses a single number: https://www.boost.org/doc/libs/1_70_0/boost/version.hpp
Example uses:
#ifndef LIBSAMPLERATE_VERSION_MAJOR
code for pre 0.1.10
#elif LIBSAMPLERATE_VERSION_MAJOR >=1
code for 1.x
#elif ...
This is 0.1.9 on MacOS 10.13.2.
Turning on --enable-option-checking
as the only arg to ./configure
says:
/Users/hans/src/libsamplerate-0.1.9/Cfg/missing: Unknown `--is-lightweight' option
Try `/Users/hans/src/libsamplerate-0.1.9/Cfg/missing --help' for more information
configure: WARNING: 'missing' script is too old or missing
Also, it continues to run, instead of exiting on an unknown option.
WAV files might be uint8 PCM format. For those it would be helpful to have conversion functions too.
Hello,
I tried to make the files following the instructions here
However it doesn't work, providing a modern VC path seems to give troubles.
Tried to modify the PROG_LINK_FLAGS variable by fixing manually some headers (it couldn't find stdio.h
for instance, so I provided it from MinGW), but it doesn't seem to recognize it.
Isn't there a more modern way to build all this ?
The filter coeffs in src/*_coeffs.h
seem to be generated by some GNU Octave scripts. Comments list the functions and parameters used like:
f = make_src_filter (cycles = 69, incr = 2381, atten = 160.000000)
The Octave files, however, are excluded from this repository in .gitignore
even though there are commits referencing them, like 87992ca.
It would be great if the scripts could be included in this repo.
I'm getting a 'macro redefinition' compiler warning when including libsamplerate
.
One of the system libraries I include (macOS 10.14/usr/include/sys/param.h
) redefines MIN and MAX:
/* Macros for min/max. */
#ifndef MIN
#define MIN(a, b) (((a)<(b))?(a):(b))
#endif /* MIN */
#ifndef MAX
#define MAX(a, b) (((a)>(b))?(a):(b))
#endif /* MAX */
How about doing the same inside this library?
./configure does not find fftw3, because configure.ac wants
PKG_CHECK_MODULES(FFTW3, fftw3 >= 0.15.0, ac_cv_fftw3=1, ac_cv_fftw3=0)
What is 0.15.0
of fftw3? It installs fftw 3.x.y, obviously.
Why do we require a certain version in the first place?
There is a bug when using src_process with sufficiently small chunks of input data. Although the result of passing the input data in chunks should be exactly the same as when passing them as 1 block the test shows that this is not the case and NO output is generated. See #87 for a reproducer.
This seems to be the issue that was discussed at #55 but now can be reproduced using (IMO) valid code: It sets the end_of_input
once it got the final samples but the output_frames_gen
is still zero.
To start off, thank you so much for the great tool, erikd!
But I have found an issue and, after some trials-and-errors, came up with a simple solution. I would like to share---
When src_process is called multiple times with a connected set of buffers, the last half_filter_chan_len
points from the input buffer are not processed. In other words, you will lose these data points (which was 47 samples when I tried with SRC_SINC_MEDIUM_QUALITY, see below). This is because the while loop on line 375 in src_sinc.c breaks when filter->out_gen
equals filter->out_count
. Logically it makes sense, except that it should further generate output (half_filter_chan_len
points more) for the very last buffer, because the processing of the very first buffer was done for filter->out_count
MINUS half_filter_chan_len
.
To resolve this issue, I am simply changing line 375 to while (1)
and let the separate termination check do the work (lines 390 and 393). And I am making sure, in my application, to allocate the data_out buffer big enough to absorb this in addition to the expected output buffer size.
The same logic should apply to other functions--sinc_stereo_vari_process, sinc_quad_vari_process, sinc_hex_vari_process
, and sinc_multichan_vari_process
, but I'm not using them and I can't check this issue in these functions. I would let others do it. But this change works well for my application, auxlab, so I'm using my own hacked version of libsamplerate for auxlab for now (as of 3/20/2019).
The easiest way to replicate the issue is the following:
float * buffer_in = (float*)calloc(sizeof(float), 10000); // input buffer size is 10000 points
float * buffer_out = (float*)calloc(sizeof(float), 10000); // output is the same size; testing src_ratio = 1
// prepare the buffer
int errcode;
SRC_STATE* handle = src_new(SRC_SINC_MEDIUM_QUALITY, 1, &errcode);
SRC_DATA data;
data.src_ratio = 1;
data.data_in = buffer_in;
data.data_out = buffer_out;
data.input_frames = 5000; // half the buffer
data.output_frames = 5000;
data.end_of_input = 0;
errcode = src_process(handle, &data); // processing the first half
//after the call,
//data.input_frames_used was 5000 but
//data.output_frames_gen was 4953, which is 5000 minus half_filter_chan_len in src_sinc.c
data.data_in = buffer_in + data.input_frames_used ;
data.data_out = buffer_out + data.output_frames_gen;
data.end_of_input = 1;
errcode = src_process(handle, &data); // processing the second half
//Now you get
//data.input_frames_used would be still 5000 (i.e., all input buffer has been read)
//data.output_frames_gen would be 5000. And, this is not right. We should have gotten 5047 points.
This hack will get you all the output data, without missing the last 47 points.
Hope this helps.
[build] [6/61 1% :: 0.547] Building C object src/CMakeFiles/samplerate.dir/src_zoh.c.obj
[build] ../src/src_zoh.c: In function 'zoh_get_name':
[build] ../src/src_zoh.c:154:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
[build] 154 | } /* zoh_get_name */
[build] | ^
https://stackoverflow.com/questions/7994415/mingw-fvisibility-hidden-does-not-seem-to-work
Documenting bug found in #87:
When a ratio smaller or equal to 1/214
is used with src_simple
and one of the SINC converters no output is produced no matter how big the input is.
Code reproducing this:
static void
src_simple_produces_output_test (int converter, int channels, double src_ratio)
{
// Choose a suitable number of frames.
// Here set to something VERY high to prove the point, do not use for unit tests!
const long NUM_FRAMES = 100000000;
int error;
float *input = calloc (NUM_FRAMES * channels, sizeof (float));
float *output = calloc (NUM_FRAMES * channels, sizeof (float));
SRC_DATA src_data;
memset (&src_data, 0, sizeof (src_data)) ;
src_data.data_in = input;
src_data.data_out = output;
src_data.input_frames = NUM_FRAMES;
src_data.output_frames = NUM_FRAMES;
src_data.src_ratio = src_ratio;
if ((error = src_simple (&src_data, converter, channels)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
if (src_data.input_frames_used == 0)
{ printf ("\n\nLine %d : No input frames used. Converter=%d, channels = %d, ratio=%g\n\n", __LINE__, converter, channels, src_ratio) ;
exit (1) ;
} ;
if (src_data.output_frames_gen == 0)
{ printf ("\n\nLine %d : No output frames generated. Converter=%d, channels = %d, ratio=%g\n\n", __LINE__, converter, channels, src_ratio) ;
exit (1) ;
} ;
free(input);
free(output);
}
// Call
src_simple_produces_output_test(SRC_SINC_FASTEST, 1, 1./214);
// Output: No output frames generated. Converter=2, channels = 1, ratio=0.0046729
Using the advanced method (repeatable callingsrc_process
with chunks of the input) the first output sample for a ratio of 1/215
is produced after about 4992 input frames, so the transport delay does not seem to be the cause. Also increasing the input frame count does not change anything.
Possible cause (from most likely to least likely):
b_len
calculated at https://github.com/erikd/libsamplerate/blob/1b3d5b1114b6cac1baed0a1a24ea8bb451cfc1b1/src/src_sinc.c#L215len
calculated at https://github.com/erikd/libsamplerate/blob/1b3d5b1114b6cac1baed0a1a24ea8bb451cfc1b1/src/src_sinc.c#L1178For non-interleaved multi-channel data, is it better (in terms of CPU load) to:
Use a separate mono converter for each channel - or - merge the channels to an interleaved buffer and apply SRC on that buffer?
Hi Erik,
thanks for this great lib!
I'd like to make it easier to ship with tools like anaconda and python.
It would be nice, if you could tag the commit which represents the current version
so that I can refer to it while building.
Thanks Stefan
yIDType DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
^
In file included from audio_out.c:435:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Headers/Carbon.h:67:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Frameworks/Ink.framework/Headers/Ink.h:200:51: error: expected ';' after top level
declarator
typedef struct OpaqueInkTextRef* InkTextRef DEPRECATED_IN_MAC_OS_X_VERSION_10_14_AND_LATER;
^
;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.