├── bin └── DUMMY_FILE ├── doc ├── sweep.png ├── wave-sweep.png ├── wave-example.png ├── libsndfile.css └── index.html ├── config.h.cmake ├── README ├── README.md ├── src ├── spectrum.h ├── window.h ├── common.h ├── mix-to-mono.c ├── common.c ├── spectrum.c ├── window.c ├── generate-chirp.c ├── resample.c └── jackplay.c ├── NEWS ├── man ├── sndfile-mix-to-mono.1 ├── sndfile-jackplay.1 ├── sndfile-resample.1 ├── sndfile-generate-chirp.1 ├── sndfile-spectrogram.1 └── sndfile-waveform.1 ├── m4 ├── ax_require_defined.m4 ├── ax_recursive_eval.m4 ├── ax_append_flag.m4 ├── ax_append_link_flags.m4 ├── ax_append_compile_flags.m4 ├── ax_check_link_flag.m4 ├── ax_check_compile_flag.m4 ├── ax_compiler_vendor.m4 └── ax_pthread.m4 ├── tests ├── test-wrapper.sh ├── kaiser_window_test.c └── common_tests.c ├── Scripts ├── git-pre-commit-hook ├── calc-hilbert-fir.m ├── localinstall.py └── cstyle.py ├── Makefile.am ├── CMakeLists.txt ├── autogen.sh ├── ChangeLog ├── configure.ac ├── AUTHORS ├── INSTALL └── COPYING /bin/DUMMY_FILE: -------------------------------------------------------------------------------- 1 | Need a file here to keep git happy. 2 | -------------------------------------------------------------------------------- /doc/sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libsndfile/sndfile-tools/HEAD/doc/sweep.png -------------------------------------------------------------------------------- /doc/wave-sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libsndfile/sndfile-tools/HEAD/doc/wave-sweep.png -------------------------------------------------------------------------------- /doc/wave-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libsndfile/sndfile-tools/HEAD/doc/wave-example.png -------------------------------------------------------------------------------- /config.h.cmake: -------------------------------------------------------------------------------- 1 | #define PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@" 2 | 3 | #cmakedefine HAVE_SYS_WAIT_H 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is sndfile-tools version 1.5. 2 | 3 | See the web page for more: 4 | 5 | http://libsndfile.github.io/libsndfile/sndfile-tools 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sndfile-tools 2 | ------------- 3 | 4 | ![build](https://github.com/libsndfile/sndfile-tools/workflows/C/C++%20CI/badge.svg) 5 | 6 | `sndfile-tools` is a collection of programs (written in C) to do interesting 7 | things with sound files. 8 | 9 | See the web page for more: 10 | -------------------------------------------------------------------------------- /src/spectrum.h: -------------------------------------------------------------------------------- 1 | 2 | typedef struct 3 | { int speclen ; 4 | enum WINDOW_FUNCTION wfunc ; 5 | fftw_plan plan ; 6 | 7 | double *time_domain ; 8 | double *window ; 9 | double *freq_domain ; 10 | double *mag_spec ; 11 | 12 | double data [] ; 13 | } spectrum ; 14 | 15 | 16 | spectrum * create_spectrum (int speclen, enum WINDOW_FUNCTION window_function) ; 17 | 18 | void destroy_spectrum (spectrum * spec) ; 19 | 20 | double calc_magnitude_spectrum (spectrum * spec) ; 21 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Version 1.5 (2021-01-31) 2 | 3 | * Use clear semantic versioning tuple. 4 | * Fix spelling mistakes. 5 | * Add experimental CMake support. 6 | * Replace Travis CI with GitHub Action CI. 7 | * Improved error handling for PCM sample bits. 8 | * Add `sndfile-resample` binary from libsamplerate. 9 | 10 | Version 1.04 (2019-06-01) 11 | * Silence GCC 7 -Wimplicit-fallthrough warnings. 12 | * Modernized Autotools build system. 13 | 14 | Version 1.03 (2009-12-14) 15 | * Add prgram sndfile-jackplay. 16 | * sndfile-spectrogram : Add --no-border option, improve frequency access 17 | interpolation. 18 | 19 | Version 1.02 (2007-10-21) 20 | * sndfile-spectrogram : Calculate longer FFTs and then interpolate to the 21 | image height. 22 | * Add documentation. 23 | 24 | Version 1.01 (2007-10-16) 25 | * Depend on libsndfile >= 1.0.18. 26 | 27 | Version 1.00 (2007-10-15) 28 | * Initial release. 29 | -------------------------------------------------------------------------------- /src/window.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2015 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | enum WINDOW_FUNCTION { RECTANGULAR = 0, KAISER = 1, NUTTALL = 2, HANN = 3 } ; 19 | 20 | void calc_kaiser_window (double * data, int datalen, double beta) ; 21 | 22 | void calc_nuttall_window (double * data, int datalen) ; 23 | 24 | void calc_hann_window (double * data, int datalen) ; 25 | -------------------------------------------------------------------------------- /man/sndfile-mix-to-mono.1: -------------------------------------------------------------------------------- 1 | .TH SNDFILE\-MIX\-TO\-MONO 1 "May 2021" "" "User Commands" 2 | .SH NAME 3 | .B sndfile\-mix\-to\-mono 4 | \(em mix a multi-channel sound file to mono 5 | .SH SYNOPSIS 6 | .B sndfile\-mix\-to\-mono 7 | .RI < multi\-channel\ input\ file > 8 | .RI < mono\ output\ file > 9 | .SH DESCRIPTION 10 | .B sndfile\-mix\-to\-mono 11 | reads a multi-channel input file and writes a single-channel output file 12 | consisting of all of the input channels mixed together (like an audio mixing 13 | desk would do). 14 | The input and output files are read/written using 15 | .UR http://www.mega\-nerd.com/libsndfile/ 16 | libsndfile 17 | .UE . 18 | .LP 19 | The format of the output file is determined by the filename extension 20 | of the output file. 21 | .SH OPTIONS 22 | .TP 23 | .BR \-h ,\ \-\-help 24 | Print a help message and exit. 25 | .SH AUTHORS 26 | This manual page was originally written by 27 | .MT erikd@mega-nerd.com 28 | Erik de Castro Lopo 29 | .ME 30 | in 2009. 31 | It has since been modified and updated by other authors. 32 | .SH "SEE ALSO" 33 | .BR sndfile\-generate\-chirp (1), 34 | .BR sndfile\-jackplay (1), 35 | .BR sndfile\-resample (1), 36 | .BR sndfile\-spectrogram (1), 37 | .BR sndfile\-waveform (1) 38 | -------------------------------------------------------------------------------- /man/sndfile-jackplay.1: -------------------------------------------------------------------------------- 1 | .TH SNDFILE\-JACKPLAY 1 "May 2021" "" "User Commands" 2 | .SH NAME 3 | .B sndfile\-jackplay 4 | \(em play a sound file via the JACK sound server 5 | .SH SYNOPSIS 6 | .B sndfile\-jackplay 7 | .RB [ OPTIONS ] 8 | .RI < input\ sound\ file > 9 | .SH DESCRIPTION 10 | .B sndfile\-jackplay 11 | plays the specified sound file via the JACK sound server. 12 | It uses 13 | .UR http://www.mega\-nerd.com/libsndfile/ 14 | libsndfile 15 | .UE 16 | to read the file. 17 | .SH OPTIONS 18 | .TP 19 | .BR \-w ,\ \-\-wait [ =\fIport ] 20 | Wait for input before starting playback; optionally auto-connect to 21 | .I port 22 | using Jack. 23 | .TP 24 | .BR \-a ,\ \-\-autoconnect [ =\fIport ] 25 | Auto-connect to 26 | .I port 27 | using Jack. 28 | .TP 29 | .BR \-l ,\ \-\-loop [ =\fIcount ] 30 | Loop the file 31 | .I count 32 | times 33 | .RB ( 0 34 | for infinite). 35 | .TP 36 | .BR \-h ,\ \-\-help 37 | Print a help message and exit. 38 | .SH AUTHORS 39 | This manual page was written by 40 | .MT erikd@mega-nerd.com 41 | Erik de Castro Lopo 42 | .ME 43 | in 2009. 44 | It has since been modified and updated by other authors. 45 | .SH "SEE ALSO" 46 | .BR sndfile\-generate\-chirp (1), 47 | .BR sndfile\-mix\-to\-mono (1), 48 | .BR sndfile\-resample (1), 49 | .BR sndfile\-spectrogram (1), 50 | .BR sndfile\-waveform (1) 51 | -------------------------------------------------------------------------------- /m4/ax_require_defined.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_require_defined.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_REQUIRE_DEFINED(MACRO) 8 | # 9 | # DESCRIPTION 10 | # 11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have 12 | # been defined and thus are available for use. This avoids random issues 13 | # where a macro isn't expanded. Instead the configure script emits a 14 | # non-fatal: 15 | # 16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found 17 | # 18 | # It's like AC_REQUIRE except it doesn't expand the required macro. 19 | # 20 | # Here's an example: 21 | # 22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2014 Mike Frysinger 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 2 34 | 35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl 36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) 37 | ])dnl AX_REQUIRE_DEFINED 38 | -------------------------------------------------------------------------------- /man/sndfile-resample.1: -------------------------------------------------------------------------------- 1 | .Dd October 9, 2016 2 | .Dt SNDFILE-RESAMPLE 1 3 | .Os 4 | .Sh NAME 5 | .Nm sndfile-resample 6 | .Nd sample rate converter 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c Ar number 10 | .Fl to Ar rate 11 | .Ar input 12 | .Ar output 13 | .Nm 14 | .Op Fl c Ar number 15 | .Fl by Ar ratio 16 | .Ar input 17 | .Ar output 18 | .Sh DESCRIPTION 19 | .Nm 20 | is a sample rate converter using libsndfile for file I/O 21 | and Secret Rabbit Code (aka libsamplerate) for performing the conversion. 22 | It works on any file format supported by libsndfile 23 | with any number of channels (limited only by host memory). 24 | .Pp 25 | The options are as follows: 26 | .Bl -tag -width converter 27 | .It Fl c Ar number 28 | Choose the converter type from the following list: 29 | .Bl -tag -width x -compact 30 | .It 0 31 | Best Sinc Interpolator 32 | .It 1 33 | Medium Sinc Interpolator (default) 34 | .It 2 35 | Fastest Sinc Interpolator 36 | .It 3 37 | ZOH Interpolator 38 | .It 4 39 | Linear Interpolator 40 | .El 41 | .It Fl to Ar rate 42 | Convert to the specified sample 43 | .Ar rate . 44 | .It Fl by Ar ratio 45 | Change the sample rate by the given 46 | .Ar ratio , 47 | which can be any positive real; 48 | the resulting rate is floored to an integer. 49 | For instance, changing the rate of 44100 by a factor of 1.3333 50 | results in a sample rate of 58798. 51 | .It Fl -no-normalize 52 | Disable clipping check and normalization. 53 | .El 54 | .Sh SEE ALSO 55 | .Lk http://www.mega-nerd.com/libsndfile/ 56 | .Lk http://www.mega-nerd.com/libsamplerate/ 57 | .Sh AUTHORS 58 | .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com 59 | -------------------------------------------------------------------------------- /tests/test-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Make sure we have valgrind. 4 | valgrind=$(which valgrind) 5 | if test $? -ne 0 ; then 6 | echo "Sorry, valgrind isn't installed so this test cannot be run." 7 | exit 0 8 | fi 9 | 10 | tmpdir=tmp-`date "+%Y%m%dT%H%M%S"` 11 | 12 | mkdir $tmpdir 13 | logfile=$tmpdir/valgrind.txt 14 | 15 | function vgtest { 16 | printf "valgrind %-28s : " $1 17 | $valgrind $@ > $logfile 2>&1 18 | errors=`grep 'ERROR SUMMARY' $logfile | sed "s/.*Y: //;s/ .*//"` 19 | lost=`grep 'definitely lost' $logfile | sed "s/.*: //;s/ .*//;s/,//"` 20 | if test -z "$lost" ; then 21 | lost="0" 22 | fi 23 | 24 | if test "$lost:$errors" != "0:0" ; then 25 | echo "$errors errors, $lost bytes leaked" 26 | else 27 | echo "ok" 28 | fi 29 | } 30 | 31 | function asantest { 32 | printf "asan %-28s : " $1 33 | $@ > $logfile 2>&1 34 | if test $? -ne 0 ; then 35 | echo "error" 36 | cat $logfile 37 | exit 1 38 | fi 39 | echo "ok" 40 | } 41 | 42 | function testwrap { 43 | if test $(ldd $1 | grep -c libasan) -eq 0 ; then 44 | vgtest $@ 45 | else 46 | asantest $@ 47 | fi 48 | } 49 | 50 | testwrap bin/sndfile-generate-chirp 44100 1 $tmpdir/chirp.wav 51 | testwrap bin/sndfile-resample -to 48000 -c 2 $tmpdir/chirp.wav $tmpdir/chirp2.wav 52 | testwrap bin/sndfile-resample -to 48000 -c 3 $tmpdir/chirp.wav $tmpdir/chirp2.wav 53 | testwrap bin/sndfile-resample -to 48000 -c 4 $tmpdir/chirp.wav $tmpdir/chirp2.wav 54 | testwrap bin/sndfile-spectrogram $tmpdir/chirp.wav 640 480 $tmpdir/chirp.png 55 | testwrap bin/sndfile-waveform $tmpdir/chirp.wav $tmpdir/wavform.png 56 | 57 | 58 | 59 | rm -rf ./$tmpdir 60 | 61 | exit 0 62 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2015 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | 19 | #include 20 | 21 | #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof (x [0]))) 22 | 23 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 24 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) 25 | 26 | 27 | 28 | /* 29 | ** Inspiration : http://sourcefrog.net/weblog/software/languages/C/unused.html 30 | */ 31 | #ifdef UNUSED 32 | #elif defined (__GNUC__) 33 | # define UNUSED(x) UNUSED_ ## x __attribute__ ((unused)) 34 | #elif defined (__LCLINT__) 35 | # define UNUSED(x) /*@unused@*/ x 36 | #else 37 | # define UNUSED(x) x 38 | #endif 39 | 40 | #ifdef __GNUC__ 41 | # define WARN_UNUSED __attribute__ ((warn_unused_result)) 42 | #else 43 | # define WARN_UNUSED 44 | #endif 45 | 46 | 47 | typedef struct 48 | { double r ; 49 | double i ; 50 | } complex_t ; 51 | 52 | extern const char * font_family ; 53 | 54 | sf_count_t sfx_mix_mono_read_double (SNDFILE * file, double * data, sf_count_t datalen) ; 55 | 56 | int parse_int_or_die (const char * input, const char * value_name) ; 57 | 58 | double parse_double_or_die (const char * input, const char * value_name) ; 59 | -------------------------------------------------------------------------------- /man/sndfile-generate-chirp.1: -------------------------------------------------------------------------------- 1 | .TH SNDFILE\-GENERATE\-CHIRP 1 "May 2021" "" "User Commands" 2 | .SH NAME 3 | .B sndfile\-generate\-chirp 4 | \(em create a sound file containing a swept sine wave 5 | .SH SYNOPSIS 6 | .B sndfile\-generate-chirp 7 | .RB [ OPTIONS ] 8 | .RI < sample\ rate > 9 | .RI < length\ in\ seconds > 10 | .RI < sound\ file > 11 | .SH DESCRIPTION 12 | .B sndfile\-generate\-chirp 13 | generates a sound file containing a sine wave that 14 | sweeps from a low starting frequency to a higher ending frequency (i.e., a 15 | chirp). 16 | The file is written using 17 | .UR http://www.mega\-nerd.com/libsndfile/ 18 | libsndfile 19 | .UE . 20 | .P 21 | The output file will contain floating point samples in the range 22 | .BR [\-1.0,\ 1.0] . 23 | The output file type is determined by the file name extension which should be 24 | one of 25 | .BR wav , 26 | .BR aifc , 27 | .BR aif , 28 | .BR aiff , 29 | .BR au , 30 | .BR caf 31 | or 32 | .BR w64 . 33 | .SH OPTIONS 34 | .TP 35 | .B \-from\fR\ \fIstart 36 | Sweep start frequency in Hz (default 200Hz). 37 | .TP 38 | .B \-to\fR\ \fIend 39 | Sweep end frequency in Hz (default fs/2). 40 | .TP 41 | .B \-amp\fR\ \fIvalue 42 | Amplitude of generated sine (default 1.0). 43 | .TP 44 | .I sweep\ type 45 | One of (default 46 | .BR \-log ): 47 | .RS +14n 48 | .TP 49 | .B \-log 50 | logarithmic sweep 51 | .TP 52 | .B \-quad 53 | quadratic sweep 54 | .TP 55 | .B \-linear 56 | linear sweep 57 | .RE 58 | .TP 59 | .BR \-h ,\ \-\-help 60 | Print a help message and exit. 61 | .P 62 | The 63 | .I length\ in\ seconds 64 | parameter can be a decimal like 65 | .BR 0.5 . 66 | .SH AUTHORS 67 | This manual page was written by 68 | .MT erikd@mega-nerd.com 69 | Erik de Castro Lopo 70 | .ME 71 | in 2009. 72 | It has since been modified and updated by other authors. 73 | .SH "SEE ALSO" 74 | .BR sndfile\-jackplay (1), 75 | .BR sndfile\-mix\-to\-mono (1), 76 | .BR sndfile\-resample (1), 77 | .BR sndfile\-spectrogram (1), 78 | .BR sndfile\-waveform (1) 79 | -------------------------------------------------------------------------------- /tests/kaiser_window_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2013 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #define ARRAY_LEN(x) ((int) ((sizeof (x)) / (sizeof (x [0])))) 25 | 26 | int 27 | main (void) 28 | { 29 | double window [2000] ; 30 | int k ; 31 | 32 | printf ("%-37s : ", "kaiser_window_test") ; 33 | fflush (stdout) ; 34 | 35 | calc_kaiser_window (window, ARRAY_LEN (window), 1.0) ; 36 | 37 | for (k = 0 ; k < ARRAY_LEN (window) ; k++) 38 | { if (window [k] > 1.0) 39 | { printf ("\nError (%s %d) : window [%d] > 1.0.\n", __func__, __LINE__, k) ; 40 | exit (1) ; 41 | } ; 42 | 43 | if (window [k] < 0.0) 44 | { printf ("\nError (%s %d) : window [%d] < 0.0.\n", __func__, __LINE__, k) ; 45 | exit (1) ; 46 | } ; 47 | } ; 48 | 49 | if (fabs (window [0] - window [ARRAY_LEN (window) - 1]) > 1e-20) 50 | { printf ("\nError (%s %d) : fabs (%f - %f) > 1e-20)\n", __func__, __LINE__, window [0], window [ARRAY_LEN (window) - 1]) ; 51 | exit (1) ; 52 | } ; 53 | 54 | calc_kaiser_window (window, ARRAY_LEN (window) - 1, 1.0) ; 55 | 56 | if (fabs (window [0] - window [ARRAY_LEN (window) - 2]) > 1e-20) 57 | { printf ("\nError (%s %d) : fabs (%f - %f) > 1e-20)\n", __func__, __LINE__, window [0], window [ARRAY_LEN (window) - 1]) ; 58 | exit (1) ; 59 | } ; 60 | 61 | puts ("ok") ; 62 | 63 | return 0 ; 64 | } /* main */ 65 | -------------------------------------------------------------------------------- /doc/libsndfile.css: -------------------------------------------------------------------------------- 1 | body { 2 | background : black ; 3 | color : white ; 4 | font-family : arial, helvetica, sans-serif ; 5 | line-height: 1.5 ; 6 | } 7 | td { 8 | font-family : arial, helvetica, sans-serif ; 9 | background : black ; 10 | color : white ; 11 | } 12 | center { 13 | font-family : arial, helvetica, sans-serif ; 14 | } 15 | p { 16 | font-family : arial, helvetica, sans-serif ; 17 | text-align : left ; 18 | margin-left : 3% ; 19 | margin-right : 3% ; 20 | } 21 | .indent_block { 22 | font-family : arial, helvetica, sans-serif ; 23 | text-align : left ; 24 | margin-left : 10% ; 25 | margin-right : 10% ; 26 | } 27 | br { 28 | font-family : arial, helvetica, sans-serif ; 29 | } 30 | form { 31 | font-family : arial, helvetica, sans-serif ; 32 | } 33 | ul { 34 | font-family : arial, helvetica, sans-serif ; 35 | text-align : left ; 36 | margin-left : 3% ; 37 | margin-right : 6% ; 38 | } 39 | ol { 40 | font-family : arial, helvetica, sans-serif ; 41 | text-align : left ; 42 | margin-left : 3% ; 43 | margin-right : 6% ; 44 | } 45 | dl { 46 | font-family : arial, helvetica, sans-serif ; 47 | text-align : left ; 48 | margin-left : 3% ; 49 | margin-right : 3% ; 50 | } 51 | h1 { 52 | font-size : xx-large ; 53 | background : black ; 54 | color : #5050FF ; 55 | text-align : left ; 56 | margin-left : 3% ; 57 | margin-right : 3% ; 58 | } 59 | h2 { 60 | font-size : x-large ; 61 | background : black ; 62 | color : #5050FF ; 63 | text-align : left ; 64 | margin-left : 3% ; 65 | margin-right : 3% ; 66 | } 67 | h3 { 68 | font-size : large ; 69 | background : black ; 70 | color : #5050FF ; 71 | text-align : left ; 72 | margin-left : 3% ; 73 | margin-right : 3% ; 74 | } 75 | h4 { 76 | font-size : medium ; 77 | background : black ; 78 | color : #5050FF ; 79 | text-align : left ; 80 | margin-left : 3% ; 81 | margin-right : 3% ; 82 | } 83 | pre { 84 | font-family : courier, monospace ; 85 | font-size : medium ; 86 | margin-left : 6% ; 87 | margin-right : 6% ; 88 | } 89 | code, 90 | kbd, 91 | samp, 92 | var { 93 | font-family: "Courier New", monospace, serif; 94 | font-size: 1em; 95 | } 96 | a:link { color : #9090FF ; } 97 | a:visited { color : #5050FF ; } 98 | a:active { color : #FF00FF ; } 99 | a:hover { background-color : #202080 ; } 100 | -------------------------------------------------------------------------------- /man/sndfile-spectrogram.1: -------------------------------------------------------------------------------- 1 | .TH SNDFILE\-SPECTROGRAM 1 "May 2021" "" "User Commands" 2 | .SH NAME 3 | .B sndfile\-spectrogram 4 | \(em generate a spectrogram from an input sound file 5 | .SH SYNOPSIS 6 | .B sndfile\-spectrogram 7 | .RB [ OPTIONS ] 8 | .RI < sound\ file > 9 | .RI < img\ width > 10 | .RI < img\ height > 11 | .RI < png\ name > 12 | .SH DESCRIPTION 13 | Create a spectrogram as a PNG file from a given sound file. 14 | The spectrogram image will be of the given width and height. 15 | .P 16 | The input file is read using 17 | .UR http://www.mega\-nerd.com/libsndfile/ 18 | libsndfile 19 | .UE , 20 | the spectrogram is calculated with the help of 21 | .UR http://fftw.org/ 22 | FFTW 23 | .UE , 24 | and the spectrogram is 25 | rendered and written to the output file using 26 | .UR https://www.cairographics.org/ 27 | libcairo 28 | .UE . 29 | .SH OPTIONS 30 | .TP 31 | .BI \-\-dyn\-range= number 32 | Dynamic range (default is 33 | .B 180 34 | for 180dB range) 35 | .TP 36 | .B \-\-no\-border 37 | Drop the border, scales, heat map and title 38 | .TP 39 | .BI \-\-min\-freq= number 40 | Set the minimum frequency in the output 41 | .TP 42 | .BI \-\-max\-freq= number 43 | Set the maximum frequency in the output 44 | .TP 45 | .BI \-\-fft\-freq= number 46 | Set the lowest resolvable frequency and the height of each band in the linear 47 | spectrogram. 48 | Lower values increase frequency resolution but smear the output horizontally 49 | and higher values improve the temporal definition but decrease the distinction 50 | between the lowest frequencies. 51 | .TP 52 | .B \-\-log\-freq 53 | Use a logarithmic frequency scale 54 | .TP 55 | .B \-\-gray\-scale 56 | Output gray pixels instead of a heat map 57 | .TP 58 | .B \-\-kaiser 59 | Use a Kaiser window function (the default) 60 | .TP 61 | .B \-\-rectangular 62 | Use a rectangular window function 63 | .TP 64 | .B \-\-nuttall 65 | Use a Nuttall window function 66 | .TP 67 | .B \-\-hann 68 | Use a Hann window function 69 | .TP 70 | .BR \-h ,\ \-\-help 71 | Print a help message and exit. 72 | .SH AUTHORS 73 | This manual page was originally written by 74 | .MT erikd@mega-nerd.com 75 | Erik de Castro Lopo 76 | .ME 77 | in 2009. 78 | It has since been modified and updated by other authors. 79 | .SH "SEE ALSO" 80 | .BR sndfile\-generate\-chirp (1), 81 | .BR sndfile\-jackplay (1), 82 | .BR sndfile\-mix\-to\-mono (1), 83 | .BR sndfile\-resample (1), 84 | .BR sndfile\-waveform (1) 85 | -------------------------------------------------------------------------------- /Scripts/git-pre-commit-hook: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | 4 | if git rev-parse --verify HEAD >/dev/null 2>&1 ; then 5 | against=HEAD 6 | else 7 | # Initial commit: diff against an empty tree object 8 | against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 9 | fi 10 | 11 | files=`git diff-index --name-only --cached $against` 12 | 13 | # Redirect output to stderr. 14 | exec 1>&2 15 | 16 | #------------------------------------------------------------------------------- 17 | # Check the copyright notice of all files to be commited. 18 | 19 | user=`git config --global user.email` 20 | year=`date +"%Y"` 21 | 22 | missing_copyright_year="" 23 | for f in $files ; do 24 | if test ! -f $f ; then 25 | # If file does not exist, it was probably part of a rename or something. 26 | echo > /dev/null 27 | elif test `head -5 $f | grep -c -i copyright` -gt 0 ; then 28 | user_copyright=`grep -i copyright $f | grep $user | grep -c $year` 29 | if test $user_copyright -lt 1 ; then 30 | missing_copyright_year="$missing_copyright_year $f" 31 | fi 32 | fi 33 | done 34 | 35 | if test -n "$missing_copyright_year" ; then 36 | echo "Missing current year in the copyright notice of the following files:" 37 | for f in $missing_copyright_year ; do 38 | echo " $f" 39 | done 40 | echo "Commit aborted." 41 | exit 1 42 | fi 43 | 44 | #------------------------------------------------------------------------------- 45 | # Check the formatting of all C files. 46 | 47 | cfiles="" 48 | for f in $files ; do 49 | if test `echo $f | grep -c "\.[ch]$"` -gt 0 ; then 50 | cfiles="$cfiles $f" 51 | fi 52 | done 53 | 54 | if test -n "$cfiles" ; then 55 | Scripts/cstyle.py $cfiles 56 | if test $? -ne 0 ; then 57 | echo 58 | echo "Commit aborted. Fix the above error before trying again." 59 | exit 1 60 | fi 61 | fi 62 | 63 | #------------------------------------------------------------------------------- 64 | # Prevent files with non-ascii filenames from being committed. 65 | 66 | if test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 ; then 67 | echo "Error: Attempt to add a non-ascii file name." 68 | echo 69 | echo "This can cause problems if you want to work" 70 | echo "with people on other platforms." 71 | echo 72 | echo "To be portable it is advisable to rename the file ..." 73 | echo 74 | echo "Commit aborted." 75 | exit 1 76 | fi 77 | 78 | exit 0 79 | -------------------------------------------------------------------------------- /tests/common_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2012-2013 Erik de Castro Lopo 3 | ** Copyright (C) 2013 driedfruit 4 | ** 5 | ** This program is free software: you can redistribute it and/or modify 6 | ** it under the terms of the GNU General Public License as published by 7 | ** the Free Software Foundation, either version 2 or version 3 of the 8 | ** License. 9 | ** 10 | ** This program is distributed in the hope that it will be useful, 11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | ** GNU General Public License for more details. 14 | ** 15 | ** You should have received a copy of the GNU General Public License 16 | ** along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | static void parse_int_test (void) ; 28 | 29 | int 30 | main (void) 31 | { 32 | parse_int_test () ; 33 | return 0 ; 34 | } /* main */ 35 | 36 | /*=============================================================================== 37 | */ 38 | 39 | static void 40 | fork_parse_int (const char * str, int value, int should_parse) 41 | { pid_t pid ; 42 | int status = 0 ; 43 | 44 | if ((pid = fork ()) < 0) 45 | { printf ("Error : fork() failed.\n") ; 46 | exit (1) ; 47 | } ; 48 | 49 | if (pid == 0) 50 | { int parsed ; 51 | 52 | if (!freopen ("/dev/null", "w", stderr)) 53 | { printf ("Error: freopen() failed.\n") ; 54 | exit (1) ; 55 | } ; 56 | 57 | parsed = parse_int_or_die (str, "test") ; 58 | if (should_parse && parsed != value) 59 | { printf ("Error : Parse of '%s' resulted in %d, not %d\n", str, parsed, value) ; 60 | exit (1) ; 61 | } ; 62 | exit (0) ; 63 | } ; 64 | 65 | if (waitpid (pid, &status, 0) != pid) 66 | { printf ("Error : waitpid() failed.\n") ; 67 | exit (1) ; 68 | } ; 69 | 70 | if (should_parse && status != 0) 71 | exit (1) ; 72 | 73 | return ; 74 | } /* fork_parse_int */ 75 | 76 | static void 77 | parse_int_test (void) 78 | { 79 | printf ("%-37s : ", __func__) ; 80 | fflush (stdout) ; 81 | fork_parse_int ("1234", 1234, SF_TRUE) ; 82 | fork_parse_int ("+1234", +1234, SF_TRUE) ; 83 | fork_parse_int ("-1234", -1234, SF_TRUE) ; 84 | fork_parse_int ("10000000000000000000000000000000000000000000000000", 0, SF_FALSE) ; 85 | fork_parse_int ("die", 0, SF_FALSE) ; 86 | puts ("ok") ; 87 | } /* parse_int_test */ 88 | -------------------------------------------------------------------------------- /m4/ax_recursive_eval.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_recursive_eval.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_RECURSIVE_EVAL(VALUE, RESULT) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Interpolate the VALUE in loop until it doesn't change, and set the 12 | # result to $RESULT. WARNING: It's easy to get an infinite loop with some 13 | # unsane input. 14 | # 15 | # LICENSE 16 | # 17 | # Copyright (c) 2008 Alexandre Duret-Lutz 18 | # 19 | # This program is free software; you can redistribute it and/or modify it 20 | # under the terms of the GNU General Public License as published by the 21 | # Free Software Foundation; either version 2 of the License, or (at your 22 | # option) any later version. 23 | # 24 | # This program is distributed in the hope that it will be useful, but 25 | # WITHOUT ANY WARRANTY; without even the implied warranty of 26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 27 | # Public License for more details. 28 | # 29 | # You should have received a copy of the GNU General Public License along 30 | # with this program. If not, see . 31 | # 32 | # As a special exception, the respective Autoconf Macro's copyright owner 33 | # gives unlimited permission to copy, distribute and modify the configure 34 | # scripts that are the output of Autoconf when processing the Macro. You 35 | # need not follow the terms of the GNU General Public License when using 36 | # or distributing such scripts, even though portions of the text of the 37 | # Macro appear in them. The GNU General Public License (GPL) does govern 38 | # all other use of the material that constitutes the Autoconf Macro. 39 | # 40 | # This special exception to the GPL applies to versions of the Autoconf 41 | # Macro released by the Autoconf Archive. When you make and distribute a 42 | # modified version of the Autoconf Macro, you may extend this special 43 | # exception to the GPL to apply to your modified version as well. 44 | 45 | #serial 1 46 | 47 | AC_DEFUN([AX_RECURSIVE_EVAL], 48 | [_lcl_receval="$1" 49 | $2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" 50 | test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" 51 | _lcl_receval_old='' 52 | while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do 53 | _lcl_receval_old="[$]_lcl_receval" 54 | eval _lcl_receval="\"[$]_lcl_receval\"" 55 | done 56 | echo "[$]_lcl_receval")`]) 57 | -------------------------------------------------------------------------------- /src/mix-to-mono.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2011 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "common.h" 24 | 25 | static void usage_exit (void) ; 26 | static void mix_to_mono (SNDFILE * infile, SNDFILE * outfile) ; 27 | 28 | int 29 | main (int argc, char ** argv) 30 | { 31 | SNDFILE *infile, *outfile ; 32 | SF_INFO sfinfo = { } ; 33 | 34 | if (argc != 3) 35 | usage_exit () ; 36 | 37 | if (strcmp (argv [argc - 2], argv [argc - 1]) == 0) 38 | { printf ("Error : input and output file names are the same.\n") ; 39 | exit (1) ; 40 | } ; 41 | 42 | if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL) 43 | { printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ; 44 | sf_close (infile) ; 45 | exit (1) ; 46 | } ; 47 | 48 | if (sfinfo.channels == 1) 49 | { printf ("Input file '%s' already mono. Exiting.\n", argv [argc - 2]) ; 50 | sf_close (infile) ; 51 | exit (0) ; 52 | } ; 53 | 54 | /* Force output channels to mono. */ 55 | sfinfo.channels = 1 ; 56 | 57 | if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) 58 | { printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ; 59 | sf_close (infile) ; 60 | exit (1) ; 61 | } ; 62 | 63 | /* Delete the output file length to zero if already exists. */ 64 | remove (argv [argc - 1]) ; 65 | 66 | mix_to_mono (infile, outfile) ; 67 | 68 | sf_close (infile) ; 69 | sf_close (outfile) ; 70 | 71 | return 0 ; 72 | } /* main */ 73 | 74 | static void 75 | mix_to_mono (SNDFILE * infile, SNDFILE * outfile) 76 | { double buffer [1024] ; 77 | sf_count_t count ; 78 | 79 | while ((count = sfx_mix_mono_read_double (infile, buffer, ARRAY_LEN (buffer))) > 0) 80 | sf_write_double (outfile, buffer, count) ; 81 | 82 | return ; 83 | } /* mix_to_mono */ 84 | 85 | static void 86 | usage_exit (void) 87 | { 88 | puts ("\n" 89 | "Usage :\n\n" 90 | " sndfile-mix-to-mono \n" 91 | ) ; 92 | exit (0) ; 93 | } /* usage_exit */ 94 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2015 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | #include "config.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "common.h" 27 | 28 | /* Global. */ 29 | const char *font_family = "DejaVu Sans Mono" ; 30 | 31 | sf_count_t 32 | sfx_mix_mono_read_double (SNDFILE * file, double * data, sf_count_t datalen) 33 | { 34 | SF_INFO info = { } ; 35 | 36 | sf_command (file, SFC_GET_CURRENT_SF_INFO, &info, sizeof (info)) ; 37 | 38 | if (info.channels == 1) 39 | return sf_read_double (file, data, datalen) ; 40 | 41 | static double multi_data [2048] ; 42 | int k, ch, frames_read ; 43 | sf_count_t dataout = 0 ; 44 | 45 | while (dataout < datalen) 46 | { int this_read ; 47 | 48 | this_read = MIN (ARRAY_LEN (multi_data) / info.channels, datalen - dataout) ; 49 | 50 | frames_read = sf_readf_double (file, multi_data, this_read) ; 51 | if (frames_read == 0) 52 | break ; 53 | 54 | for (k = 0 ; k < frames_read ; k++) 55 | { double mix = 0.0 ; 56 | 57 | for (ch = 0 ; ch < info.channels ; ch++) 58 | mix += multi_data [k * info.channels + ch] ; 59 | data [dataout + k] = mix / info.channels ; 60 | } ; 61 | 62 | dataout += frames_read ; 63 | } ; 64 | 65 | return dataout ; 66 | } /* sfx_mix_mono_read_double */ 67 | 68 | int 69 | parse_int_or_die (const char * input, const char * value_name) 70 | { char * endptr ; 71 | 72 | long value = strtol (input, &endptr, 10) ; 73 | 74 | if (endptr == input || endptr [0] != 0 || value >= INT_MAX) 75 | { fprintf (stderr, "Error : Can't parse int value %s : %s\n", value_name, input) ; 76 | exit (1) ; 77 | } ; 78 | 79 | return value ; 80 | } /* parse_int_or_die */ 81 | 82 | double 83 | parse_double_or_die (const char * input, const char * value_name) 84 | { char * endptr ; 85 | 86 | double value = strtod (input, &endptr) ; 87 | 88 | if (endptr == input || endptr [0] != 0) 89 | { fprintf (stderr, "Error : Can't parse double value %s : %s\n", value_name, input) ; 90 | exit (1) ; 91 | } ; 92 | 93 | return value ; 94 | } /* parse_double_or_die */ 95 | -------------------------------------------------------------------------------- /m4/ax_append_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_append_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # FLAG is appended to the FLAGS-VARIABLE shell variable, with a space 12 | # added in between. 13 | # 14 | # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. 15 | # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains 16 | # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly 17 | # FLAG. 18 | # 19 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. 20 | # 21 | # LICENSE 22 | # 23 | # Copyright (c) 2008 Guido U. Draheim 24 | # Copyright (c) 2011 Maarten Bosmans 25 | # 26 | # This program is free software: you can redistribute it and/or modify it 27 | # under the terms of the GNU General Public License as published by the 28 | # Free Software Foundation, either version 3 of the License, or (at your 29 | # option) any later version. 30 | # 31 | # This program is distributed in the hope that it will be useful, but 32 | # WITHOUT ANY WARRANTY; without even the implied warranty of 33 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 34 | # Public License for more details. 35 | # 36 | # You should have received a copy of the GNU General Public License along 37 | # with this program. If not, see . 38 | # 39 | # As a special exception, the respective Autoconf Macro's copyright owner 40 | # gives unlimited permission to copy, distribute and modify the configure 41 | # scripts that are the output of Autoconf when processing the Macro. You 42 | # need not follow the terms of the GNU General Public License when using 43 | # or distributing such scripts, even though portions of the text of the 44 | # Macro appear in them. The GNU General Public License (GPL) does govern 45 | # all other use of the material that constitutes the Autoconf Macro. 46 | # 47 | # This special exception to the GPL applies to versions of the Autoconf 48 | # Macro released by the Autoconf Archive. When you make and distribute a 49 | # modified version of the Autoconf Macro, you may extend this special 50 | # exception to the GPL to apply to your modified version as well. 51 | 52 | #serial 7 53 | 54 | AC_DEFUN([AX_APPEND_FLAG], 55 | [dnl 56 | AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF 57 | AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) 58 | AS_VAR_SET_IF(FLAGS,[ 59 | AS_CASE([" AS_VAR_GET(FLAGS) "], 60 | [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], 61 | [ 62 | AS_VAR_APPEND(FLAGS,[" $1"]) 63 | AC_RUN_LOG([: FLAGS="$FLAGS"]) 64 | ]) 65 | ], 66 | [ 67 | AS_VAR_SET(FLAGS,[$1]) 68 | AC_RUN_LOG([: FLAGS="$FLAGS"]) 69 | ]) 70 | AS_VAR_POPDEF([FLAGS])dnl 71 | ])dnl AX_APPEND_FLAG 72 | -------------------------------------------------------------------------------- /m4/ax_append_link_flags.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # For every FLAG1, FLAG2 it is checked whether the linker works with the 12 | # flag. If it does, the flag is added FLAGS-VARIABLE 13 | # 14 | # If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is 15 | # used. During the check the flag is always added to the linker's flags. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG. 25 | # Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2011 Maarten Bosmans 30 | # 31 | # This program is free software: you can redistribute it and/or modify it 32 | # under the terms of the GNU General Public License as published by the 33 | # Free Software Foundation, either version 3 of the License, or (at your 34 | # option) any later version. 35 | # 36 | # This program is distributed in the hope that it will be useful, but 37 | # WITHOUT ANY WARRANTY; without even the implied warranty of 38 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 39 | # Public License for more details. 40 | # 41 | # You should have received a copy of the GNU General Public License along 42 | # with this program. If not, see . 43 | # 44 | # As a special exception, the respective Autoconf Macro's copyright owner 45 | # gives unlimited permission to copy, distribute and modify the configure 46 | # scripts that are the output of Autoconf when processing the Macro. You 47 | # need not follow the terms of the GNU General Public License when using 48 | # or distributing such scripts, even though portions of the text of the 49 | # Macro appear in them. The GNU General Public License (GPL) does govern 50 | # all other use of the material that constitutes the Autoconf Macro. 51 | # 52 | # This special exception to the GPL applies to versions of the Autoconf 53 | # Macro released by the Autoconf Archive. When you make and distribute a 54 | # modified version of the Autoconf Macro, you may extend this special 55 | # exception to the GPL to apply to your modified version as well. 56 | 57 | #serial 6 58 | 59 | AC_DEFUN([AX_APPEND_LINK_FLAGS], 60 | [AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 61 | AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) 62 | for flag in $1; do 63 | AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4]) 64 | done 65 | ])dnl AX_APPEND_LINK_FLAGS 66 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = \ 2 | README.md \ 3 | Scripts/calc-hilbert-fir.m 4 | 5 | dist_html_DATA = \ 6 | doc/index.html \ 7 | doc/sweep.png \ 8 | doc/wave-example.png \ 9 | doc/wave-sweep.png \ 10 | doc/libsndfile.css 11 | 12 | bin_PROGRAMS = \ 13 | bin/sndfile-generate-chirp \ 14 | bin/sndfile-spectrogram \ 15 | bin/sndfile-mix-to-mono \ 16 | bin/sndfile-resample \ 17 | bin/sndfile-waveform 18 | 19 | CLEANFILES = src/*~ 20 | 21 | dist_man_MANS = \ 22 | man/sndfile-generate-chirp.1 \ 23 | man/sndfile-spectrogram.1 \ 24 | man/sndfile-mix-to-mono.1 \ 25 | man/sndfile-jackplay.1 \ 26 | man/sndfile-resample.1 \ 27 | man/sndfile-waveform.1 28 | 29 | #========================================================================================= 30 | # The bin targets. 31 | 32 | bin_sndfile_generate_chirp_SOURCES = \ 33 | src/common.c \ 34 | src/common.h \ 35 | src/generate-chirp.c 36 | bin_sndfile_generate_chirp_CFLAGS = $(SNDFILE_CFLAGS) 37 | bin_sndfile_generate_chirp_LDADD = $(SNDFILE_LIBS) 38 | 39 | bin_sndfile_spectrogram_SOURCES = \ 40 | src/common.c \ 41 | src/common.h \ 42 | src/spectrogram.c \ 43 | src/spectrum.c \ 44 | src/spectrum.h \ 45 | src/window.c \ 46 | src/window.h 47 | bin_sndfile_spectrogram_CFLAGS = $(SNDFILE_CFLAGS) $(FFTW3_CFLAGS) $(CAIRO_CFLAGS) 48 | bin_sndfile_spectrogram_LDADD = $(SNDFILE_LIBS) $(FFTW3_LIBS) $(CAIRO_LIBS) 49 | 50 | bin_sndfile_mix_to_mono_SOURCES = \ 51 | src/common.c \ 52 | src/common.h \ 53 | src/mix-to-mono.c 54 | bin_sndfile_mix_to_mono_CFLAGS = $(SNDFILE_CFLAGS) 55 | bin_sndfile_mix_to_mono_LDADD = $(SNDFILE_LIBS) 56 | 57 | bin_sndfile_waveform_SOURCES = \ 58 | src/common.c \ 59 | src/common.h \ 60 | src/waveform.c 61 | bin_sndfile_waveform_CFLAGS = $(SNDFILE_CFLAGS) $(CAIRO_CFLAGS) 62 | bin_sndfile_waveform_LDADD = $(SNDFILE_LIBS) $(CAIRO_LIBS) 63 | 64 | bin_sndfile_resample_SOURCES = \ 65 | src/common.c \ 66 | src/common.h \ 67 | src/resample.c 68 | bin_sndfile_resample_CFLAGS = $(SNDFILE_CFLAGS) $(SAMPLERATE_CFLAGS) 69 | bin_sndfile_resample_LDADD = $(SNDFILE_LIBS) $(SAMPLERATE_LIBS) 70 | 71 | if HAVE_JACK 72 | bin_PROGRAMS += bin/sndfile-jackplay 73 | bin_sndfile_jackplay_SOURCES = src/jackplay.c 74 | bin_sndfile_jackplay_CFLAGS = $(SNDFILE_CFLAGS) $(JACK_CFLAGS) 75 | bin_sndfile_jackplay_LDADD = $(SNDFILE_LIBS) $(JACK_LIBS) 76 | endif 77 | 78 | #========================================================================================= 79 | # The make check targets. 80 | 81 | # Test programs or programs not yet working. 82 | check_PROGRAMS = \ 83 | tests/common_tests \ 84 | tests/kaiser_window_test 85 | 86 | tests_kaiser_window_test_SOURCES = \ 87 | src/window.c \ 88 | src/window.h \ 89 | tests/kaiser_window_test.c 90 | 91 | tests_common_tests_SOURCES = \ 92 | src/common.c \ 93 | src/common.h \ 94 | tests/common_tests.c 95 | tests_common_tests_CFLAGS = $(SNDFILE_CFLAGS) 96 | tests_common_tests_LDADD = $(SNDFILE_LIBS) 97 | 98 | EXTRA_DIST += tests/test-wrapper.sh 99 | TESTS = \ 100 | $(check_PROGRAMS) \ 101 | tests/test-wrapper.sh 102 | 103 | # The 'dist-clean' target on Mac OSX fails without this. 104 | clean-local: 105 | rm -rf bin/*.dSYM 106 | -------------------------------------------------------------------------------- /m4/ax_append_compile_flags.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html 3 | # ============================================================================ 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # For every FLAG1, FLAG2 it is checked whether the compiler works with the 12 | # flag. If it does, the flag is added FLAGS-VARIABLE 13 | # 14 | # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. 15 | # CFLAGS) is used. During the check the flag is always added to the 16 | # current language's flags. 17 | # 18 | # If EXTRA-FLAGS is defined, it is added to the current language's default 19 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 20 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 21 | # force the compiler to issue an error when a bad flag is given. 22 | # 23 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 24 | # 25 | # NOTE: This macro depends on the AX_APPEND_FLAG and 26 | # AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with 27 | # AX_APPEND_LINK_FLAGS. 28 | # 29 | # LICENSE 30 | # 31 | # Copyright (c) 2011 Maarten Bosmans 32 | # 33 | # This program is free software: you can redistribute it and/or modify it 34 | # under the terms of the GNU General Public License as published by the 35 | # Free Software Foundation, either version 3 of the License, or (at your 36 | # option) any later version. 37 | # 38 | # This program is distributed in the hope that it will be useful, but 39 | # WITHOUT ANY WARRANTY; without even the implied warranty of 40 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 41 | # Public License for more details. 42 | # 43 | # You should have received a copy of the GNU General Public License along 44 | # with this program. If not, see . 45 | # 46 | # As a special exception, the respective Autoconf Macro's copyright owner 47 | # gives unlimited permission to copy, distribute and modify the configure 48 | # scripts that are the output of Autoconf when processing the Macro. You 49 | # need not follow the terms of the GNU General Public License when using 50 | # or distributing such scripts, even though portions of the text of the 51 | # Macro appear in them. The GNU General Public License (GPL) does govern 52 | # all other use of the material that constitutes the Autoconf Macro. 53 | # 54 | # This special exception to the GPL applies to versions of the Autoconf 55 | # Macro released by the Autoconf Archive. When you make and distribute a 56 | # modified version of the Autoconf Macro, you may extend this special 57 | # exception to the GPL to apply to your modified version as well. 58 | 59 | #serial 6 60 | 61 | AC_DEFUN([AX_APPEND_COMPILE_FLAGS], 62 | [AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) 63 | AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) 64 | for flag in $1; do 65 | AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) 66 | done 67 | ])dnl AX_APPEND_COMPILE_FLAGS 68 | -------------------------------------------------------------------------------- /Scripts/calc-hilbert-fir.m: -------------------------------------------------------------------------------- 1 | # For all the gory details, I suggest the paper: 2 | # 3 | # Andrew Reilly and Gordon Frazer and Boualem Boashash: 4 | # Analytic signal generation---tips and traps, 5 | # IEEE Transactions on Signal Processing, 6 | # no. 11, vol. 42, Nov. 1994, pp. 3241-3245. 7 | # 8 | # For comp.dsp, the gist is: 9 | # 10 | # 1. Design a half-bandwidth real low-pass FIR filter using whatever optimal method 11 | # you choose, with the principle design criterion being minimization of the 12 | # maximum attenuation in the band f_s/4 to f_s/2. 13 | # 14 | # 2. Modulate this by exp(2 pi f_s/4 t), so that now your stop-band is the negative 15 | # frequencies, the pass-band is the positive frequencies, and the roll-off at 16 | # each end does not extend into the negative frequency band. 17 | # 18 | # 3. either use it as a complex FIR filter, or a pair of I/Q real filters in 19 | # whatever FIR implementation you have available. 20 | # 21 | # If your original filter design produced an impulse response with an even number 22 | # of taps, then the filtering in 3 will introduce a spurious half-sample delay 23 | # (resampling the real signal component), but that does not matter for many 24 | # applications, and such filters have other features to recommend them. 25 | # 26 | # Andrew Reilly [Reilly@zeta.org.au] 27 | 28 | 29 | # Don't make the filter a full half bandwidth filter. 30 | # We need the bandwidth to extend well down towards DC, but we don't really 31 | # need the bandwidht to extend all the way up to fs/2. 32 | # 33 | # Therefore build a filter that is slightly less than half band and modulate 34 | # into place with a special factor. 35 | 36 | nargin ; 37 | 38 | if nargin >= 1, 39 | arg_list = argv () ; 40 | file = fopen (arg_list {1}, "w") ; 41 | else 42 | file = stdout ; 43 | endif 44 | 45 | b = remez (255, [0 0.356 0.4 1], [1, 1, 0, 0]) ; 46 | 47 | len = length (b) ; 48 | 49 | if rem (len , 2) !+ 0 50 | error ("Filter length should be even.") ; 51 | endif 52 | 53 | half_len = len / 2 ; 54 | 55 | # Normally, when using something like a half band filter, the factor would be 56 | # 0.5. We choose something less, so the low frequency transition band 57 | # straddles zero frquency. 58 | 59 | factor = 0.386 ; 60 | modulator = exp (factor * pi * i * linspace (-(len-1)/2, (len-1)/2, len)) ; 61 | 62 | # plot (real (modulator)) ; pause ; exit (0) ; 63 | 64 | bc = 2 * (b' .* modulator) ; 65 | 66 | # plot (1:len, real (bc), 1:len, imag (bc)) ; pause ; exit (0) ; 67 | 68 | magspec = abs (fft ([bc zeros(1,1000-length(b))])) ; 69 | 70 | # plot (real (magspec)) ; pause ; exit (0) ; 71 | 72 | bchalf = bc (1:half_len) ; 73 | 74 | error = abs (bchalf - conj (fliplr (bc (half_len+1:len)))) ; 75 | 76 | if error > 1e-10, 77 | # plot (error) ; pause ; exit (0) ; 78 | fprintf (stderr, "Error : %f\n", max (error)) ; 79 | exit (1) ; 80 | endif 81 | 82 | fprintf (file, "#define FIR_HILBERT_HALF_LEN %d\n\n", half_len) ; 83 | 84 | fprintf (file, "static complex_t half_hilbert_coeffs [FIR_HILBERT_HALF_LEN] =\n{") ; 85 | 86 | for coeff = fliplr (bchalf) 87 | fprintf (file, "\t{\t%22.18f, %22.18f },\n", real (coeff), imag (coeff)) ; 88 | endfor 89 | 90 | fprintf (file, "} ; \n") ; 91 | 92 | if file != stdout, 93 | fclose (file) ; 94 | endif 95 | 96 | # fprintf (stderr, "\nPress any key to exit.\n") ; 97 | # plot (20 * log10 (magspec)) ; grid ; pause 98 | 99 | -------------------------------------------------------------------------------- /m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_LINK_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # This program is free software: you can redistribute it and/or modify it 33 | # under the terms of the GNU General Public License as published by the 34 | # Free Software Foundation, either version 3 of the License, or (at your 35 | # option) any later version. 36 | # 37 | # This program is distributed in the hope that it will be useful, but 38 | # WITHOUT ANY WARRANTY; without even the implied warranty of 39 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 40 | # Public License for more details. 41 | # 42 | # You should have received a copy of the GNU General Public License along 43 | # with this program. If not, see . 44 | # 45 | # As a special exception, the respective Autoconf Macro's copyright owner 46 | # gives unlimited permission to copy, distribute and modify the configure 47 | # scripts that are the output of Autoconf when processing the Macro. You 48 | # need not follow the terms of the GNU General Public License when using 49 | # or distributing such scripts, even though portions of the text of the 50 | # Macro appear in them. The GNU General Public License (GPL) does govern 51 | # all other use of the material that constitutes the Autoconf Macro. 52 | # 53 | # This special exception to the GPL applies to versions of the Autoconf 54 | # Macro released by the Autoconf Archive. When you make and distribute a 55 | # modified version of the Autoconf Macro, you may extend this special 56 | # exception to the GPL to apply to your modified version as well. 57 | 58 | #serial 5 59 | 60 | AC_DEFUN([AX_CHECK_LINK_FLAG], 61 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 62 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 63 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 64 | ax_check_save_flags=$LDFLAGS 65 | LDFLAGS="$LDFLAGS $4 $1" 66 | AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 67 | [AS_VAR_SET(CACHEVAR,[yes])], 68 | [AS_VAR_SET(CACHEVAR,[no])]) 69 | LDFLAGS=$ax_check_save_flags]) 70 | AS_VAR_IF(CACHEVAR,yes, 71 | [m4_default([$2], :)], 72 | [m4_default([$3], :)]) 73 | AS_VAR_POPDEF([CACHEVAR])dnl 74 | ])dnl AX_CHECK_LINK_FLAGS 75 | -------------------------------------------------------------------------------- /src/spectrum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "common.h" 12 | #include "window.h" 13 | #include "spectrum.h" 14 | 15 | 16 | 17 | spectrum * 18 | create_spectrum (int speclen, enum WINDOW_FUNCTION window_function) 19 | { spectrum *spec ; 20 | 21 | spec = calloc (1, sizeof (spectrum)) ; 22 | if (spec == NULL) 23 | { printf ("%s : Not enough memory.\n", __func__) ; 24 | exit (1) ; 25 | } ; 26 | 27 | spec->wfunc = window_function ; 28 | spec->speclen = speclen ; 29 | 30 | /* mag_spec has values from [0..speclen] inclusive for 0Hz to Nyquist. 31 | ** time_domain has an extra element to be able to interpolate between 32 | ** samples for better time precision, hoping to eliminate artifacts. 33 | */ 34 | spec->time_domain = calloc (2 * speclen + 1, sizeof (double)) ; 35 | spec->window = calloc (2 * speclen, sizeof (double)) ; 36 | spec->freq_domain = calloc (2 * speclen, sizeof (double)) ; 37 | spec->mag_spec = calloc (speclen + 1, sizeof (double)) ; 38 | if (spec->time_domain == NULL 39 | || spec->window == NULL 40 | || spec->freq_domain == NULL 41 | || spec->mag_spec == NULL) 42 | { printf ("%s : Not enough memory.\n", __func__) ; 43 | exit (1) ; 44 | } ; 45 | 46 | spec->plan = fftw_plan_r2r_1d (2 * speclen, spec->time_domain, spec->freq_domain, FFTW_R2HC, FFTW_MEASURE | FFTW_PRESERVE_INPUT) ; 47 | if (spec->plan == NULL) 48 | { printf ("%s:%d : fftw create plan failed.\n", __func__, __LINE__) ; 49 | free (spec) ; 50 | exit (1) ; 51 | } ; 52 | 53 | switch (spec->wfunc) 54 | { case RECTANGULAR : 55 | break ; 56 | case KAISER : 57 | calc_kaiser_window (spec->window, 2 * speclen, 20.0) ; 58 | break ; 59 | case NUTTALL: 60 | calc_nuttall_window (spec->window, 2 * speclen) ; 61 | break ; 62 | case HANN : 63 | calc_hann_window (spec->window, 2 * speclen) ; 64 | break ; 65 | default : 66 | printf ("Internal error: Unknown window_function.\n") ; 67 | free (spec) ; 68 | exit (1) ; 69 | } ; 70 | 71 | return spec ; 72 | } /* create_spectrum */ 73 | 74 | 75 | void 76 | destroy_spectrum (spectrum * spec) 77 | { 78 | fftw_destroy_plan (spec->plan) ; 79 | free (spec->time_domain) ; 80 | free (spec->window) ; 81 | free (spec->freq_domain) ; 82 | free (spec->mag_spec) ; 83 | free (spec) ; 84 | } /* destroy_spectrum */ 85 | 86 | double 87 | calc_magnitude_spectrum (spectrum * spec) 88 | { 89 | double max ; 90 | int k, freqlen ; 91 | 92 | freqlen = 2 * spec->speclen ; 93 | 94 | if (spec->wfunc != RECTANGULAR) 95 | for (k = 0 ; k < 2 * spec->speclen ; k++) 96 | spec->time_domain [k] *= spec->window [k] ; 97 | 98 | 99 | fftw_execute (spec->plan) ; 100 | 101 | /* Convert from FFTW's "half complex" format to an array of magnitudes. 102 | ** In HC format, the values are stored: 103 | ** r0, r1, r2 ... r(n/2), i(n+1)/2-1 .. i2, i1 104 | **/ 105 | max = spec->mag_spec [0] = fabs (spec->freq_domain [0]) ; 106 | 107 | for (k = 1 ; k < spec->speclen ; k++) 108 | { double re = spec->freq_domain [k] ; 109 | double im = spec->freq_domain [freqlen - k] ; 110 | spec->mag_spec [k] = sqrt (re * re + im * im) ; 111 | max = MAX (max, spec->mag_spec [k]) ; 112 | } ; 113 | /* Lastly add the point for the Nyquist frequency */ 114 | spec->mag_spec [spec->speclen] = fabs (spec->freq_domain [spec->speclen]) ; 115 | 116 | return max ; 117 | } /* calc_magnitude_spectrum */ 118 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # This program is free software: you can redistribute it and/or modify it 33 | # under the terms of the GNU General Public License as published by the 34 | # Free Software Foundation, either version 3 of the License, or (at your 35 | # option) any later version. 36 | # 37 | # This program is distributed in the hope that it will be useful, but 38 | # WITHOUT ANY WARRANTY; without even the implied warranty of 39 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 40 | # Public License for more details. 41 | # 42 | # You should have received a copy of the GNU General Public License along 43 | # with this program. If not, see . 44 | # 45 | # As a special exception, the respective Autoconf Macro's copyright owner 46 | # gives unlimited permission to copy, distribute and modify the configure 47 | # scripts that are the output of Autoconf when processing the Macro. You 48 | # need not follow the terms of the GNU General Public License when using 49 | # or distributing such scripts, even though portions of the text of the 50 | # Macro appear in them. The GNU General Public License (GPL) does govern 51 | # all other use of the material that constitutes the Autoconf Macro. 52 | # 53 | # This special exception to the GPL applies to versions of the Autoconf 54 | # Macro released by the Autoconf Archive. When you make and distribute a 55 | # modified version of the Autoconf Macro, you may extend this special 56 | # exception to the GPL to apply to your modified version as well. 57 | 58 | #serial 5 59 | 60 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 61 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 62 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 63 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 64 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 65 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 66 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 67 | [AS_VAR_SET(CACHEVAR,[yes])], 68 | [AS_VAR_SET(CACHEVAR,[no])]) 69 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 70 | AS_VAR_IF(CACHEVAR,yes, 71 | [m4_default([$2], :)], 72 | [m4_default([$3], :)]) 73 | AS_VAR_POPDEF([CACHEVAR])dnl 74 | ])dnl AX_CHECK_COMPILE_FLAGS 75 | -------------------------------------------------------------------------------- /m4/ax_compiler_vendor.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_COMPILER_VENDOR 8 | # 9 | # DESCRIPTION 10 | # 11 | # Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, 12 | # hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, 13 | # watcom, etc. The vendor is returned in the cache variable 14 | # $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. 15 | # 16 | # LICENSE 17 | # 18 | # Copyright (c) 2008 Steven G. Johnson 19 | # Copyright (c) 2008 Matteo Frigo 20 | # 21 | # This program is free software: you can redistribute it and/or modify it 22 | # under the terms of the GNU General Public License as published by the 23 | # Free Software Foundation, either version 3 of the License, or (at your 24 | # option) any later version. 25 | # 26 | # This program is distributed in the hope that it will be useful, but 27 | # WITHOUT ANY WARRANTY; without even the implied warranty of 28 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 29 | # Public License for more details. 30 | # 31 | # You should have received a copy of the GNU General Public License along 32 | # with this program. If not, see . 33 | # 34 | # As a special exception, the respective Autoconf Macro's copyright owner 35 | # gives unlimited permission to copy, distribute and modify the configure 36 | # scripts that are the output of Autoconf when processing the Macro. You 37 | # need not follow the terms of the GNU General Public License when using 38 | # or distributing such scripts, even though portions of the text of the 39 | # Macro appear in them. The GNU General Public License (GPL) does govern 40 | # all other use of the material that constitutes the Autoconf Macro. 41 | # 42 | # This special exception to the GPL applies to versions of the Autoconf 43 | # Macro released by the Autoconf Archive. When you make and distribute a 44 | # modified version of the Autoconf Macro, you may extend this special 45 | # exception to the GPL to apply to your modified version as well. 46 | 47 | #serial 16 48 | 49 | AC_DEFUN([AX_COMPILER_VENDOR], 50 | [AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, 51 | dnl Please add if possible support to ax_compiler_version.m4 52 | [# note: don't check for gcc first since some other compilers define __GNUC__ 53 | vendors="intel: __ICC,__ECC,__INTEL_COMPILER 54 | ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ 55 | pathscale: __PATHCC__,__PATHSCALE__ 56 | clang: __clang__ 57 | cray: _CRAYC 58 | fujitsu: __FUJITSU 59 | gnu: __GNUC__ 60 | sun: __SUNPRO_C,__SUNPRO_CC 61 | hp: __HP_cc,__HP_aCC 62 | dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER 63 | borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ 64 | comeau: __COMO__ 65 | kai: __KCC 66 | lcc: __LCC__ 67 | sgi: __sgi,sgi 68 | microsoft: _MSC_VER 69 | metrowerks: __MWERKS__ 70 | watcom: __WATCOMC__ 71 | portland: __PGI 72 | tcc: __TINYC__ 73 | unknown: UNKNOWN" 74 | for ventest in $vendors; do 75 | case $ventest in 76 | *:) vendor=$ventest; continue ;; 77 | *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; 78 | esac 79 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ 80 | #if !($vencpp) 81 | thisisanerror; 82 | #endif 83 | ])], [break]) 84 | done 85 | ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` 86 | ]) 87 | ]) 88 | -------------------------------------------------------------------------------- /Scripts/localinstall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os, re, string, sys, time 4 | 5 | # AC_INIT(libsndfile,1.1.0pre1,) 6 | def find_configure_version (filename): 7 | file = open (filename) 8 | while 1: 9 | line = file.readline () 10 | if re.search ("AC_INIT\(", line): 11 | line = re.sub ("AC_INIT\(", "", line) 12 | x = re.sub ("\).*\n", "", line) 13 | package, version, rubbish = string.split (x, ",", 3) 14 | package = re.sub ("[\[\]]", "", package) 15 | version = re.sub ("[\[\]]", "", version) 16 | break 17 | file.close () 18 | # version = re.escape (version) 19 | return package, version 20 | 21 | def find_header_version (filename): 22 | file = open (filename) 23 | while 1: 24 | line = file.readline () 25 | if not line: 26 | print "Error : could not find version in :", filename 27 | sys.exit (1) 28 | if re.search ("#define[ \t]+VERSION", line): 29 | version = re.sub ("[#a-zA-Z \t]+\"", "", line) 30 | version = re.sub ("\".*\n", "", version) 31 | break 32 | file.close () 33 | # version = re.escape (version) 34 | return version 35 | 36 | def html_find_configure_version (data): 37 | if os.path.isfile (data): 38 | file = open (data, "r") 39 | data = file.read () 40 | file.close () 41 | version = re.search ("", data) 42 | version = re.search ("sndfile-tools-[^\"]+\"", version.group (0)) 43 | version = re.sub ("(sndfile-tools-|\")", "", version.group (0)) 44 | return version 45 | 46 | def html_fix_version (filename, new_version): 47 | file = open (filename, "r") 48 | data = file.read () 49 | file.close () 50 | temp_filename = "%s.%d" % (filename, int (time.time ())) 51 | os.rename (filename, temp_filename) 52 | html_version = html_find_configure_version (data) 53 | 54 | try: 55 | if html_version != new_version: 56 | print "Updating html file version number." 57 | 58 | data = re.sub (re.escape ("-%s" % html_version), "-%s" % new_version, data) 59 | 60 | file = open (filename, "w") 61 | file.write (data) 62 | file.close () 63 | os.unlink (temp_filename) 64 | else: 65 | os.rename (temp_filename, filename) 66 | 67 | except: 68 | print "Html file update failed." 69 | os.rename (temp_filename, filename) 70 | sys.exit (1) 71 | 72 | #print html_find_configure_version ("doc/index.html") 73 | # 74 | #sys.exit (0) 75 | 76 | 77 | #========================================================================= 78 | # Main program. 79 | 80 | conf_package, conf_version = find_configure_version ("configure.ac") 81 | 82 | header_version = find_header_version ("src/config.h") 83 | 84 | if conf_version != header_version: 85 | print "Configure/header version mismatch!", conf_version, header_version 86 | sys.exit (0) 87 | 88 | # os.system ("mgdiff Win32/sndfile.h src/sndfile.h") 89 | 90 | os.system ("nedit AUTHORS NEWS README ChangeLog") 91 | 92 | os.system ("nedit doc/*.html") 93 | 94 | # Generate the filenames from the versions. 95 | 96 | tar_gz_file = "%s-%s.tar.gz" % (conf_package, conf_version) 97 | 98 | if not os.path.isfile (tar_gz_file): 99 | print "No tarball. Exiting!" 100 | sys.exit (1) 101 | 102 | #if not os.path.isfile (tar_gz_file + ".asc"): 103 | # print "No GPG signature for tarball. Exiting!" 104 | # print "gpg -a -detach-sign file" 105 | # sys.exit (1) 106 | 107 | # Edit the html files :-) 108 | html_fix_version ("doc/index.html", conf_version) 109 | 110 | if not os.path.isfile ("doc/index.html"): 111 | print "\n\n************* No doc/index.html ****************\n" 112 | sys.exit (1) 113 | 114 | if len(sys.argv) == 2 and sys.argv [1] == "--copy": 115 | print "**************** Copying to Web Directory. ****************" ; 116 | dest = "/home/erikd/HTML/Mega-Nerd/libsndfile/tools/" 117 | 118 | os.system ("cp -f AUTHORS NEWS README ChangeLog " + dest) 119 | 120 | os.system (("cp -f doc/*.html doc/*.png %s " + dest) % (tar_gz_file)) 121 | os.system ("chmod a+r /home/erikd/HTML/Mega-Nerd/libsndfile/tools/*") 122 | sys.exit (0) 123 | else: 124 | print "Not copying." 125 | 126 | -------------------------------------------------------------------------------- /man/sndfile-waveform.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.17. 2 | .TH SNDFILE-WAVEFORM "1" "January 2021" "sndfile-waveform 1.5" "User Commands" 3 | .SH NAME 4 | sndfile-waveform \- manual page for sndfile-waveform 1.5 5 | .SH SYNOPSIS 6 | .B sndfile-waveform 7 | [\fI\,OPTION\/\fR] \fI\, \/\fR 8 | .SH DESCRIPTION 9 | sndfile\-waveform \- waveform image generator 10 | .PP 11 | Creates a PNG image depicting the wave\-form of an audio file. 12 | Peak\-signal and RMS values can be displayed in the same plot, 13 | where the horizontal axis always represents time. 14 | .PP 15 | The vertical axis can be plotted logarithmically, and the signal 16 | can optionally be rectified. 17 | .PP 18 | The Time\-axis annotation unit is either seconds, audio\-frames or timecode 19 | using broadcast\-wave time reference meta\-data. 20 | .PP 21 | The tool can plot individual channels, reduce the file to mono, 22 | or plot all channels in vertically arrangement. 23 | .PP 24 | Colours (ARGB) and image\- or waveform geometry can be freely specified. 25 | .SH OPTIONS 26 | .TP 27 | \fB\-A\fR, \fB\-\-textcolour\fR 28 | specify text and border colour; default 0xffffffff 29 | all colours as hexadecimal AA RR GG BB values 30 | .TP 31 | \fB\-b\fR, \fB\-\-border\fR 32 | display a border with annotations 33 | .TP 34 | \fB\-B\fR, \fB\-\-background\fR 35 | specify background colour; default 0x8099999f 36 | .TP 37 | \fB\-c\fR, \fB\-\-channel\fR 38 | choose channel (s) to plot, 0: merge to mono; 39 | < 0: render all channels vertically separated; 40 | > 0: render only specified channel. (default: 0) 41 | .TP 42 | \fB\-C\fR, \fB\-\-centerline\fR 43 | set colour of zero/center line (default 0x4cffffff) 44 | .TP 45 | \fB\-F\fR, \fB\-\-foreground\fR 46 | specify foreground colour; default 0xff333333 47 | .TP 48 | \fB\-g\fR x, \fB\-\-geometry\fR x 49 | specify the size of the image to create 50 | default: 800x192 51 | .TP 52 | \fB\-G\fR, \fB\-\-borderbg\fR 53 | specify border/annotation background colour; 54 | default 0xb3ffffff 55 | .TP 56 | \fB\-h\fR, \fB\-\-help\fR 57 | display this help and exit 58 | .TP 59 | \fB\-l\fR, \fB\-\-logscale\fR 60 | use logarithmic scale 61 | .TP 62 | \fB\-\-no\-peak\fR 63 | only draw RMS signal using foreground colour 64 | .TP 65 | \fB\-\-no\-rms\fR 66 | only draw signal peaks (exclusive with \fB\-\-no\-peak\fR). 67 | .TP 68 | \fB\-r\fR, \fB\-\-rectified\fR 69 | rectify waveform 70 | .TP 71 | \fB\-R\fR, \fB\-\-rmscolour\fR 72 | specify RMS colour; default 0xffb3b3b3 73 | .TP 74 | \fB\-s\fR, \fB\-\-gainscale\fR 75 | zoom into y\-axis, map max signal to height. 76 | .TP 77 | \fB\-S\fR, \fB\-\-separator\fR 78 | vertically separate channels by N pixels 79 | (default: 12) \- only used with \fB\-c\fR \fB\-1\fR 80 | .TP 81 | \fB\-t\fR [/], \fB\-\-timecode\fR [/] 82 | use timecode instead of seconds for x\-axis; 83 | The numerator must be set, the denominator 84 | defaults to 1 if omitted. 85 | If the value is negative, audio\-frames are used. 86 | .TP 87 | \fB\-T\fR 88 | override the BWF time\-reference (if any); 89 | the offset is specified in audio\-frames 90 | and only used with timecode (\fB\-t\fR) annotation. 91 | .TP 92 | \fB\-O\fR, \fB\-\-border\-width\fR 93 | change outer border width 94 | default: 1.0 95 | .TP 96 | \fB\-V\fR, \fB\-\-version\fR 97 | output version information and exit 98 | .TP 99 | \fB\-W\fR, \fB\-\-wavesize\fR 100 | given geometry applies to the plain wave\-form. 101 | image height depends on number of channels. 102 | border\-sizes are added to width and height. 103 | .SH "REPORTING BUGS" 104 | Report bugs to . 105 | .br 106 | Website and manual: 107 | .br 108 | Example images: 109 | .SH COPYRIGHT 110 | Copyright \(co 2007\-2012 Erik de Castro Lopo 111 | Written 2011,2012 by Robin Gareus 112 | .PP 113 | .br 114 | This is free software; see the source for copying conditions. There is NO 115 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 116 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | sndfile-tools 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |


sndfile-tools

16 | 17 |

18 | Sndfile-tools is a small collection of programs that use libsndfile and other 19 | libraries to do useful things. 20 | The collection currently includes the following programs: 21 |

22 | 23 | 29 | 30 |

31 | The sndfile-tools package is released under the terms of the 32 | 33 | GNU General Public License 34 | (version 2 or version 3). 35 |

36 | 37 |

38 | The latest version is 1.5 and it can be downloaded here: 39 | 40 | sndfile-tools-1.5.tar.bz2 41 | ( 42 | GPG signature). 43 | 44 |

45 | 46 |

47 | It should be trivial to compile on Linux and relatively easy to compile on 48 | other Unices (including Mac OSX). 49 | Its probably possible to compile it on windows, but why would anyone bother? 50 |

51 | 52 | 53 | 54 |

55 | 56 |

sndfile-generate-chirp

57 | 58 |

59 | Create a sound file containing a swept sine wave (ie a chirp). 60 |

61 | 62 |
 63 |     sndfile-generate-chirp  [options] <sample rate> <length in seconds> <sound file>
 64 | 
 65 |     Options include:
 66 | 
 67 |         -from <start>    Sweep start frequency in Hz (default 200Hz).
 68 |         -to <end>        Sweep end frequency in Hz (default fs/2).
 69 |         -amp <value>     Amplitude of generated sine (default 1.0).
 70 |         <sweep type>     One of (default -log):
 71 |                              -log     logarithmic sweep
 72 |                              -quad    quadratic sweep
 73 |                              -linear  linear sweep
 74 | 
 75 |     The output file will contain floating point samples in the range [-1.0, 1.0].
 76 |     The output file type is determined by the file name extension which should be one
 77 |     of 'wav', 'aifc', 'aif', 'aiff', 'au', 'caf' and 'w64'.
 78 | 
79 | 80 | 81 |

82 | 83 |

sndfile-jackplay

84 | 85 |

86 | Play a sound file via the JACK Audio Connect Kit daemon. 87 |

88 | 89 |
 90 |     sndfile-jackplay <filename>
 91 | 
92 | 93 | 94 | 95 |

96 | 97 |

sndfile-spectrogram

98 | 99 |

100 | Generate a spectrogram as a PNG file from a given sound file. 101 |

102 | 103 | 104 |
105 |     sndfile-spectrogram <sound file> <img width> <img height> <png name>
106 | 
107 | 108 | 109 |

110 | This program (in conjunction with sndfile-generate-chirp) is particularly useful 111 | for evaluating the quality of sample rate converters. 112 | For instance, a chirp can be generated at 96kHz, passed through the converter 113 | and a spectrogram generated for the converter output file. For example: 114 |

115 | 116 |
117 | 118 |
119 | Example spectrogram 120 |
121 | 122 | 123 |

124 | 125 |

sndfile-mix-to-mono

126 | 127 | 128 |

129 | Convert a multi-channel input file to a mono output file, by mixing all input 130 | channels into one. 131 |

132 | 133 | 134 |
135 |     sndfile-mix-to-mono <input file> <output file>
136 | 
137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | project(sndfile-tools 4 | VERSION 1.5 5 | DESCRIPTION "Collection of programs for operating on sound files" 6 | HOMEPAGE_URL "http://libsndfile.github.io/libsamplerate/" 7 | LANGUAGES C 8 | ) 9 | 10 | include(CheckIncludeFile) 11 | include(CheckLibraryExists) 12 | include(CMakeDependentOption) 13 | include(CPack) 14 | include(GNUInstallDirs) 15 | include(FeatureSummary) 16 | include(CTest) 17 | 18 | find_library(HAVE_LIBM m) 19 | if(HAVE_LIBM) 20 | check_library_exists(m floor "" HAVE_FLOOR_IN_LIBM) 21 | if(HAVE_FLOOR_IN_LIBM) 22 | list(APPEND CMAKE_REQUIRED_LIBRARIES m) 23 | endif() 24 | endif() 25 | 26 | check_include_file(sys/wait.h HAVE_SYS_WAIT_H) 27 | 28 | find_package(PkgConfig) 29 | 30 | pkg_check_modules(SNDFILE REQUIRED IMPORTED_TARGET sndfile>=1.0.19) 31 | pkg_check_modules(SAMPLERATE REQUIRED IMPORTED_TARGET samplerate>=0.1.5) 32 | pkg_check_modules(FFTW3 REQUIRED IMPORTED_TARGET fftw3>=0.15.0) 33 | pkg_check_modules(CAIRO REQUIRED IMPORTED_TARGET cairo>=1.4.0) 34 | pkg_check_modules(JACK IMPORTED_TARGET jack>=0.100) 35 | if(JACK_FOUND) 36 | find_package(Threads) 37 | endif() 38 | 39 | configure_file(config.h.cmake config.h) 40 | add_compile_definitions(HAVE_CONFIG_H) 41 | include_directories(${PROJECT_BINARY_DIR}) 42 | 43 | cmake_dependent_option(ENABLE_JACK "Enable libjack" ON "ENABLE_JACK" OFF) 44 | 45 | add_executable(sndfile-generate-chirp 46 | src/generate-chirp.c 47 | src/common.c 48 | src/common.h 49 | ) 50 | target_link_libraries(sndfile-generate-chirp PRIVATE PkgConfig::SNDFILE) 51 | 52 | add_executable(sndfile-spectrogram 53 | src/spectrogram.c 54 | src/window.c 55 | src/common.c 56 | src/window.h 57 | src/common.h 58 | src/spectrum.c 59 | src/spectrum.h 60 | ) 61 | target_link_libraries(sndfile-spectrogram 62 | PRIVATE 63 | PkgConfig::SNDFILE 64 | PkgConfig::FFTW3 65 | PkgConfig::CAIRO 66 | ) 67 | 68 | add_executable(sndfile-mix-to-mono 69 | src/mix-to-mono.c 70 | src/common.h 71 | src/common.c 72 | ) 73 | target_link_libraries(sndfile-mix-to-mono PRIVATE PkgConfig::SNDFILE) 74 | 75 | add_executable(sndfile-waveform 76 | src/waveform.c 77 | src/common.c 78 | src/common.h 79 | ) 80 | target_link_libraries(sndfile-waveform 81 | PRIVATE 82 | PkgConfig::SNDFILE 83 | PkgConfig::CAIRO 84 | ) 85 | 86 | add_executable(sndfile-resample 87 | src/resample.c 88 | src/common.c 89 | src/common.h 90 | ) 91 | target_link_libraries(sndfile-resample 92 | PRIVATE 93 | PkgConfig::SNDFILE 94 | PkgConfig::SAMPLERATE 95 | ) 96 | 97 | if(ENABLE_JACK) 98 | add_executable(sndfile-jackplay src/jackplay.c) 99 | target_link_libraries(sndfile-jackplay 100 | PRIVATE 101 | PkgConfig::SNDFILE 102 | PkgConfig::JACK 103 | ) 104 | if(Threads_FOUND) 105 | target_link_libraries(sndfile-jackplay PRIVATE Threads::Threads) 106 | endif() 107 | endif() 108 | 109 | set(SNDFILE_TOOLS_TARGETS 110 | sndfile-generate-chirp 111 | sndfile-spectrogram 112 | sndfile-mix-to-mono 113 | sndfile-waveform 114 | sndfile-resample 115 | ) 116 | if(ENABLE_JACK) 117 | list(APPEND SNDFILE_TOOLS_TARGETS sndfile-jackplay) 118 | endif() 119 | 120 | install(TARGETS ${SNDFILE_TOOLS_TARGETS} 121 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 122 | ) 123 | 124 | set(SNDFILE_TOOLS_MANS 125 | man/sndfile-generate-chirp.1 126 | man/sndfile-mix-to-mono.1 127 | man/sndfile-resample.1 128 | man/sndfile-spectrogram.1 129 | man/sndfile-waveform.1 130 | ) 131 | if(ENABLE_JACK) 132 | list(APPEND SNDFILE_TOOLS_MANS man/sndfile-jackplay.1) 133 | endif() 134 | 135 | install(FILES ${SNDFILE_TOOLS_MANS} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) 136 | 137 | add_feature_info(ENABLE_JACK ENABLE_JACK "build sndfile-jackplay (requires libjack library).") 138 | 139 | feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES) 140 | 141 | if(BUILD_TESTING) 142 | add_executable(kaiser_window_test tests/kaiser_window_test.c src/window.h src/window.c) 143 | target_include_directories(kaiser_window_test PRIVATE ${PROJECT_SOURCE_DIR}) 144 | add_test(COMMAND kaiser_window_test NAME kaiser_window_test) 145 | 146 | if(HAVE_SYS_WAIT_H) 147 | add_executable(common_tests tests/common_tests.c src/common.c src/common.h) 148 | target_include_directories(common_tests PRIVATE ${PROJECT_SOURCE_DIR}) 149 | add_test(COMMAND common_tests NAME common_tests) 150 | endif() 151 | endif() 152 | -------------------------------------------------------------------------------- /src/window.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2015 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "window.h" 24 | 25 | #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof (x [0]))) 26 | 27 | 28 | static double besseli0 (double x) ; 29 | static double factorial (int k) ; 30 | 31 | void 32 | calc_kaiser_window (double * data, int datalen, double beta) 33 | { 34 | /* 35 | ** besseli0 (beta * sqrt (1- (2*x/N).^2)) 36 | ** w (x) = --------------------------------------, -N/2 <= x <= N/2 37 | ** besseli0 (beta) 38 | */ 39 | 40 | double two_n_on_N, denom ; 41 | int k ; 42 | 43 | denom = besseli0 (beta) ; 44 | 45 | if (! isfinite (denom)) 46 | { printf ("besseli0 (%f) : %f\nExiting\n", beta, denom) ; 47 | exit (1) ; 48 | } ; 49 | 50 | for (k = 0 ; k < datalen ; k++) 51 | { double n = k + 0.5 - 0.5 * datalen ; 52 | two_n_on_N = (2.0 * n) / datalen ; 53 | data [k] = besseli0 (beta * sqrt (1.0 - two_n_on_N * two_n_on_N)) / denom ; 54 | } ; 55 | 56 | return ; 57 | } /* calc_kaiser_window */ 58 | 59 | void 60 | calc_nuttall_window (double * data, int datalen) 61 | { 62 | const double a [4] = { 0.355768, 0.487396, 0.144232, 0.012604 } ; 63 | int k ; 64 | 65 | /* 66 | ** Nuttall window function from : 67 | ** 68 | ** http://en.wikipedia.org/wiki/Window_function 69 | */ 70 | 71 | for (k = 0 ; k < datalen ; k++) 72 | { double scale ; 73 | 74 | scale = M_PI * k / (datalen - 1) ; 75 | 76 | data [k] = a [0] - a [1] * cos (2.0 * scale) + a [2] * cos (4.0 * scale) - a [3] * cos (6.0 * scale) ; 77 | } ; 78 | 79 | return ; 80 | } /* calc_nuttall_window */ 81 | 82 | void 83 | calc_hann_window (double * data, int datalen) 84 | { 85 | int k ; 86 | 87 | /* 88 | ** Hann window function from : 89 | ** 90 | ** http://en.wikipedia.org/wiki/Window_function 91 | */ 92 | 93 | for (k = 0 ; k < datalen ; k++) 94 | data [k] = 0.5 * (1.0 - cos (2.0 * M_PI * k / (datalen - 1))) ; 95 | 96 | return ; 97 | } /* calc_hann_window */ 98 | 99 | /*============================================================================== 100 | */ 101 | 102 | static double 103 | besseli0 (double x) 104 | { int k ; 105 | double result = 0.0 ; 106 | 107 | for (k = 1 ; k < 25 ; k++) 108 | { double temp ; 109 | 110 | temp = pow (0.5 * x, k) / factorial (k) ; 111 | result += temp * temp ; 112 | } ; 113 | 114 | return 1.0 + result ; 115 | } /* besseli0 */ 116 | 117 | static double 118 | factorial (int val) 119 | { static double memory [64] = { 1.0 } ; 120 | static int have_entry = 0 ; 121 | 122 | int k ; 123 | 124 | if (val < 0) 125 | { printf ("Oops : val < 0.\n") ; 126 | exit (1) ; 127 | } ; 128 | 129 | if (val > ARRAY_LEN (memory)) 130 | { printf ("Oops : val > ARRAY_LEN (memory).\n") ; 131 | exit (1) ; 132 | } ; 133 | 134 | if (val < have_entry) 135 | return memory [val] ; 136 | 137 | for (k = have_entry + 1 ; k <= val ; k++) 138 | memory [k] = k * memory [k - 1] ; 139 | 140 | have_entry = val ; 141 | 142 | return memory [val] ; 143 | } /* factorial */ 144 | 145 | /*============================================================================== 146 | */ 147 | 148 | static void init_test (void) __attribute__ ((constructor)) ; 149 | 150 | static void 151 | init_test (void) 152 | { 153 | /* puts (__func__) ;*/ 154 | 155 | assert (factorial (0) == 1.0) ; 156 | assert (factorial (2) == 2.0) ; 157 | assert (factorial (0) == 1.0) ; 158 | assert (factorial (5) == 120.0) ; 159 | assert (factorial (8) == 40320.0) ; 160 | 161 | assert (fabs (besseli0 (0.0) - 1.0) < 1e-8) ; 162 | assert (fabs (besseli0 (0.5) - 1.06348337074132) < 1e-8) ; 163 | assert (fabs (besseli0 (1.0) - 1.26606587775201) < 1e-14) ; 164 | assert (fabs (besseli0 (2.0) - 2.27958530233607) < 1e-14) ; 165 | assert (fabs (besseli0 (3.5) - 7.37820343222548) < 1e-14) ; 166 | 167 | } /* init_test */ 168 | 169 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to set up the build system: configure, makefiles, etc. 3 | # (based on the version in enlightenment's cvs) 4 | 5 | package="sndfile-tools" 6 | 7 | olddir=`pwd` 8 | srcdir=`dirname $0` 9 | test -z "$srcdir" && srcdir=. 10 | 11 | cd "$srcdir" 12 | DIE=0 13 | 14 | echo -n "checking for autoconf... " 15 | result="yes" 16 | (autoconf --version) < /dev/null > /dev/null 2>&1 || { 17 | echo 18 | echo "You must have autoconf installed to compile $package." 19 | echo "Download the appropriate package for your distribution," 20 | echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" 21 | result="no" 22 | DIE=1 23 | } 24 | echo $result 25 | 26 | VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/" 27 | VERSIONMKMAJ="sed -e s/\([0-9][0-9]*\)[^0-9].*/\\1/" 28 | VERSIONMKMIN="sed -e s/.*[0-9][0-9]*\.//" 29 | 30 | # do we need automake? 31 | if test -r Makefile.am; then 32 | AM_OPTIONS=`fgrep AUTOMAKE_OPTIONS Makefile.am` 33 | AM_NEEDED=`echo $AM_OPTIONS | $VERSIONGREP` 34 | if test x"$AM_NEEDED" = "x$AM_OPTIONS"; then 35 | AM_NEEDED="" 36 | fi 37 | if test -z $AM_NEEDED; then 38 | echo -n "checking for automake... " 39 | AUTOMAKE=automake 40 | ACLOCAL=aclocal 41 | if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then 42 | echo "yes" 43 | else 44 | echo "no" 45 | AUTOMAKE= 46 | fi 47 | else 48 | echo -n "checking for automake $AM_NEEDED or later... " 49 | majneeded=`echo $AM_NEEDED | $VERSIONMKMAJ` 50 | minneeded=`echo $AM_NEEDED | $VERSIONMKMIN` 51 | for am in automake-$AM_NEEDED automake$AM_NEEDED \ 52 | automake automake-1.7 automake-1.8 automake-1.9 automake-1.10; do 53 | ($am --version < /dev/null > /dev/null 2>&1) || continue 54 | ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP` 55 | maj=`echo $ver | $VERSIONMKMAJ` 56 | min=`echo $ver | $VERSIONMKMIN` 57 | if test $maj -eq $majneeded -a $min -ge $minneeded; then 58 | AUTOMAKE=$am 59 | echo $AUTOMAKE 60 | break 61 | fi 62 | done 63 | test -z $AUTOMAKE && echo "no" 64 | echo -n "checking for aclocal $AM_NEEDED or later... " 65 | for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED \ 66 | aclocal aclocal-1.7 aclocal-1.8 aclocal-1.9 aclocal-1.10; do 67 | ($ac --version < /dev/null > /dev/null 2>&1) || continue 68 | ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP` 69 | maj=`echo $ver | $VERSIONMKMAJ` 70 | min=`echo $ver | $VERSIONMKMIN` 71 | if test $maj -eq $majneeded -a $min -ge $minneeded; then 72 | ACLOCAL=$ac 73 | echo $ACLOCAL 74 | break 75 | fi 76 | done 77 | test -z $ACLOCAL && echo "no" 78 | fi 79 | test -z $AUTOMAKE || test -z $ACLOCAL && { 80 | echo 81 | echo "You must have automake installed to compile $package." 82 | echo "Download the appropriate package for your distribution," 83 | echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" 84 | exit 1 85 | } 86 | fi 87 | 88 | echo -n "checking for libtool... " 89 | for LIBTOOLIZE in libtoolize glibtoolize nope; do 90 | ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break 91 | done 92 | if test x$LIBTOOLIZE = xnope; then 93 | echo "nope." 94 | LIBTOOLIZE=libtoolize 95 | else 96 | echo $LIBTOOLIZE 97 | fi 98 | ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || { 99 | echo 100 | echo "You must have libtool installed to compile $package." 101 | echo "Download the appropriate package for your system," 102 | echo "or get the source from one of the GNU ftp sites" 103 | echo "listed in http://www.gnu.org/order/ftp.html" 104 | DIE=1 105 | } 106 | 107 | echo -n "checking for pkg-config ... " 108 | result="yes" 109 | (pkg-config --version) < /dev/null > /dev/null 2>&1 || { 110 | echo 111 | echo "You must have pkg-config installed to compile $package." 112 | echo "Download the appropriate package for your distribution." 113 | result="no" 114 | DIE=1 115 | } 116 | echo $result 117 | 118 | if test "$DIE" -eq 1; then 119 | exit 1 120 | fi 121 | 122 | if test ! -d build-aux ; then 123 | echo "Creating 'build-aux' directory." 124 | mkdir build-aux 125 | fi 126 | 127 | echo "Generating configuration files for $package, please wait ... " 128 | 129 | echo " $ACLOCAL $ACLOCAL_FLAGS" 130 | $ACLOCAL $ACLOCAL_FLAGS || exit 1 131 | echo " $LIBTOOLIZE --automake --force" 132 | $LIBTOOLIZE --automake --force || exit 1 133 | 134 | echo " autoheader" 135 | autoheader || exit 1 136 | echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS" 137 | $AUTOMAKE --copy --add-missing $AUTOMAKE_FLAGS || exit 1 138 | echo " autoconf" 139 | autoconf || exit 1 140 | 141 | if test -d .git; then 142 | fprecommit=.git/hooks/pre-commit 143 | if test ! -f $fprecommit ; then 144 | echo "Installing git pre-commit hook for this project." 145 | cat > $fprecommit << 'foobar' 146 | #!/bin/sh 147 | exec Scripts/git-pre-commit-hook 148 | foobar 149 | chmod u+x $fprecommit 150 | echo 151 | fi 152 | fi 153 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2012-09-06 Erik de Castro Lopo 2 | 3 | * src/resample.c 4 | Fix valgrind warning. 5 | 6 | * Makefile.am tests/valgrind-test.sh 7 | Add a valgrind test for some of the executables. 8 | 9 | 2012-09-04 Erik de Castro Lopo 10 | 11 | * configure.ac 12 | Remove un-needed AC_LANG_SOURCE statement. Thanks to Robin Gareus. 13 | 14 | 2012-07-24 Erik de Castro Lopo 15 | 16 | * src/common.c 17 | Fix minor bug in sfx_mix_mono_read_double(). Patch from Martin Guy. Thanks. 18 | 19 | 2012-02-25 Erik de Castro Lopo 20 | 21 | * M4/extra_pkg.m4 22 | Update PKG_CHECK_MOD_VERSION macro to add an AC_TRY_LINK step. This fix 23 | allows the configure process to catch attempts to link incompatible 24 | libraries. For example, linking 32 bit version of eg libFLAC to a 64 bit 25 | version of sndfile-tools will now fail at the configure stage. 26 | 27 | 2011-01-14 Robin Gareus 28 | 29 | * src/waveform.c 30 | added sndfile-waveform, a waveform image generator 31 | 32 | 2011-01-13 Erik de Castro Lopo 33 | 34 | * src/jackplay.c 35 | Improve reporting of loop count. 36 | 37 | 2011-01-12 Erik de Castro Lopo 38 | 39 | * src/*.[ch] 40 | Update copyright years. 41 | 42 | * src/jackplay.c 43 | Add ability to play a file in a loop. 44 | 45 | * man/sndfile-jackplay.1 46 | Update with new options. 47 | 48 | 2011-01-11 Erik de Castro Lopo 49 | 50 | * configure.ac 51 | Add AM_SILENT_RULES and other tweaks. 52 | 53 | * src/common.c 54 | Fix bug in sfx_mix_mono_read_double() where a bunch of crap got appended to 55 | the end of the mixed down file. Thanks to Tom Szilagyi for the bug report. 56 | Remove cruft. 57 | 58 | 2010-04-07 Erik de Castro Lopo 59 | 60 | * src/jackplay.c 61 | Use jack_client_open() instead of deprecated jack_client_new(). 62 | 63 | * man/sndfile-spectrogram.1 64 | Fix two typos reported by Igor Murzov. 65 | 66 | 2010-02-22 Erik de Castro Lopo 67 | 68 | * configure.ac 69 | Detect presence of libsamplerate. 70 | 71 | * src/resample.c Makefile.am 72 | Add file originally from the libsamplerate source distribution and hook 73 | into build. 74 | 75 | 2009-12-21 Erik de Castro Lopo 76 | 77 | * src/*c 78 | Remove 'sndfile-' parts of file names. 79 | 80 | * src/jackplay.c 81 | Reorder JACK initialisation calls to remove click at start of playback. 82 | 83 | 2009-12-14 Erik de Castro Lopo 84 | 85 | * configure.ac 86 | Don't test for a fortran compiler. 87 | 88 | * man/sndfile-generate-chirp.1 man/sndfile-mix-to-mono.1 89 | man/sndfile-spectrogram.1 90 | New man pages. 91 | 92 | * Makefile.am 93 | Hook new man pages into build. 94 | 95 | * NEWS doc/index.html 96 | Update for 1.03 release. 97 | 98 | 2009-12-07 Erik de Castro Lopo 99 | 100 | * M4/*.m4 configure.ac 101 | Rename custom M4 macros to MN_*. 102 | 103 | * man/sndfile-jackplay.1 Makefile.am 104 | Add man page for sndfile-jackplay. 105 | 106 | * doc/index.html 107 | Add sndfile-jackplay. 108 | 109 | 2009-12-04 Erik de Castro Lopo 110 | 111 | * src/sndfile-merge.c 112 | Remove this (moved to libsndfile source distribution). 113 | 114 | * src/sndfile-jackplay.c 115 | Add file originally from the libsndfile source distribution. 116 | 117 | * M4/extra_pkg.m4 configure.ac 118 | Add M4 macro for using in configure.ac to find the JACK library. 119 | 120 | * Makefile.am 121 | Fix build after previous changes. 122 | 123 | 2009-11-28 Erik de Castro Lopo 124 | 125 | * src/sndfile-spectrogram.c 126 | Improve the way the spectrogram is interpolated. 127 | 128 | 2009-11-26 Erik de Castro Lopo 129 | 130 | * src/sndfile-spectrogram.c 131 | Initialize colour to black so it writes black instead of random values from 132 | the stack. 133 | Add a --dyn-range=XXX command line option to set spectrogram dynamic range. 134 | Add --no-border command line option to disable rendering of border, scales, 135 | heat map and title. 136 | 137 | * src/sndfile-merge.c 138 | New program contributed by Jonatan Liljedahl that takes two mono files and 139 | merges them into a stereo file. 140 | 141 | 2009-03-02 Erik de Castro Lopo 142 | 143 | * src/window.c 144 | Add bounds check before array access. 145 | 146 | 2007-10-21 Erik de Castro Lopo 147 | 148 | * src/sndfile-spectrogram.c 149 | Calculate longer FFTs and then interpolate to the image height. 150 | 151 | * src/kaiser_window_test.c 152 | Test a longer window length. 153 | 154 | * doc/* 155 | Add rudimentary documentation. 156 | 157 | * configure.ac src/common.c 158 | Detect presence of sf_get_info() and SFC_GET_CURRENT_SF_INFO. 159 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2002-2021 Erik de Castro Lopo 2 | 3 | dnl Require autoconf version >= 2.69) 4 | AC_PREREQ([2.69]) 5 | 6 | AC_INIT([sndfile-tools],[1.5],[sndfile@mega-nerd.com], 7 | [sndfile-tools],[https://github.com/libsndfile/sndfile-tools/]) 8 | 9 | dnl Check whether we want to set defaults for CFLAGS, CPPFLAGS and LDFLAGS 10 | AC_MSG_CHECKING([whether configure should try to set CFLAGS/CPPFLAGS/LDFLAGS]) 11 | AS_IF([test "x${CFLAGS+set}" = "xset" || test "x${CPPFLAGS+set}" = "xset" || test "x${LDFLAGS+set}" = "xset"], [ 12 | enable_flags_setting=no 13 | : ${CFLAGS=""} 14 | ], [ 15 | enable_flags_setting=yes 16 | dnl Set to empty flags so AC_PROG_CC does not add -g -O2 17 | CFLAGS="" 18 | ]) 19 | AC_MSG_RESULT([${enable_flags_setting}]) 20 | 21 | dnl Put config stuff in 'build-aux'. 22 | AC_CONFIG_AUX_DIR([build-aux]) 23 | 24 | AC_CONFIG_SRCDIR([src/spectrogram.c]) 25 | AC_CANONICAL_HOST 26 | 27 | AC_CONFIG_MACRO_DIR([m4]) 28 | AC_CONFIG_HEADERS([src/config.h]) 29 | 30 | AM_INIT_AUTOMAKE([1.14 foreign dist-bzip2 no-dist-gzip subdir-objects]) 31 | AM_SILENT_RULES([yes]) 32 | 33 | dnl ==================================================================================== 34 | 35 | AC_PROG_CC 36 | AC_PROG_CC_C99 37 | 38 | AS_IF([test "x$ac_cv_prog_cc_c99" = "xno"], [ 39 | AC_MSG_ERROR([sndfile-tools requires a C99 capable compiler!]) 40 | ]) 41 | 42 | AC_LANG([C]) 43 | AX_COMPILER_VENDOR 44 | AX_COMPILER_VERSION 45 | 46 | dnl ==================================================================================== 47 | dnl Finished checking, handle options. 48 | 49 | AC_ARG_ENABLE([werror], 50 | [AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])]) 51 | 52 | AC_ARG_ENABLE([jack], 53 | [AS_HELP_STRING([--disable-jack], [disable use of JACK (default=autodetect)])], [], [enable_jack=auto]) 54 | 55 | dnl ==================================================================================== 56 | dnl Check for functions. 57 | 58 | AC_SEARCH_LIBS([floor], [m], [], [ 59 | AC_MSG_ERROR([unable to find the floor() function!]) 60 | ]) 61 | AC_CHECK_FUNCS([floor ceil fmod lrint lrintf]) 62 | 63 | dnl ==================================================================================== 64 | dnl Check for libsndfile. 65 | 66 | PKG_CHECK_MODULES([SNDFILE], [sndfile >= 1.0.19], [ 67 | AC_DEFINE([HAVE_SNDFILE], [1], [Set to 1 if you have libsndfile]) 68 | ], [ 69 | AC_MSG_ERROR([libsndfile could not be found!]) 70 | ]) 71 | 72 | dnl ==================================================================================== 73 | dnl Check for libsamplerate. 74 | 75 | PKG_CHECK_MODULES([SAMPLERATE], [samplerate >= 0.1.5], [ 76 | AC_DEFINE([HAVE_SAMPLERATE], [1], [Set to 1 if you have libsamplerate]) 77 | ], [ 78 | AC_MSG_ERROR([libsamplerate could not be found!]) 79 | ]) 80 | 81 | dnl ==================================================================================== 82 | dnl Check for libfftw3 which is required for src/sndfile-spectrogram.c). 83 | 84 | PKG_CHECK_MODULES([FFTW3], [fftw3 >= 0.15.0], [ 85 | AC_DEFINE([HAVE_FFTW3], [1], [Set to 1 if you have FFTW]) 86 | ], [ 87 | AC_MSG_ERROR([FFTW could not be found!]) 88 | ]) 89 | 90 | dnl ==================================================================================== 91 | dnl Check for libcairo which is required for src/sndfile-spectrogram.c. 92 | 93 | PKG_CHECK_MODULES([CAIRO], [cairo >= 1.4.0], [ 94 | AC_DEFINE([HAVE_CAIRO], [1], [Set to 1 if you have Cairo]) 95 | ], [ 96 | AC_MSG_ERROR([Cairo could not be found!]) 97 | ]) 98 | 99 | dnl ==================================================================================== 100 | dnl Check for JACK which is required for src/sndfile-jackplay.c. 101 | 102 | AS_IF([test "x$enable_jack" != "xno"], [ 103 | PKG_CHECK_MODULES([JACK], [jack >= 0.100], [ 104 | AC_DEFINE([HAVE_JACK], [1], [Set to 1 if you have JACK]) 105 | enable_jack="yes" 106 | 107 | AX_PTHREAD 108 | JACK_CFLAGS="${JACK_CFLAGS} ${PTHREAD_CFLAGS}" 109 | JACK_LIBS="${JACK_LIBS} ${PTHREAD_LIBS}" 110 | ], [ 111 | AS_IF([test "x$enable_jack" = "xyes"], [ 112 | dnl explicitly passed --enable-jack, hence error out loud and clearly 113 | AC_MSG_ERROR([You explicitly requested JACK support, but JACK could not be found!]) 114 | ], [ 115 | dnl did not explicitly pass --enable-jack, relying on default automagic on 116 | enable_jack="no (auto)" 117 | ]) 118 | ]) 119 | ]) 120 | AM_CONDITIONAL([HAVE_JACK], [test "x$enable_jack" = "xyes"]) 121 | 122 | dnl ==================================================================================== 123 | dnl Compiler stuff. 124 | 125 | AS_IF([test "x$enable_flags_setting" = "xyes"], [ 126 | AX_APPEND_COMPILE_FLAGS([-O2 -pipe], [CFLAGS]) 127 | 128 | AS_CASE([${host_os}], 129 | [darwin*], [ 130 | ldflags_test="-Wl,-dead_strip_dylibs"], 131 | [linux*], [ 132 | ldflags_test="-Wl,-O1 -Wl,--as-needed -Wl,--no-undefined -Wl,--gc-sections"] 133 | ) 134 | AX_APPEND_LINK_FLAGS([${ldflags_test}], [LDFLAGS]) 135 | ]) 136 | 137 | AS_IF([test "x$enable_werror" = "xyes"], [ 138 | AX_APPEND_COMPILE_FLAGS([-Werror], [CFLAGS]) 139 | ]) 140 | 141 | AX_APPEND_COMPILE_FLAGS([-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wpointer-arith], [CFLAGS]) 142 | 143 | dnl ==================================================================================== 144 | dnl Now use the information from the checking stage. 145 | 146 | AC_CONFIG_FILES([Makefile]) 147 | AC_OUTPUT 148 | 149 | dnl ==================================================================================== 150 | 151 | AX_RECURSIVE_EVAL([$bindir], [full_absolute_bindir]) 152 | AC_MSG_RESULT([ 153 | -=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-=- 154 | 155 | Configuration summary : 156 | 157 | sndfile-tools version : ............... ${VERSION} 158 | 159 | Host CPU : ............................ ${host_cpu} 160 | Host Vendor : ......................... ${host_vendor} 161 | Host OS : ............................. ${host_os} 162 | 163 | CFLAGS : .............................. ${CFLAGS} 164 | CPPFLAGS : ............................ ${CPPFLAGS} 165 | LDFLAGS : ............................. ${LDFLAGS} 166 | 167 | Tools : 168 | 169 | C Compiler Vendor is : ................ ${ax_cv_c_compiler_vendor} (${ax_cv_c_compiler_version}) 170 | 171 | Extra tools required for testing and examples : 172 | 173 | Found libjack ......................... ${enable_jack} 174 | 175 | Installation directories : 176 | 177 | Program directory : ................... ${full_absolute_bindir} 178 | 179 | ]) 180 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Original author: 2 | 3 | The main author of libsndfile is Erik de Castro Lopo . 4 | 5 | Current maintainers: 6 | 7 | After the release of version 1.04, @erikd transferred the project to 8 | [the libsndfile team](https://github.com/libsndfile) consisting of: 9 | 10 | * Erik de Castro Lopo aka @erikd 11 | * David Seifert aka @SoapGentoo 12 | * Arthur Taylor aka @arthurt 13 | * @evpobr 14 | 15 | Current release manager is David Seifert: 16 | 17 | -----BEGIN PGP PUBLIC KEY BLOCK----- 18 | Version: GnuPG v2 19 | 20 | mQINBFppABgBEAC42ZiNvV7BTIgR6TQy0YnF54fx3mVRP1u8Mq00UZa7reAsNKh7 21 | 1H60j0W4s6+4pVVIKGfpVGxLwUdJe+KVCYw1Cd3YW6uMf5zZrC/ZWqnJiH/n6S6o 22 | 1l4INII2o6YbGBnzIWBPRo7PlOL+mvgKTLpBSJPnhD8XDGN5wRiV8rL2+6Dptg0F 23 | nJt7oxECGF3OD3gk6HMel0o82CVkIqMtNaX1L/bhcdF7K0Rp2MXPZMmpn1izW5sI 24 | asN1G9+w+Zwj7kMJzq1Aw3ac+rsX4SEYdvXjS2QhDHQUIr6LXri3D2WbcEqIZj2R 25 | JVoVwblsrG11dYXFDBbgrq4NhgTBsxHYDlkr/qF2W+kbPC/nhSqTVZeCYvTBZbOQ 26 | +RqyN/I0izukglnWmV1jGijFA8snyP8efx732hw/24zRYmtXOtnEITUpw8WOeZCq 27 | 6uiHaQ+eopnY2ojBg9BI7WZm0AFn58xxT9soMsyFOUFgXTqaWFZWlJ3fhZE8/0v8 28 | JEu/kPGE5aJReT3b34B+Bojkj74XR+h2u7iJJBHMTE8RwGoUOZHer/XsL9xlcdks 29 | I+7TCjiq++ShaSSt2XsJmw2BhREohrjW/2KkwmvT3b44RMpKPB4WTH+++aqJQNeM 30 | IqmswOMoZvzEZezInj7WVY/r0WEei1Y6wt1tBrJ/cFf1oQBM1UmphxcrfQARAQAB 31 | tB9EYXZpZCBTZWlmZXJ0IDxzb2FwQGdlbnRvby5vcmc+iQJUBBMBCgA+BQsJCAcD 32 | BRUKCQgLBRYCAwEAAh4BAheAAhsBFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/V 33 | CvoFCQkuceIACgkQpHYg6AHkfpXYxA//aiJW1NwunpmzEc62id8lRMnoLHWVjISZ 34 | b+xSlm+hk4LYq+ZbthJDzKcT86/3DJOSE1zQw9wLuCao9IW2UfFJQBtR+TAfbagG 35 | 0Yyk/kMcLoFJxnG1ywdJWypCAauuIhia52Z7PmmjsBbFwr6LygDwSQmZAyACMAs7 36 | TLQe+yERc2RNDsIEsquLSxxRF0Spk9gagWtKgrPc2XBjuNtQDwW7JgsOUoEeHyxC 37 | 29fRUjC3o/pG2I6iAZp17OROZI5yl4TSORrSBDGIi2sayxyxP0x+IPKtrCUcBGNx 38 | wGp+56bP/V0hA6sgCPh/iwvqLoeibso6l/Kd4ltVAEQnHTd6fr8g+wLEUXfbJVTR 39 | 7aeFUoaFmWjSPlQrNr6HlxSLV/kRx9kVJp1Pn16vkfVBF7fG7iDLiqphwEeQg5ND 40 | nmGeKAbRRNxFHyBHf0XRsaYiFZQckguO+71XSRtVx8/YP5nyNbtl9y1h/4JlT6Gy 41 | t7hb5twYFQyQrKss83E/Bo1sRdHpj0ibtqb4ZbYANbh482E6yFhAkuo8YjVTJipI 42 | 1Ve8EBKnX3R+pDt147uyysNvtPVXML+sWpGSMVSm4NA8uT3F5nqxVwj+SeXy3Wq/ 43 | CHQ2VBKGBC655G+wFD5C6O7cTx2MwH+2H8tzhWm+gFlI3MFKEXa/PC+YUC/diYcb 44 | BrApavriTRa5Ag0EWmkAZgEQAPXMD3mZI+ChvBysXZWksC88/uSEwFeb3XkcRm7v 45 | 04GN7hcz+bfrmnUTB3tuE/ZQgv+u7ZjetvH1aEKieznn/GjnWoOBoJusOYvfAQeF 46 | 0mQVi118QiOZRCnEZpkz+RY9TiXVgrZJg+AGqHZ3Ol4GkInEV2NWgH37Xal+HkFl 47 | rwI2U7mL0kZRG+LAVCQHKzqU0R0HE1XyJ4qf0awtG5Qi/TZvgXBdZPDXgr8i9Vlf 48 | UUu10c2XnXM0Av/YAlZmBFjVYrSOUCFenqSVqL+s9sTCVdWlJrGjrr3Ja4uT3kl2 49 | rLva0AR4oSQoxt8adKohmFz0vzOkQtCoRzhrCwoo3JvNjKdSNoOP1nSsxlO5ji8r 50 | ih5d+ajPgi580XyHLnrvG7vobR48qqscv1hizKuCgTacOTe6Db2Gqc8xF6v8HhJa 51 | KwWJtmFllIfN/tIvZ6BbbgHQn0IGf4CYnWf0SksPZqpBmTRpD2jfBxcj2UEg+AR3 52 | LARjuyUVpFJScyu6ExQG+6O+ByLL31iWP5MgUrza1rIpriPa3NT3rZ3DG2pvQrS3 53 | ySsrPzH7VRX8L1ThSMSzjwF96aMsd14s7XzR4EzNuWwZDukfs0yavZk6l4o1M0mb 54 | tbJi7hE4cz13KRHYvIkKMdZGYUnzRzZUDlsj2imakk3BR6GXnxZ1ST6062g+QxiL 55 | AJFLABEBAAGJBHIEGAEKACYCGwIWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9UL 56 | DQUJCS5xpwJAwXQgBBkBCgAdFiEEuNUxXaAAcsCoYIifzjbhFyAuOEIFAlppAGYA 57 | CgkQzjbhFyAuOELmrQ/9H9wrWsWa21STZdxUmyU2sh9VXAWEHl1Ey0fVTznDM0Fl 58 | zx5YSR/TmmnE36rpaz31Ttkx8SP914oV+mMgseecdya9Bf6uZL9Cv7V3KEsJBRL/ 59 | ncrOWQBHP/Xy1X+mLD6A19xq7H4RihSLj0LeK2YVjrJzJ7wMf4mKXuBayQeAHImU 60 | WRCRTbmK3umh2nB5V0iPd/XZEIiYtiTPe+7E/va6+0bBvOumF3a+Z0iui7eU4hFC 61 | 7Jk71D0dcg09SlIaNoMOrw7cMC3j2pMdKtsj8+0I6WBv14PhhqPAsnjdf7I/4NfK 62 | L7Jav8T/gDS01uA2Jxm72d+wr+eSjOBXa6x8CEbTqfkjAGxsWENThCp6zDkaXSDd 63 | JsV0va47vjzG8+wTDAvPy5IxIM/KZZdl4uWM+mF5K+q+eSTOHe7aLF2OdcussoBA 64 | A18zm994dAkG1COX/qpxanxx2bv/2IvCGPg+x6JtAN8ji2kncWu3dWGQdE5XbVjc 65 | fDwgsUPpp04G27Mr/x+HpEbgZ5SdA0dAqJktlNvCcHALhlblCWrsh/1QNjT/2iG8 66 | wsjcpEy/s4tWAuV4PTa4xvZ1JPS7Z7Eo5aBy9ZGOWG9SrHEiHnhkUsiswbHBOEjd 67 | pBSkmNElDcv9fRUahVCTPfvWBATFDrQyMjJBSm+cV8c/iFQM7isVSu8W7E0eetsJ 68 | EKR2IOgB5H6Vv9sP/1dxTvH0N0UoEoxIG/hnirEkbRpljdvqy4/uikYBKyQgSbo8 69 | VITTjea7gIhDztil9WZYt35jbOmoaGM2Z6TP2LEDOWgljYUNq9pl9Sc2GS8cNtEO 70 | WxExzGOc1Flo730dX3A85Ks3+0WPXZjLDcRRcPVkFd5WLQQDV1YVYopWkuQBC+Br 71 | 4q3uv+sk+bw6gDa9+zFBbDuegdsYuTXrFHoxHz2GRv9Yb7ULCMgpFeNKDgtQq91u 72 | RqewoTwQp9tlp91LH/hh7R0Q4DRgeFDkLnVRXwSKjVvCrT5cBgImGwtFTGS4egoy 73 | MDKd/KKjZllp1ahRCln1XfmFQyQVMVvuF/JTtt31n6KwXwK2yxIlXB01xvRH+Ees 74 | AWeRYWKWXydaAY/9Ve0/PLFlgsr/XUGvt0GoEKe7odD3nZgg6015+/8JTroKw19L 75 | NZkhdfFMl11Zi0j5k3UbyzjYVpFSd8K2o0VoOG1LFsPp8tlRxNoVzpId0CX1au/p 76 | y1H7Wy/39mzriRG3rw+mJAQbBjN09putCltXFXpOEWk08n/N3vufCVQUoSu/2Bqw 77 | 2HYj8VtToQp+O5dG3XxvDHINtInP1yr2Wcw2plna0KoXLwv/lZgDm3LN+eCWpG6d 78 | N/xk25DTSqTHArUQIEkhcHYK6GnyxUcvoKtG88hXtqEPYXiK08FZYAUPTnDYuQIN 79 | BFppAIkBEADDjvQZUs1NoqJpxkD2QDBudU1DBCaeI1D6CancMtb5FebPUxgFlDMd 80 | CBGOun48dY5i87gDhT/qS3gP/Mv9rjKJmcG9JHfhpXdW73owxrcsQ96nxxVJNEVl 81 | UHJw00z8C9eGWqr0SzSoE33K/PkzSkgtsaotF6+3uCerWulweulmGa5dpVfV0mbS 82 | aVw8VmrhZ5NmCeodyy/lR85rPik5pb32NT6v7xBkgkfS0VYtPB2E5gW1pXX/jEOi 83 | Mfq9idOEP9lxrNXV9j49Lr0JQCwAcrYbQ2+VPe6eacJEjzJ/6HiUqhPrYdnvydmb 84 | hU+xmv2NjGp2UnDZDEhzQfwm6fMx+8Nx2uPzCnXQGoyRBwiC/KcdW0F1ZPKdSXqH 85 | NKoOF62pLvIMSmfI3ZVOrTohArfr1kFEYVDv9Nl7oY+qg2rZEc2srOF74a9Z46bR 86 | TDPsEQzE2UMCvu3+rofhSD7aRotlKeDCvbe2s0yE4Man457Xc3LXh8Gva8CzCOLE 87 | 2eMhNTsHIZk68WgXp3/uvE4Xy42myrk1AV8XXDdlWgx0Kc/I6tE59O5NVPSfuGvH 88 | 1a15KKx0F6euEnYDKKpQ5PDR6dSn61po0tfbt96m044G/xQFjrfhHei4jji9Ogd9 89 | vlXVAi2vn3+NCSHFP5l3igLByBHy9iLIdmz7yQuus/1nwRmxOHOf2QARAQABiQI8 90 | BBgBCgAmAhsMFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/VCxkFCQkucZAACgkQ 91 | pHYg6AHkfpVPSRAAmheYkYJmtDbkzPBBnj5mbCIQN1/G5PI9eixc/TXWFOXtcjU1 92 | mJlJpSidHJyLRrx7r0c+N+s8vnY/JuUBsNoMJMER+Mv/CFW4iFi59V534SyAb2S0 93 | 7NINJnFNkXBY62CDz9KsMuv/MdSv2yLhPH2Tfrm/eDRQesj1PanE4U1cgjWyJRc/ 94 | IOlaRHvTasWDLgwbQi8ykt+4xUWzL/YKHzB+KyyzBK7vPBXqySX8ka4BOw7SDwG5 95 | lX2gtmhk4AGBwVChLXKflqVx1WXj4DPOt0kmOKVnKFyvUijK58M0A2FMgFMXDTIS 96 | DRtoZPdx/rkODXxgS+W+27NcYAnxJiM0cQqizEnQh7PQ1KzgdChPejYXMKe9lwdn 97 | ssMUxrBpbuAuagEf+pebNjD2eaNR4p8kfaDdGn53q55ysDvoyxKvnVQGSk1FAR9Q 98 | s4N5a4f02U7dzlyEhEfIcuUlRCfnlpn4n725YIhHheDig5zKWoEZCkNIfiRcGzDl 99 | 8Drj+tlZiUR+gDkIoWSBaCkKbIQlc8qCYy6Hm7oZBaol6xKlUnTMK2rjK8fR4i8r 100 | bVDWBAaWj3jcDHJ0Jg3fS/qBpeya/JXMp89TR8NK5Ys7PZpWbor+puXBYyXDAVx3 101 | rXQ7JBA5klHPxrgjso1S/LqwscKLENtrVjdjhryLBmPifrmofJRnrpiHIEa5Ag0E 102 | WmkAswEQAL0hKwsRybQzkNGpJP+ElLSwFHd7XQhr+qIwLllpumWtnIK/DHmv8SpW 103 | FqAYajmRTXipFcBHH25x2jIIliZidn0a9826l+sMzrFadMC6/W4pitP71TeqZzwn 104 | pAuHs14YL7Wiy0aJQnfbCpRzPq3kYyOXmhmY7lPWO0WdUpR6W8wUbleK5XOVDDRx 105 | aIC/M3hhDOxZOMzQ+pdn4BaOFQQ0ygsRkqOudbuc0R1giYRt1i6gMeT8gfzL9jlw 106 | HcJ+aVnxdUQQ4uC47oKo/+lg7qh7LsiW79pQC1Bcdm8lhRmqtxe6ub60ecjax3XU 107 | 1ILIEfIFCv6M7LRUAwz0bqk35spgkJqrGGKkdeWEKAFHg2QWR2F0zy+HdlPLfKxO 108 | uhaccpwc9EJtf744GS0SXa2AXr32j56n7CFcEjFcIQPBC6OJn6eA3hOVUYGZ7SrT 109 | 4fsmZiFAdGEkvLKFuNhju1Hj2EJQUY1pm4GSBco7BR8x+QqoYrt5clU3WxRMNfTR 110 | 0Rtuzsh4xskXNVMMgvKOahAtxENv2M2Cx6zJPVL5dmaysP7d6QRVeOQA5PwkcZ5Q 111 | qK6JtDZj2jpaKQH4Za715kiIcdqMDSkwxa6avc0kARHvfFcBR4hwDm1GAlaKG7eH 112 | 8TOGGQIk8x2F3s4l8mTJVLWTP/uJYnkYBdqANYo5t1NIQLvwLFV3ABEBAAGJAjwE 113 | GAEKACYCGyAWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9ULIwUJCS5xcAAKCRCk 114 | diDoAeR+leekD/sF7aHH0W35ckWrXZlfSp0qHPWrBUaLBI9OAUHenRhgs4SbK0D4 115 | wqEiu0C5iDQojpXAeALQ8g/1pUsZ1yuFqYbGYWrHkA0Pm+P3tAGB4LMZ41YfvROP 116 | uaiW/+IMJbWllgRtaDt8/NtCgs30WI9I+az5M29HcGfvEwEUykrBx3dE9T+1ui3O 117 | capdd+GMvdAAsX5PyVkjWgZ7GrZeH8mG7UysYfT4qthxEtQfZ/u8ceSduKA46ugh 118 | C2eafIDNvluqn7BU4oKxME61u6C8BN2yHLI6LV0Tr4z5H8joVbM4BSFMwLVGlsXf 119 | HhB8kLiErN6bXolxsjARlmYiD9S9H2AcYidr6RYXf2EVFSpBG59xn1WTDN+DsHQf 120 | 7btNPEPl/OPxa3OQjG+xn8USddiP0N0B4xsyzMNCCKDgvXXcIhX55KG9eh3Tc98S 121 | fEyhxu8ybZBIGmTJysPKxijfvSgQF+RPNTsz9lvXqkoK7RTgeYMschpjJEznCLbt 122 | M6eTDb5z0G5uLXh6+dYxtDOlPogI5OHd+G51LwCjvrQ+AtIUCgafuemwA9mpFT2b 123 | svb/qcxSVUb44bVaNHn1JHebX2YbokGtBOm1x2PI5fT8n6YIIYz3jKYOZAYdUT7x 124 | 6qURyNjOfG4aPJIATwuh4GSNuxUG40+yuT+XfQF24mu1esS1J3wzRloJ7w== 125 | =K3x+ 126 | -----END PGP PUBLIC KEY BLOCK----- 127 | 128 | Previous release manager: 129 | 130 | Versions before 1.5 - Erik de Castro Lopo. 131 | 132 | The public GPG key: 133 | 134 | -----BEGIN PGP SIGNATURE----- 135 | 136 | iQIzBAABCAAdFiEEapGlzyLCTJmjXgE/z9z5H7JCrO0FAljgv0wACgkQz9z5H7JC 137 | rO2RhxAAnIuHquhkhaY8CVsIOGImMxEF8RKDyFoioV9RnckNzBb592EYxU9hS0MM 138 | cT6xPZU0bJa8CvmCxEABMlkk60JP4VmmOtWxD8EEyktbHGyao80mDR82yVKYv78L 139 | zTRzz/JoTncgwWz/QataMbkAfy3KpxkwDW87az0kzkqGuSm3Jg3medt+t/iBe0Wm 140 | jcxIexxEZCmIhty6VyaVEkGWax0zdJHe7aD9FK2C/R3DU5Byp4e9pcp/a8v74G1n 141 | dgD4S3YlqvJGuU9S6QD4PzsoWD1X8f6pHzxpRP/OkqHAe11sSRo6sSYYCjsYi9Ca 142 | IJSlVC1nMx9OUxxAA8ZqtnztOo7GZcJ5NAL5X3GNV6YfQ7Bqxvtr6QG26F06MB6i 143 | p08UC7NC0bxFsD3f07wY22QnbnM052rniTn5sqQZv+GVls6t1b3u1iHzEjAjlgvi 144 | eOjVVt/A8iaOzMbKC/3+SZ9/GYqbSAQOCIoWAXmhV9IaMQyQeLCIC1YD5NMGBXal 145 | HPfSHV0hSUDbKjAYXFigJRzFU125bXTgg+v13Kd0KklIEjoaZYZLAYs0BupXdjBf 146 | jSPv8pwUaXJkv9/bGH0Ot1fvwDqPDOlGFINQbGAWdxwsdhiYBeXMFeFNTEfiqEMz 147 | BhhMxKa+Mfd9fkrX4NNigGW5QgRBS+FHNLf6ZfiXSnBGjjxMcbI= 148 | =UUA0 149 | -----END PGP SIGNATURE----- 150 | -------------------------------------------------------------------------------- /Scripts/cstyle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python -tt 2 | # 3 | # Copyright (C) 2005-2012 Erik de Castro Lopo 4 | # 5 | # Released under the 2 clause BSD license. 6 | 7 | """ 8 | This program checks C code for compliance to coding standards used in 9 | libsndfile and other projects I run. 10 | """ 11 | 12 | import re 13 | import sys 14 | 15 | 16 | class Preprocessor: 17 | """ 18 | Preprocess lines of C code to make it easier for the CStyleChecker class to 19 | test for correctness. Preprocessing works on a single line at a time but 20 | maintains state between consecutive lines so it can preprocessess multi-line 21 | comments. 22 | Preprocessing involves: 23 | - Strip C++ style comments from a line. 24 | - Strip C comments from a series of lines. When a C comment starts and 25 | ends on the same line it will be replaced with 'comment'. 26 | - Replace arbitrary C strings with the zero length string. 27 | - Replace '#define f(x)' with '#define f (c)' (The C #define requires that 28 | there be no space between defined macro name and the open paren of the 29 | argument list). 30 | Used by the CStyleChecker class. 31 | """ 32 | def __init__ (self): 33 | self.comment_nest = 0 34 | self.leading_space_re = re.compile ('^(\t+| )') 35 | self.trailing_space_re = re.compile ('(\t+| )$') 36 | self.define_hack_re = re.compile ("(#\s*define\s+[a-zA-Z0-9_]+)\(") 37 | 38 | def comment_nesting (self): 39 | """ 40 | Return the currect comment nesting. At the start and end of the file, 41 | this value should be zero. Inside C comments it should be 1 or 42 | (possibly) more. 43 | """ 44 | return self.comment_nest 45 | 46 | def __call__ (self, line): 47 | """ 48 | Strip the provided line of C and C++ comments. Stripping of multi-line 49 | C comments works as expected. 50 | """ 51 | 52 | line = self.define_hack_re.sub (r'\1 (', line) 53 | 54 | line = self.process_strings (line) 55 | 56 | # Strip C++ style comments. 57 | if self.comment_nest == 0: 58 | line = re.sub ("( |\t*)//.*", '', line) 59 | 60 | # Strip C style comments. 61 | open_comment = line.find ('/*') 62 | close_comment = line.find ('*/') 63 | 64 | if self.comment_nest > 0 and close_comment < 0: 65 | # Inside a comment block that does not close on this line. 66 | return "" 67 | 68 | if open_comment >= 0 and close_comment < 0: 69 | # A comment begins on this line but doesn't close on this line. 70 | self.comment_nest += 1 71 | return self.trailing_space_re.sub ('', line [:open_comment]) 72 | 73 | if open_comment < 0 and close_comment >= 0: 74 | # Currently open comment ends on this line. 75 | self.comment_nest -= 1 76 | return self.trailing_space_re.sub ('', line [close_comment + 2:]) 77 | 78 | if open_comment >= 0 and close_comment > 0 and self.comment_nest == 0: 79 | # Comment begins and ends on this line. Replace it with 'comment' 80 | # so we don't need to check whitespace before and after the comment 81 | # we're removing. 82 | newline = line [:open_comment] + "comment" + line [close_comment + 2:] 83 | return self.__call__ (newline) 84 | 85 | return line 86 | 87 | def process_strings (self, line): 88 | """ 89 | Given a line of C code, return a string where all literal C strings have 90 | been replaced with the empty string literal "". 91 | """ 92 | for k in range (0, len (line)): 93 | if line [k] == '"': 94 | start = k 95 | for k in range (start + 1, len (line)): 96 | if line [k] == '"' and line [k - 1] != '\\': 97 | return line [:start + 1] + '"' + self.process_strings (line [k + 1:]) 98 | return line 99 | 100 | 101 | class CStyleChecker: 102 | """ 103 | A class for checking the whitespace and layout of a C code. 104 | """ 105 | def __init__ (self, debug): 106 | self.debug = debug 107 | self.filename = None 108 | self.error_count = 0 109 | self.line_num = 1 110 | self.orig_line = '' 111 | self.trailing_newline_re = re.compile ('[\r\n]+$') 112 | self.indent_re = re.compile ("^\s*") 113 | self.last_line_indent = "" 114 | self.last_line_indent_curly = False 115 | self.re_checks = \ 116 | [ ( re.compile (" "), "multiple space instead of tab" ) 117 | , ( re.compile ("\t "), "space after tab" ) 118 | , ( re.compile ("[^ ];"), "missing space before semi-colon" ) 119 | , ( re.compile ("{[^\s]"), "missing space after open brace" ) 120 | , ( re.compile ("[^\s]}"), "missing space before close brace" ) 121 | , ( re.compile ("[ \t]+$"), "contains trailing whitespace" ) 122 | 123 | , ( re.compile (",[^\s\n]"), "missing space after comma" ) 124 | , ( re.compile (";[a-zA-Z0-9]"), "missing space after semi-colon" ) 125 | , ( re.compile ("=[^\s\"'=]"), "missing space after assignment" ) 126 | 127 | # Open and close parenthesis. 128 | , ( re.compile ("[^\s\(\[\*&']\("), "missing space before open parenthesis" ) 129 | , ( re.compile ("\)(-[^>]|[^,'\s\n\)\]-])"), "missing space after close parenthesis" ) 130 | , ( re.compile ("\s(do|for|if|when)\s.*{$"), "trailing open parenthesis at end of line" ) 131 | , ( re.compile ("\( [^;]"), "space after open parenthesis" ) 132 | , ( re.compile ("[^;] \)"), "space before close parenthesis" ) 133 | 134 | # Open and close square brace. 135 | , ( re.compile ("[^\s\(\]]\["), "missing space before open square brace" ) 136 | , ( re.compile ("\][^,\)\]\[\s\.-]"), "missing space after close square brace" ) 137 | , ( re.compile ("\[ "), "space after open square brace" ) 138 | , ( re.compile (" \]"), "space before close square brace" ) 139 | 140 | # Space around operators. 141 | , ( re.compile ("[^\s][\*/%+-][=][^\s]"), "missing space around opassign" ) 142 | , ( re.compile ("[^\s][<>!=^/][=]{1,2}[^\s]"), "missing space around comparison" ) 143 | 144 | # Parens around single argument to return. 145 | , ( re.compile ("\s+return\s+\([a-zA-Z0-9_]+\)\s+;"), "parens around return value" ) 146 | ] 147 | 148 | def get_error_count (self): 149 | """ 150 | Return the current error count for this CStyleChecker object. 151 | """ 152 | return self.error_count 153 | 154 | def check_files (self, files): 155 | """ 156 | Run the style checker on all the specified files. 157 | """ 158 | for filename in files: 159 | self.check_file (filename) 160 | 161 | def check_file (self, filename): 162 | """ 163 | Run the style checker on the specified file. 164 | """ 165 | self.filename = filename 166 | try: 167 | cfile = open (filename, "r") 168 | except IOError as e: 169 | return 170 | 171 | self.line_num = 1 172 | 173 | preprocess = Preprocessor () 174 | while 1: 175 | line = cfile.readline () 176 | if not line: 177 | break 178 | 179 | line = self.trailing_newline_re.sub ('', line) 180 | self.orig_line = line 181 | 182 | self.line_checks (preprocess (line)) 183 | 184 | self.line_num += 1 185 | 186 | cfile.close () 187 | self.filename = None 188 | 189 | # Check for errors finding comments. 190 | if preprocess.comment_nesting () != 0: 191 | print ("Weird, comments nested incorrectly.") 192 | sys.exit (1) 193 | 194 | return 195 | 196 | def line_checks (self, line): 197 | """ 198 | Run the style checker on provided line of text, but within the context 199 | of how the line fits within the file. 200 | """ 201 | 202 | indent = len (self.indent_re.search (line).group ()) 203 | if re.search ("^\s+}", line): 204 | if not self.last_line_indent_curly and indent != self.last_line_indent: 205 | None # self.error ("bad indent on close curly brace") 206 | self.last_line_indent_curly = True 207 | else: 208 | self.last_line_indent_curly = False 209 | 210 | # Now all the regex checks. 211 | for (check_re, msg) in self.re_checks: 212 | if check_re.search (line): 213 | self.error (msg) 214 | 215 | if re.search ("[a-zA-Z0-9][<>!=^/&\|]{1,2}[a-zA-Z0-9]", line): 216 | if not re.search (".*#include.*[a-zA-Z0-9]/[a-zA-Z]", line): 217 | self.error ("missing space around operator") 218 | 219 | self.last_line_indent = indent 220 | return 221 | 222 | def error (self, msg): 223 | """ 224 | Print an error message and increment the error count. 225 | """ 226 | print ("%s (%d) : %s" % (self.filename, self.line_num, msg)) 227 | if self.debug: 228 | print ("'" + self.orig_line + "'") 229 | self.error_count += 1 230 | 231 | #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 232 | 233 | if len (sys.argv) < 1: 234 | print ("Usage : yada yada") 235 | sys.exit (1) 236 | 237 | # Create a new CStyleChecker object 238 | if sys.argv [1] == '-d' or sys.argv [1] == '--debug': 239 | cstyle = CStyleChecker (True) 240 | cstyle.check_files (sys.argv [2:]) 241 | else: 242 | cstyle = CStyleChecker (False) 243 | cstyle.check_files (sys.argv [1:]) 244 | 245 | 246 | if cstyle.get_error_count (): 247 | sys.exit (1) 248 | 249 | sys.exit (0) 250 | -------------------------------------------------------------------------------- /src/generate-chirp.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2015 Erik de Castro Lopo 3 | ** 4 | ** This program is free software: you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation, either version 2 or version 3 of the 7 | ** License. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program. If not, see . 16 | */ 17 | 18 | /* Generate a sound file containing a chirp */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "common.h" 26 | 27 | #include 28 | 29 | typedef double (*freq_func_t) (double w0, double w1, double total_length) ; 30 | 31 | typedef struct 32 | { double amplitude ; 33 | int samplerate, format ; 34 | double start_freq, end_freq, seconds ; 35 | freq_func_t sweep_func ; 36 | } PARAMS ; 37 | 38 | static void usage_exit (const char * argv0) ; 39 | static void check_int_range (const char * name, int value, int lower, int upper) ; 40 | static void check_double_range (const char * name, double value, double lower, double upper) ; 41 | static freq_func_t parse_sweep_type (const char * name) ; 42 | static int guess_major_format (const char * filename) ; 43 | static void generate_file (const char * filename, const PARAMS * params) ; 44 | 45 | 46 | int 47 | main (int argc, char * argv []) 48 | { 49 | PARAMS params = { 1.0, -1, -1, 0, 0, 0, NULL } ; 50 | const char * filename ; 51 | int k ; 52 | 53 | if (argc < 4) 54 | usage_exit (argv [0]) ; 55 | 56 | for (k = 1 ; k < argc - 3 ; k++) 57 | { if (strcmp (argv [k], "-from") == 0) 58 | { k++ ; 59 | params.start_freq = parse_double_or_die (argv [k], "from frequency") ; 60 | continue ; 61 | } ; 62 | if (strcmp (argv [k], "-to") == 0) 63 | { k++ ; 64 | params.end_freq = parse_double_or_die (argv [k], "to frequency") ; 65 | continue ; 66 | } ; 67 | if (strcmp (argv [k], "-amp") == 0) 68 | { k++ ; 69 | params.amplitude = strtod (argv [k], NULL) ; 70 | continue ; 71 | } ; 72 | 73 | if (argv [k][0] == '-') 74 | { params.sweep_func = parse_sweep_type (argv [k]) ; 75 | continue ; 76 | } ; 77 | 78 | printf ("\nUnknown option '%s'.\n\n", argv [k]) ; 79 | exit (1) ; 80 | } ; 81 | 82 | params.samplerate = parse_int_or_die (argv [argc - 3], "sample rate") ; 83 | params.seconds = parse_double_or_die (argv [argc - 2], "seconds") ; 84 | filename = argv [argc - 1] ; 85 | 86 | check_int_range ("sample rate", params.samplerate, 1000, 200 * 1000) ; 87 | check_double_range ("seconds", params.seconds, 0.1, 100.0) ; 88 | 89 | if (params.sweep_func == NULL) 90 | params.sweep_func = parse_sweep_type ("-log") ; 91 | if (params.start_freq <= 0.0) 92 | params.start_freq = 100.0 ; 93 | if (params.end_freq <= 0.0) 94 | params.end_freq = params.samplerate / 2.0 - 100.0 ; 95 | 96 | if (params.end_freq <= params.start_freq) 97 | { printf ("\nError : end frequency %g < start frequency %g.\n\n", params.end_freq, params.start_freq) ; 98 | exit (1) ; 99 | } ; 100 | 101 | params.format = guess_major_format (filename) | SF_FORMAT_FLOAT ; 102 | 103 | generate_file (filename, ¶ms) ; 104 | 105 | return 0 ; 106 | } /* main */ 107 | 108 | /*============================================================================== 109 | */ 110 | 111 | static void 112 | usage_exit (const char * argv0) 113 | { 114 | const char * progname ; 115 | 116 | progname = strrchr (argv0, '/') ; 117 | progname = (progname == NULL) ? argv0 : progname + 1 ; 118 | 119 | puts ("\nCreate a sound file containing a swept sine wave (ie a chirp).") ; 120 | 121 | printf ("\nUsage :\n\n %s [options] \n\n", progname) ; 122 | 123 | puts ( 124 | " Options include:\n\n" 125 | " -from Sweep start frequency in Hz (default 200Hz).\n" 126 | " -to Sweep end frequency in Hz (default fs/2).\n" 127 | " -amp Amplitude of generated sine (default 1.0).\n" 128 | " One of (default -log):\n" 129 | " -log logarithmic sweep\n" 130 | " -quad quadratic sweep\n" 131 | " -linear linear sweep\n" 132 | "\n" 133 | " The parameter can be a decimal like 1.5.\n" 134 | ) ; 135 | 136 | puts ( 137 | " The output file will contain floating point samples in the range [-1.0, 1.0].\n" 138 | " The output file type is determined by the file name extension which should be one\n" 139 | " of 'wav', 'aifc', 'aif', 'aiff', 'au', 'caf' and 'w64'.\n" 140 | ) ; 141 | 142 | exit (0) ; 143 | } /* usage_exit */ 144 | 145 | static void 146 | check_int_range (const char * name, int value, int lower, int upper) 147 | { 148 | if (value < lower || value > upper) 149 | { printf ("Error : '%s' parameter must be in range [%d, %d]\n", name, lower, upper) ; 150 | exit (1) ; 151 | } ; 152 | } /* check_int_range */ 153 | 154 | static void 155 | check_double_range (const char * name, double value, double lower, double upper) 156 | { 157 | if (value < lower || value > upper) 158 | { printf ("Error : '%s' parameter must be in range [%.1f, %.1f]\n", name, lower, upper) ; 159 | exit (1) ; 160 | } ; 161 | } /* check_double_range */ 162 | 163 | static void 164 | write_chirp (SNDFILE * file, int samplerate, double seconds, double amp, double w0, double w1, freq_func_t sweep_func) 165 | { 166 | double instantaneous_w, current_phase ; 167 | float * data ; 168 | int total_samples, k ; 169 | 170 | total_samples = lrint (seconds * samplerate) ; 171 | 172 | data = malloc (total_samples * sizeof (data [0])) ; 173 | if (data == NULL) 174 | { printf ("\nError : malloc failed : %s\n", strerror (errno)) ; 175 | exit (1) ; 176 | } ; 177 | 178 | current_phase = 0.0 ; 179 | instantaneous_w = w0 ; 180 | 181 | printf ("Start frequency : %8.1f Hz (%f rad/sec)\n", instantaneous_w * samplerate / (2.0 * M_PI), instantaneous_w) ; 182 | 183 | for (k = 0 ; k < total_samples ; k++) 184 | { data [k] = amp * sin (current_phase) ; 185 | 186 | instantaneous_w = sweep_func (w0, w1, (1.0 * k) / total_samples) ; 187 | current_phase = fmod (current_phase + instantaneous_w, 2.0 * M_PI) ; 188 | 189 | } ; 190 | 191 | sf_write_float (file, data, total_samples) ; 192 | 193 | printf ("End frequency : %8.1f Hz (%f rad/sec)\n", instantaneous_w * samplerate / (2.0 * M_PI), instantaneous_w) ; 194 | 195 | free (data) ; 196 | } /* write_chirp */ 197 | 198 | static void 199 | generate_file (const char * filename, const PARAMS * params) 200 | { 201 | char buffer [1024] ; 202 | SNDFILE * file ; 203 | SF_INFO info = { } ; 204 | double w0, w1 ; 205 | 206 | info.format = params->format ; 207 | info.samplerate = params->samplerate ; 208 | info.channels = 1 ; 209 | 210 | file = sf_open (filename, SFM_WRITE, &info) ; 211 | if (file == NULL) 212 | { printf ("\nError : Not able to create file named '%s' : %s/\n", filename, sf_strerror (NULL)) ; 213 | exit (1) ; 214 | } ; 215 | 216 | sf_set_string (file, SF_STR_TITLE, "Logarithmic chirp signal") ; 217 | 218 | snprintf (buffer, sizeof (buffer), "start_freq : %g Hz end_freq : %g Hz amplitude : %g", params->start_freq, params->end_freq, params->amplitude) ; 219 | sf_set_string (file, SF_STR_COMMENT, buffer) ; 220 | 221 | sf_set_string (file, SF_STR_SOFTWARE, "sndfile-generate-chirp") ; 222 | sf_set_string (file, SF_STR_COPYRIGHT, "No copyright.") ; 223 | 224 | w0 = 2.0 * M_PI * params->start_freq / params->samplerate ; 225 | w1 = 2.0 * M_PI * params->end_freq / params->samplerate ; 226 | 227 | write_chirp (file, params->samplerate, params->seconds, params->amplitude, w0, w1, params->sweep_func) ; 228 | 229 | sf_close (file) ; 230 | } /* generate_file */ 231 | 232 | static double 233 | log_freq_func (double w0, double w1, double indx) 234 | { return pow (10.0, log10 (w0) + (log10 (w1) - log10 (w0)) * indx) ; 235 | } /* log_freq_func */ 236 | 237 | static double 238 | quad_freq_func (double w0, double w1, double indx) 239 | { return w0 + (w1 - w0) * indx * indx ; 240 | } /* log_freq_func */ 241 | 242 | static double 243 | linear_freq_func (double w0, double w1, double indx) 244 | { return w0 + (w1 - w0) * indx ; 245 | } /* linear_freq_func */ 246 | 247 | static freq_func_t 248 | parse_sweep_type (const char * name) 249 | { 250 | if (strcmp (name, "-log") == 0) 251 | return log_freq_func ; 252 | if (strcmp (name, "-quad") == 0) 253 | return quad_freq_func ; 254 | if (strcmp (name, "-linear") == 0) 255 | return linear_freq_func ; 256 | 257 | printf ("\nError : Bad sweep type. Should be one of '-log', '-quad' and '-linear'.\n\n") ; 258 | exit (1) ; 259 | return NULL ; 260 | } /* parse_sweep_type */ 261 | 262 | static int 263 | guess_major_format (const char * filename) 264 | { 265 | const char * ext ; 266 | 267 | ext = strrchr (filename, '.') ; 268 | if (ext == NULL) 269 | { printf ("\nError : cannot figure out file type from file name '%s'.\n\n", filename) ; 270 | exit (1) ; 271 | } ; 272 | 273 | if (strcasecmp (ext, ".wav") == 0) 274 | return SF_FORMAT_WAV ; 275 | if (strcasecmp (ext, ".aif") == 0 || strcasecmp (ext, ".aiff") == 0 || strcasecmp (ext, ".aifc") == 0) 276 | return SF_FORMAT_AIFF ; 277 | if (strcasecmp (ext, ".au") == 0) 278 | return SF_FORMAT_AU ; 279 | if (strcasecmp (ext, ".caf") == 0) 280 | return SF_FORMAT_CAF ; 281 | if (strcasecmp (ext, ".w64") == 0) 282 | return SF_FORMAT_W64 ; 283 | 284 | printf ("\nError : Can only generate files with extensions 'wav', 'aifc', 'aiff', 'aif', 'au', 'w64' and 'caf'.\n\n") ; 285 | exit (1) ; 286 | return 0 ; 287 | } /* guess_major_format */ 288 | 289 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free 5 | Software Foundation, Inc. 6 | 7 | This file is free documentation; the Free Software Foundation gives 8 | unlimited permission to copy, distribute and modify it. 9 | 10 | Basic Installation 11 | ================== 12 | 13 | These are generic installation instructions. 14 | 15 | The `configure' shell script attempts to guess correct values for 16 | various system-dependent variables used during compilation. It uses 17 | those values to create a `Makefile' in each directory of the package. 18 | It may also create one or more `.h' files containing system-dependent 19 | definitions. Finally, it creates a shell script `config.status' that 20 | you can run in the future to recreate the current configuration, and a 21 | file `config.log' containing compiler output (useful mainly for 22 | debugging `configure'). 23 | 24 | It can also use an optional file (typically called `config.cache' 25 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 26 | the results of its tests to speed up reconfiguring. (Caching is 27 | disabled by default to prevent problems with accidental use of stale 28 | cache files.) 29 | 30 | If you need to do unusual things to compile the package, please try 31 | to figure out how `configure' could check whether to do them, and mail 32 | diffs or instructions to the address given in the `README' so they can 33 | be considered for the next release. If you are using the cache, and at 34 | some point `config.cache' contains results you don't want to keep, you 35 | may remove or edit it. 36 | 37 | The file `configure.ac' (or `configure.in') is used to create 38 | `configure' by a program called `autoconf'. You only need 39 | `configure.ac' if you want to change it or regenerate `configure' using 40 | a newer version of `autoconf'. 41 | 42 | The simplest way to compile this package is: 43 | 44 | 1. `cd' to the directory containing the package's source code and type 45 | `./configure' to configure the package for your system. If you're 46 | using `csh' on an old version of System V, you might need to type 47 | `sh ./configure' instead to prevent `csh' from trying to execute 48 | `configure' itself. 49 | 50 | Running `configure' takes awhile. While running, it prints some 51 | messages telling which features it is checking for. 52 | 53 | 2. Type `make' to compile the package. 54 | 55 | 3. Optionally, type `make check' to run any self-tests that come with 56 | the package. 57 | 58 | 4. Type `make install' to install the programs and any data files and 59 | documentation. 60 | 61 | 5. You can remove the program binaries and object files from the 62 | source code directory by typing `make clean'. To also remove the 63 | files that `configure' created (so you can compile the package for 64 | a different kind of computer), type `make distclean'. There is 65 | also a `make maintainer-clean' target, but that is intended mainly 66 | for the package's developers. If you use it, you may have to get 67 | all sorts of other programs in order to regenerate files that came 68 | with the distribution. 69 | 70 | Compilers and Options 71 | ===================== 72 | 73 | Some systems require unusual options for compilation or linking that the 74 | `configure' script does not know about. Run `./configure --help' for 75 | details on some of the pertinent environment variables. 76 | 77 | You can give `configure' initial values for configuration parameters 78 | by setting variables in the command line or in the environment. Here 79 | is an example: 80 | 81 | ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix 82 | 83 | *Note Defining Variables::, for more details. 84 | 85 | Compiling For Multiple Architectures 86 | ==================================== 87 | 88 | You can compile the package for more than one kind of computer at the 89 | same time, by placing the object files for each architecture in their 90 | own directory. To do this, you must use a version of `make' that 91 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 92 | directory where you want the object files and executables to go and run 93 | the `configure' script. `configure' automatically checks for the 94 | source code in the directory that `configure' is in and in `..'. 95 | 96 | If you have to use a `make' that does not support the `VPATH' 97 | variable, you have to compile the package for one architecture at a 98 | time in the source code directory. After you have installed the 99 | package for one architecture, use `make distclean' before reconfiguring 100 | for another architecture. 101 | 102 | Installation Names 103 | ================== 104 | 105 | By default, `make install' installs the package's commands under 106 | `/usr/local/bin', include files under `/usr/local/include', etc. You 107 | can specify an installation prefix other than `/usr/local' by giving 108 | `configure' the option `--prefix=PREFIX'. 109 | 110 | You can specify separate installation prefixes for 111 | architecture-specific files and architecture-independent files. If you 112 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 113 | PREFIX as the prefix for installing programs and libraries. 114 | Documentation and other data files still use the regular prefix. 115 | 116 | In addition, if you use an unusual directory layout you can give 117 | options like `--bindir=DIR' to specify different values for particular 118 | kinds of files. Run `configure --help' for a list of the directories 119 | you can set and what kinds of files go in them. 120 | 121 | If the package supports it, you can cause programs to be installed 122 | with an extra prefix or suffix on their names by giving `configure' the 123 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 124 | 125 | Optional Features 126 | ================= 127 | 128 | Some packages pay attention to `--enable-FEATURE' options to 129 | `configure', where FEATURE indicates an optional part of the package. 130 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 131 | is something like `gnu-as' or `x' (for the X Window System). The 132 | `README' should mention any `--enable-' and `--with-' options that the 133 | package recognizes. 134 | 135 | For packages that use the X Window System, `configure' can usually 136 | find the X include and library files automatically, but if it doesn't, 137 | you can use the `configure' options `--x-includes=DIR' and 138 | `--x-libraries=DIR' to specify their locations. 139 | 140 | Specifying the System Type 141 | ========================== 142 | 143 | There may be some features `configure' cannot figure out automatically, 144 | but needs to determine by the type of machine the package will run on. 145 | Usually, assuming the package is built to be run on the _same_ 146 | architectures, `configure' can figure that out, but if it prints a 147 | message saying it cannot guess the machine type, give it the 148 | `--build=TYPE' option. TYPE can either be a short name for the system 149 | type, such as `sun4', or a canonical name which has the form: 150 | 151 | CPU-COMPANY-SYSTEM 152 | 153 | where SYSTEM can have one of these forms: 154 | 155 | OS KERNEL-OS 156 | 157 | See the file `config.sub' for the possible values of each field. If 158 | `config.sub' isn't included in this package, then this package doesn't 159 | need to know the machine type. 160 | 161 | If you are _building_ compiler tools for cross-compiling, you should 162 | use the option `--target=TYPE' to select the type of system they will 163 | produce code for. 164 | 165 | If you want to _use_ a cross compiler, that generates code for a 166 | platform different from the build platform, you should specify the 167 | "host" platform (i.e., that on which the generated programs will 168 | eventually be run) with `--host=TYPE'. 169 | 170 | Sharing Defaults 171 | ================ 172 | 173 | If you want to set default values for `configure' scripts to share, you 174 | can create a site shell script called `config.site' that gives default 175 | values for variables like `CC', `cache_file', and `prefix'. 176 | `configure' looks for `PREFIX/share/config.site' if it exists, then 177 | `PREFIX/etc/config.site' if it exists. Or, you can set the 178 | `CONFIG_SITE' environment variable to the location of the site script. 179 | A warning: not all `configure' scripts look for a site script. 180 | 181 | Defining Variables 182 | ================== 183 | 184 | Variables not defined in a site shell script can be set in the 185 | environment passed to `configure'. However, some packages may run 186 | configure again during the build, and the customized values of these 187 | variables may be lost. In order to avoid this problem, you should set 188 | them in the `configure' command line, using `VAR=value'. For example: 189 | 190 | ./configure CC=/usr/local2/bin/gcc 191 | 192 | causes the specified `gcc' to be used as the C compiler (unless it is 193 | overridden in the site shell script). Here is a another example: 194 | 195 | /bin/bash ./configure CONFIG_SHELL=/bin/bash 196 | 197 | Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent 198 | configuration-related scripts to be executed by `/bin/bash'. 199 | 200 | `configure' Invocation 201 | ====================== 202 | 203 | `configure' recognizes the following options to control how it operates. 204 | 205 | `--help' 206 | `-h' 207 | Print a summary of the options to `configure', and exit. 208 | 209 | `--version' 210 | `-V' 211 | Print the version of Autoconf used to generate the `configure' 212 | script, and exit. 213 | 214 | `--cache-file=FILE' 215 | Enable the cache: use and save the results of the tests in FILE, 216 | traditionally `config.cache'. FILE defaults to `/dev/null' to 217 | disable caching. 218 | 219 | `--config-cache' 220 | `-C' 221 | Alias for `--cache-file=config.cache'. 222 | 223 | `--quiet' 224 | `--silent' 225 | `-q' 226 | Do not print messages saying which checks are being made. To 227 | suppress all normal output, redirect it to `/dev/null' (any error 228 | messages will still be shown). 229 | 230 | `--srcdir=DIR' 231 | Look for the package's source code in directory DIR. Usually 232 | `configure' can determine that directory automatically. 233 | 234 | `configure' also accepts some other, not widely useful, options. Run 235 | `configure --help' for more details. 236 | 237 | -------------------------------------------------------------------------------- /src/resample.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2020, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "common.h" 18 | 19 | #include 20 | #include 21 | 22 | #define DEFAULT_CONVERTER SRC_SINC_MEDIUM_QUALITY 23 | 24 | #define BUFFER_LEN 4096 /*-(1<<16)-*/ 25 | 26 | static void usage_exit (const char *progname) ; 27 | static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain, int normalize, sf_count_t nframes) ; 28 | static double apply_gain (float * data, long frames, int channels, double max, double gain) ; 29 | 30 | int 31 | main (int argc, char *argv []) 32 | { SNDFILE *infile, *outfile = NULL ; 33 | SF_INFO sfinfo = { } ; 34 | sf_count_t nframes ; 35 | 36 | int normalize = 1 ; 37 | sf_count_t count ; 38 | double src_ratio = -1.0, gain = 1.0 ; 39 | int new_sample_rate = -1, k, converter, max_speed = SF_FALSE, raw_bits ; 40 | char raw_type ; 41 | 42 | if (argc == 2 && strcmp (argv [1], "--version") == 0) 43 | { char buffer [64], *cptr ; 44 | 45 | if ((cptr = strrchr (argv [0], '/')) != NULL) 46 | argv [0] = cptr + 1 ; 47 | if ((cptr = strrchr (argv [0], '\\')) != NULL) 48 | argv [0] = cptr + 1 ; 49 | 50 | sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ; 51 | 52 | printf ("%s (%s,%s)\n", argv [0], src_get_version (), buffer) ; 53 | exit (0) ; 54 | } ; 55 | 56 | if (argc < 5 || argc > 10) 57 | usage_exit (argv [0]) ; 58 | 59 | /* Set default converter. */ 60 | converter = DEFAULT_CONVERTER ; 61 | 62 | for (k = 1 ; k < argc - 2 ; k++) 63 | { if (strcmp (argv [k], "--max-speed") == 0) 64 | max_speed = SF_TRUE ; 65 | else if (strcmp (argv [k], "--no-normalize") == 0) 66 | normalize = 0 ; 67 | else if (strcmp (argv [k], "-to") == 0) 68 | { k ++ ; 69 | new_sample_rate = parse_int_or_die (argv [k], "sample rate") ; 70 | } 71 | else if (strcmp (argv [k], "-by") == 0) 72 | { k ++ ; 73 | src_ratio = atof (argv [k]) ; 74 | } 75 | else if (strcmp (argv [k], "-c") == 0) 76 | { k ++ ; 77 | converter = parse_int_or_die (argv [k], "converter") ; 78 | } 79 | else if (strcmp (argv [k], "-r") == 0) 80 | { k ++ ; 81 | if (sscanf (argv [k], "%d,%d,%c,%d", &sfinfo.samplerate, &sfinfo.channels, &raw_type, &raw_bits) != 4) 82 | { printf ("Error : unable to decode raw audio parameters.\n") ; 83 | usage_exit (argv [0]) ; 84 | } 85 | sfinfo.format = SF_FORMAT_RAW ; 86 | if (raw_type == 'i' && (raw_bits == 8 || raw_bits == 16 || raw_bits == 24 || raw_bits == 32)) 87 | { switch (raw_bits) 88 | { case 8: 89 | sfinfo.format |= SF_FORMAT_PCM_S8 ; 90 | break ; 91 | 92 | case 16: 93 | sfinfo.format |= SF_FORMAT_PCM_16 ; 94 | break ; 95 | 96 | case 24: 97 | sfinfo.format |= SF_FORMAT_PCM_24 ; 98 | break ; 99 | 100 | case 32: 101 | sfinfo.format |= SF_FORMAT_PCM_32 ; 102 | break ; 103 | 104 | default: 105 | printf ("Error : PCM bits per sample should be 8, 16, 24 or 32.\n") ; 106 | usage_exit (argv [0]) ; 107 | } 108 | } 109 | else if (raw_type == 'f' && (raw_bits == 32 || raw_bits == 64)) 110 | { switch (raw_bits) 111 | { case 32: 112 | sfinfo.format |= SF_FORMAT_FLOAT ; 113 | break ; 114 | 115 | case 64: 116 | sfinfo.format |= SF_FORMAT_DOUBLE ; 117 | break ; 118 | 119 | default: 120 | printf ("Error : Floating point bits per sample should be 32 or 64.\n") ; 121 | usage_exit (argv [0]) ; 122 | } 123 | } 124 | else 125 | { printf ("Error : invalid raw audio parameters.\n") ; 126 | usage_exit (argv [0]) ; 127 | } 128 | } 129 | else 130 | usage_exit (argv [0]) ; 131 | } ; 132 | 133 | if (new_sample_rate <= 0 && src_ratio <= 0.0) 134 | usage_exit (argv [0]) ; 135 | 136 | if (src_get_name (converter) == NULL) 137 | { printf ("Error : bad converter number.\n") ; 138 | usage_exit (argv [0]) ; 139 | } ; 140 | 141 | if (strcmp (argv [argc - 2], argv [argc - 1]) == 0) 142 | { printf ("Error : input and output file names are the same.\n") ; 143 | exit (1) ; 144 | } ; 145 | 146 | if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL) 147 | { printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ; 148 | exit (1) ; 149 | } ; 150 | 151 | printf ("Input File : %s\n", argv [argc - 2]) ; 152 | printf ("Sample Rate : %d\n", sfinfo.samplerate) ; 153 | printf ("Input Frames : %ld\n\n", (long) sfinfo.frames) ; 154 | 155 | nframes = sfinfo.frames ; 156 | 157 | if (new_sample_rate > 0) 158 | { src_ratio = (1.0 * new_sample_rate) / sfinfo.samplerate ; 159 | sfinfo.samplerate = new_sample_rate ; 160 | } 161 | else if (src_is_valid_ratio (src_ratio)) 162 | sfinfo.samplerate = (int) floor (sfinfo.samplerate * src_ratio) ; 163 | else 164 | { printf ("Not able to determine new sample rate. Exiting.\n") ; 165 | sf_close (infile) ; 166 | exit (1) ; 167 | } ; 168 | 169 | if (fabs (src_ratio - 1.0) < 1e-20) 170 | { printf ("Target samplerate and input samplerate are the same. Exiting.\n") ; 171 | sf_close (infile) ; 172 | exit (0) ; 173 | } ; 174 | 175 | printf ("SRC Ratio : %f\n", src_ratio) ; 176 | printf ("Converter : %s\n\n", src_get_name (converter)) ; 177 | 178 | if (src_is_valid_ratio (src_ratio) == 0) 179 | { printf ("Error : Sample rate change out of valid range.\n") ; 180 | sf_close (infile) ; 181 | exit (1) ; 182 | } ; 183 | 184 | /* Delete the output file length to zero if already exists. */ 185 | remove (argv [argc - 1]) ; 186 | 187 | printf ("Output File : %s\n", argv [argc - 1]) ; 188 | printf ("Sample Rate : %d\n", sfinfo.samplerate) ; 189 | 190 | do 191 | { sf_close (outfile) ; 192 | 193 | if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) 194 | { printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ; 195 | sf_close (infile) ; 196 | exit (1) ; 197 | } ; 198 | 199 | if (max_speed) 200 | { /* This is mainly for the comparison program tests/src-evaluate.c */ 201 | sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; 202 | } 203 | else 204 | { /* Update the file header after every write. */ 205 | sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ; 206 | } ; 207 | 208 | sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ; 209 | 210 | count = sample_rate_convert (infile, outfile, converter, src_ratio, sfinfo.channels, &gain, normalize, nframes) ; 211 | } 212 | while (count < 0) ; 213 | 214 | printf ("Output Frames : %ld\n\n", (long) count) ; 215 | 216 | sf_close (infile) ; 217 | sf_close (outfile) ; 218 | 219 | return 0 ; 220 | } /* main */ 221 | 222 | /*============================================================================== 223 | */ 224 | 225 | static sf_count_t 226 | sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain, int normalize, sf_count_t nframes) 227 | { static float input [BUFFER_LEN] ; 228 | static float output [BUFFER_LEN] ; 229 | 230 | SRC_STATE *src_state ; 231 | SRC_DATA src_data ; 232 | int error ; 233 | double max = 0.0 ; 234 | sf_count_t output_count = 0 ; 235 | 236 | char anim [4] = "-\\|/" ; 237 | short p_anim = 0 ; 238 | 239 | sf_seek (infile, 0, SEEK_SET) ; 240 | sf_seek (outfile, 0, SEEK_SET) ; 241 | 242 | /* Initialize the sample rate converter. */ 243 | if ((src_state = src_new (converter, channels, &error)) == NULL) 244 | { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ; 245 | exit (1) ; 246 | } ; 247 | 248 | src_data.end_of_input = 0 ; /* Set this later. */ 249 | 250 | /* Start with zero to force load in while loop. */ 251 | src_data.input_frames = 0 ; 252 | src_data.data_in = input ; 253 | 254 | src_data.src_ratio = src_ratio ; 255 | 256 | src_data.data_out = output ; 257 | src_data.output_frames = BUFFER_LEN /channels ; 258 | 259 | while (1) 260 | { 261 | /* If the input buffer is empty, refill it. */ 262 | if (src_data.input_frames == 0) 263 | { src_data.input_frames = sf_readf_float (infile, input, BUFFER_LEN / channels) ; 264 | src_data.data_in = input ; 265 | 266 | /* The last read will not be a full buffer, so snd_of_input. */ 267 | if (src_data.input_frames < BUFFER_LEN / channels) 268 | src_data.end_of_input = SF_TRUE ; 269 | } ; 270 | 271 | if ((error = src_process (src_state, &src_data))) 272 | { printf ("\nError : %s\n", src_strerror (error)) ; 273 | exit (1) ; 274 | } ; 275 | 276 | /* Terminate if done. */ 277 | if (src_data.end_of_input && src_data.output_frames_gen == 0) 278 | break ; 279 | 280 | max = apply_gain (src_data.data_out, src_data.output_frames_gen, channels, max, *gain) ; 281 | 282 | /* Write output. */ 283 | sf_writef_float (outfile, output, src_data.output_frames_gen) ; 284 | output_count += src_data.output_frames_gen ; 285 | 286 | src_data.data_in += src_data.input_frames_used * channels ; 287 | src_data.input_frames -= src_data.input_frames_used ; 288 | nframes -= src_data.input_frames_used ; 289 | printf (" %c remaining : %19lld\r", anim [p_anim], (long long int) nframes) ; 290 | p_anim = (p_anim + 1) % 4 ; 291 | } ; 292 | printf ("\n") ; 293 | 294 | src_delete (src_state) ; 295 | 296 | if (normalize && max > 1.0) 297 | { *gain = 1.0 / max ; 298 | printf ("\nOutput has clipped. Restarting conversion to prevent clipping.\n\n") ; 299 | return -1 ; 300 | } ; 301 | 302 | return output_count ; 303 | } /* sample_rate_convert */ 304 | 305 | static double 306 | apply_gain (float * data, long frames, int channels, double max, double gain) 307 | { 308 | long k ; 309 | 310 | for (k = 0 ; k < frames * channels ; k++) 311 | { data [k] *= gain ; 312 | 313 | if (fabs (data [k]) > max) 314 | max = fabs (data [k]) ; 315 | } ; 316 | 317 | return max ; 318 | } /* apply_gain */ 319 | 320 | static void 321 | usage_exit (const char *progname) 322 | { char lsf_ver [128] ; 323 | const char *cptr ; 324 | int k ; 325 | 326 | if ((cptr = strrchr (progname, '/')) != NULL) 327 | progname = cptr + 1 ; 328 | 329 | if ((cptr = strrchr (progname, '\\')) != NULL) 330 | progname = cptr + 1 ; 331 | 332 | 333 | sf_command (NULL, SFC_GET_LIB_VERSION, lsf_ver, sizeof (lsf_ver)) ; 334 | 335 | printf ("\n" 336 | " A Sample Rate Converter using libsndfile for file I/O and Secret \n" 337 | " Rabbit Code (aka libsamplerate) for performing the conversion.\n" 338 | " It works on any file format supported by libsndfile with any \n" 339 | " number of channels (limited only by host memory).\n" 340 | "\n" 341 | " %s\n" 342 | " %s\n" 343 | "\n" 344 | " Usage : \n" 345 | " %s -to [-c ] \n" 346 | " %s -by [-c ] \n" 347 | "\n", src_get_version (), lsf_ver, progname, progname) ; 348 | 349 | puts ( 350 | " The optional -c argument allows the converter type to be chosen from\n" 351 | " the following list :" 352 | "\n" 353 | ) ; 354 | 355 | for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++) 356 | printf (" %d : %s%s\n", k, cptr, k == DEFAULT_CONVERTER ? " (default)" : "") ; 357 | 358 | puts ("\n" 359 | " The --no-normalize option disables clipping check and normalization.") ; 360 | 361 | puts ("\n" 362 | " Sound parameters for raw input may be specified using option -r RRRR,C,s,BB\n" 363 | " where RRRR is the sample rate, C is the channels number, s is 'i' (as integer)\n" 364 | " or 'f' (as float) and BB the bits per sample (8, 16, ...)\n" 365 | " Note: when raw audio input is used, then a raw output audio file will be\n" 366 | " created as well.") ; 367 | 368 | puts ("") ; 369 | 370 | exit (1) ; 371 | } /* usage_exit */ 372 | -------------------------------------------------------------------------------- /src/jackplay.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2007-2016 Erik de Castro Lopo 3 | ** Copyright (C) 2014 Alexander Regueiro 4 | ** Copyright (C) 2013 elboulangero 5 | ** Copyright (C) 2007 Jonatan Liljedahl 6 | ** 7 | ** This program is free software ; you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation ; either version 2 of the License, or 10 | ** (at your option) any later version. 11 | ** 12 | ** This program is distributed in the hope that it will be useful, 13 | ** but WITHOUT ANY WARRANTY ; without even the implied warranty of 14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ** GNU General Public License for more details. 16 | ** 17 | ** You should have received a copy of the GNU General Public License 18 | ** along with this program ; if not, write to the Free Software 19 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | */ 21 | 22 | #include "src/config.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | 42 | #include 43 | 44 | #define RB_SIZE (1 << 16) 45 | #define SAMPLE_SIZE (sizeof (jack_default_audio_sample_t)) 46 | 47 | #define NOT(x) (! (x)) 48 | 49 | typedef struct 50 | { jack_client_t *client ; 51 | jack_ringbuffer_t *ringbuf ; 52 | jack_nframes_t pos ; 53 | jack_default_audio_sample_t ** outs ; 54 | jack_port_t ** output_port ; 55 | 56 | SNDFILE *sndfile ; 57 | 58 | unsigned int channels ; 59 | unsigned int samplerate ; 60 | 61 | volatile int can_process ; 62 | volatile int read_done ; 63 | 64 | volatile unsigned int loop_count ; 65 | volatile unsigned int current_loop ; 66 | } thread_info_t ; 67 | 68 | static pthread_mutex_t disk_thread_lock = PTHREAD_MUTEX_INITIALIZER ; 69 | static pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER ; 70 | static volatile int play_done = 0 ; 71 | 72 | static void 73 | close_signal_handler (int sig) 74 | { (void) sig ; 75 | play_done = 1 ; 76 | } 77 | 78 | static int 79 | process_callback (jack_nframes_t nframes, void * arg) 80 | { 81 | thread_info_t *info = (thread_info_t *) arg ; 82 | jack_default_audio_sample_t buf [info->channels] ; 83 | unsigned i, n ; 84 | 85 | for (n = 0 ; n < info->channels ; n++) 86 | info->outs [n] = jack_port_get_buffer (info->output_port [n], nframes) ; 87 | 88 | if (play_done || NOT (info->can_process)) 89 | { /* output silence */ 90 | for (n = 0 ; n < info->channels ; n++) 91 | memset (info->outs [n], 0, sizeof (float) * nframes) ; 92 | return 0 ; 93 | } ; 94 | 95 | for (i = 0 ; i < nframes ; i++) 96 | { size_t read_count ; 97 | 98 | /* Read one frame of audio. */ 99 | read_count = jack_ringbuffer_read (info->ringbuf, (void *) buf, SAMPLE_SIZE * info->channels) ; 100 | if (read_count == 0 && info->read_done) 101 | { /* File is done, so stop the main loop. */ 102 | play_done = 1 ; 103 | /* Silence the rest of the audio buffer. */ 104 | for (n = 0 ; n < info->channels ; n++) 105 | info->outs [n][i] = 0.0f ; 106 | return 0 ; 107 | } ; 108 | 109 | /* Update play-position counter. */ 110 | info->pos += read_count / (SAMPLE_SIZE * info->channels) ; 111 | 112 | /* Output each channel of the frame. */ 113 | for (n = 0 ; n < info->channels ; n++) 114 | info->outs [n][i] = buf [n] ; 115 | } ; 116 | 117 | /* Wake up the disk thread to read more data. */ 118 | if (pthread_mutex_trylock (&disk_thread_lock) == 0) 119 | { pthread_cond_signal (&data_ready) ; 120 | pthread_mutex_unlock (&disk_thread_lock) ; 121 | } ; 122 | 123 | return 0 ; 124 | } /* process_callback */ 125 | 126 | 127 | /* 128 | ** This seemingly needless memcpy-ing is needed because the `buf` field of 129 | ** `jack_ringbuffer_data_t` is a `char*` and may not have the correct alignment 130 | ** for the `float` data read from the file. 131 | */ 132 | static sf_count_t 133 | fill_jack_buffer (thread_info_t *info, jack_ringbuffer_data_t * vec) 134 | { sf_count_t frame_count = vec->len / sizeof (float) / info->channels ; 135 | sf_count_t buffer_frames ; 136 | static float buf [1 << 16] ; 137 | 138 | buffer_frames = ARRAY_LEN (buf) / info->channels ; 139 | frame_count = frame_count < buffer_frames ? frame_count : buffer_frames ; 140 | 141 | frame_count = sf_readf_float (info->sndfile, buf, frame_count) ; 142 | memcpy (vec->buf, buf, frame_count * info->channels * sizeof (buf [0])) ; 143 | 144 | return frame_count ; 145 | } /* fill_jack_buffer */ 146 | 147 | static void * 148 | disk_thread (void *arg) 149 | { thread_info_t *info = (thread_info_t *) arg ; 150 | sf_count_t read_frames ; 151 | jack_ringbuffer_data_t vec [2] ; 152 | size_t bytes_per_frame = SAMPLE_SIZE * info->channels ; 153 | 154 | pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ; 155 | pthread_mutex_lock (&disk_thread_lock) ; 156 | 157 | while (NOT (play_done)) 158 | { /* `vec` is *always* a two element array. See: 159 | ** http://jackaudio.org/files/docs/html/ringbuffer_8h.html 160 | */ 161 | jack_ringbuffer_get_write_vector (info->ringbuf, vec) ; 162 | 163 | read_frames = 0 ; 164 | 165 | if (vec [0].len) 166 | { /* Fill the first part of the ringbuffer. */ 167 | read_frames = fill_jack_buffer (info, vec) ; 168 | 169 | if (vec [1].len) 170 | { /* Fill the second part of the ringbuffer? */ 171 | read_frames += fill_jack_buffer (info, vec + 1) ; 172 | } ; 173 | } ; 174 | 175 | if (read_frames == 0) 176 | { info->current_loop ++ ; 177 | 178 | if (info->loop_count >= 1 && info->current_loop >= info->loop_count) 179 | break ; /* end of file? */ 180 | 181 | sf_seek (info->sndfile, 0, SEEK_SET) ; 182 | continue ; 183 | } 184 | 185 | jack_ringbuffer_write_advance (info->ringbuf, read_frames * bytes_per_frame) ; 186 | 187 | /* Tell process_callback that we've filled the ringbuffer. */ 188 | info->can_process = 1 ; 189 | 190 | /* Wait for the process_callback thread to wake us up. */ 191 | pthread_cond_wait (&data_ready, &disk_thread_lock) ; 192 | } ; 193 | 194 | /* Tell that we're done reading the file. */ 195 | info->read_done = 1 ; 196 | pthread_mutex_unlock (&disk_thread_lock) ; 197 | 198 | return NULL ; 199 | } /* disk_thread */ 200 | 201 | static void 202 | jack_shutdown (void *arg) 203 | { (void) arg ; 204 | exit (1) ; 205 | } /* jack_shutdown */ 206 | 207 | static inline void 208 | print_time (jack_nframes_t pos, int jack_sr) 209 | { float sec = pos / (1.0 * jack_sr) ; 210 | int min = sec / 60.0 ; 211 | fprintf (stderr, "%02d:%05.2f", min, fmod (sec, 60.0)) ; 212 | } /* print_time */ 213 | 214 | static inline void 215 | print_status (const thread_info_t * info) 216 | { 217 | if (info->loop_count == 0) 218 | fprintf (stderr, "\r-> %6d ", info->current_loop) ; 219 | else if (info->loop_count > 1) 220 | fprintf (stderr, "\r-> %6d/%d ", info->current_loop, info->loop_count) ; 221 | else 222 | fprintf (stderr, "\r-> ") ; 223 | 224 | print_time (info->pos, info->samplerate) ; 225 | fflush (stdout) ; 226 | } /* print_status */ 227 | 228 | static void 229 | usage_exit (char * argv0, int status) 230 | { 231 | printf ("\n" 232 | "Usage : %s [options] \n" 233 | "\n" 234 | " Where [options] is one of:\n" 235 | "\n" 236 | " -w --wait[=] : Wait for input before starting playback; optionally auto-connect to using Jack.\n" 237 | " -a --autoconnect= : Auto-connect to using Jack.\n" 238 | " -l --loop= : Loop the file times (0 for infinite).\n" 239 | " -h --help : Show this help message.\n" 240 | "\n" 241 | "Using %s.\n" 242 | "\n", 243 | basename (argv0), sf_version_string ()) ; 244 | exit (status) ; 245 | } /* usage_exit */ 246 | 247 | static struct option const long_options [] = 248 | { 249 | { "wait", optional_argument, NULL, 'w' } , 250 | { "autoconnect", required_argument, NULL, 'a' } , 251 | { "loop", required_argument, NULL, 'l' } , 252 | { "help", no_argument, NULL, 'h' } , 253 | { NULL, 0, NULL, 0 } 254 | } ; 255 | 256 | int 257 | main (int argc, char * argv []) 258 | { pthread_t thread_id ; 259 | SNDFILE *sndfile ; 260 | SF_INFO sfinfo = { } ; 261 | const char * filename ; 262 | jack_client_t *client ; 263 | jack_status_t status = 0 ; 264 | char * auto_connect_str = "system:playback_%d" ; 265 | bool wait_before_play = false ; 266 | int i, jack_sr, loop_count = 1 ; 267 | int c ; 268 | 269 | /* Parse options */ 270 | while ((c = getopt_long (argc, argv, 271 | "w::" /* --wait */ 272 | "a::" /* --autoconnect */ 273 | "l:" /* --loop */ 274 | "h", /* --help */ 275 | long_options, NULL)) != EOF) 276 | { if (optarg != NULL && optarg [0] == '=') 277 | { optarg++ ; 278 | } 279 | switch (c) 280 | { case 'w' : 281 | wait_before_play = true ; 282 | auto_connect_str = optarg ; 283 | break ; 284 | case 'a' : 285 | auto_connect_str = optarg ; 286 | break ; 287 | case 'l' : 288 | loop_count = strtol (optarg, NULL, 10) ; 289 | break ; 290 | case 'h' : 291 | usage_exit (argv [0], EXIT_SUCCESS) ; 292 | break ; 293 | default : 294 | usage_exit (argv [0], EXIT_FAILURE) ; 295 | } ; 296 | } 297 | 298 | if (argc - optind != 1) 299 | usage_exit (argv [0], EXIT_FAILURE) ; 300 | 301 | filename = argv [optind] ; 302 | 303 | /* Create jack client */ 304 | if ((client = jack_client_open ("jackplay", JackNullOption | JackNoStartServer, &status)) == 0) 305 | { if (status & JackServerFailed) 306 | fprintf (stderr, "Unable to connect to JACK server\n") ; 307 | else 308 | fprintf (stderr, "jack_client_open () failed, status = 0x%2.0x\n", status) ; 309 | 310 | exit (1) ; 311 | } ; 312 | 313 | if (status & JackServerStarted) 314 | fprintf (stderr, "JACK server started\n") ; 315 | 316 | if (status & JackNameNotUnique) 317 | { const char * client_name = jack_get_client_name (client) ; 318 | fprintf (stderr, "Unique name `%s' assigned\n", client_name) ; 319 | } ; 320 | 321 | /* Open the soundfile. */ 322 | sndfile = sf_open (filename, SFM_READ, &sfinfo) ; 323 | if (sndfile == NULL) 324 | { fprintf (stderr, "Could not open soundfile '%s'\n", filename) ; 325 | return 1 ; 326 | } ; 327 | 328 | fprintf (stderr, "Channels : %d\nSample rate : %d Hz\nDuration : ", sfinfo.channels, sfinfo.samplerate) ; 329 | print_time (loop_count * sfinfo.frames, sfinfo.samplerate) ; 330 | fprintf (stderr, "\n") ; 331 | 332 | if (loop_count < 1) 333 | fprintf (stderr, "Loop count : infinite\n") ; 334 | else if (loop_count > 1) 335 | fprintf (stderr, "Loop count : %d\n", loop_count) ; 336 | 337 | jack_sr = jack_get_sample_rate (client) ; 338 | 339 | if (sfinfo.samplerate != jack_sr) 340 | fprintf (stderr, "Warning: samplerate of soundfile (%d Hz) does not match jack server (%d Hz).\n", sfinfo.samplerate, jack_sr) ; 341 | 342 | struct sigaction sig = { 343 | .sa_handler = close_signal_handler , 344 | .sa_flags = SA_RESTART } ; 345 | 346 | sigemptyset (&sig.sa_mask) ; 347 | sigaction (SIGINT, &sig, NULL) ; 348 | sigaction (SIGTERM, &sig, NULL) ; 349 | 350 | thread_info_t info = { 351 | .sndfile = sndfile , 352 | .channels = sfinfo.channels , 353 | .samplerate = jack_sr , 354 | .client = client , 355 | .loop_count = loop_count , 356 | /* Allocate output ports. */ 357 | .output_port = calloc (sfinfo.channels, sizeof (jack_port_t *)) , 358 | .outs = calloc (sfinfo.channels, sizeof (jack_default_audio_sample_t *)) } ; 359 | 360 | for (i = 0 ; i < sfinfo.channels ; i++) 361 | { char name [16] ; 362 | 363 | snprintf (name, sizeof (name), "out_%d", i + 1) ; 364 | info.output_port [i] = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0) ; 365 | } ; 366 | 367 | /* Allocate and clear ringbuffer. */ 368 | info.ringbuf = jack_ringbuffer_create (sizeof (jack_default_audio_sample_t) * RB_SIZE) ; 369 | memset (info.ringbuf->buf, 0, info.ringbuf->size) ; 370 | 371 | /* Set up callbacks. */ 372 | jack_set_process_callback (client, process_callback, &info) ; 373 | jack_on_shutdown (client, jack_shutdown, 0) ; 374 | 375 | /* Activate client. */ 376 | if (jack_activate (client)) 377 | { fprintf (stderr, "Cannot activate client.\n") ; 378 | return 1 ; 379 | } ; 380 | 381 | if (auto_connect_str != NULL) 382 | { /* Auto-connect all channels. */ 383 | for (i = 0 ; i < sfinfo.channels ; i++) 384 | { char name [64] ; 385 | 386 | snprintf (name, sizeof (name), auto_connect_str, i + 1) ; 387 | 388 | if (jack_connect (client, jack_port_name (info.output_port [i]), name)) 389 | fprintf (stderr, "Cannot connect output port %d (%s).\n", i, name) ; 390 | } ; 391 | } 392 | 393 | if (wait_before_play) 394 | { /* Wait for key press before playing. */ 395 | printf ("Press key to start playing...") ; 396 | getchar () ; 397 | } 398 | 399 | /* Start the disk thread. */ 400 | pthread_create (&thread_id, NULL, disk_thread, &info) ; 401 | 402 | /* Sit in a loop, displaying the current play position. */ 403 | while (NOT (play_done)) 404 | { print_status (&info) ; 405 | usleep (10000) ; 406 | } ; 407 | 408 | jack_deactivate (client) ; 409 | 410 | pthread_cond_signal (&data_ready) ; 411 | pthread_join (thread_id, NULL) ; 412 | 413 | print_status (&info) ; 414 | 415 | /* Clean up. */ 416 | for (i = 0 ; i < sfinfo.channels ; i++) 417 | jack_port_unregister (client, info.output_port [i]) ; 418 | 419 | jack_ringbuffer_free (info.ringbuf) ; 420 | jack_client_close (client) ; 421 | 422 | free (info.output_port) ; 423 | free (info.outs) ; 424 | 425 | sf_close (sndfile) ; 426 | 427 | puts ("") ; 428 | 429 | return 0 ; 430 | } /* main */ 431 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /m4/ax_pthread.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_pthread.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro figures out how to build C programs using POSIX threads. It 12 | # sets the PTHREAD_LIBS output variable to the threads library and linker 13 | # flags, and the PTHREAD_CFLAGS output variable to any special C compiler 14 | # flags that are needed. (The user can also force certain compiler 15 | # flags/libs to be tested by setting these environment variables.) 16 | # 17 | # Also sets PTHREAD_CC to any special C compiler that is needed for 18 | # multi-threaded programs (defaults to the value of CC otherwise). (This 19 | # is necessary on AIX to use the special cc_r compiler alias.) 20 | # 21 | # NOTE: You are assumed to not only compile your program with these flags, 22 | # but also to link with them as well. For example, you might link with 23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS 24 | # 25 | # If you are only building threaded programs, you may wish to use these 26 | # variables in your default LIBS, CFLAGS, and CC: 27 | # 28 | # LIBS="$PTHREAD_LIBS $LIBS" 29 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 30 | # CC="$PTHREAD_CC" 31 | # 32 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant 33 | # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to 34 | # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). 35 | # 36 | # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the 37 | # PTHREAD_PRIO_INHERIT symbol is defined when compiling with 38 | # PTHREAD_CFLAGS. 39 | # 40 | # ACTION-IF-FOUND is a list of shell commands to run if a threads library 41 | # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it 42 | # is not found. If ACTION-IF-FOUND is not specified, the default action 43 | # will define HAVE_PTHREAD. 44 | # 45 | # Please let the authors know if this macro fails on any platform, or if 46 | # you have any other suggestions or comments. This macro was based on work 47 | # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help 48 | # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by 49 | # Alejandro Forero Cuervo to the autoconf macro repository. We are also 50 | # grateful for the helpful feedback of numerous users. 51 | # 52 | # Updated for Autoconf 2.68 by Daniel Richard G. 53 | # 54 | # LICENSE 55 | # 56 | # Copyright (c) 2008 Steven G. Johnson 57 | # Copyright (c) 2011 Daniel Richard G. 58 | # 59 | # This program is free software: you can redistribute it and/or modify it 60 | # under the terms of the GNU General Public License as published by the 61 | # Free Software Foundation, either version 3 of the License, or (at your 62 | # option) any later version. 63 | # 64 | # This program is distributed in the hope that it will be useful, but 65 | # WITHOUT ANY WARRANTY; without even the implied warranty of 66 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 67 | # Public License for more details. 68 | # 69 | # You should have received a copy of the GNU General Public License along 70 | # with this program. If not, see . 71 | # 72 | # As a special exception, the respective Autoconf Macro's copyright owner 73 | # gives unlimited permission to copy, distribute and modify the configure 74 | # scripts that are the output of Autoconf when processing the Macro. You 75 | # need not follow the terms of the GNU General Public License when using 76 | # or distributing such scripts, even though portions of the text of the 77 | # Macro appear in them. The GNU General Public License (GPL) does govern 78 | # all other use of the material that constitutes the Autoconf Macro. 79 | # 80 | # This special exception to the GPL applies to versions of the Autoconf 81 | # Macro released by the Autoconf Archive. When you make and distribute a 82 | # modified version of the Autoconf Macro, you may extend this special 83 | # exception to the GPL to apply to your modified version as well. 84 | 85 | #serial 24 86 | 87 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) 88 | AC_DEFUN([AX_PTHREAD], [ 89 | AC_REQUIRE([AC_CANONICAL_HOST]) 90 | AC_REQUIRE([AC_PROG_CC]) 91 | AC_REQUIRE([AC_PROG_SED]) 92 | AC_LANG_PUSH([C]) 93 | ax_pthread_ok=no 94 | 95 | # We used to check for pthread.h first, but this fails if pthread.h 96 | # requires special compiler flags (e.g. on Tru64 or Sequent). 97 | # It gets checked for in the link test anyway. 98 | 99 | # First of all, check if the user has set any of the PTHREAD_LIBS, 100 | # etcetera environment variables, and if threads linking works using 101 | # them: 102 | if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then 103 | ax_pthread_save_CC="$CC" 104 | ax_pthread_save_CFLAGS="$CFLAGS" 105 | ax_pthread_save_LIBS="$LIBS" 106 | AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) 107 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 108 | LIBS="$PTHREAD_LIBS $LIBS" 109 | AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) 110 | AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) 111 | AC_MSG_RESULT([$ax_pthread_ok]) 112 | if test "x$ax_pthread_ok" = "xno"; then 113 | PTHREAD_LIBS="" 114 | PTHREAD_CFLAGS="" 115 | fi 116 | CC="$ax_pthread_save_CC" 117 | CFLAGS="$ax_pthread_save_CFLAGS" 118 | LIBS="$ax_pthread_save_LIBS" 119 | fi 120 | 121 | # We must check for the threads library under a number of different 122 | # names; the ordering is very important because some systems 123 | # (e.g. DEC) have both -lpthread and -lpthreads, where one of the 124 | # libraries is broken (non-POSIX). 125 | 126 | # Create a list of thread flags to try. Items starting with a "-" are 127 | # C compiler flags, and other items are library names, except for "none" 128 | # which indicates that we try without any flags at all, and "pthread-config" 129 | # which is a program returning the flags for the Pth emulation library. 130 | 131 | ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" 132 | 133 | # The ordering *is* (sometimes) important. Some notes on the 134 | # individual items follow: 135 | 136 | # pthreads: AIX (must check this before -lpthread) 137 | # none: in case threads are in libc; should be tried before -Kthread and 138 | # other compiler flags to prevent continual compiler warnings 139 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) 140 | # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 141 | # (Note: HP C rejects this with "bad form for `-t' option") 142 | # -pthreads: Solaris/gcc (Note: HP C also rejects) 143 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it 144 | # doesn't hurt to check since this sometimes defines pthreads and 145 | # -D_REENTRANT too), HP C (must be checked before -lpthread, which 146 | # is present but should not be used directly; and before -mthreads, 147 | # because the compiler interprets this as "-mt" + "-hreads") 148 | # -mthreads: Mingw32/gcc, Lynx/gcc 149 | # pthread: Linux, etcetera 150 | # --thread-safe: KAI C++ 151 | # pthread-config: use pthread-config program (for GNU Pth library) 152 | 153 | case $host_os in 154 | 155 | freebsd*) 156 | 157 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) 158 | # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) 159 | 160 | ax_pthread_flags="-kthread lthread $ax_pthread_flags" 161 | ;; 162 | 163 | hpux*) 164 | 165 | # From the cc(1) man page: "[-mt] Sets various -D flags to enable 166 | # multi-threading and also sets -lpthread." 167 | 168 | ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" 169 | ;; 170 | 171 | openedition*) 172 | 173 | # IBM z/OS requires a feature-test macro to be defined in order to 174 | # enable POSIX threads at all, so give the user a hint if this is 175 | # not set. (We don't define these ourselves, as they can affect 176 | # other portions of the system API in unpredictable ways.) 177 | 178 | AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], 179 | [ 180 | # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) 181 | AX_PTHREAD_ZOS_MISSING 182 | # endif 183 | ], 184 | [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) 185 | ;; 186 | 187 | solaris*) 188 | 189 | # On Solaris (at least, for some versions), libc contains stubbed 190 | # (non-functional) versions of the pthreads routines, so link-based 191 | # tests will erroneously succeed. (N.B.: The stubs are missing 192 | # pthread_cleanup_push, or rather a function called by this macro, 193 | # so we could check for that, but who knows whether they'll stub 194 | # that too in a future libc.) So we'll check first for the 195 | # standard Solaris way of linking pthreads (-mt -lpthread). 196 | 197 | ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" 198 | ;; 199 | esac 200 | 201 | # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) 202 | 203 | AS_IF([test "x$GCC" = "xyes"], 204 | [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) 205 | 206 | # The presence of a feature test macro requesting re-entrant function 207 | # definitions is, on some systems, a strong hint that pthreads support is 208 | # correctly enabled 209 | 210 | case $host_os in 211 | darwin* | hpux* | linux* | osf* | solaris*) 212 | ax_pthread_check_macro="_REENTRANT" 213 | ;; 214 | 215 | aix*) 216 | ax_pthread_check_macro="_THREAD_SAFE" 217 | ;; 218 | 219 | *) 220 | ax_pthread_check_macro="--" 221 | ;; 222 | esac 223 | AS_IF([test "x$ax_pthread_check_macro" = "x--"], 224 | [ax_pthread_check_cond=0], 225 | [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) 226 | 227 | # Are we compiling with Clang? 228 | 229 | AC_CACHE_CHECK([whether $CC is Clang], 230 | [ax_cv_PTHREAD_CLANG], 231 | [ax_cv_PTHREAD_CLANG=no 232 | # Note that Autoconf sets GCC=yes for Clang as well as GCC 233 | if test "x$GCC" = "xyes"; then 234 | AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], 235 | [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ 236 | # if defined(__clang__) && defined(__llvm__) 237 | AX_PTHREAD_CC_IS_CLANG 238 | # endif 239 | ], 240 | [ax_cv_PTHREAD_CLANG=yes]) 241 | fi 242 | ]) 243 | ax_pthread_clang="$ax_cv_PTHREAD_CLANG" 244 | 245 | ax_pthread_clang_warning=no 246 | 247 | # Clang needs special handling, because older versions handle the -pthread 248 | # option in a rather... idiosyncratic way 249 | 250 | if test "x$ax_pthread_clang" = "xyes"; then 251 | 252 | # Clang takes -pthread; it has never supported any other flag 253 | 254 | # (Note 1: This will need to be revisited if a system that Clang 255 | # supports has POSIX threads in a separate library. This tends not 256 | # to be the way of modern systems, but it's conceivable.) 257 | 258 | # (Note 2: On some systems, notably Darwin, -pthread is not needed 259 | # to get POSIX threads support; the API is always present and 260 | # active. We could reasonably leave PTHREAD_CFLAGS empty. But 261 | # -pthread does define _REENTRANT, and while the Darwin headers 262 | # ignore this macro, third-party headers might not.) 263 | 264 | PTHREAD_CFLAGS="-pthread" 265 | PTHREAD_LIBS= 266 | 267 | ax_pthread_ok=yes 268 | 269 | # However, older versions of Clang make a point of warning the user 270 | # that, in an invocation where only linking and no compilation is 271 | # taking place, the -pthread option has no effect ("argument unused 272 | # during compilation"). They expect -pthread to be passed in only 273 | # when source code is being compiled. 274 | # 275 | # Problem is, this is at odds with the way Automake and most other 276 | # C build frameworks function, which is that the same flags used in 277 | # compilation (CFLAGS) are also used in linking. Many systems 278 | # supported by AX_PTHREAD require exactly this for POSIX threads 279 | # support, and in fact it is often not straightforward to specify a 280 | # flag that is used only in the compilation phase and not in 281 | # linking. Such a scenario is extremely rare in practice. 282 | # 283 | # Even though use of the -pthread flag in linking would only print 284 | # a warning, this can be a nuisance for well-run software projects 285 | # that build with -Werror. So if the active version of Clang has 286 | # this misfeature, we search for an option to squash it. 287 | 288 | AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], 289 | [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], 290 | [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown 291 | # Create an alternate version of $ac_link that compiles and 292 | # links in two steps (.c -> .o, .o -> exe) instead of one 293 | # (.c -> exe), because the warning occurs only in the second 294 | # step 295 | ax_pthread_save_ac_link="$ac_link" 296 | ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' 297 | ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` 298 | ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" 299 | ax_pthread_save_CFLAGS="$CFLAGS" 300 | for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do 301 | AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) 302 | CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" 303 | ac_link="$ax_pthread_save_ac_link" 304 | AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], 305 | [ac_link="$ax_pthread_2step_ac_link" 306 | AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], 307 | [break]) 308 | ]) 309 | done 310 | ac_link="$ax_pthread_save_ac_link" 311 | CFLAGS="$ax_pthread_save_CFLAGS" 312 | AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) 313 | ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" 314 | ]) 315 | 316 | case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in 317 | no | unknown) ;; 318 | *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; 319 | esac 320 | 321 | fi # $ax_pthread_clang = yes 322 | 323 | if test "x$ax_pthread_ok" = "xno"; then 324 | for ax_pthread_try_flag in $ax_pthread_flags; do 325 | 326 | case $ax_pthread_try_flag in 327 | none) 328 | AC_MSG_CHECKING([whether pthreads work without any flags]) 329 | ;; 330 | 331 | -mt,pthread) 332 | AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) 333 | PTHREAD_CFLAGS="-mt" 334 | PTHREAD_LIBS="-lpthread" 335 | ;; 336 | 337 | -*) 338 | AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) 339 | PTHREAD_CFLAGS="$ax_pthread_try_flag" 340 | ;; 341 | 342 | pthread-config) 343 | AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) 344 | AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) 345 | PTHREAD_CFLAGS="`pthread-config --cflags`" 346 | PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" 347 | ;; 348 | 349 | *) 350 | AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) 351 | PTHREAD_LIBS="-l$ax_pthread_try_flag" 352 | ;; 353 | esac 354 | 355 | ax_pthread_save_CFLAGS="$CFLAGS" 356 | ax_pthread_save_LIBS="$LIBS" 357 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 358 | LIBS="$PTHREAD_LIBS $LIBS" 359 | 360 | # Check for various functions. We must include pthread.h, 361 | # since some functions may be macros. (On the Sequent, we 362 | # need a special flag -Kthread to make this header compile.) 363 | # We check for pthread_join because it is in -lpthread on IRIX 364 | # while pthread_create is in libc. We check for pthread_attr_init 365 | # due to DEC craziness with -lpthreads. We check for 366 | # pthread_cleanup_push because it is one of the few pthread 367 | # functions on Solaris that doesn't have a non-functional libc stub. 368 | # We try pthread_create on general principles. 369 | 370 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include 371 | # if $ax_pthread_check_cond 372 | # error "$ax_pthread_check_macro must be defined" 373 | # endif 374 | static void routine(void *a) { a = 0; } 375 | static void *start_routine(void *a) { return a; }], 376 | [pthread_t th; pthread_attr_t attr; 377 | pthread_create(&th, 0, start_routine, 0); 378 | pthread_join(th, 0); 379 | pthread_attr_init(&attr); 380 | pthread_cleanup_push(routine, 0); 381 | pthread_cleanup_pop(0) /* ; */])], 382 | [ax_pthread_ok=yes], 383 | []) 384 | 385 | CFLAGS="$ax_pthread_save_CFLAGS" 386 | LIBS="$ax_pthread_save_LIBS" 387 | 388 | AC_MSG_RESULT([$ax_pthread_ok]) 389 | AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) 390 | 391 | PTHREAD_LIBS="" 392 | PTHREAD_CFLAGS="" 393 | done 394 | fi 395 | 396 | # Various other checks: 397 | if test "x$ax_pthread_ok" = "xyes"; then 398 | ax_pthread_save_CFLAGS="$CFLAGS" 399 | ax_pthread_save_LIBS="$LIBS" 400 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 401 | LIBS="$PTHREAD_LIBS $LIBS" 402 | 403 | # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. 404 | AC_CACHE_CHECK([for joinable pthread attribute], 405 | [ax_cv_PTHREAD_JOINABLE_ATTR], 406 | [ax_cv_PTHREAD_JOINABLE_ATTR=unknown 407 | for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do 408 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], 409 | [int attr = $ax_pthread_attr; return attr /* ; */])], 410 | [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], 411 | []) 412 | done 413 | ]) 414 | AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ 415 | test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ 416 | test "x$ax_pthread_joinable_attr_defined" != "xyes"], 417 | [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], 418 | [$ax_cv_PTHREAD_JOINABLE_ATTR], 419 | [Define to necessary symbol if this constant 420 | uses a non-standard name on your system.]) 421 | ax_pthread_joinable_attr_defined=yes 422 | ]) 423 | 424 | AC_CACHE_CHECK([whether more special flags are required for pthreads], 425 | [ax_cv_PTHREAD_SPECIAL_FLAGS], 426 | [ax_cv_PTHREAD_SPECIAL_FLAGS=no 427 | case $host_os in 428 | solaris*) 429 | ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" 430 | ;; 431 | esac 432 | ]) 433 | AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ 434 | test "x$ax_pthread_special_flags_added" != "xyes"], 435 | [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" 436 | ax_pthread_special_flags_added=yes]) 437 | 438 | AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], 439 | [ax_cv_PTHREAD_PRIO_INHERIT], 440 | [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], 441 | [[int i = PTHREAD_PRIO_INHERIT;]])], 442 | [ax_cv_PTHREAD_PRIO_INHERIT=yes], 443 | [ax_cv_PTHREAD_PRIO_INHERIT=no]) 444 | ]) 445 | AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ 446 | test "x$ax_pthread_prio_inherit_defined" != "xyes"], 447 | [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) 448 | ax_pthread_prio_inherit_defined=yes 449 | ]) 450 | 451 | CFLAGS="$ax_pthread_save_CFLAGS" 452 | LIBS="$ax_pthread_save_LIBS" 453 | 454 | # More AIX lossage: compile with *_r variant 455 | if test "x$GCC" != "xyes"; then 456 | case $host_os in 457 | aix*) 458 | AS_CASE(["x/$CC"], 459 | [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], 460 | [#handle absolute path differently from PATH based program lookup 461 | AS_CASE(["x$CC"], 462 | [x/*], 463 | [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], 464 | [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) 465 | ;; 466 | esac 467 | fi 468 | fi 469 | 470 | test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" 471 | 472 | AC_SUBST([PTHREAD_LIBS]) 473 | AC_SUBST([PTHREAD_CFLAGS]) 474 | AC_SUBST([PTHREAD_CC]) 475 | 476 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: 477 | if test "x$ax_pthread_ok" = "xyes"; then 478 | ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) 479 | : 480 | else 481 | ax_pthread_ok=no 482 | $2 483 | fi 484 | AC_LANG_POP 485 | ])dnl AX_PTHREAD 486 | --------------------------------------------------------------------------------