History

Merge branch 'master' into feature/pitchshift

Paul Brossier committed 7 years ago

Commit 633400d2 parents 5b46bc3 f19db54230 files · +12450 −4607Browse files

Unified · Split

230 files
  1. .appveyor.yml +49 −40
  2. .circleci/config.yml +104 −0
  3. .coveragerc +3 −0
  4. .gitignore +7 −0
  5. .travis.yml +59 −42
  6. ChangeLog +508 −0
  7. MANIFEST.in +8 −9
  8. Makefile +253 −56
  9. README.md +49 −114
  10. VERSION +3 −3
  11. aubio.pc.in +1 −1
  12. azure-pipelines.yml +38 −0
  13. doc/Makefile +2 −0
  14. doc/about.rst +73 −0
  15. doc/android.rst +9 −0
  16. doc/aubio.txt +141 −0
  17. doc/aubiocut.txt +5 −3
  18. doc/aubiomfcc.txt +2 −2
  19. doc/aubionotes.txt +10 −2
  20. doc/aubioonset.txt +13 −5
  21. doc/aubiopitch.txt +6 −0
  22. doc/aubiotrack.txt +7 −2
  23. doc/binaries.rst +12 −0
  24. doc/building.rst +37 −6
  25. doc/cli.rst +25 −6
  26. doc/cli_features.rst +42 −0
  27. doc/conf.py +37 −9
  28. doc/debian_packages.rst +1 −1
  29. doc/develop.rst +89 −35
  30. doc/download.rst +4 −8
  31. doc/full.cfg +3 −2346
  32. doc/index.rst +35 −60
  33. doc/installing.rst +69 −9
  34. doc/py_datatypes.rst +43 −0
  35. doc/py_examples.rst +42 −0
  36. doc/py_io.rst +118 −0
  37. doc/py_utils.rst +84 −0
  38. doc/python.rst +55 −0
  39. doc/python_module.rst +69 −40
  40. doc/requirements.rst +256 −81
  41. doc/statuslinks.rst +24 −0
  42. doc/web.cfg +211 −120
  43. doc/xcode_frameworks.rst +37 −5
  44. examples/aubiomfcc.c +7 −2
  45. examples/aubionotes.c +33 −6
  46. examples/aubioonset.c +22 −11
  47. examples/aubiopitch.c +5 −2
  48. examples/aubioquiet.c +1 −0
  49. examples/aubiotrack.c +12 −5
  50. examples/parse_args.h +62 −11
  51. examples/utils.c +22 −13
  52. examples/utils.h +1 −1
  53. python/README.md +88 −79
  54. python/__init__.py +0 −0
  55. python/demos/demo_alsa.py +45 −0
  56. python/demos/demo_bench_yin.py +50 −0
  57. python/demos/demo_bpm_extract.py +44 −27
  58. python/demos/demo_filter.py +31 −14
  59. python/demos/demo_filterbank.py +31 −17
  60. python/demos/demo_notes.py +37 −0
  61. python/demos/demo_pitch_sinusoid.py +1 −1
  62. python/demos/demo_pyaudio.py +75 −0
  63. python/demos/demo_source_simple.py +13 −9
  64. python/demos/demo_tapthebeat.py +78 −0
  65. python/demos/demo_timestretch.py +1 −1
  66. python/demos/demo_timestretch_online.py +5 −3
  67. python/demos/demo_wav2midi.py +77 −0
  68. python/demos/demo_yin_compare.py +175 −0
  69. python/ext/aubio-types.h +9 −1
  70. python/ext/aubiomodule.c +167 −27
  71. python/ext/py-cvec.c +42 −12
  72. python/ext/py-filterbank.c +133 −9
  73. python/ext/py-musicutils.c +102 −0
  74. python/ext/py-musicutils.h +322 −25
  75. python/ext/py-phasevoc.c +116 −8
  76. python/ext/py-sink.c +89 −50
  77. python/ext/py-source.c +370 −41
  78. python/ext/ufuncs.c +44 −3
  79. python/lib/__init__.py +0 −0
  80. python/lib/aubio/__init__.py +72 −5
  81. python/lib/aubio/cmd.py +623 −0
  82. python/lib/aubio/cut.py +163 −0
  83. python/lib/aubio/midiconv.py +142 −17
  84. python/lib/aubio/slicing.py +81 −14
  85. python/lib/gen_code.py +65 −23
  86. python/lib/gen_external.py +180 −89
  87. python/lib/moresetuptools.py +78 −26
  88. python/scripts/aubiocut +0 −206
  89. python/tests/__init__.py +1 −0
  90. python/tests/eval_pitch +1 −1
  91. python/tests/test_aubio.py +5 −0
  92. python/tests/test_aubio_cmd.py +34 −0
  93. python/tests/test_aubio_cut.py +16 −0
  94. python/tests/test_dct.py +68 −0
  95. python/tests/test_fft.py +39 −12
  96. python/tests/test_filter.py +11 −1
  97. python/tests/test_filterbank.py +12 −5
  98. python/tests/test_filterbank_mel.py +136 −13
  99. python/tests/test_fvec.py +8 −0
  100. python/tests/test_fvec_shift.py +35 −0
  101. python/tests/test_hztomel.py +109 −0
  102. python/tests/test_mfcc.py +37 −0
  103. python/tests/test_midi2note.py +6 −4
  104. python/tests/test_note2midi.py +67 −7
  105. python/tests/test_notes.py +95 −0
  106. python/tests/test_onset.py +40 −8
  107. python/tests/test_phasevoc.py +17 −1
  108. python/tests/test_pitch.py +2 −2
  109. python/tests/test_sink.py +32 −1
  110. python/tests/test_slicing.py +27 −6
  111. python/tests/test_source.py +34 −7
  112. python/tests/test_source_channels.py +93 −0
  113. python/tests/test_tempo.py +91 −0
  114. scripts/build_android +41 −0
  115. scripts/build_apple_frameworks +3 −0
  116. scripts/build_emscripten +4 −7
  117. scripts/build_mingw +109 −18
  118. scripts/get_waf.sh +48 −4
  119. scripts/setenv_local.sh +7 −19
  120. setup.py +41 −50
  121. src/aubio.h +14 −9
  122. src/aubio_priv.h +66 −12
  123. src/cvec.c +36 −8
  124. src/cvec.h +10 −0
  125. src/fmat.c +3 −3
  126. src/fvec.c +40 −31
  127. src/io/audio_unit.c +1 −2
  128. src/io/ioutils.c +53 −0
  129. src/io/ioutils.h +60 −0
  130. src/io/sink.c +5 −3
  131. src/io/sink_apple_audio.c +16 −9
  132. src/io/sink_sndfile.c +20 −11
  133. src/io/sink_wavwrite.c +17 −12
  134. src/io/source.c +7 −3
  135. src/io/source_apple_audio.c +2 −3
  136. src/io/source_avcodec.c +266 −81
  137. src/io/source_sndfile.c +17 −8
  138. src/io/source_wavread.c +48 −14
  139. src/io/utils_apple_audio.c +1 −2
  140. src/mathutils.c +90 −36
  141. src/mathutils.h +22 −0
  142. src/musicutils.c +85 −0
  143. src/musicutils.h +107 −0
  144. src/notes/notes.c +97 −11
  145. src/notes/notes.h +81 −2
  146. src/onset/onset.c +135 −19
  147. src/onset/onset.h +59 −0
  148. src/onset/peakpicker.c +11 −15
  149. src/pitch/pitch.c +50 −1
  150. src/pitch/pitch.h +7 −0
  151. src/pitch/pitchfcomb.c +6 −1
  152. src/pitch/pitchmcomb.c +8 −1
  153. src/pitch/pitchspecacf.c +6 −1
  154. src/pitch/pitchyin.c +29 −22
  155. src/pitch/pitchyinfast.c +201 −0
  156. src/pitch/pitchyinfast.h +102 −0
  157. src/pitch/pitchyinfft.c +18 −7
  158. src/spectral/awhitening.c +120 −0
  159. src/spectral/awhitening.h +125 −0
  160. src/spectral/dct.c +174 −0
  161. src/spectral/dct.h +85 −0
  162. src/spectral/dct_accelerate.c +102 −0
  163. src/spectral/dct_fftw.c +130 −0
  164. src/spectral/dct_ipp.c +150 −0
  165. src/spectral/dct_ooura.c +96 −0
  166. src/spectral/dct_plain.c +105 −0
  167. src/spectral/fft.c +214 −46
  168. src/spectral/filterbank.c +48 −0
  169. src/spectral/filterbank.h +41 −0
  170. src/spectral/filterbank_mel.c +126 −35
  171. src/spectral/filterbank_mel.h +51 −4
  172. src/spectral/mfcc.c +90 −29
  173. src/spectral/mfcc.h +96 −2
  174. src/spectral/ooura_fft8g.c +11 −10
  175. src/spectral/phasevoc.c +15 −1
  176. src/spectral/phasevoc.h +11 −0
  177. src/spectral/specdesc.c +30 −1
  178. src/spectral/specdesc.h +12 −2
  179. src/synth/sampler.c +0 −1
  180. src/synth/wavetable.c +9 −2
  181. src/synth/wavetable.h +2 −0
  182. src/tempo/beattracking.h +1 −1
  183. src/tempo/tempo.c +30 −17
  184. src/tempo/tempo.h +2 −2
  185. src/temporal/biquad.c +1 −1
  186. src/temporal/resampler.c +4 −2
  187. src/utils/hist.c +3 −0
  188. src/utils/log.c +1 −2
  189. src/utils/log.h +2 −1
  190. src/utils/parameter.c +0 −1
  191. src/utils/windll.c +3 −3
  192. src/vecutils.c +0 −1
  193. src/wscript_build +14 −3
  194. tests/create_tests_source.py +42 −0
  195. tests/src/io/test-sink-multi.c +4 −5
  196. tests/src/io/test-sink.c +2 −2
  197. tests/src/io/test-sink_apple_audio-multi.c +5 −5
  198. tests/src/io/test-sink_apple_audio.c +3 −3
  199. tests/src/io/test-sink_sndfile-multi.c +5 −6
  200. tests/src/io/test-sink_sndfile.c +3 −4
  201. tests/src/io/test-sink_wavwrite-multi.c +5 −5
  202. tests/src/io/test-sink_wavwrite.c +3 −3
  203. tests/src/io/test-source.c +4 −4
  204. tests/src/io/test-source_apple_audio.c +5 −5
  205. tests/src/io/test-source_avcodec.c +5 −5
  206. tests/src/io/test-source_multi.c +2 −2
  207. tests/src/io/test-source_seek.c +4 −4
  208. tests/src/io/test-source_sndfile.c +5 −5
  209. tests/src/io/test-source_wavread.c +5 −6
  210. tests/src/notes/test-notes.c +24 −0
  211. tests/src/onset/test-onset.c +42 −4
  212. tests/src/pitch/test-pitch.c +37 −0
  213. tests/src/spectral/test-awhitening.c +102 −0
  214. tests/src/spectral/test-dct.c +49 −0
  215. tests/src/spectral/test-filterbank.c +12 −0
  216. tests/src/spectral/test-mfcc.c +8 −3
  217. tests/src/spectral/test-phasevoc.c +8 −1
  218. tests/src/spectral/test-tss.c +4 −0
  219. tests/src/synth/test-sampler.c +14 −5
  220. tests/src/synth/test-wavetable.c +4 −4
  221. tests/src/tempo/test-tempo.c +78 −8
  222. tests/src/temporal/test-filter.c +19 −0
  223. tests/src/test-mathutils.c +2 −1
  224. tests/src/utils/test-hist.c +1 −0
  225. tests/src/utils/test-log.c +17 −13
  226. tests/utils_tests.h +138 −2
  227. tests/wscript_build +19 −2
  228. this_version.py +107 −0
  229. waf_gensyms.py +40 −0
  230. wscript +297 −77
.appveyor.yml+49−40
@@ -7,63 +7,72 @@ environment: · 6 unmodified lines
77
88 # pre-installed python version, see:
99 # http://www.appveyor.com/docs/installed-software#python
10− - PYTHON: "C:\\Python27"
11− PYTHON_VERSION: "2.7.x"
12− PYTHON_ARCH: "32"
10+ - PYTHONDIR: C:\Python27
11+ PYTHON_VERSION: 2.7.x
12+ PYTHON_ARCH: 32
1313
14− - PYTHON: "C:\\Python27-x64"
15− PYTHON_VERSION: "2.7.x"
16− PYTHON_ARCH: "64"
14+ - PYTHONDIR: C:\Python27-x64
15+ PYTHON_VERSION: 2.7.x
16+ PYTHON_ARCH: 64
1717
18− - PYTHON: "C:\\Python34"
19− PYTHON_VERSION: "3.4.x"
20− PYTHON_ARCH: "32"
18+ - PYTHONDIR: C:\Python35
19+ PYTHON_VERSION: 3.5.x
20+ PYTHON_ARCH: 32
2121
22− - PYTHON: "C:\\Python34-x64"
23− PYTHON_VERSION: "3.4.x"
24− PYTHON_ARCH: "64"
22+ - PYTHONDIR: C:\Python35-x64
23+ PYTHON_VERSION: 3.5.x
24+ PYTHON_ARCH: 64
2525
26− - PYTHON: "C:\\Python35"
27− PYTHON_VERSION: "3.5.x"
28− PYTHON_ARCH: "32"
26+ - PYTHONDIR: C:\Python36
27+ PYTHON_VERSION: 3.6.x
28+ PYTHON_ARCH: 32
2929
30− - PYTHON: "C:\\Python35-x64"
31− PYTHON_VERSION: "3.5.x"
32− PYTHON_ARCH: "64"
33− # add path required to run preprocessor step
34− PATH_EXTRAS: "c:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin"
30+ - PYTHONDIR: C:\Python36-x64
31+ PYTHON_VERSION: 3.6.x
32+ PYTHON_ARCH: 64
3533
36−install:
34+ - PYTHONDIR: C:\Python37
35+ PYTHON_VERSION: 3.7.x
36+ PYTHON_ARCH: 32
37+
38+ - PYTHONDIR: C:\Python37-x64
39+ PYTHON_VERSION: 3.7.x
40+ PYTHON_ARCH: 64
3741
42+install:
3843 - ECHO "Installed SDKs:"
3944 - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
4045
46+ - "SET PATH=%PYTHONDIR%;%PYTHONDIR%\\Scripts;%PATH%"
47+
4148 # Check that we have the expected version and architecture for Python
42− - "%PYTHON%\\python.exe --version"
43− - "%PYTHON%\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\""
49+ - "python --version"
50+ - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
4451
45− # We need wheel installed to build wheels
46− - "%PYTHON%\\python.exe -m pip install wheel"
52+ - "python -m pip install --disable-pip-version-check --user --upgrade pip"
53+ - "python -m pip install --upgrade setuptools"
4754
48− - "SET PATH=%PATH_EXTRAS%;%PYTHON%;%PYTHON%\\Scripts;%PATH%"
55+ # We need wheel installed to build wheels
56+ - "python -m pip install wheel"
4957
50− - "pip install --disable-pip-version-check --user --upgrade pip"
51− - "pip install --upgrade setuptools"
58+ - "pip install -r requirements.txt"
5259
5360 before_build:
54− - curl -fsS -o waf https://waf.io/waf-1.8.22
55− - curl -fsS -o waf.bat https://raw.githubusercontent.com/waf-project/waf/master/utils/waf.bat
61+ - "bash scripts/get_waf.sh"
5662
5763 build_script:
58− # build python module without using libaubio
59− - "pip install -r requirements.txt"
60− - "python setup.py build"
61− - "pip install ."
64+ # also build libaubio with waf
65+ - python waf configure build install --verbose --msvc_version="msvc 14.0"
66+ # clean before building python package
67+ - python waf distclean
68+ # build, upload and install wheel (inspired by numpy's appveyor)
69+ - ps: |
70+ pip wheel -v -v -v --wheel-dir=dist .
71+ ls dist -r | Foreach-Object {
72+ Push-AppveyorArtifact $_.FullName
73+ pip install $_.FullName
74+ }
75+
76+test_script:
6277 - "python python\\demos\\demo_create_test_sounds.py"
6378 - "nose2 --verbose"
64− # clean up
65− - waf distclean
66− # build libaubio
67− - waf configure build --verbose
68− # build python module using libaubio dll
69− - "python setup.py build"
.circleci/config.yml+104−0
@@ -0,0 +1,104 @@
1+apt-run: &apt-install
2+ name: Install apt packages
3+ command: |
4+ sudo apt-get update
5+ sudo apt-get -y install make sox pkg-config libavcodec-dev libavformat-dev libavresample-dev libavutil-dev libsndfile1-dev libsamplerate-dev
6+
7+pip-install: &pip-install
8+ name: Install pip dependencies
9+ command: |
10+ pip install --user -r requirements.txt
11+
12+build-wheel: &build-wheel
13+ name: Build python wheel
14+ command: |
15+ pip wheel -v -v -v --wheel-dir=dist .
16+
17+install-wheel: &install-wheel
18+ name: Install python wheel
19+ command: |
20+ pip install --user dist/aubio*.whl
21+
22+test-nose2: &test-nose2
23+ name: Test python wheel
24+ command: |
25+ make create_test_sounds
26+ PATH=/home/circleci/.local/bin:$PATH nose2 -v
27+
28+test-nose2-nosounds: &test-nose2-nosounds
29+ name: Test python wheel
30+ command: |
31+ PATH=/home/circleci/.local/bin:$PATH nose2 -v
32+
33+uninstall-wheel: &uninstall-wheel
34+ name: Uninstall python wheel
35+ command: |
36+ pip show -f aubio
37+ pip uninstall --verbose --yes aubio
38+
39+version: 2
40+jobs:
41+ build-27:
42+ docker:
43+ - image: circleci/python:2.7
44+ steps:
45+ - checkout
46+ - run: *apt-install
47+ - run: *pip-install
48+ - run: *build-wheel
49+ - run: *install-wheel
50+ - run: *test-nose2
51+ - run: *uninstall-wheel
52+ - store_artifacts:
53+ path: dist/
54+
55+ build-36:
56+ docker:
57+ - image: circleci/python:3.6
58+ steps:
59+ - checkout
60+ - run: *apt-install
61+ - run: *pip-install
62+ - run: *build-wheel
63+ - run: *install-wheel
64+ - run: *test-nose2
65+ - run: *uninstall-wheel
66+ - store_artifacts:
67+ path: dist/
68+
69+ build-37:
70+ docker:
71+ - image: circleci/python:3.7
72+ steps:
73+ - checkout
74+ - run: *apt-install
75+ - run: *pip-install
76+ - run: *build-wheel
77+ - run: *install-wheel
78+ - run: *test-nose2
79+ - run: *uninstall-wheel
80+ - store_artifacts:
81+ path: dist/
82+
83+ build-37-nodeps:
84+ docker:
85+ - image: circleci/python:3.7
86+ steps:
87+ - checkout
88+ - run: *pip-install
89+ - run: *build-wheel
90+ - run: *install-wheel
91+ - run: *test-nose2-nosounds
92+ - run: *uninstall-wheel
93+ - store_artifacts:
94+ path: dist/
95+
96+workflows:
97+ version: 2
98+
99+ test-wheel:
100+ jobs:
101+ - build-27
102+ - build-36
103+ - build-37
104+ - build-37-nodeps
.coveragerc+3−0
@@ -0,0 +1,3 @@
1+[run]
2+branch = True
3+source = aubio
.gitignore+7−0
@@ -30,6 +30,7 @@ build/ · 29 unmodified lines
3030 # doxygen
3131 doc/web/
3232 doc/full/
33+doc/_build/
3334
3435 python/gen
3536 python/dist
@@ -37,9 +38,15 @@ python/MANIFEST · 1 unmodified line
3738 python/*.db
3839 python/*.wav
3940
41+pip-delete-this-directory.txt
42+
4043 aubio-*.tar.bz2
4144 aubio-*.zip
45+dist/*.tar.gz
46+dist/*.whl
4247
4348 # test sounds
4449 python/tests/sounds
4550 aubio.egg-info
51+.eggs
52+.cache
.travis.yml+59−42
@@ -2,67 +2,59 @@ language: python · 1 unmodified line
22
33 matrix:
44 include:
5− - python: 2.7
6− os: linux
7− compiler: gcc
8− env: ARCH=x86_64
9− - python: 2.7
10− os: linux
11− compiler: gcc
12− env: ARCH=i386
13− - python: 3.4
5+ - python: 3.5
146 os: linux
157 compiler: gcc
16− env: ARCH=x86_64
178 - python: 3.4
189 os: linux
1910 compiler: gcc
20− env: ARCH=i386 WAFOPTS=--enable-fftw3f
21− - language: C
22− os: osx
23− compiler: clang
24− env: ARCH=x86_64
25− - language: C
26− os: osx
27− compiler: clang
28− env: ARCH=i386
2911 - python: 2.7
3012 os: linux
3113 compiler: gcc
32− env: ARCH=x86_64 HAVE_DOUBLE=1 WAFOPTS=--enable-fftw3
33− - python: 2.7
14+ - python: 3.5
3415 os: linux
3516 compiler: gcc
36− env: ARCH=i386 HAVE_DOUBLE=1
17+ env: CFLAGS="-Os" WAFOPTS="--disable-samplerate --disable-sndfile"
3718 - python: 3.4
3819 os: linux
3920 compiler: gcc
40− env: ARCH=x86_64 HAVE_DOUBLE=1
41− - python: 3.4
21+ env: HAVE_AUBIO_DOUBLE=1 CFLAGS="-O3" WAFOPTS="--enable-fftw3"
22+ - python: 2.7
4223 os: linux
4324 compiler: gcc
44− env: ARCH=i386 HAVE_DOUBLE=1
25+ env: CFLAGS="`dpkg-buildflags --get CFLAGS`" LDFLAGS="`dpkg-buildflags --get LDFLAGS`"
26+ - language: C
27+ os: osx
28+ compiler: clang
4529 - language: C
4630 os: osx
4731 compiler: clang
48− env: ARCH=x86_64 HAVE_DOUBLE=1
32+ env: CFLAGS="-Os" HAVE_AUBIO_DOUBLE=1 WAFOPTS="--disable-accelerate"
4933 - language: C
5034 os: osx
5135 compiler: clang
52− env: ARCH=i386 HAVE_DOUBLE=1
36+ env: WAFOPTS="--enable-fat --disable-avcodec --disable-sndfile --disable-samplerate --disable-rubberband"
5337 - language: C
5438 os: osx
5539 compiler: clang
56− env: ARCH=x86_64 WAFOPTS="--enable-fat --disable-sndfile --disable-samplerate --disable-rubberband"
40+ env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
5741 - language: C
5842 os: osx
5943 compiler: clang
60− env: ARCH=i386 WAFOPTS="--enable-fat --disable-sndfile --disable-samplerate --disable-rubberband"
44+ env: WAFOPTS="--with-target-platform=iosimulator --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
45+
46+# use trusty
47+dist: trusty
48+sudo: required
6149
6250 addons:
6351 apt:
6452 packages:
6553 - bzip2
54+ - libavcodec-dev
55+ - libavformat-dev
56+ - libavresample-dev
57+ - libavutil-dev
6658 - libsndfile1-dev
6759 - libsamplerate-dev
6860 - libjack-dev
@@ -70,33 +62,58 @@ addons: · 1 unmodified line
7062 - libfftw3-dev
7163 - librubberband-dev
7264 - sox
65+ - lcov
66+ homebrew:
67+ packages:
68+ - sox
69+ - ffmpeg
70+ - libsndfile
71+ - libsamplerate
72+ - rubberband
73+ - lcov
74+ #update: true
7375
7476 before_install:
7577 - |
7678 if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
77− brew update
78− brew install sox libsamplerate libsndfile rubberband
7979 export PATH="$HOME/Library/Python/2.7/bin/:$PATH"
8080 fi;
8181
82−
8382 install:
84− - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry pip install nose2; fi
85− - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_retry pip install --user nose2; fi
83+ - |
84+ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
85+ alias pip=pip2
86+ fi;
87+ - travis_retry pip install --upgrade pip
88+ - travis_retry make getwaf expandwaf deps_python
89+ - which pip
90+ - pip --version
8691
8792 script:
8893 - make create_test_sounds
89− - make build
90− - make build_python
91− - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make test_python; fi
92− - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make test_python_osx; fi
93− - make clean_python
94− - make clean
95− - make distcheck
96− - make test_pure_python
94+ - |
95+ if [[ -z "$AUBIO_NOTESTS" ]]; then
96+ make test_lib_python_clean
97+ make coverage
98+ else
99+ make test_lib_only_clean
100+ fi;
101+
102+after_success:
103+ - |
104+ if [[ -z "$AUBIO_NOTESTS" ]]; then
105+ # upload to codecov
106+ bash <(curl -s https://codecov.io/bash)
107+ fi
97108
98109 notifications:
99110 irc:
100111 channels:
101112 - "irc.freenode.org#aubio"
102113 use_notice: true
114+ webhooks:
115+ urls:
116+ - https://webhooks.gitter.im/e/81e7733a5b1d977854b4
117+ on_success: change # options: [always|never|change] default: always
118+ on_failure: always # options: [always|never|change] default: always
119+ on_start: never # options: [always|never|change] default: always
ChangeLog+508−0
@@ -1,3 +1,511 @@
1+2018-11-21 Paul Brossier <piem@aubio.org>
2+
3+ [ Overview ]
4+
5+ * VERSION: bump to 0.4.8
6+ * notes: new option release_drop (gh-203)
7+ * spectral: new parameters added to filterbank and mfcc (gh-206)
8+ * python: start documenting module (gh-73, debian #480018), improve build for
9+ win-amd64 (gh-154, gh-199, gh-208)
10+ * fixes: prevent crash when using fft sizes unsupported by vDSP (gh-207),
11+ prevent saturation when down-mixing a multi-channel source (avcodec/ffmpeg)
12+
13+ [ Fixes ]
14+
15+ * avcodec: prevent saturation when down-mixing a multi-channel source, emit
16+ a warning if compiling against avutil < 53 (gh-137), wrap long lines
17+ * examples/: avoid hiding global and unreachable code
18+ * fft: limit to r*2*n sizes, with r in [1, 3, 5, 15] (vDSP only) (gh-207)
19+ * fft: fix reconstruction for odd sizes (fftw only)
20+ * pvoc: add missing implementations for aubio_pvoc_get_hop/win
21+ * mathutils: increase ln(2) precision of in freqtomidi/miditofreq
22+ * wavetable: stop sets playing to 0, add dummy implementation for _load
23+
24+ [ New features ]
25+
26+ * src/musicutils.h: new aubio_meltohz, aubio_hztomel, with _htk versions
27+ * src/spectral/filterbank.h: new set_mel_coeffs, set_mel_coeffs_htk,
28+ set_power, and set_norm methods, improved set_triangle_bands
29+ * src/spectral/mfcc.h: new set_scale, set_power, set_norm, set_mel_coeffs,
30+ set_mel_coeffs_htk, set_mel_coeffs_slaney
31+ * src/mathutils.h: new fvec_mul
32+ * src/notes: new option release_drop to prevent missing note-offs (gh-203)
33+
34+ [ Python module ]
35+
36+ * fix: rounding to nearest integer in midi2note and freq2note
37+ * general: supports code generation of setters with none or multiple
38+ parameters
39+ * documentation: add docstrings do fvec, cvec, source, sink, pvoc, frequency
40+ conversion and level detection routines (gh-73, debian #480018)
41+ * slicing: improve and document slice_source_at_stamps
42+ * module: new note2freq function, recover error log when raising exceptions
43+ on failed set_ methods, prevent cyclic import, coding style improvements
44+ * demos: improve coding style, fix bpm_extract arguments
45+ * MANIFEST.in: exclude *.pyc, improve patterns
46+
47+ [ Documentation ]
48+
49+ * doc/: use sphinx autodoc to load docstrings from aubio module, reorganize
50+ python module documentation, add a note about double precision, use https
51+ when possible
52+ * src/spectral/: update Auditory Toolbox url, update copyright year
53+
54+ [ Tools ]
55+
56+ * aubionotes: add --release-drop option
57+ * aubio: add --release-drop and --silence options to `aubio notes`,
58+ workaround for -V to really show version (py2)
59+ * aubiocut: add option --create-first to always create first slice
60+
61+ [ Tests ]
62+
63+ * tests/, python/tests: add tests for new methods, check source channel
64+ down-mix, improve coverage
65+
66+ [ Build system ]
67+
68+ * Makefile: disable docs when measuring coverage, add branch coverage
69+ option, add coverage_zero_counters target, improve html report
70+ * waf: update to 2.0.12, improve wscript style, prevent shipping some
71+ generated files
72+ * python: always show compiler warnings when pre-processing headers,
73+ workaround to fix code generation for win-amd64 (gh-154, gh-199, gh-208).
74+ * continuous integration: add azure pipelines, update and improve
75+ configurations for appveyor, circleci, and travis.
76+
77+2018-09-22 Paul Brossier <piem@aubio.org>
78+
79+ [ Overview ]
80+
81+ * VERSION: bump to 0.4.7
82+ * src/spectral/dct.h: add dct type II object with optimised versions
83+ * src/io/, src/notes/, src/pitch: prevent crashes on corrupted files
84+ * examples/: fix jack midi output, improve messages when jack disabled
85+ * python/: add dct support, minor bug fixes tests and demos
86+ * wscript: improve support for BLAS/ATLAS
87+
88+ [ Library fixes ]
89+
90+ * src/pitch/pitchyinfft.c: fix out of bound read when samplerate > 50kHz
91+ thanks to @fCorleone (closes #189, CVE-2018-14523, debian #904906)
92+ * src/notes/notes.c: bail out if pitch creation failed (see #188)
93+ * src/io/source_wavread.c:
94+ - also exit if samplerate is negative (closes #188, CVE-2018-14522,
95+ debian #904907)
96+ - add some input validation (closes #148 and #158, CVE-2017-17054,
97+ debian #883355)
98+ * src/io/source_avcodec.c:
99+ - give up if resampling context failed opening (see #137, closes #187,
100+ CVE-2018-14521, debian #904908)
101+ - give up reading file if number of channel changes during stream (closes
102+ #137, CVE-2017-17554, debian #884237)
103+ - make sure libavutil > 52 before checking avFrame->channels (see #137)
104+ - fix build with ffmpeg 4.0, thanks to @jcowgill (closes #168, #173)
105+ - avoid deprecated call for ffmpeg >= 4.0
106+ * src/onset/onset.c: add dummy default parameters for wphase (closes #150)
107+
108+ [ Tools ]
109+
110+ * examples/parse_args.h: hide jack options if not available, improve error
111+ message (closes #182)
112+ * examples/utils.h: process_block returns void
113+ * examples/utils.c: fix examples failing to send more than one JACK midi
114+ event per frame, thanks to @cyclopsian (closes #201)
115+
116+ [ New features ]
117+
118+ * src/spectral/dct.h: add dct type II object with implementation factory
119+ * src/spectral/dct_plain.c: add plain dct implementation
120+ * src/spectral/dct_ooura.c: add ooura implementation
121+ * src/spectral/dct_fftw.c: add fftw implementation
122+ * src/spectral/dct_ipp.c: add ipp version
123+ * src/spectral/dct_accelerate.c: add vdsp/accelerate dct
124+ * tests/src/spectral/test-dct.c: check reconstruction works
125+ * src/spectral/mfcc.c: use new dct to compute mfcc
126+
127+ [ Library internals ]
128+
129+ * src/aubio_priv.h: avoid hard-coded undefs, split BLAS and ATLAS support,
130+ add vdsp scalar add and multiply
131+
132+ [ Build system ]
133+
134+ * wscript:
135+ - add options to disable examples and tests
136+ - detect includes for openblas/libblas/atlas
137+ * scripts/get_waf.sh: bump to 2.0.11, verify signature if gpg available
138+ * python/lib/gen_external.py: pass '-x c' to emcc only
139+
140+ [ Python ]
141+
142+ * python/lib/gen_code.py: add support for rdo methods
143+ * python/tests/test_dct.py: add tests for new dct
144+ * python/demos/demo_pitch_sinusoid.py: use // to yield an integer, fixing
145+ demo on py3, thanks to @ancorcruz (closes #176)
146+ * python/ext/py-musicutils.*: add shift(fvec) and ishift(fvec)
147+ * python/tests/test_fvec_shift.py: add tests for shift() and ishift()
148+ * python/lib/aubio/cmd.py: fix typo in comment
149+
150+ [ Documentation ]
151+
152+ * README.md, doc/statuslinks.rst: use latest for commits-since
153+ * examples/parse_args.h: add yinfast to pitch algorithms
154+ * doc/requirements.rst: add some blas documentation
155+ * doc/requirements.rst: split media/optimisation libraries
156+ * doc/develop.rst: fixed spelling error, thanks to Jon Williams (closes #161)
157+ * doc/aubio{pitch,notes}.txt: add yinfast to list of pitch methods
158+
159+ [ Continuous integration ]
160+
161+ * .travis.yml: remove xcode8.2 builds, group osx, add alias pip=pip2
162+ * .appveyor.yml: upgrade pip first, always use python -m pip
163+
164+2017-10-02 Paul Brossier <piem@aubio.org>
165+
166+ [ Overview ]
167+
168+ * VERSION: bump to 0.4.6
169+ * src/spectral/fft.c, src/*.c: add support for Intel IPP (many thanks to
170+ Eduard Mueller)
171+ * wscript: add support for emscripten (thanks to Martin Hermant)
172+ * src/pitch/pitchyinfast.h: new fast method to compute YIN algorithm
173+ * src/pitch/pitchyin*.c: improve confidence measure, making sure its value
174+ corresponds to the selected period (thanks to Eduard Mueller)
175+ * python/lib/aubio/cmd.py: add `quiet`, `cut`, and `help` subcommands
176+
177+ [ Library ]
178+
179+ * src/aubio_priv.h: add missing aubio_vDSP_vclr (Eduard Mueller)
180+ * src/io/source_avcodec.c: improve error message, prevent un-opened bracket,
181+ no declaration after statements for older compilers, avoid unused variable
182+ * src/mathutils.c: prevent segfault with Accelerate.framework (closes #58,
183+ closes #102)
184+ * src/spectral/phasevoc.h: add aubio_pvoc_set_window to change the windowing
185+ function
186+ * src/mathutils.c: add window type `ones` (no windowing)
187+
188+ [ Python ]
189+
190+ * python/demos/demo_tapthebeat.py: add a real-time example to play beats
191+ using pyaudio
192+ * python/lib/gen_external.py: improve parsing and syntax, use results in
193+ emscripten build (Martin Hermant)
194+ * python/lib/aubio/cmd.py: add option `-u` to `aubio pitch`, improve error
195+ messages, add `quiet` subcommand (closes #124), improve syntax, add some
196+ documentation, add `cut` and `help` subcommand, add silence and time format
197+ options
198+ * python/lib/aubio/cut.py: upgrade to argparse, set samplerate as needed
199+ * python/demos/demo_yin_compare.py: add comparison of yin implementations
200+ * python/demos/demo_wav2midi.py: add an example to create a midi from a
201+ sound file using mido (closes: #134)
202+ * python/demos/demo_bpm_extract.py: use argparse, use beats_to_bpm function
203+ * python/ext/py-cvec.c: fix support for pypy by changing setters to return a
204+ negative value on error (closes #17)
205+
206+ [ Documentation ]
207+
208+ * src/tempo/beattracking.h: fix typo (thanks to Hannes Fritz)
209+ * doc/requirements.rst: fix broken link (thanks to @ssj71, closes #99)
210+ * doc/aubiomfcc.txt: fix typo in 'coefficients'
211+
212+ [ Tests ]
213+
214+ * python/tests/tests_aubio_{cmd,cut}.py: add basic tests
215+ * python/tests/test_filterbank*.py: ignore UserWarnings, clean-up,
216+ improve get_coeff tests
217+
218+ [ Build system ]
219+
220+ * wscript: add support for emscripten, see scripts/build_emscripten
221+ * scripts/get_waf.sh: update waf to 2.0.1, build waf from source tarball
222+ * scripts/build_emscripten: update to build aubio.js
223+ * Makefile: add coverage and coverage_report targets, run tests once
224+
225+ [ Continuous integration ]
226+
227+ * .travis.yml: add coverage report on osx
228+ * .appveyor.yml: use msvc 14.0 (VS 2015) and scripts/get_waf.sh
229+ * .coveragerc: add minimal python coverage configuration
230+
231+2017-04-10 Paul Brossier <piem@aubio.org>
232+
233+ [Overview]
234+
235+ * VERSION: bump to 0.4.5
236+ * src/io/source_avcodec.c: add support for libswresample
237+ * aubio: new python command line tool to extract information
238+ * src/onset/onset.c: add spectral whitening and compression, improve default
239+ parameters
240+ * this_version.py: use centralized script to get current version, adding git
241+ sha when building from git repo (thanks to MartinHN)
242+
243+ [Interface]
244+
245+ * src/spectral/awhithening.h: add adaptive whitening
246+ * src/{cvec,mathutils,musicutils}.h: add cvec_logmag, fvec_logmag, and fvec_push
247+ * src/onset/onset.h: add aubio_onset_set_default_parameters to load optimal
248+ parameters of each novelty function, _{set,get}_compression and
249+ _{set,get}_awhitening to turn on/off compression and adaptive whitening
250+ * src/spectral/specdesc.h: add weighted phase
251+
252+ [Library]
253+
254+ * src/onset/onset.c: improve default onset parameters (thanks to @superbock
255+ for access to his evaluation database), see commit dccfad2 for more details
256+ * src/pitch/pitch.c: avoid segfault when using invalid parameters
257+ * src/temporal/biquad.c: fix biquad parameters initialization (thanks to
258+ @jurlhardt)
259+
260+ [Tools]
261+
262+ * examples/aubio{onset,track}.c: add options --miditap-note and
263+ --miditap-velo to set which midi note is triggered at onset/beat (thanks to
264+ @tseaver)
265+ * examples/aubioonset.c: show actual parameters in verbose mode
266+ * examples/utils.c: improve memory usage to emit midi notes
267+
268+ [Python]
269+
270+ * python/ext/py-source.c: add with (PEP 343) and iter (PEP 234) interface
271+ * python/ext/py-sink.c: add with interface (PEP 343)
272+ * python/lib/aubio/cmd.py: new `aubio` command line tool
273+ * python/lib/aubio/cut.py: moved from python/scripts/aubiocut
274+
275+ [Documentation]
276+
277+ * doc/*.rst: reorganize and improve sphinx manual
278+ * doc/*.txt: update manpages, add simple manpage for aubio command line
279+ * doc/full.cfg: derive from doc/web.cfg
280+ * README.md: simplify and add contribute information
281+
282+ [Build system]
283+
284+ * wscript: prefer libswresample over libavsamplerate when available, use
285+ current version in manpages, doxygen, and sphinx, update to newest waf
286+ * setup.py: use entry_points console_scripts to generate scripts, use
287+ centralized version from this_version.py, clean up
288+ * python/lib/moresetuptools.py: detect if libswresample is available
289+
290+2017-01-08 Paul Brossier <piem@aubio.org>
291+
292+ [ Overview ]
293+
294+ * VERSION: bump to 0.4.4
295+ * src/utils/log.h: new function to redirect log, error, and warnings
296+ * python/: AUBIO_ERR raises python exception, AUBIO_WRN to emit py warning
297+ * doc/: add some documentation, fix errors in manpages
298+ * wscript: new rules to build 'manpages', 'doxygen', and 'sphinx', new
299+ --build-type=<release|debug> option (thanks to Eduard Mueller)
300+ * src/notes/notes.h: add minioi and silence methods
301+ * examples/: add --minioi (minimum inter-onset interval) option
302+ * src/pitch/pitchyin.c: improve msvc compiler optimisations (thanks to
303+ Eduard Mueller)
304+ * python/, src/: improve error messages, fix minor memory leaks
305+ * src/io/source_avcodec.c: improve compatibility with latest ffmpeg and with
306+ older libav/ffmpeg versions
307+ * python/demos/: new demos to capture microphone in real time
308+
309+ [ Interface]
310+
311+ * src/aubio.h: include utils/log.h
312+ * src/utils/log.h: add new aubio_log_set_function to redirect log messages
313+ * src/notes/notes.h: add aubio_notes_{get,set}_minioi_ms, add
314+ _{get,set}_silence methods
315+
316+ [ Library ]
317+
318+ * src/aubio_priv.h: add AUBIO_INF to print to stdout with header, use new
319+ logging function, add ATAN alias, add stdarg.h, move #include "config.h"
320+ * src/{fmat,fvec}.c: avoid integer division
321+ * src/pitch/pitchyin.c: [msvc] help compiler to optimize aubio_pitchyin_do
322+ by giving it addresses for all arrays which are referenced in inner loops,
323+ thanks to Eduard Mueller.
324+ * src/pitch/pitch.c: declare internal functions as static, fail on wrong
325+ method, warn on wrong unit, improve error messages, fix error string
326+ * src/spectral/specdesc.c: return NULL if wrong mode asked, remove trailing
327+ spaces
328+ * src/onset/onset.c: return null and clean-up if new_aubio_specdesc failed,
329+ fix error message
330+ * src/notes/notes.c: use midi note to store pitch candidate, round to
331+ nearest note, add a variable to define precision, fix out-of-bound write,
332+ fix unset silence_threshold, fix error message
333+ * src/spectral/ooura_fft8g.c: add cast to avoid conversion warnings, prefix
334+ public function with aubio_ooura_ to avoid with other apps using ooura (e.g.
335+ puredata), make internal functions static,
336+ * src/spectral/fft.c: add message about fftw3 being able to do non-power of
337+ two sizes, make calls to fftw_destroy_plan thread-safe, use prefixed
338+ aubio_ooura_rdft
339+ * src/spectral/phasevoc.c: fix error string
340+ * src/temporal/resampler.c: throw an error when using libsamplerate with doubles
341+ * src/io/ioutils.h: add functions to check samplerate and channels, use in sink_*.c
342+ * src/io/source.c: add error message when aubio was compiled with no source,
343+ only show error message from last child source_
344+ * src/io/source_avcodec.c: call avformat_free_context after
345+ avformat_close_input, keep a reference to packet to remove it when closing
346+ file, avoid deprecation warnings with ffmpeg 3.2, add backward compatibility
347+ for libavcodec55, fix for old libavcodec54, use AV_SAMPLE_FMT_DBL when
348+ compiling with HAVE_AUBIO_DOUBLE, fix missing samples in eof block, avoid
349+ function calls before declarations, improve error messages, replace with new
350+ context before closing old one, make sure s->path is set to null
351+ * src/io/{source_wavread,sink_wavwrite}.c: declare internal functions as static
352+ * src/io/source_wavread.c: fix bytes_read for JUNK headers, improve error
353+ messages, initialize buffer, skip chunks until data is found, or abort, skip
354+ junk chunk
355+ * src/io/source_sndfile.c: add support for multi-channel resampling, set
356+ handle to null after sucessful close, add missing floor in ratio comparison,
357+ improve formatting
358+ * src/io/sink.c: only show error message from last child sink_
359+ * src/io/sink_apple_audio.c: avoid crash on empty file name
360+ * src/io/sink_sndfile.c: improve error message
361+ * src/io/sink_{sndfile,wavwrite}.c: use AUBIO_MAX_CHANNELS, fix error message
362+
363+ [ Documentation ]
364+
365+ * README.md: update copyright dates, use https
366+ * src/aubio.h: add some links to examples, use https
367+ * src/pitch/pitch.h: add aubio_pitch_get_tolerance, add basic description of
368+ unit modes
369+ * src/notes/notes.h: add doxygen header
370+ * src/spectral/fft.h: strip example path
371+ * doc/*.rst: improve sphinx documentation
372+ * doc/android.rst: add reference to it scripts/build_android
373+ * doc/debian_packages.rst: added page on debian packages
374+ * doc/python_module.rst: add demo_source_simple.py, add note on pip, add
375+ `print(aubio.version)`
376+ * doc/cli.rst: include command line manpages
377+ * doc/cli_features.rst: add matrix of command line features
378+ * doc/requirements.rst: add a note about --notests (closes #77), document
379+ --msvc options, improve description of options
380+ * doc/download.rst: added page on download
381+ * doc/installing.rst: update
382+ * doc/xcode_frameworks.rst: added page on xcode frameworks
383+ * doc/**: use https://aubio.org
384+ * doc/conf.py: use pyramid theme, update copyright, remove hardcoded path
385+ * doc/web.cfg: exclude ioutils from doc
386+ * doc/aubionotes.txt: document -M option (see #18),
387+ * doc/aubioonset.txt: add documentation for -M, --minioi, improve threshold
388+ description (thanks to Peter Parker), fix typo (onset, not pitch)
389+ * doc/aubio*.txt: document -T/--timeformat option
390+
391+ [ Build ]
392+
393+ * Makefile: add a brief intro, avoid offline operations, add html and dist
394+ targets, add rules for documentation, simplify listing, avoid offline
395+ operations, bump waf to 1.9.6, check for waf before clean, chmod go-w
396+ waflib, improve clean, use pip to install, factorise pip options, generate
397+ more test sounds, improve test_python and test_pure_python, pass build_ext
398+ in test_pure_python{,_wheel}, quieten uninstall_python if already
399+ uninstalled, improve test targets, use bdist_wheel in test_pure_python,
400+ build_ext only for --enable-double, verbose waf rules, add cleanwaf
401+ * wscript: added debug/release build type configurations release (default)
402+ enables optimizations, debug symbols are enabled in both configurations,
403+ thanks to Eduard Mueller.
404+ * wscript: add options to disable source_wavread/sink_wavwrite, add check
405+ for stdarg.h, new rules 'manpages', 'sphinx', and 'doxygen' to build
406+ documentation, add version to sphinx and manpages, disable libsamplerate
407+ if double precision enabled (libsamplerate only supports float), fix typos,
408+ remove trailing spaces, improve tarball creation (./waf dist), remove
409+ full.cfg from tarball, prepend to CFLAGS to honor user cflags
410+ * wscript, src/wscript_build: improve install locations using DATAROOTDIR,
411+ MANDIR, INCLUDEDIR
412+ * wscript: default to no atlas for now
413+ * src/wscript_build: always build static library
414+ * scripts/build_android: add an example script to build aubio on android,
415+
416+ [ Tools ]
417+
418+ * examples/aubionotes.c: use new notes, set minioi, send last note off when
419+ needed, add warning for missing options
420+ * examples/aubioonset.c: add minioi option, in seconds
421+ * examples/: only send a last note off when using jack
422+ * examples/: return 1 if object creation failed
423+ * examples/: use PROG_HAS_OUTPUT, add PROG_HAS_SILENCE
424+
425+ [ Tests ]
426+
427+ * tests/src/spectral/test-fft.c: fix default size
428+ * tests/src/spectral/test-phasevoc.c: fix typos
429+ * tests/src/utils/test-log.c: add AUBIO_INF, add example for
430+ aubio_log_set_function, improve messages
431+
432+ [ Python ]
433+
434+ * python/ext/aubiomodule.c: add aubio._aubio.__version__ and import it as
435+ aubio.version, use custom logging function for errors and warnings, remove
436+ duplicated add_generated_objects, use <> for non local aubio
437+ * python/ext/py-cvec.c: use NPY_INTP_FMT
438+ * python/ext/py-fft.c: use error string set in src/spectral/fft.c
439+ * python/ext/py-phasevoc.c: use error string set in src/spectral/phasevoc.c
440+ * python/ext/py-sink.c: always set samplerate and channels in init
441+ * python/ext/py-source.c: use error string set in src/io/source.c
442+ * python/lib/aubio/midiconv.py: add unicode double sharp and double flat,
443+ improve unicode handling, skip UnicodeEncodeError on python 2.x
444+
445+ [ Python build ]
446+
447+ * MANIFEST.in: add src/**.c, exclude full.cfg, include waflib, remove
448+ python/ext/config.h
449+ * setup.py: define AUBIO_VERSION use sorted glob.glob to improve
450+ reproducibility, remove extra quotes, remove status from version string,
451+ update description, use custom build_ext instead of 'generate' command,
452+ define HAVE_AUBIO_DOUBLE to 1 if needed
453+ * python/lib/gen_code.py: add support for multiple _do outputs, fix number
454+ of output, improve del_ function, safer DECREF, fix indentation, emit RuntimeError
455+ * python/lib/gen_external.py: clean-up, enable tss, remove duplicate,
456+ sort generated files
457+ * python/lib/moresetuptools.py: add HAVE_STDARG_H, also check for
458+ HAVE_AUBIO_DOUBLE, cleaner clean, look first for system library, then for
459+ local build, then local sources, mo nore fake config.h here, use
460+ samplerate in single precision only
461+ * python/README.md: add a note about nose2 for python tests (closes #74)
462+ * scripts/setenv_local.sh: python3 compat
463+
464+ [ Python demos ]
465+
466+ * python/demos/demo_alsa.py: add example using alsaaudio (closes #72)
467+ * python/demos/demo_mfcc.py: add options to plot first and second
468+ derivatives, and set samplerate/win_s/hop_s, thanks to @jhoelzl (closes #68)
469+ * python/demos/demo_notes.py: add simple notes demos
470+ * python/demos/demo_pyaudio.py: added simple demo for pyaudio, see #6,
471+ closes #78, thanks to @jhoelzl and @notalentgeek, add some comments, avoid
472+ overwriting aubio.pitch
473+ * python/demos/demo_source_simple.py: fix indentation, make executable
474+ * python/demos/demo_timestretch{,_online}.py: fix usage string, remove
475+ unused import, use // to yield an integer (closes #71)
476+ * python/demos/demo_timestretch_online.py: use 512, fix block counter
477+ * python/demos/demo_tss.py: improve default parameters, exit before plotting
478+
479+ [ Python tests ]
480+
481+ * python/tests/: use local import, add __init__.py
482+ * python/tests/test_cvec.py: simplify
483+ * python/tests/test_fft.py: skip test fft(zeros).phas == 0 if needed, expected powerpc
484+ * python/tests/test_fvec.py: reduce alpha norm precision to 10.-4
485+ * python/tests/test_{midi2note,note2midi}.py: use nose2.params, add unicode tests
486+ * python/tests/test_notes.py: add basic tests
487+ * python/tests/test_notes.py: test results are correct for 44100Hz_44100f_sine441.wav
488+ * python/tests/test_sink.py: add more tests, quiet warnings
489+ * python/tests/test_source.py: break long line, check the tail of the file
490+ is non-zero on non silent test files, filter user warnings to avoid spamming
491+ the console, only check if last frames are non silent on brownnoise (weak),
492+ remove fragile brownnoise test, check duration on short files, use nose2
493+ params to process one sound file per test
494+ * python/tests/test_specdesc.py: RuntimeError is now raised on wrong mode
495+ * python/tests/utils.py: by default, use 5 seconds brownoise
496+
497+ [ Only in git ]
498+
499+ * .travis.yml: add debian dpkg-buildflags config, switch from precise to
500+ trusty, sudo required, add ffmpeg on osx, add targets ios, iosimulator,
501+ and osx noopt configs, bump to xcode8, add xcode8.2 config, mimick
502+ build_apple_frameworks options, alway upgrade pip, add pip --version and
503+ which pip after upgrading, remove --user, use expandwaf in install, remove
504+ unused ARCH, shuffle order, remove duplicate, add missing opening quote,
505+ use AUBIO_NOTESTS to build only lib on ios, add gitter webhook
506+ * .appveyor.yml: fix path for windows+python 3.5, fix typo in path, make
507+ nose2 tests verbose
508+
1509 2016-08-16 Paul Brossier <piem@aubio.org>
2510
3511 [ Interface ]
MANIFEST.in+8−9
@@ -1,7 +1,10 @@
11 include AUTHORS COPYING README.md VERSION ChangeLog
22 include python/README.md
3−include Makefile wscript */wscript_build
3+include this_version.py
4+include waf_gensyms.py
45 include waf
6+recursive-include waflib *.py
7+include Makefile wscript */wscript_build
58 include aubio.pc.in
69 include nose2.cfg
710 include requirements.txt
@@ -10,16 +13,12 @@ include src/*/*.c src/*/*.h · 2 unmodified lines
1013 include examples/*.c examples/*.h
1114 include tests/*.h tests/*/*.c tests/*/*/*.c
1215 include python/ext/*.h
13−include python/__init__.py
14−include python/lib/__init__.py
15−include python/lib/moresetuptools.py
16−include python/lib/gen_external.py
17−include python/lib/gen_code.py
16+recursive-include python *.py
17+include python/README.md
1818 include python/tests/run_all_tests
19−include python/tests/*.py
20−include python/demos/*.py
19+include python/tests/eval_pitch
2120 include python/tests/*.expected
2221 include doc/*.txt doc/*.rst doc/*.cfg doc/Makefile doc/make.bat doc/conf.py
22+exclude doc/full.cfg
2323 include scripts/* scripts/apple/Info.plist scripts/apple/Modules/module.modulemap
2424 exclude python/gen/*
25−exclude python/ext/config.h
Makefile+253−56
@@ -1,87 +1,179 @@
1+#!/usr/bin/make -f
2+# -*- makefile -*-
3+#
4+# This makefile contains simple rules to prepare, compile, test, and install
5+# aubio. Try one of the following rules:
6+#
7+# $ make configure
8+# $ make build
9+# $ make install
10+# $ make test_python
11+
112 WAFCMD=python waf
2−WAFURL=https://waf.io/waf-1.8.22
13+
14+#WAFOPTS:=
15+# turn on verbose mode
16+WAFOPTS += --verbose
17+# build wafopts
18+WAFOPTS += --destdir $(DESTDIR)
19+# multiple jobs
20+WAFOPTS += --jobs 4
21+# if HAVE_AUBIO_DOUBLE is defined, pass --enable-double to waf
22+# python/lib/moresetuptools.py also checks for HAVE_AUBIO_DOUBLE
23+WAFOPTS += $(shell [ -z $(HAVE_AUBIO_DOUBLE) ] || echo --enable-double )
24+
25+PIPOPTS += --verbose
26+
27+DESTDIR:=$(PWD)/build/dist
28+PYDESTDIR:=$(PWD)/build/pydist
29+
30+# default install locations
31+PREFIX?=/usr/local
32+EXEC_PREFIX?=$(PREFIX)
33+LIBDIR?=$(PREFIX)/lib
34+INCLUDEDIR?=$(PREFIX)/include
35+DATAROOTDIR?=$(PREFIX)/share
36+MANDIR?=$(DATAROOTDIR)/man
37+
38+# default nose2 command
39+NOSE2?=nose2 -N 4 --verbose
340
441 SOX=sox
542
6−ENABLE_DOUBLE := $(shell [ -z $(HAVE_DOUBLE) ] || echo --enable-double )
743 TESTSOUNDS := python/tests/sounds
844
45+LCOVOPTS += --rc lcov_branch_coverage=1
46+
947 all: build
1048
1149 checkwaf:
1250 @[ -f waf ] || make getwaf
1351
1452 getwaf:
15− @./scripts/get_waf.sh
53+ ./scripts/get_waf.sh
54+
55+expandwaf: getwaf
56+ [ -d wafilb ] || rm -fr waflib
57+ $(WAFCMD) --help > /dev/null
58+ mv .waf*/waflib . && rm -fr .waf*
59+ sed '/^#==>$$/,$$d' waf > waf2 && mv waf2 waf
60+ chmod +x waf && chmod -R go-w waflib
1661
17−expandwaf:
18− @[ -d wafilb ] || rm -fr waflib
19− @$(WAFCMD) --help > /dev/null
20− @mv .waf*/waflib . && rm -fr .waf*
21− @sed '/^#==>$$/,$$d' waf > waf2 && mv waf2 waf
22− @chmod +x waf
62+cleanwaf:
63+ rm -rf waf waflib .waf*
2364
2465 configure: checkwaf
25− $(WAFCMD) configure $(WAFOPTS) $(ENABLE_DOUBLE)
66+ $(WAFCMD) configure $(WAFOPTS)
2667
2768 build: configure
2869 $(WAFCMD) build $(WAFOPTS)
2970
71+install:
72+ # install
73+ $(WAFCMD) install $(WAFOPTS)
74+
75+list_installed:
76+ find $(DESTDIR) -ls | sed 's|$(DESTDIR)|/«destdir»|'
77+
78+list_installed_python:
79+ pip show -f aubio
80+
81+list_all_installed: list_installed list_installed_python
82+
83+uninstall:
84+ # uninstall
85+ $(WAFCMD) uninstall $(WAFOPTS)
86+
87+delete_install:
88+ rm -rf $(PWD)/dist/test
89+
3090 build_python:
31− python ./setup.py generate $(ENABLE_DOUBLE) build
91+ # build python-aubio, using locally built libaubio if found
92+ python ./setup.py build
93+
94+build_python_extlib:
95+ # build python-aubio using (locally) installed libaubio
96+ [ -f $(DESTDIR)/$(INCLUDEDIR)/aubio/aubio.h ]
97+ [ -d $(DESTDIR)/$(LIBDIR) ]
98+ [ -f $(DESTDIR)/$(LIBDIR)/pkgconfig/aubio.pc ]
99+ PKG_CONFIG_PATH=$(DESTDIR)/$(LIBDIR)/pkgconfig \
100+ CFLAGS="-I$(DESTDIR)/$(INCLUDEDIR)" \
101+ LDFLAGS="-L$(DESTDIR)/$(LIBDIR)" \
102+ make build_python
103+
104+deps_python:
105+ # install or upgrade python requirements
106+ pip install $(PIPOPTS) --requirement requirements.txt
107+
108+# use pip or distutils?
109+install_python: install_python_with_pip
110+uninstall_python: uninstall_python_with_pip
111+#install_python: install_python_with_distutils
112+#uninstall_python: uninstall_python_with_distutils
32113
33−test_python: export LD_LIBRARY_PATH=$(PWD)/build/src
34−test_python:
35− pip install -v -r requirements.txt
36− pip install -v .
37− nose2 --verbose
38− pip uninstall -y -v aubio
114+install_python_with_pip:
115+ # install package
116+ pip install $(PIPOPTS) .
39117
40−test_python_osx:
118+uninstall_python_with_pip:
119+ # uninstall package
120+ ( pip show aubio | grep -l aubio > /dev/null ) && \
121+ pip uninstall -y -v aubio || echo "info: aubio package is not installed"
122+
123+install_python_with_distutils:
124+ ./setup.py install $(PIPOPTS) $(DISTUTILSOPTS)
125+
126+uninstall_python_with_distutils:
127+ #./setup.py uninstall
128+ [ -d $(PYDESTDIR)/$(LIBDIR) ] && echo Warning: did not clean $(PYDESTDIR)/$(LIBDIR) || true
129+
130+force_uninstall_python:
131+ # ignore failure if not installed
132+ -make uninstall_python
133+
134+local_dylib:
135+ # DYLD_LIBRARY_PATH is no more on mac os
41136 # create links from ~/lib/lib* to build/src/lib*
42− [ -f build/src/libaubio.[0-9].dylib ] && ( mkdir -p ~/lib && cp -prv build/src/libaubio.[0-9].dylib ~/lib ) || true
43− # then run the tests
44− pip install --user -v -r requirements.txt
45− pip install --user -v .
46− nose2 --verbose
47− pip uninstall -y -v aubio
137+ [ -f $(PWD)/build/src/libaubio.[0-9].dylib ] && ( mkdir -p ~/lib && cp -prv build/src/libaubio.[0-9].dylib ~/lib ) || true
138+
139+test_python: export LD_LIBRARY_PATH=$(DESTDIR)/$(LIBDIR)
140+test_python: export PYTHONPATH=$(PYDESTDIR)/$(LIBDIR)
141+test_python: local_dylib
142+ # run test with installed package
143+ # ./python/tests/run_all_tests --verbose
144+ # run with nose2, multiple processes
145+ $(NOSE2)
48146
49147 clean_python:
50148 ./setup.py clean
51149
52−test_pure_python:
53− -pip uninstall -v -y aubio
54− -rm -rf build/ python/gen/
55− -rm -f dist/*.egg
56− -pip install -v -r requirements.txt
57− CFLAGS=-Os python setup.py bdist_egg
58− [ "$(TRAVIS_OS_NAME)" == "osx" ] && easy_install --user dist/*.egg || \
59− easy_install dist/*.egg
60− nose2 -N 4
61− pip uninstall -v -y aubio
62−
63−test_pure_python_wheel:
64− -pip uninstall -v -y aubio
65− -rm -rf build/ python/gen/
66− -rm -f dist/*.whl
67− -pip install -v -r requirements.txt
68− -pip install -v wheel
69− CFLAGS=-Os python setup.py bdist_wheel --universal
70− wheel install dist/*.whl
71− nose2 -N 4
72− pip uninstall -v -y aubio
73−
74−build_python3:
75− python3 ./setup.py generate $(ENABLE_DOUBLE) build
76−
77−clean_python3:
78− python3 ./setup.py clean
79−
80−clean:
150+check_clean_python:
151+ # check cleaning a second time works
152+ make clean_python
153+ make clean_python
154+
155+clean: checkwaf
156+ # optionnaly clean before build
157+ -$(WAFCMD) clean
158+ # remove possible left overs
159+ -rm -rf doc/_build
160+
161+check_clean:
162+ # check cleaning after build works
163+ $(WAFCMD) clean
164+ # check cleaning a second time works
81165 $(WAFCMD) clean
82166
167+distclean:
168+ $(WAFCMD) distclean
169+ -rm -rf doc/_build/
170+ -rm -rf doc/web/
171+
172+check_distclean:
173+ make distclean
174+
83175 distcheck: checkwaf
84− $(WAFCMD) distcheck $(WAFOPTS) $(ENABLE_DOUBLE)
176+ $(WAFCMD) distcheck $(WAFOPTS)
85177
86178 help:
87179 $(WAFCMD) --help
@@ -89,8 +181,113 @@ help: · 1 unmodified line
89181 create_test_sounds:
90182 -[ -z `which $(SOX)` ] && ( echo $(SOX) could not be found) || true
91183 -mkdir -p $(TESTSOUNDS)
92− -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_1f_silence.wav" synth 1s silence 0
184+ -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_1f_silence.wav" trim 0 1s
93185 -$(SOX) -r 22050 -b 16 -n "$(TESTSOUNDS)/22050Hz_5s_brownnoise.wav" synth 5 brownnoise vol 0.9
94186 -$(SOX) -r 32000 -b 16 -n "$(TESTSOUNDS)/32000Hz_127f_sine440.wav" synth 127s sine 440 vol 0.9
95− -$(SOX) -r 8000 -b 16 -n "$(TESTSOUNDS)/8000Hz_30s_silence.wav" synth 30 silence 0 vol 0.9
187+ -$(SOX) -r 8000 -b 16 -n "$(TESTSOUNDS)/8000Hz_30s_silence.wav" trim 0 30
96188 -$(SOX) -r 48000 -b 32 -n "$(TESTSOUNDS)/48000Hz_60s_sweep.wav" synth 60 sine 100-20000 vol 0.9
189+ -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_44100f_sine441.wav" synth 44100s sine 441 vol 0.9
190+ -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_100f_sine441.wav" synth 100s sine 441 vol 0.9
191+
192+# build only libaubio, no python-aubio
193+test_lib_only: clean distclean configure build install list_installed
194+# additionally, clean after a fresh build
195+test_lib_only_clean: test_lib_only uninstall check_clean check_distclean
196+
197+# build libaubio, build and test python-aubio against it
198+test_lib_python: force_uninstall_python deps_python \
199+ clean_python clean distclean \
200+ configure build build_python \
201+ install install_python \
202+ test_python \
203+ list_all_installed
204+
205+test_lib_python_clean: test_lib_python \
206+ uninstall_python uninstall \
207+ check_clean_python \
208+ check_clean \
209+ check_distclean
210+
211+# build libaubio, install it, build python-aubio against it
212+test_lib_install_python: force_uninstall_python deps_python \
213+ clean_python distclean \
214+ configure build \
215+ install \
216+ build_python_extlib \
217+ install_python \
218+ test_python \
219+ list_all_installed
220+
221+test_lib_install_python_clean: test_lib_install_python \
222+ uninstall_python \
223+ delete_install \
224+ check_clean_python \
225+ check_distclean
226+
227+# build a python-aubio that includes libaubio
228+test_python_only: force_uninstall_python deps_python \
229+ clean_python clean distclean \
230+ build_python \
231+ install_python \
232+ test_python \
233+ list_installed_python
234+
235+test_python_only_clean: test_python_only \
236+ uninstall_python \
237+ check_clean_python
238+
239+coverage_cycle: coverage_zero_counters coverage_report
240+
241+coverage_zero_counters:
242+ lcov --zerocounters --directory .
243+
244+coverage: export CFLAGS=--coverage
245+coverage: export LDFLAGS=--coverage
246+coverage: export PYTHONPATH=$(PWD)/python/lib
247+coverage: export LD_LIBRARY_PATH=$(PWD)/build/src
248+coverage: force_uninstall_python deps_python \
249+ clean_python clean distclean build local_dylib
250+ # capture coverage after running c tests
251+ lcov $(LCOVOPTS) --capture --no-external --directory . \
252+ --output-file build/coverage_lib.info
253+ # build and test python
254+ pip install -v -e .
255+ # run tests, with python coverage
256+ coverage run `which nose2`
257+ # capture coverage again
258+ lcov $(LCOVOPTS) --capture --no-external --directory . \
259+ --output-file build/coverage_python.info
260+ # merge both coverage info files
261+ lcov $(LCOVOPTS) -a build/coverage_python.info -a build/coverage_lib.info \
262+ --output-file build/coverage.info
263+ # remove tests
264+ lcov $(LCOVOPTS) --remove build/coverage.info '*/ooura_fft8g*' \
265+ --output-file build/coverage_lib.info
266+
267+# make sure we don't build the doc, which builds a temporary python module
268+coverage_report: export WAFOPTS += --disable-docs
269+coverage_report: coverage
270+ # generate report with lcov's genhtml
271+ genhtml build/coverage_lib.info --output-directory build/coverage_c \
272+ --branch-coverage --highlight --legend
273+ # generate python report with coverage python package
274+ coverage report
275+ coverage html -d build/coverage_python
276+ # show links to generated reports
277+ for i in $$(ls build/coverage_*/index.html); do echo file://$(PWD)/$$i; done
278+
279+sphinx: configure
280+ $(WAFCMD) sphinx $(WAFOPTS)
281+
282+doxygen: configure
283+ $(WAFCMD) doxygen $(WAFOPTS)
284+
285+manpages: configure
286+ $(WAFCMD) manpages $(WAFOPTS)
287+
288+html: doxygen sphinx
289+
290+docs: html manpages
291+
292+dist: distclean expandwaf
293+ $(WAFCMD) dist
README.md+49−114
@@ -1,5 +1,13 @@
1−aubio library
2−=============
1+aubio
2+=====
3+
4+[![Travis build status](https://travis-ci.org/aubio/aubio.svg?branch=master)](https://travis-ci.org/aubio/aubio "Travis build status")
5+[![Appveyor build status](https://img.shields.io/appveyor/ci/piem/aubio/master.svg)](https://ci.appveyor.com/project/piem/aubio "Appveyor build status")
6+[![Landscape code health](https://landscape.io/github/aubio/aubio/master/landscape.svg?style=flat)](https://landscape.io/github/aubio/aubio/master "Landscape code health")
7+[![Commits since last release](https://img.shields.io/github/commits-since/aubio/aubio/latest.svg)](https://github.com/aubio/aubio "Commits since last release")
8+
9+[![Documentation](https://readthedocs.org/projects/aubio/badge/?version=latest)](http://aubio.readthedocs.io/en/latest/?badge=latest "Latest documentation")
10+[![DOI](https://zenodo.org/badge/396389.svg)](https://zenodo.org/badge/latestdoi/396389)
311
412 aubio is a library to label music and sounds. It listens to audio signals and
513 attempts to detect events. For instance, when a drum is hit, at which frequency
@@ -20,7 +28,7 @@ aubio provide several algorithms and routines, including: · 14 unmodified lines
2028 - digital filters (low pass, high pass, and more)
2129 - spectral filtering
2230 - transient/steady-state separation
23− - sound file and audio devices read and write access
31+ - sound file read and write access
2432 - various mathematics utilities for music applications
2533
2634 The name aubio comes from _audio_ with a typo: some errors are likely to be
@@ -29,14 +37,19 @@ found in the results. · 2 unmodified lines
2937 Python module
3038 -------------
3139
32−A python module to access the library functions is also provided. Please see
33−the file [`python/README.md`](python/README.md) for more information on how to
34−use it.
40+A python module for aubio is provided. For more information on how to use it,
41+please see the file [`python/README.md`](python/README.md) and the
42+[manual](https://aubio.org/manual/latest/) .
43+
44+Tools
45+-----
3546
36−Examples tools
37−--------------
47+The python module comes with the following command line tools:
48+
49+ - `aubio` extracts informations from sound files
50+ - `aubiocut` slices sound files at onset or beat timestamps
3851
39−A few simple command line tools are included along with the library:
52+Additional command line tools are included along with the library:
4053
4154 - `aubioonset` outputs the time stamp of detected note onsets
4255 - `aubiopitch` attempts to identify a fundamental frequency, or pitch, for
@@ -46,26 +59,11 @@ A few simple command line tools are included along with the library: · 3 unmodified lines
4659 - `aubionotes` emits midi-like notes, with an onset, a pitch, and a duration
4760 - `aubioquiet` extracts quiet and loud regions
4861
49−Additionally, the python module comes with the following script:
50−
51− - `aubiocut` slices sound files at onset or beat timestamps
52−
53−Implementation and Design Basics
54−--------------------------------
55−
56−The library is written in C and is optimised for speed and portability.
57−
58−The C API is designed in the following way:
59−
60− aubio_something_t * new_aubio_something (void * args);
61− audio_something_do (aubio_something_t * t, void * args);
62− smpl_t aubio_something_get_a_parameter (aubio_something_t *t);
63− uint_t aubio_something_set_a_parameter (aubio_something_t *t, smpl_t a_parameter);
64− void del_aubio_something (aubio_something_t * t);
62+Documentation
63+-------------
6564
66−For performance and real-time operation, no memory allocation or freeing take
67−place in the `_do` methods. Instead, memory allocation should always take place
68−in the `new_` methods, whereas free operations are done in the `del_` methods.
65+ - [manual](https://aubio.org/manual/latest/), generated with sphinx
66+ - [developer documentation](https://aubio.org/doc/latest/), generated with Doxygen
6967
7068 The latest version of the documentation can be found at:
7169
@@ -74,105 +72,42 @@ The latest version of the documentation can be found at: · 2 unmodified lines
7472 Build Instructions
7573 ------------------
7674
77−A number of distributions already include aubio. Check your favorite package
78−management system, or have a look at the [download
79−page](https://aubio.org/download).
80−
81−aubio uses [waf](https://waf.io/) to configure, compile, and test the source:
82−
83− ./waf configure
84− ./waf build
85−
86−If waf is not found in the directory, you can download and install it with:
87−
88− make getwaf
89−
90−aubio compiles on Linux, Mac OS X, Cygwin, and iOS.
91−
92−Installation
93−------------
94−
95−To install aubio library and headers on your system, use:
75+aubio compiles on Linux, Mac OS X, Windows, Cygwin, and iOS.
9676
97− sudo ./waf install
77+To compile aubio, you should be able to simply run:
9878
99−To uninstall:
79+ make
10080
101− sudo ./waf uninstall
81+To compile the python module:
10282
103−If you don't have root access to install libaubio on your system, you can use
104−libaubio without installing libaubio either by setting `LD_LIBRARY_PATH`, or by
105−copying it to `~/lib`.
83+ ./setup.py build
10684
107−On Linux, you should be able to set `LD_LIBRARY_PATH` with:
85+See the [manual](https://aubio.org/manual/latest/) for more information about
86+[installing aubio](https://aubio.org/manual/latest/installing.html).
10887
109− $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/src
88+Citation
89+--------
11090
111−On Mac OS X, a copy or a symlink can be made in `~/lib`:
91+Please use the DOI link above to cite this release in your publications. For
92+more information, see also the [about
93+page](https://aubio.org/manual/latest/about.html) in [aubio
94+manual](https://aubio.org/manual/latest/).
11295
113− $ mkdir -p ~/lib
114− $ ln -sf $PWD/build/src/libaubio*.dylib ~/lib/
115−
116−Note on Mac OS X systems older than El Capitan (10.11), the `DYLD_LIBRARY_PATH`
117−variable can be set as follows:
118−
119− $ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$PWD/build/src
120−
121−Credits and Publications
122−------------------------
123−
124−This library gathers music signal processing algorithms designed at the Centre
125−for Digital Music and elsewhere. This software project was developed along the
126−research I did at the Centre for Digital Music, Queen Mary, University of
127−London. Most of this C code was written by myself, starting from published
128−papers and existing code. The header files of each algorithm contains brief
129−descriptions and references to the corresponding papers.
130−
131−Special thanks go Juan Pablo Bello, Chris Duxbury, Samer Abdallah, Alain de
132−Cheveigne for their help and publications. Also many thanks to Miguel Ramirez
133−and Nicolas Wack for their bug fixing.
134−
135−Substantial informations about the algorithms and their evaluation are gathered
136−in:
137−
138− - Paul Brossier, _[Automatic annotation of musical audio for interactive
139− systems](https://aubio.org/phd)_, PhD thesis, Centre for Digital music,
140−Queen Mary University of London, London, UK, 2006.
141−
142−Additional results obtained with this software were discussed in the following
143−papers:
144−
145− - P. M. Brossier and J. P. Bello and M. D. Plumbley, [Real-time temporal
146− segmentation of note objects in music signals](https://aubio.org/articles/brossier04fastnotes.pdf),
147−in _Proceedings of the International Computer Music Conference_, 2004, Miami,
148−Florida, ICMA
149−
150− - P. M. Brossier and J. P. Bello and M. D. Plumbley, [Fast labelling of note
151− objects in music signals] (https://aubio.org/articles/brossier04fastnotes.pdf),
152−in _Proceedings of the International Symposium on Music Information Retrieval_,
153−2004, Barcelona, Spain
154−
155−
156−Contact Info and Mailing List
157−-----------------------------
96+Homepage
97+--------
15898
15999 The home page of this project can be found at: https://aubio.org/
160100
161−Questions, comments, suggestions, and contributions are welcome. Use the
162−mailing list: <aubio-user@aubio.org>.
163−
164−To subscribe to the list, use the mailman form:
165−http://lists.aubio.org/listinfo/aubio-user/
166−
167−Alternatively, feel free to contact directly the author.
168−
169−
170−Copyright and License Information
171−---------------------------------
172−
173−Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
101+License
102+-------
174103
175104 aubio is free software: you can redistribute it and/or modify it under the
176105 terms of the GNU General Public License as published by the Free Software
177106 Foundation, either version 3 of the License, or (at your option) any later
178107 version.
108+
109+Contributing
110+------------
111+
112+Patches are welcome: please fork the latest git repository and create a feature
113+branch. Submitted requests should pass all continuous integration tests.
VERSION+3−3
@@ -1,7 +1,7 @@
11 AUBIO_MAJOR_VERSION=0
22 AUBIO_MINOR_VERSION=4
3−AUBIO_PATCH_VERSION=4
3+AUBIO_PATCH_VERSION=9
44 AUBIO_VERSION_STATUS='~alpha'
55 LIBAUBIO_LT_CUR=5
6−LIBAUBIO_LT_REV=0
7−LIBAUBIO_LT_AGE=4
6+LIBAUBIO_LT_REV=4
7+LIBAUBIO_LT_AGE=8
aubio.pc.in+1−1
@@ -7,4 +7,4 @@ Name: aubio · 6 unmodified lines
77 Description: a library for audio labelling
88 Version: @VERSION@
99 Libs: -L${libdir} -laubio
10−Cflags: -I${includedir}
10+Cflags: -I${includedir}
azure-pipelines.yml+38−0
@@ -0,0 +1,38 @@
1+# configuration file for azure continuous integration
2+jobs:
3+
4+- job: linux
5+ pool:
6+ vmImage: 'Ubuntu 16.04'
7+ steps:
8+ - script: |
9+ make
10+ displayName: 'make'
11+ env:
12+ CFLAGS: -Werror
13+
14+- job: windows
15+ pool:
16+ vmIMage: 'VS2017-Win2016'
17+ steps:
18+ - script: |
19+ make
20+ displayName: 'make'
21+ env:
22+ # fail on error
23+ CFLAGS: /WX
24+
25+- job: macos
26+ pool:
27+ vmIMage: macOS-10.13
28+ steps:
29+ - script: |
30+ brew update
31+ brew install pkg-config gnupg
32+ brew install sox ffmpeg libsndfile lcov
33+ displayName: 'brew install'
34+ - script: |
35+ make
36+ displayName: 'make'
37+ env:
38+ CFLAGS: -Werror
doc/Makefile+2−0
@@ -39,9 +39,11 @@ help: · 38 unmodified lines
3939 @echo " doctest to run all doctests embedded in the documentation (if enabled)"
4040
4141 clean:
42+ -rm -rf _static
4243 -rm -rf $(BUILDDIR)/*
4344
4445 html:
46+ mkdir -p _static
4547 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
4648 @echo
4749 @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
doc/about.rst+73−0
@@ -0,0 +1,73 @@
1+About
2+=====
3+
4+This library gathers a collection of music signal processing algorithms written
5+by several people. The documentation of each algorithms contains a brief
6+description and references to the corresponding papers.
7+
8+Credits
9+-------
10+
11+Many thanks to everyone who contributed to aubio, including:
12+
13+ - Martin Hermant (`MartinHN <https://github.com/MartinHN>`_)
14+ - Eduard Müller (`emuell <https://github.com/emuell>`_)
15+ - Nils Philippsen (`nphilipp <https://github.com/nphilipp>`_)
16+ - Tres Seaver (`tseaver <https://github.com/tseaver>`_)
17+ - Dirkjan Rijnders (`dirkjankrijnders <https://github.com/dirkjankrijnders>`_)
18+ - Jeffrey Kern (`anwserman <https:/ /github.com/anwserman>`_)
19+ - Sam Alexander (`sxalexander <https://github.com/sxalexander>`_)
20+
21+Special thanks to Juan Pablo Bello, Chris Duxbury, Samer Abdallah, Alain de
22+Cheveigne for their help. Also many thanks to Miguel Ramirez and Nicolas Wack
23+for their advices and help fixing bugs.
24+
25+Publications
26+------------
27+
28+Substantial informations about several of the algorithms and their evaluation
29+are gathered in:
30+
31+ - Paul Brossier, `Automatic annotation of musical audio for interactive
32+ systems <https://aubio.org/phd>`_, PhD thesis, Centre for Digital music,
33+ Queen Mary University of London, London, UK, 2006.
34+
35+Additional results obtained with this software were discussed in the following
36+papers:
37+
38+ - P. M. Brossier and J. P. Bello and M. D. Plumbley, `Real-time temporal
39+ segmentation of note objects in music signals
40+ <https://aubio.org/articles/brossier04fastnotes.pdf>`_ in *Proceedings of
41+ the International Computer Music Conference*, 2004, Miami, Florida, ICMA
42+
43+ - P. M. Brossier and J. P. Bello and M. D. Plumbley, `Fast labelling of note
44+ objects in music signals
45+ <https://aubio.org/articles/brossier04fastnotes.pdf>`, in *Proceedings of
46+ the International Symposium on Music Information Retrieval*, 2004,
47+ Barcelona, Spain
48+
49+Citation
50+--------
51+
52+Please refer to the Zenodo link in the file README.md to cite this release.
53+
54+Copyright
55+---------
56+
57+Copyright © 2003-2017 Paul Brossier <piem@aubio.org>
58+
59+License
60+-------
61+
62+aubio is a `free <https://www.debian.org/intro/free>`_ and `open source
63+<http://www.opensource.org/docs/definition.php>`_ software; **you** can
64+redistribute it and/or modify it under the terms of the `GNU
65+<https://www.gnu.org/>`_ `General Public License
66+<https://www.gnu.org/licenses/gpl.html>`_ as published by the `Free Software
67+Foundation <https://fsf.org>`_, either version 3 of the License, or (at your
68+option) any later version.
69+
70+.. note::
71+
72+ aubio is not MIT or BSD licensed. Contact us if you need it in your
73+ commercial product.
doc/android.rst+9−0
@@ -0,0 +1,9 @@
1+.. _android:
2+
3+Android build
4+-------------
5+
6+To compile aubio for android, you will need to get the `Android Native
7+Development Toolkit (NDK) <https://developer.android.com/ndk/>`_, prepare a
8+standalone toolchain, and tell waf to use the NDK toolchain. An example script
9+to complete these tasks is available in ``scripts/build_android``.
doc/aubio.txt+141−0
@@ -0,0 +1,141 @@
1+NAME
2+ aubio - a command line tool to extract information from sound files
3+
4+SYNOPSIS
5+
6+ aubio [-h] [-V] <command> ...
7+
8+COMMANDS
9+
10+ The general syntax is "aubio <command> <soundfile> [options]". The following
11+ commands are available:
12+
13+ onset get onset times
14+ pitch extract fundamental frequency
15+ beat get locations of beats
16+ tempo get overall tempo in bpm
17+ notes get midi-like notes
18+ mfcc extract mel-frequency cepstrum coefficients
19+ melbands extract mel-frequency energies per band
20+
21+ For a list of available commands, use "aubio -h". For more info about each
22+ command, use "aubio <command> --help".
23+
24+GENERAL OPTIONS
25+
26+ These options can be used before any command has been specified.
27+
28+ -h, --help show help message and exit
29+
30+ -V, --version show version
31+
32+COMMON OPTIONS
33+
34+ The following options can be used with all commands:
35+
36+ <source_uri>, -i <source_uri>, --input <source_uri> input sound file to
37+ analyse (required)
38+
39+ -r <freq>, --samplerate <freq> samplerate at which the file should be
40+ represented (default: 0, e.g. samplerate of the input sound)
41+
42+ -H <size>, --hopsize <size> overlap size, number of samples between two
43+ consecutive analysis (default: 256)
44+
45+ -B <size>, --bufsize <size> buffer size, number of samples used for each
46+ analysis, (e.g. FFT length, default: 512)
47+
48+ -h, --help show help message and exit
49+
50+ -T format, --time-format format select time values output format (samples,
51+ ms, seconds) (default: seconds)
52+
53+ -v, --verbose be verbose (increment verbosity by 1, default: 1)
54+
55+ -q, --quiet be quiet (set verbosity to 0)
56+
57+ONSET
58+
59+ The following additional options can be used with the "onset" subcommand.
60+
61+ -m <method>, --method <method> onset novelty function
62+ <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux> (default:
63+ default)
64+
65+ -t <threshold>, --threshold <threshold> threshold (default: unset)
66+
67+ -s <value>, --silence <value> silence threshold, in dB (default: -70)
68+
69+ -M <value>, --minioi <value> minimum Inter-Onset Interval (default: 12ms)
70+
71+PITCH
72+
73+ The following additional options can be used with the "pitch" subcommand.
74+
75+ -m <method>, --method <method> pitch detection method
76+ <default|yinfft|yin|mcomb|fcomb|schmitt> (default: default, e.g. yinfft)
77+
78+ -t <threshold>, --threshold <threshold> tolerance (default: unset)
79+
80+ -s <value>, --silence <value> silence threshold, in dB (default: -70)
81+
82+ The default buffer size for the beat algorithm is 2048. The default hop size
83+ is 256.
84+
85+BEAT
86+
87+ The "beat" command accepts all common options and no additional options.
88+
89+ The default buffer size for the beat algorithm is 1024. The default hop size
90+ is 512.
91+
92+TEMPO
93+
94+ The "tempo" command accepts all common options and no additional options.
95+
96+ The default buffer size for the beat algorithm is 1024. The default hop size
97+ is 512.
98+
99+NOTES
100+
101+ The following additional options can be used with the "notes" subcommand.
102+
103+ -s <value>, --silence <value> silence threshold, in dB (default: -70)
104+
105+ -d <value>, --release-drop <value> release drop level, in dB. If the level
106+ drops more than this amount since the last note started, the note will be
107+ turned off (default: 10).
108+
109+MFCC
110+
111+ The "mfcc" command accepts all common options and no additional options.
112+
113+MELBANDS
114+
115+ The "melbands" command accepts all common options and no additional options.
116+
117+EXAMPLES
118+
119+ Extract onsets using a minimum inter-onset interval of 30ms:
120+
121+ aubio onset /path/to/input_file -M 30ms
122+
123+ Extract pitch with method "mcomb" and a silence threshold of -90dB:
124+
125+ aubio pitch /path/to/input_file -m mcomb -s -90.0
126+
127+ Extract MFCC using the standard Slaney implementation:
128+
129+ aubio mfcc /path/to/input_file -r 44100
130+
131+
132+SEE ALSO
133+
134+ aubiocut(1)
135+
136+AUTHOR
137+
138+ This manual page was written by Paul Brossier <piem@aubio.org>. Permission is
139+ granted to copy, distribute and/or modify this document under the terms of
140+ the GNU General Public License as published by the Free Software Foundation,
141+ either version 3 of the License, or (at your option) any later version.
doc/aubiocut.txt+5−3
@@ -34,9 +34,9 @@ OPTIONS · 33 unmodified lines
3434 -b, --beat Use beat locations instead of onset locations.
3535
3636 -t, --onset-threshold thres Set the threshold value for the onset peak
37− picking. Typical values are typically within 0.001 and 0.900. Defaults to
38− 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
39− over-detections. Defaults to 0.3.
37+ picking. Values are typically in the range [0.001, 0.900]. Lower threshold
38+ values imply more onsets detected. Increasing this threshold should reduce
39+ the number of incorrect detections. Defaults to 0.3.
4040
4141 -c, --cut Cut input sound file at detected labels. A new sound files for
4242 each slice will be created in the current directory.
@@ -50,6 +50,8 @@ OPTIONS · 7 unmodified lines
5050 --cut-until-nslices n How many extra slices should be added at the end of
5151 each slice (default 0).
5252
53+ --create-first Alway create first slice.
54+
5355 -h, --help Print a short help message and exit.
5456
5557 -v, --verbose Be verbose.
doc/aubiomfcc.txt+2−2
@@ -15,7 +15,7 @@ DESCRIPTION · 14 unmodified lines
1515
1616 MFCCs are coefficients that make up for the mel-frequency spectrum, a
1717 representation of the short-term power spectrum of a sound. By default, 13
18− coefficents are computed using 40 filters.
18+ coefficients are computed using 40 filters.
1919
2020 When started with an input source (-i/--input), the coefficients are given on
2121 the console, prefixed by their timestamps in seconds.
@@ -51,7 +51,7 @@ REFERENCES · 29 unmodified lines
5151 according to Malcolm Slaney's Auditory Toolbox, available at the following
5252 url:
5353
54− http://cobweb.ecn.purdue.edu/~malcolm/interval/1998-010/ (see file mfcc.m)
54+ https://engineering.purdue.edu/~malcolm/interval/1998-010/ (see file mfcc.m)
5555
5656 SEE ALSO
5757
doc/aubionotes.txt+10−2
@@ -6,7 +6,7 @@ SYNOPSIS · 5 unmodified lines
66 aubionotes source
77 aubionotes [[-i] source]
88 [-r rate] [-B win] [-H hop]
9− [-O method] [-t thres]
9+ [-O method] [-t thres] [-d drop]
1010 [-p method] [-u unit] [-l thres]
1111 [-T time-format]
1212 [-s sil]
@@ -50,6 +50,9 @@ OPTIONS · 37 unmodified lines
5050 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
5151 over-detections. Defaults to 0.3.
5252
53+ -M, --minioi value Set the minimum inter-onset interval, in seconds, the
54+ shortest interval between two consecutive notes. Defaults to 0.030
55+
5356 -p, --pitch method The pitch detection method to use. See PITCH METHODS
5457 below. Defaults to 'default'.
5558
@@ -65,6 +68,10 @@ OPTIONS · 9 unmodified lines
6568 will not be detected. A value of -20.0 would eliminate most onsets but the
6669 loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
6770
71+ -d, --release-drop Set the release drop threshold, in dB. If the level drops
72+ more than this amount since the last note started, the note will be turned
73+ off. Defaults to 10.
74+
6875 -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
6976 seconds.
7077
@@ -84,7 +91,8 @@ ONSET METHODS · 13 unmodified lines
8491
8592 PITCH METHODS
8693
87− Available methods: default, schmitt, fcomb, mcomb, specacf, yin, yinfft.
94+ Available methods: default, schmitt, fcomb, mcomb, specacf, yin, yinfft,
95+ yinfast.
8896
8997 See aubiopitch(1) for details about these methods.
9098
doc/aubioonset.txt+13−5
@@ -9,7 +9,8 @@ SYNOPSIS · 8 unmodified lines
99 [-O method] [-t thres]
1010 [-T time-format]
1111 [-s sil] [-m] [-f]
12− [-j] [-v] [-h]
12+ [-j] [-N miditap-note] [-V miditap-velo]
13+ [-v] [-h]
1314
1415 DESCRIPTION
1516
@@ -48,11 +49,14 @@ OPTIONS · 32 unmodified lines
4849 below. Defaults to 'default'.
4950
5051 -t, --onset-threshold thres Set the threshold value for the onset peak
51− picking. Typical values are typically within 0.001 and 0.900. Defaults to
52− 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
53− over-detections. Defaults to 0.3.
52+ picking. Values are typically in the range [0.001, 0.900]. Lower threshold
53+ values imply more onsets detected. Increasing this threshold should reduce
54+ the number of incorrect detections. Defaults to 0.3.
5455
55− -s, --silence sil Set the silence threshold, in dB, under which the pitch
56+ -M, --minioi value Set the minimum inter-onset interval, in seconds, the
57+ shortest interval between two consecutive onsets. Defaults to 0.020
58+
59+ -s, --silence sil Set the silence threshold, in dB, under which the onset
5660 will not be detected. A value of -20.0 would eliminate most onsets but the
5761 loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
5862
@@ -67,6 +71,10 @@ OPTIONS · 8 unmodified lines
6771 -j, --jack Use Jack input/output. You will need a Jack connection
6872 controller to feed aubio some signal and listen to its output.
6973
74+ -N, --miditap-note Override note value for MIDI tap. Defaults to 69.
75+
76+ -V, --miditap-velop Override velocity value for MIDI tap. Defaults to 65.
77+
7078 -h, --help Print a short help message and exit.
7179
7280 -v, --verbose Be verbose.
doc/aubiopitch.txt+6−0
@@ -120,6 +120,12 @@ PITCH METHODS · 119 unmodified lines
120120 Chapter 3, Pitch Analysis, PhD thesis, Centre for Digital music, Queen Mary
121121 University of London, London, UK, 2006.
122122
123+ yinfast YIN algorithm (accelerated)
124+
125+ An optimised implementation of the YIN algorithm, yielding results identical
126+ to the original YIN algorithm, while reducing its computational cost from
127+ O(n^2) to O(n log(n)).
128+
123129 SEE ALSO
124130
125131 aubioonset(1),
doc/aubiotrack.txt+7−2
@@ -8,7 +8,8 @@ SYNOPSIS · 7 unmodified lines
88 [-r rate] [-B win] [-H hop]
99 [-T time-format]
1010 [-s sil] [-m]
11− [-j] [-v] [-h]
11+ [-j] [-N miditap-note] [-V miditap-velo]
12+ [-v] [-h]
1213
1314 DESCRIPTION
1415
@@ -54,6 +55,10 @@ OPTIONS · 39 unmodified lines
5455 -j, --jack Use Jack input/output. You will need a Jack connection
5556 controller to feed aubio some signal and listen to its output.
5657
58+ -N, --miditap-note Override note value for MIDI tap. Defaults to 69.
59+
60+ -V, --miditap-velop Override velocity value for MIDI tap. Defaults to 65.
61+
5762 -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
5863 seconds.
5964
@@ -72,7 +77,7 @@ BEAT TRACKING METHODS · 12 unmodified lines
7277
7378 Matthew E. P. Davies, Paul Brossier, and Mark D. Plumbley. Beat tracking
7479 towards automatic musical accompaniment. In Proceedings of the Audio
75− Engeeniring Society 118th Convention, Barcelona, Spain, May 2005.
80+ Engineering Society 118th Convention, Barcelona, Spain, May 2005.
7681
7782 SEE ALSO
7883
doc/binaries.rst+12−0
@@ -0,0 +1,12 @@
1+Pre-compiled binaries
2+---------------------
3+
4+`Pre-compiled binaries <https://aubio.org/download>`_
5+are available for
6+`macOS <https://aubio.org/download#osx>`_,
7+`iOS <https://aubio.org/download#ios>`_,
8+and
9+`windows <https://aubio.org/download#win>`_
10+
11+To use aubio in a macOS or iOS application, see :ref:`xcode-frameworks-label`.
12+
doc/building.rst+37−6
@@ -20,9 +20,9 @@ Latest release · 19 unmodified lines
2020
2121 The **latest stable release** can be downloaded from https://aubio.org/download::
2222
23− $ curl -O http://aubio.org/pub/aubio-0.4.3.tar.bz2
24− $ tar xf aubio-0.4.3.tar.bz2
25− $ cd aubio-0.4.3
23+ $ curl -O http://aubio.org/pub/aubio-<version>.tar.bz2
24+ $ tar xf aubio-<version>.tar.bz2
25+ $ cd aubio-<version>/
2626
2727 Git repository
2828 --------------
@@ -30,7 +30,7 @@ Git repository · 1 unmodified line
3030 The **latest git branch** can be obtained with::
3131
3232 $ git clone git://git.aubio.org/git/aubio
33− $ cd aubio
33+ $ cd aubio/
3434
3535 The following command will fetch the correct `waf`_ version (not included in
3636 aubio's git)::
@@ -73,6 +73,34 @@ command:: · 36 unmodified lines
7373
7474 $ waf configure build
7575
76+
77+Running as a user
78+-----------------
79+
80+To use aubio without actually installing, for instance if you don't have root
81+access to install libaubio on your system,
82+
83+On Linux or macOS, sourcing the script ``scripts/setenv_local.sh`` should help::
84+
85+ $ source ./scripts/setenv_local.sh
86+
87+This script sets ``LD_LIBRARY_PATH``, for libaubio, and ``PYTHONPATH`` for the
88+python module.
89+
90+On Linux, you should be able to set ``LD_LIBRARY_PATH`` with::
91+
92+ $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/src
93+
94+On Mac OS X, a copy or a symlink can be made in ``~/lib``::
95+
96+ $ mkdir -p ~/lib
97+ $ ln -sf $PWD/build/src/libaubio*.dylib ~/lib/
98+
99+Note on Mac OS X systems older than El Capitan (10.11), the ``DYLD_LIBRARY_PATH``
100+variable can be set as follows::
101+
102+ $ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$PWD/build/src
103+
76104 Cleaning
77105 --------
78106
@@ -94,5 +122,8 @@ invocation, use the ``distclean`` command:: · 15 unmodified lines
94122
95123 .. _Git Bash: https://git-for-windows.github.io/
96124
97−.. toctree::
98− :maxdepth: 2
125+.. _xcode-frameworks-label:
126+
127+.. include:: xcode_frameworks.rst
128+
129+.. include:: android.rst
doc/cli.rst+25−6
@@ -3,7 +3,12 @@ · 2 unmodified lines
33 Command line tools
44 ==================
55
6−A few simple command line tools are included along with the library.
6+The python module comes with the following tools:
7+
8+ - ``aubio`` estimate and extract descriptors from sound files
9+ - ``aubiocut`` slices sound files at onset or beat timestamps
10+
11+More command line tools are included along with the library.
712
813 - ``aubioonset`` outputs the time stamp of detected note onsets
914 - ``aubiopitch`` attempts to identify a fundamental frequency, or pitch, for
@@ -13,42 +18,56 @@ A few simple command line tools are included along with the library. · 3 unmodified lines
1318 - ``aubionotes`` emits midi-like notes, with an onset, a pitch, and a duration
1419 - ``aubioquiet`` extracts quiet and loud regions
1520
16−Additionally, the python module comes with the following script:
1721
18− - ``aubiocut`` slices sound files at onset or beat timestamps
22+``aubio``
23+---------
24+
25+.. literalinclude:: aubio.txt
26+ :language: text
27+
28+
29+``aubiocut``
30+--------------
31+
32+.. literalinclude:: aubiocut.txt
33+ :language: text
1934
2035
2136 ``aubioonset``
2237 --------------
2338
2439 .. literalinclude:: aubioonset.txt
40+ :language: text
2541
2642 ``aubiopitch``
2743 --------------
2844
2945 .. literalinclude:: aubiopitch.txt
46+ :language: text
3047
3148 ``aubiomfcc``
3249 --------------
3350
3451 .. literalinclude:: aubiomfcc.txt
52+ :language: text
3553
3654 ``aubiotrack``
3755 --------------
3856
3957 .. literalinclude:: aubiotrack.txt
58+ :language: text
4059
4160 ``aubionotes``
4261 --------------
4362
4463 .. literalinclude:: aubionotes.txt
64+ :language: text
4565
4666 ``aubioquiet``
4767 --------------
4868
4969 .. literalinclude:: aubioquiet.txt
70+ :language: text
5071
51−``aubiocut``
52−--------------
5372
54−.. literalinclude:: aubiocut.txt
73+.. include:: cli_features.rst
doc/cli_features.rst+42−0
@@ -0,0 +1,42 @@
1+Command line features
2+---------------------
3+
4++--------------+-------+-------+------+-------+-------+-------+------+------------------+
5+| feat vs. prg | onset | pitch | mfcc | track | notes | quiet | cut1 | short options |
6++==============+=======+=======+======+=======+=======+=======+======+==================+
7+| input | Y | Y | Y | Y | Y | Y | Y | -i |
8++--------------+-------+-------+------+-------+-------+-------+------+------------------+
9+| output | Y | Y | N | Y | Y | N | Y!1 | -o,-m,-f |
10++--------------+-------+-------+------+-------+-------+-------+------+------------------+
11+| Hz/buf/hop | Y | Y | Y | Y | Y | Y!2 | Y | -r,-B-,H |
12++--------------+-------+-------+------+-------+-------+-------+------+------------------+
13+| jack | Y | Y | N | Y | Y | N!3 | N | -j |
14++--------------+-------+-------+------+-------+-------+-------+------+------------------+
15+| onset | Y | N | N | Y!8 | Y!6 | N | Y | -O,-t,-M |
16++--------------+-------+-------+------+-------+-------+-------+------+------------------+
17+| pitch | N | Y | N | N | Y!6 | N | N!5 | -p,-u,-l |
18++--------------+-------+-------+------+-------+-------+-------+------+------------------+
19+| silence | Y | Y | N | Y | Y!7 | Y | N!4 | -s |
20++--------------+-------+-------+------+-------+-------+-------+------+------------------+
21+| timefmt | Y | Y | Y | Y | Y | Y | ! | -T |
22++--------------+-------+-------+------+-------+-------+-------+------+------------------+
23+| help | Y | Y | Y | Y | Y | Y | Y | -h |
24++--------------+-------+-------+------+-------+-------+-------+------+------------------+
25+| verbose | Y | Y | Y | Y | Y | Y | Y | -v |
26++--------------+-------+-------+------+-------+-------+-------+------+------------------+
27+
28+1. ``aubiocut --output`` is used to specify a directory, not a file.
29+
30+2. Option ``--bufsize`` is useless for ``aubioquiet``
31+
32+3. ``aubioquiet`` could have a jack output
33+
34+4. Regression, re-add slicing at silences to ``aubiocut``
35+
36+5. ``aubiocut`` could cut on notes
37+
38+6. ``aubionotes`` needs onset/pitch setters.
39+
40+7. Silence was different for pitch and onset, test.
41+
42+8. Some ``aubiotrack`` options should be disabled (minioi, threshold).
doc/conf.py+37−9
@@ -13,10 +13,14 @@ · 12 unmodified lines
1313
1414 import sys, os
1515
16+# get version using this_version.py
17+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
18+from this_version import get_aubio_version
19+
1620 # If extensions (or modules to document with autodoc) are in another directory,
1721 # add these directories to sys.path here. If the directory is relative to the
1822 # documentation root, use os.path.abspath to make it absolute, like shown here.
19−sys.path.insert(0, os.path.abspath('../../python/build/lib.macosx-10.6-intel-2.7'))
23+#sys.path.insert(0, os.path.abspath('../../python/build/...'))
2024
2125 # -- General configuration -----------------------------------------------------
2226
@@ -25,7 +29,14 @@ sys.path.insert(0, os.path.abspath('../../python/build/lib.macosx-10.6-intel-2.7 · 2 unmodified lines
2529
2630 # Add any Sphinx extension module names here, as strings. They can be extensions
2731 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28−extensions = ['sphinx.ext.viewcode', 'sphinx.ext.autodoc']
32+extensions = ['sphinx.ext.viewcode', 'sphinx.ext.autodoc',
33+ 'sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
34+
35+autodoc_member_order = 'groupwise'
36+
37+intersphinx_mapping = {
38+ 'numpy': ('https://docs.scipy.org/doc/numpy/', None),
39+ }
2940
3041 # Add any paths that contain templates here, relative to this directory.
3142 templates_path = ['_templates']
@@ -41,16 +52,17 @@ master_doc = 'index' · 9 unmodified lines
4152
4253 # General information about the project.
4354 project = u'aubio'
44−copyright = u'2016, Paul Brossier'
55+copyright = u'2018, Paul Brossier'
4556
4657 # The version info for the project you're documenting, acts as replacement for
4758 # |version| and |release|, also used in various other places throughout the
4859 # built documents.
4960 #
5061 # The short X.Y version.
51−version = '0.4'
62+
63+version = get_aubio_version()[:3]
5264 # The full version, including alpha/beta/rc tags.
53−release = 'latest'
65+release = get_aubio_version()
5466
5567 # The language for content autogenerated by Sphinx. Refer to documentation
5668 # for a list of supported languages.
@@ -64,7 +76,17 @@ release = 'latest' · 7 unmodified lines
6476
6577 # List of patterns, relative to source directory, that match files and
6678 # directories to ignore when looking for source files.
67−exclude_patterns = ['_build']
79+exclude_patterns = ['_build',
80+ 'statuslinks.rst',
81+ 'download.rst',
82+ 'binaries.rst',
83+ 'debian_packages.rst',
84+ 'building.rst',
85+ 'android.rst',
86+ 'xcode_frameworks.rst',
87+ 'requirements.rst',
88+ 'cli_features.rst',
89+ ]
6890
6991 # The reST default role (used for this markup: `text`) to use for all documents.
7092 #default_role = None
@@ -91,7 +113,10 @@ modindex_common_prefix = ['aubio.'] · 20 unmodified lines
91113
92114 # The theme to use for HTML and HTML Help pages. See the documentation for
93115 # a list of builtin themes.
94−html_theme = 'default'
116+#html_theme = 'agogo'
117+#html_theme = 'default'
118+#html_theme = 'haiku'
119+html_theme = 'pyramid'
95120
96121 # Theme options are theme-specific and customize the look and feel of a theme
97122 # further. For a list of options available for each theme, see the
@@ -120,7 +145,7 @@ html_theme = 'default' · 22 unmodified lines
120145 # Add any paths that contain custom static files (such as style sheets) here,
121146 # relative to this directory. They are copied after the builtin static files,
122147 # so a file named "default.css" will overwrite the builtin "default.css".
123−html_static_path = ['_static']
148+html_static_path = [] #['_static']
124149
125150 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126151 # using the given strftime format.
@@ -150,7 +175,7 @@ html_static_path = ['_static'] · 23 unmodified lines
150175 #html_show_sourcelink = True
151176
152177 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153−#html_show_sphinx = True
178+html_show_sphinx = False
154179
155180 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156181 #html_show_copyright = True
@@ -240,3 +265,6 @@ texinfo_documents = [ · 83 unmodified lines
240265
241266 # How to display URL addresses: 'footnote', 'no', or 'inline'.
242267 #texinfo_show_urls = 'footnote'
268+
269+def setup(app):
270+ if release.endswith('~alpha'): app.tags.add('devel')
doc/debian_packages.rst+1−1
@@ -9,7 +9,7 @@ For the latest version of the packages, see · 8 unmodified lines
99 https://anonscm.debian.org/cgit/collab-maint/aubio.git/. Use
1010 ``git-buildpackage`` to build from the git repository. For instance:
1111
12−.. code-block:: bash
12+.. code-block:: console
1313
1414 $ git clone git://anonscm.debian.org/collab-maint/aubio.git
1515 $ cd aubio
doc/develop.rst+89−35
@@ -1,46 +1,94 @@
1−Developping with aubio
2−======================
1+.. _develop:
32
4−Read `Contribute`_ to report issues and request new features.
3+Developing with aubio
4+=====================
55
6−See `Doxygen documentation`_ for the complete documentation of the C library,
7−built using `Doxygen <http://www.doxygen.org/>`_.
6+Here is a brief overview of the C library.
87
9−Below is a brief `Library overview`_.
8+For a more detailed list of available functions, see the `API documentation
9+<https://aubio.org/doc/latest/>`_.
1010
11−Library overview
12−----------------
11+To report issues, ask questions, and request new features, use `Github Issues
12+<https://github.com/aubio/aubio/issues>`_
1313
14−Here is a brief overview of the C library. See also the `Doxygen
15−documentation`_ for a more detailed list of available functions.
14+Design Basics
15+-------------
1616
17−Vectors and matrix
18−``````````````````
17+The library is written in C and is optimised for speed and portability.
1918
20−``fvec_t`` are used to hold vectors of float (``smpl_t``).
19+All memory allocations take place in the `new_` methods. Each successful call
20+to `new_` should have a matching call to `del_` to deallocate the object.
2121
22−.. literalinclude:: ../tests/src/test-fvec.c
23− :language: C
24− :lines: 7
22+.. code-block:: C
2523
24+ // new_ to create an object foobar
25+ aubio_foobar_t * new_aubio_foobar(void * args);
26+ // del_ to delete foobar
27+ void del_aubio_foobar (aubio_foobar_t * foobar);
28+
29+The main computations are done in the `_do` methods.
2630
2731 .. code-block:: C
2832
29− // set some elements
30− vec->data[511] = 2.;
31− vec->data[vec->length-2] = 1.;
33+ // _do to process output = foobar(input)
34+ audio_foobar_do (aubio_foobar_t * foobar, fvec_t * input, cvec_t * output);
3235
33−Similarly, ``fmat_t`` are used to hold matrix of floats.
36+Most parameters can be read and written at any time:
37+
38+.. code-block:: C
39+
40+ // _get_param to get foobar.param
41+ smpl_t aubio_foobar_get_a_parameter (aubio_foobar_t * foobar);
42+ // _set_param to set foobar.param
43+ uint_t aubio_foobar_set_a_parameter (aubio_foobar_t * foobar, smpl_t a_parameter);
44+
45+In some case, more functions are available:
46+
47+.. code-block:: C
48+
49+ // non-real time functions
50+ uint_t aubio_foobar_reset(aubio_foobar_t * t);
51+
52+Basic Types
53+-----------
54+
55+.. code-block:: C
56+
57+ // integers
58+ uint_t n = 10; // unsigned
59+ sint_t delay = -90; // signed
60+
61+ // float
62+ smpl_t a = -90.; // simple precision
63+ lsmp_t f = 0.024; // double precision
64+
65+ // vector of floats (simple precision)
66+ fvec_t * vec = new_fvec(n);
67+ vec->data[0] = 1;
68+ vec->data[vec->length-1] = 1.; // vec->data has n elements
69+ fvec_print(vec);
70+ del_fvec(vec);
71+
72+ // complex data
73+ cvec_t * fftgrain = new_cvec(n);
74+ vec->norm[0] = 1.; // vec->norm has n/2+1 elements
75+ vec->phas[n/2] = 3.1415; // vec->phas as well
76+ del_cvec(fftgrain);
77+
78+ // matrix
79+ fmat_t * mat = new_fmat (height, length);
80+ mat->data[height-1][0] = 1; // mat->data has height rows
81+ mat->data[0][length-1] = 10; // mat->data[0] has length columns
82+ del_fmat(mat);
3483
35−.. literalinclude:: ../tests/src/test-fmat.c
36− :language: C
37− :lines: 9-19
3884
3985 Reading a sound file
40−````````````````````
41−In this example, ``aubio_source`` is used to read a media file.
86+--------------------
4287
43−First, create the objects we need.
88+In this example, `aubio_source <https://aubio.org/doc/latest/source_8h.html>`_
89+is used to read a media file.
90+
91+First, define a few variables and allocate some memory.
4492
4593 .. literalinclude:: ../tests/src/io/test-source.c
4694 :language: C
@@ -56,17 +104,17 @@ Now for the processing loop: · 9 unmodified lines
56104 :language: C
57105 :lines: 40-44
58106
59−At the end of the processing loop, clean-up and de-allocate memory:
107+At the end of the processing loop, memory is deallocated:
60108
61109 .. literalinclude:: ../tests/src/io/test-source.c
62110 :language: C
63− :lines: 50-56
111+ :lines: 55-56
64112
65113 See the complete example: :download:`test-source.c
66114 <../tests/src/io/test-source.c>`.
67115
68−Computing the spectrum
69−``````````````````````
116+Computing a spectrum
117+--------------------
70118
71119 Now let's create a phase vocoder:
72120
@@ -74,11 +122,17 @@ Now let's create a phase vocoder: · 1 unmodified line
74122 :language: C
75123 :lines: 6-11
76124
77−The processing loop could know look like:
125+The processing loop could now look like:
126+
127+.. literalinclude:: ../tests/src/spectral/test-phasevoc.c
128+ :language: C
129+ :lines: 20-37
130+
131+Time to clean up the previously allocated memory:
78132
79133 .. literalinclude:: ../tests/src/spectral/test-phasevoc.c
80134 :language: C
81− :lines: 21-35
135+ :lines: 39-44
82136
83137 See the complete example: :download:`test-phasevoc.c
84138 <../tests/src/spectral/test-phasevoc.c>`.
@@ -88,13 +142,13 @@ See the complete example: :download:`test-phasevoc.c · 3 unmodified lines
88142 Doxygen documentation
89143 ---------------------
90144
91−The latest version of the doxygen documentation is available at:
145+The latest version of the API documentation is built using `Doxygen
146+<http://www.doxygen.org/>`_ and is available at:
92147
93− https://aubio.org/doc/latest
148+ https://aubio.org/doc/latest/
94149
95150 Contribute
96151 ----------
97152
98153 Please report any issue and feature request at the `Github issue tracker
99154 <https://github.com/aubio/aubio/issues>`_. Patches and pull-requests welcome!
100−
doc/download.rst+4−8
@@ -5,16 +5,12 @@ Downloading aubio · 4 unmodified lines
55
66 A number of distributions already include aubio. Check your favorite package
77 management system, or have a look at the `aubio download page
8−<http://aubio.org/download>`_ for more options.
9−
10−To use aubio in a macOS or iOS application, see :ref:`xcode-frameworks-label`.
8+<https://aubio.org/download>`_ for more options.
119
1210 To use aubio in an android project, see :ref:`android`.
1311
14−.. toctree::
12+To compile aubio from source, read :ref:`building`.
1513
16− debian_packages
17− xcode_frameworks
18− android
14+.. include:: binaries.rst
1915
20−To compile aubio from source, read :ref:`building`.
16+.. include:: debian_packages.rst
doc/full.cfg+3−2346
@@ -1,2354 +1,11 @@
1−# Doxyfile 1.8.8
2−
3−# This file describes the settings to be used by the documentation system
4−# doxygen (www.doxygen.org) for a project.
5−#
6−# All text after a double hash (##) is considered a comment and is placed in
7−# front of the TAG it is preceding.
8−#
9−# All text after a single hash (#) is considered a comment and will be ignored.
10−# The format is:
11−# TAG = value [value, ...]
12−# For lists, items can also be appended using:
13−# TAG += value [value, ...]
14−# Values that contain spaces should be placed between quotes (\" \").
15−
16−#---------------------------------------------------------------------------
17−# Project related configuration options
18−#---------------------------------------------------------------------------
19−
20−# This tag specifies the encoding used for all characters in the config file
21−# that follow. The default is UTF-8 which is also the encoding used for all text
22−# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
23−# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
24−# for the list of possible encodings.
25−# The default value is: UTF-8.
26−
27−DOXYFILE_ENCODING = UTF-8
28−
29−# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
30−# double-quotes, unless you are using Doxywizard) that should identify the
31−# project for which the documentation is generated. This name is used in the
32−# title of most generated pages and in a few other places.
33−# The default value is: My Project.
34−
35−PROJECT_NAME = aubio
36−
37−# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
38−# could be handy for archiving the generated documentation or if some version
39−# control system is used.
40−
41−PROJECT_NUMBER = "0.4.2~alpha full"
42−
43−# Using the PROJECT_BRIEF tag one can provide an optional one line description
44−# for a project that appears at the top of each page and should give viewer a
45−# quick idea about the purpose of the project. Keep the description short.
46−
47−PROJECT_BRIEF =
48−
49−# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
50−# the documentation. The maximum height of the logo should not exceed 55 pixels
51−# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
52−# to the output directory.
53−
54−PROJECT_LOGO =
55−
56−# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
57−# into which the generated documentation will be written. If a relative path is
58−# entered, it will be relative to the location where doxygen was started. If
59−# left blank the current directory will be used.
1+@INCLUDE_PATH = ./doc
2+@INCLUDE = web.cfg
603
614 OUTPUT_DIRECTORY = full
62−
63−# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
64−# directories (in 2 levels) under the output directory of each output format and
65−# will distribute the generated files over these directories. Enabling this
66−# option can be useful when feeding doxygen a huge amount of source files, where
67−# putting all generated files in the same directory would otherwise causes
68−# performance problems for the file system.
69−# The default value is: NO.
70−
71−CREATE_SUBDIRS = NO
72−
73−# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
74−# characters to appear in the names of generated files. If set to NO, non-ASCII
75−# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
76−# U+3044.
77−# The default value is: NO.
78−
79−ALLOW_UNICODE_NAMES = NO
80−
81−# The OUTPUT_LANGUAGE tag is used to specify the language in which all
82−# documentation generated by doxygen is written. Doxygen will use this
83−# information to generate all constant output in the proper language.
84−# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
85−# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
86−# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
87−# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
88−# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
89−# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
90−# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
91−# Ukrainian and Vietnamese.
92−# The default value is: English.
93−
94−OUTPUT_LANGUAGE = English
95−
96−# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
97−# descriptions after the members that are listed in the file and class
98−# documentation (similar to Javadoc). Set to NO to disable this.
99−# The default value is: YES.
100−
101−BRIEF_MEMBER_DESC = YES
102−
103−# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
104−# description of a member or function before the detailed description
105−#
106−# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
107−# brief descriptions will be completely suppressed.
108−# The default value is: YES.
109−
110−REPEAT_BRIEF = YES
111−
112−# This tag implements a quasi-intelligent brief description abbreviator that is
113−# used to form the text in various listings. Each string in this list, if found
114−# as the leading text of the brief description, will be stripped from the text
115−# and the result, after processing the whole list, is used as the annotated
116−# text. Otherwise, the brief description is used as-is. If left blank, the
117−# following values are used ($name is automatically replaced with the name of
118−# the entity):The $name class, The $name widget, The $name file, is, provides,
119−# specifies, contains, represents, a, an and the.
120−
121−ABBREVIATE_BRIEF =
122−
123−# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
124−# doxygen will generate a detailed section even if there is only a brief
125−# description.
126−# The default value is: NO.
127−
128−ALWAYS_DETAILED_SEC = NO
129−
130−# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
131−# inherited members of a class in the documentation of that class as if those
132−# members were ordinary class members. Constructors, destructors and assignment
133−# operators of the base classes will not be shown.
134−# The default value is: NO.
135−
136−INLINE_INHERITED_MEMB = NO
137−
138−# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
139−# before files name in the file list and in the header files. If set to NO the
140−# shortest path that makes the file name unique will be used
141−# The default value is: YES.
142−
143−FULL_PATH_NAMES = YES
144−
145−# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
146−# Stripping is only done if one of the specified strings matches the left-hand
147−# part of the path. The tag can be used to show relative paths in the file list.
148−# If left blank the directory from which doxygen is run is used as the path to
149−# strip.
150−#
151−# Note that you can specify absolute paths here, but also relative paths, which
152−# will be relative from the directory where doxygen is started.
153−# This tag requires that the tag FULL_PATH_NAMES is set to YES.
154−
155−STRIP_FROM_PATH = ../src
156−
157−# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
158−# path mentioned in the documentation of a class, which tells the reader which
159−# header file to include in order to use a class. If left blank only the name of
160−# the header file containing the class definition is used. Otherwise one should
161−# specify the list of include paths that are normally passed to the compiler
162−# using the -I flag.
163−
164−STRIP_FROM_INC_PATH =
165−
166−# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
167−# less readable) file names. This can be useful is your file systems doesn't
168−# support long names like on DOS, Mac, or CD-ROM.
169−# The default value is: NO.
170−
171−SHORT_NAMES = NO
172−
173−# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
174−# first line (until the first dot) of a Javadoc-style comment as the brief
175−# description. If set to NO, the Javadoc-style will behave just like regular Qt-
176−# style comments (thus requiring an explicit @brief command for a brief
177−# description.)
178−# The default value is: NO.
179−
180−JAVADOC_AUTOBRIEF = YES
181−
182−# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
183−# line (until the first dot) of a Qt-style comment as the brief description. If
184−# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
185−# requiring an explicit \brief command for a brief description.)
186−# The default value is: NO.
187−
188−QT_AUTOBRIEF = NO
189−
190−# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
191−# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
192−# a brief description. This used to be the default behavior. The new default is
193−# to treat a multi-line C++ comment block as a detailed description. Set this
194−# tag to YES if you prefer the old behavior instead.
195−#
196−# Note that setting this tag to YES also means that rational rose comments are
197−# not recognized any more.
198−# The default value is: NO.
199−
200−MULTILINE_CPP_IS_BRIEF = NO
201−
202−# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
203−# documentation from any documented member that it re-implements.
204−# The default value is: YES.
205−
206−INHERIT_DOCS = YES
207−
208−# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
209−# new page for each member. If set to NO, the documentation of a member will be
210−# part of the file/class/namespace that contains it.
211−# The default value is: NO.
212−
213−SEPARATE_MEMBER_PAGES = NO
214−
215−# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
216−# uses this value to replace tabs by spaces in code fragments.
217−# Minimum value: 1, maximum value: 16, default value: 4.
218−
219−TAB_SIZE = 4
220−
221−# This tag can be used to specify a number of aliases that act as commands in
222−# the documentation. An alias has the form:
223−# name=value
224−# For example adding
225−# "sideeffect=@par Side Effects:\n"
226−# will allow you to put the command \sideeffect (or @sideeffect) in the
227−# documentation, which will result in a user-defined paragraph with heading
228−# "Side Effects:". You can put \n's in the value part of an alias to insert
229−# newlines.
230−
231−ALIASES =
232−
233−# This tag can be used to specify a number of word-keyword mappings (TCL only).
234−# A mapping has the form "name=value". For example adding "class=itcl::class"
235−# will allow you to use the command class in the itcl::class meaning.
236−
237−TCL_SUBST =
238−
239−# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
240−# only. Doxygen will then generate output that is more tailored for C. For
241−# instance, some of the names that are used will be different. The list of all
242−# members will be omitted, etc.
243−# The default value is: NO.
244−
245−OPTIMIZE_OUTPUT_FOR_C = YES
246−
247−# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
248−# Python sources only. Doxygen will then generate output that is more tailored
249−# for that language. For instance, namespaces will be presented as packages,
250−# qualified scopes will look different, etc.
251−# The default value is: NO.
252−
253−OPTIMIZE_OUTPUT_JAVA = NO
254−
255−# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
256−# sources. Doxygen will then generate output that is tailored for Fortran.
257−# The default value is: NO.
258−
259−OPTIMIZE_FOR_FORTRAN = NO
260−
261−# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
262−# sources. Doxygen will then generate output that is tailored for VHDL.
263−# The default value is: NO.
264−
265−OPTIMIZE_OUTPUT_VHDL = NO
266−
267−# Doxygen selects the parser to use depending on the extension of the files it
268−# parses. With this tag you can assign which parser to use for a given
269−# extension. Doxygen has a built-in mapping, but you can override or extend it
270−# using this tag. The format is ext=language, where ext is a file extension, and
271−# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
272−# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
273−# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
274−# Fortran. In the later case the parser tries to guess whether the code is fixed
275−# or free formatted code, this is the default for Fortran type files), VHDL. For
276−# instance to make doxygen treat .inc files as Fortran files (default is PHP),
277−# and .f files as C (default is Fortran), use: inc=Fortran f=C.
278−#
279−# Note For files without extension you can use no_extension as a placeholder.
280−#
281−# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
282−# the files are not read by doxygen.
283−
284−EXTENSION_MAPPING =
285−
286−# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
287−# according to the Markdown format, which allows for more readable
288−# documentation. See http://daringfireball.net/projects/markdown/ for details.
289−# The output of markdown processing is further processed by doxygen, so you can
290−# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
291−# case of backward compatibilities issues.
292−# The default value is: YES.
293−
294−MARKDOWN_SUPPORT = YES
295−
296−# When enabled doxygen tries to link words that correspond to documented
297−# classes, or namespaces to their corresponding documentation. Such a link can
298−# be prevented in individual cases by by putting a % sign in front of the word
299−# or globally by setting AUTOLINK_SUPPORT to NO.
300−# The default value is: YES.
301−
302−AUTOLINK_SUPPORT = YES
303−
304−# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
305−# to include (a tag file for) the STL sources as input, then you should set this
306−# tag to YES in order to let doxygen match functions declarations and
307−# definitions whose arguments contain STL classes (e.g. func(std::string);
308−# versus func(std::string) {}). This also make the inheritance and collaboration
309−# diagrams that involve STL classes more complete and accurate.
310−# The default value is: NO.
311−
312−BUILTIN_STL_SUPPORT = NO
313−
314−# If you use Microsoft's C++/CLI language, you should set this option to YES to
315−# enable parsing support.
316−# The default value is: NO.
317−
318−CPP_CLI_SUPPORT = NO
319−
320−# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
321−# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
322−# will parse them like normal C++ but will assume all classes use public instead
323−# of private inheritance when no explicit protection keyword is present.
324−# The default value is: NO.
325−
326−SIP_SUPPORT = NO
327−
328−# For Microsoft's IDL there are propget and propput attributes to indicate
329−# getter and setter methods for a property. Setting this option to YES will make
330−# doxygen to replace the get and set methods by a property in the documentation.
331−# This will only work if the methods are indeed getting or setting a simple
332−# type. If this is not the case, or you want to show the methods anyway, you
333−# should set this option to NO.
334−# The default value is: YES.
335−
336−IDL_PROPERTY_SUPPORT = YES
337−
338−# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
339−# tag is set to YES, then doxygen will reuse the documentation of the first
340−# member in the group (if any) for the other members of the group. By default
341−# all members of a group must be documented explicitly.
342−# The default value is: NO.
343−
344−DISTRIBUTE_GROUP_DOC = NO
345−
346−# Set the SUBGROUPING tag to YES to allow class member groups of the same type
347−# (for instance a group of public functions) to be put as a subgroup of that
348−# type (e.g. under the Public Functions section). Set it to NO to prevent
349−# subgrouping. Alternatively, this can be done per class using the
350−# \nosubgrouping command.
351−# The default value is: YES.
352−
353−SUBGROUPING = YES
354−
355−# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
356−# are shown inside the group in which they are included (e.g. using \ingroup)
357−# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
358−# and RTF).
359−#
360−# Note that this feature does not work in combination with
361−# SEPARATE_MEMBER_PAGES.
362−# The default value is: NO.
363−
364−INLINE_GROUPED_CLASSES = NO
365−
366−# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
367−# with only public data fields or simple typedef fields will be shown inline in
368−# the documentation of the scope in which they are defined (i.e. file,
369−# namespace, or group documentation), provided this scope is documented. If set
370−# to NO, structs, classes, and unions are shown on a separate page (for HTML and
371−# Man pages) or section (for LaTeX and RTF).
372−# The default value is: NO.
373−
374−INLINE_SIMPLE_STRUCTS = NO
375−
376−# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
377−# enum is documented as struct, union, or enum with the name of the typedef. So
378−# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
379−# with name TypeT. When disabled the typedef will appear as a member of a file,
380−# namespace, or class. And the struct will be named TypeS. This can typically be
381−# useful for C code in case the coding convention dictates that all compound
382−# types are typedef'ed and only the typedef is referenced, never the tag name.
383−# The default value is: NO.
384−
385−TYPEDEF_HIDES_STRUCT = NO
386−
387−# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
388−# cache is used to resolve symbols given their name and scope. Since this can be
389−# an expensive process and often the same symbol appears multiple times in the
390−# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
391−# doxygen will become slower. If the cache is too large, memory is wasted. The
392−# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
393−# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
394−# symbols. At the end of a run doxygen will report the cache usage and suggest
395−# the optimal cache size from a speed point of view.
396−# Minimum value: 0, maximum value: 9, default value: 0.
397−
398−LOOKUP_CACHE_SIZE = 0
399−
400−#---------------------------------------------------------------------------
401−# Build related configuration options
402−#---------------------------------------------------------------------------
403−
404−# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
405−# documentation are documented, even if no documentation was available. Private
406−# class members and static file members will be hidden unless the
407−# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
408−# Note: This will also disable the warnings about undocumented members that are
409−# normally produced when WARNINGS is set to YES.
410−# The default value is: NO.
411−
4125 EXTRACT_ALL = YES
413−
414−# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
415−# be included in the documentation.
416−# The default value is: NO.
417−
4186 EXTRACT_PRIVATE = YES
419−
420−# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
421−# scope will be included in the documentation.
422−# The default value is: NO.
423−
424−EXTRACT_PACKAGE = NO
425−
426−# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
427−# included in the documentation.
428−# The default value is: NO.
429−
4307 EXTRACT_STATIC = YES
431−
432−# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
433−# locally in source files will be included in the documentation. If set to NO
434−# only classes defined in header files are included. Does not have any effect
435−# for Java sources.
436−# The default value is: YES.
437−
438−EXTRACT_LOCAL_CLASSES = YES
439−
440−# This flag is only useful for Objective-C code. When set to YES local methods,
441−# which are defined in the implementation section but not in the interface are
442−# included in the documentation. If set to NO only methods in the interface are
443−# included.
444−# The default value is: NO.
445−
446−EXTRACT_LOCAL_METHODS = NO
447−
448−# If this flag is set to YES, the members of anonymous namespaces will be
449−# extracted and appear in the documentation as a namespace called
450−# 'anonymous_namespace{file}', where file will be replaced with the base name of
451−# the file that contains the anonymous namespace. By default anonymous namespace
452−# are hidden.
453−# The default value is: NO.
454−
455−EXTRACT_ANON_NSPACES = NO
456−
457−# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
458−# undocumented members inside documented classes or files. If set to NO these
459−# members will be included in the various overviews, but no documentation
460−# section is generated. This option has no effect if EXTRACT_ALL is enabled.
461−# The default value is: NO.
462−
463−HIDE_UNDOC_MEMBERS = NO
464−
465−# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
466−# undocumented classes that are normally visible in the class hierarchy. If set
467−# to NO these classes will be included in the various overviews. This option has
468−# no effect if EXTRACT_ALL is enabled.
469−# The default value is: NO.
470−
471−HIDE_UNDOC_CLASSES = NO
472−
473−# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
474−# (class|struct|union) declarations. If set to NO these declarations will be
475−# included in the documentation.
476−# The default value is: NO.
477−
478−HIDE_FRIEND_COMPOUNDS = NO
479−
480−# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
481−# documentation blocks found inside the body of a function. If set to NO these
482−# blocks will be appended to the function's detailed documentation block.
483−# The default value is: NO.
484−
485−HIDE_IN_BODY_DOCS = NO
486−
487−# The INTERNAL_DOCS tag determines if documentation that is typed after a
488−# \internal command is included. If the tag is set to NO then the documentation
489−# will be excluded. Set it to YES to include the internal documentation.
490−# The default value is: NO.
491−
492−INTERNAL_DOCS = NO
493−
494−# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
495−# names in lower-case letters. If set to YES upper-case letters are also
496−# allowed. This is useful if you have classes or files whose names only differ
497−# in case and if your file system supports case sensitive file names. Windows
498−# and Mac users are advised to set this option to NO.
499−# The default value is: system dependent.
500−
501−CASE_SENSE_NAMES = NO
502−
503−# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
504−# their full class and namespace scopes in the documentation. If set to YES the
505−# scope will be hidden.
506−# The default value is: NO.
507−
508−HIDE_SCOPE_NAMES = NO
509−
510−# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
511−# the files that are included by a file in the documentation of that file.
512−# The default value is: YES.
513−
514−SHOW_INCLUDE_FILES = YES
515−
516−# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
517−# grouped member an include statement to the documentation, telling the reader
518−# which file to include in order to use the member.
519−# The default value is: NO.
520−
521−SHOW_GROUPED_MEMB_INC = NO
522−
523−# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
524−# files with double quotes in the documentation rather than with sharp brackets.
525−# The default value is: NO.
526−
527−FORCE_LOCAL_INCLUDES = NO
528−
529−# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
530−# documentation for inline members.
531−# The default value is: YES.
532−
533−INLINE_INFO = YES
534−
535−# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
536−# (detailed) documentation of file and class members alphabetically by member
537−# name. If set to NO the members will appear in declaration order.
538−# The default value is: YES.
539−
540−SORT_MEMBER_DOCS = YES
541−
542−# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
543−# descriptions of file, namespace and class members alphabetically by member
544−# name. If set to NO the members will appear in declaration order. Note that
545−# this will also influence the order of the classes in the class list.
546−# The default value is: NO.
547−
548−SORT_BRIEF_DOCS = NO
549−
550−# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
551−# (brief and detailed) documentation of class members so that constructors and
552−# destructors are listed first. If set to NO the constructors will appear in the
553−# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
554−# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
555−# member documentation.
556−# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
557−# detailed member documentation.
558−# The default value is: NO.
559−
560−SORT_MEMBERS_CTORS_1ST = NO
561−
562−# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
563−# of group names into alphabetical order. If set to NO the group names will
564−# appear in their defined order.
565−# The default value is: NO.
566−
567−SORT_GROUP_NAMES = NO
568−
569−# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
570−# fully-qualified names, including namespaces. If set to NO, the class list will
571−# be sorted only by class name, not including the namespace part.
572−# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
573−# Note: This option applies only to the class list, not to the alphabetical
574−# list.
575−# The default value is: NO.
576−
577−SORT_BY_SCOPE_NAME = NO
578−
579−# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
580−# type resolution of all parameters of a function it will reject a match between
581−# the prototype and the implementation of a member function even if there is
582−# only one candidate or it is obvious which candidate to choose by doing a
583−# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
584−# accept a match between prototype and implementation in such cases.
585−# The default value is: NO.
586−
587−STRICT_PROTO_MATCHING = NO
588−
589−# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
590−# todo list. This list is created by putting \todo commands in the
591−# documentation.
592−# The default value is: YES.
593−
594−GENERATE_TODOLIST = YES
595−
596−# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
597−# test list. This list is created by putting \test commands in the
598−# documentation.
599−# The default value is: YES.
600−
601−GENERATE_TESTLIST = YES
602−
603−# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
604−# list. This list is created by putting \bug commands in the documentation.
605−# The default value is: YES.
606−
607−GENERATE_BUGLIST = YES
608−
609−# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
610−# the deprecated list. This list is created by putting \deprecated commands in
611−# the documentation.
612−# The default value is: YES.
613−
614−GENERATE_DEPRECATEDLIST= YES
615−
616−# The ENABLED_SECTIONS tag can be used to enable conditional documentation
617−# sections, marked by \if <section_label> ... \endif and \cond <section_label>
618−# ... \endcond blocks.
619−
620−ENABLED_SECTIONS =
621−
622−# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
623−# initial value of a variable or macro / define can have for it to appear in the
624−# documentation. If the initializer consists of more lines than specified here
625−# it will be hidden. Use a value of 0 to hide initializers completely. The
626−# appearance of the value of individual variables and macros / defines can be
627−# controlled using \showinitializer or \hideinitializer command in the
628−# documentation regardless of this setting.
629−# Minimum value: 0, maximum value: 10000, default value: 30.
630−
631−MAX_INITIALIZER_LINES = 30
632−
633−# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
634−# the bottom of the documentation of classes and structs. If set to YES the list
635−# will mention the files that were used to generate the documentation.
636−# The default value is: YES.
637−
638−SHOW_USED_FILES = YES
639−
640−# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
641−# will remove the Files entry from the Quick Index and from the Folder Tree View
642−# (if specified).
643−# The default value is: YES.
644−
645−SHOW_FILES = YES
646−
647−# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
648−# page. This will remove the Namespaces entry from the Quick Index and from the
649−# Folder Tree View (if specified).
650−# The default value is: YES.
651−
652−SHOW_NAMESPACES = YES
653−
654−# The FILE_VERSION_FILTER tag can be used to specify a program or script that
655−# doxygen should invoke to get the current version for each file (typically from
656−# the version control system). Doxygen will invoke the program by executing (via
657−# popen()) the command command input-file, where command is the value of the
658−# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
659−# by doxygen. Whatever the program writes to standard output is used as the file
660−# version. For an example see the documentation.
661−
662−FILE_VERSION_FILTER =
663−
664−# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
665−# by doxygen. The layout file controls the global structure of the generated
666−# output files in an output format independent way. To create the layout file
667−# that represents doxygen's defaults, run doxygen with the -l option. You can
668−# optionally specify a file name after the option, if omitted DoxygenLayout.xml
669−# will be used as the name of the layout file.
670−#
671−# Note that if you run doxygen from a directory containing a file called
672−# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
673−# tag is left empty.
674−
675−LAYOUT_FILE =
676−
677−# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
678−# the reference definitions. This must be a list of .bib files. The .bib
679−# extension is automatically appended if omitted. This requires the bibtex tool
680−# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
681−# For LaTeX the style of the bibliography can be controlled using
682−# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
683−# search path. See also \cite for info how to create references.
684−
685−CITE_BIB_FILES =
686−
687−#---------------------------------------------------------------------------
688−# Configuration options related to warning and progress messages
689−#---------------------------------------------------------------------------
690−
691−# The QUIET tag can be used to turn on/off the messages that are generated to
692−# standard output by doxygen. If QUIET is set to YES this implies that the
693−# messages are off.
694−# The default value is: NO.
695−
696−QUIET = NO
697−
698−# The WARNINGS tag can be used to turn on/off the warning messages that are
699−# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
700−# this implies that the warnings are on.
701−#
702−# Tip: Turn warnings on while writing the documentation.
703−# The default value is: YES.
704−
705−WARNINGS = YES
706−
707−# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
708−# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
709−# will automatically be disabled.
710−# The default value is: YES.
711−
712−WARN_IF_UNDOCUMENTED = YES
713−
714−# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
715−# potential errors in the documentation, such as not documenting some parameters
716−# in a documented function, or documenting parameters that don't exist or using
717−# markup commands wrongly.
718−# The default value is: YES.
719−
720−WARN_IF_DOC_ERROR = YES
721−
722−# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
723−# are documented, but have no documentation for their parameters or return
724−# value. If set to NO doxygen will only warn about wrong or incomplete parameter
725−# documentation, but not about the absence of documentation.
726−# The default value is: NO.
727−
728−WARN_NO_PARAMDOC = NO
729−
730−# The WARN_FORMAT tag determines the format of the warning messages that doxygen
731−# can produce. The string should contain the $file, $line, and $text tags, which
732−# will be replaced by the file and line number from which the warning originated
733−# and the warning text. Optionally the format may contain $version, which will
734−# be replaced by the version of the file (if it could be obtained via
735−# FILE_VERSION_FILTER)
736−# The default value is: $file:$line: $text.
737−
738−WARN_FORMAT = "$file:$line: $text"
739−
740−# The WARN_LOGFILE tag can be used to specify a file to which warning and error
741−# messages should be written. If left blank the output is written to standard
742−# error (stderr).
743−
744−WARN_LOGFILE =
745−
746−#---------------------------------------------------------------------------
747−# Configuration options related to the input files
748−#---------------------------------------------------------------------------
749−
750−# The INPUT tag is used to specify the files and/or directories that contain
751−# documented source files. You may enter file names like myfile.cpp or
752−# directories like /usr/src/myproject. Separate the files or directories with
753−# spaces.
754−# Note: If this tag is empty the current directory is searched.
755−
756−INPUT = ../src
757−
758−# This tag can be used to specify the character encoding of the source files
759−# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
760−# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
761−# documentation (see: http://www.gnu.org/software/libiconv) for the list of
762−# possible encodings.
763−# The default value is: UTF-8.
764−
765−INPUT_ENCODING = UTF-8
766−
767−# If the value of the INPUT tag contains directories, you can use the
768−# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
769−# *.h) to filter out the source-files in the directories. If left blank the
770−# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
771−# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
772−# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
773−# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
774−# *.qsf, *.as and *.js.
775−
776−FILE_PATTERNS = *.h \
777− *.c
778−
779−# The RECURSIVE tag can be used to specify whether or not subdirectories should
780−# be searched for input files as well.
781−# The default value is: NO.
782−
783−RECURSIVE = YES
784−
785−# The EXCLUDE tag can be used to specify files and/or directories that should be
786−# excluded from the INPUT source files. This way you can easily exclude a
787−# subdirectory from a directory tree whose root is specified with the INPUT tag.
788−#
789−# Note that relative paths are relative to the directory from which doxygen is
790−# run.
791−
8+FILE_PATTERNS = *.h *.c
7929 EXCLUDE =
793−
794−# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
795−# directories that are symbolic links (a Unix file system feature) are excluded
796−# from the input.
797−# The default value is: NO.
798−
799−EXCLUDE_SYMLINKS = NO
800−
801−# If the value of the INPUT tag contains directories, you can use the
802−# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
803−# certain files from those directories.
804−#
805−# Note that the wildcards are matched against the file with absolute path, so to
806−# exclude all test directories for example use the pattern */test/*
807−
808−EXCLUDE_PATTERNS =
809−
810−# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
811−# (namespaces, classes, functions, etc.) that should be excluded from the
812−# output. The symbol name can be a fully qualified name, a word, or if the
813−# wildcard * is used, a substring. Examples: ANamespace, AClass,
814−# AClass::ANamespace, ANamespace::*Test
815−#
816−# Note that the wildcards are matched against the file with absolute path, so to
817−# exclude all test directories use the pattern */test/*
818−
819−EXCLUDE_SYMBOLS =
820−
821−# The EXAMPLE_PATH tag can be used to specify one or more files or directories
822−# that contain example code fragments that are included (see the \include
823−# command).
824−
825−EXAMPLE_PATH = ../examples \
826− ../tests/src
827−
828−# If the value of the EXAMPLE_PATH tag contains directories, you can use the
829−# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
830−# *.h) to filter out the source-files in the directories. If left blank all
831−# files are included.
832−
833−EXAMPLE_PATTERNS =
834−
835−# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
836−# searched for input files to be used with the \include or \dontinclude commands
837−# irrespective of the value of the RECURSIVE tag.
838−# The default value is: NO.
839−
840−EXAMPLE_RECURSIVE = NO
841−
842−# The IMAGE_PATH tag can be used to specify one or more files or directories
843−# that contain images that are to be included in the documentation (see the
844−# \image command).
845−
846−IMAGE_PATH =
847−
848−# The INPUT_FILTER tag can be used to specify a program that doxygen should
849−# invoke to filter for each input file. Doxygen will invoke the filter program
850−# by executing (via popen()) the command:
851−#
852−# <filter> <input-file>
853−#
854−# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
855−# name of an input file. Doxygen will then use the output that the filter
856−# program writes to standard output. If FILTER_PATTERNS is specified, this tag
857−# will be ignored.
858−#
859−# Note that the filter must not add or remove lines; it is applied before the
860−# code is scanned, but not when the output code is generated. If lines are added
861−# or removed, the anchors will not be placed correctly.
862−
863−INPUT_FILTER =
864−
865−# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
866−# basis. Doxygen will compare the file name with each pattern and apply the
867−# filter if there is a match. The filters are a list of the form: pattern=filter
868−# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
869−# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
870−# patterns match the file name, INPUT_FILTER is applied.
871−
872−FILTER_PATTERNS =
873−
874−# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
875−# INPUT_FILTER ) will also be used to filter the input files that are used for
876−# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
877−# The default value is: NO.
878−
879−FILTER_SOURCE_FILES = NO
880−
881−# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
882−# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
883−# it is also possible to disable source filtering for a specific pattern using
884−# *.ext= (so without naming a filter).
885−# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
886−
887−FILTER_SOURCE_PATTERNS =
888−
889−# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
890−# is part of the input, its contents will be placed on the main page
891−# (index.html). This can be useful if you have a project on for instance GitHub
892−# and want to reuse the introduction page also for the doxygen output.
893−
894−USE_MDFILE_AS_MAINPAGE =
895−
896−#---------------------------------------------------------------------------
897−# Configuration options related to source browsing
898−#---------------------------------------------------------------------------
899−
900−# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
901−# generated. Documented entities will be cross-referenced with these sources.
902−#
903−# Note: To get rid of all source code in the generated output, make sure that
904−# also VERBATIM_HEADERS is set to NO.
905−# The default value is: NO.
906−
907−SOURCE_BROWSER = YES
908−
909−# Setting the INLINE_SOURCES tag to YES will include the body of functions,
910−# classes and enums directly into the documentation.
911−# The default value is: NO.
912−
913−INLINE_SOURCES = NO
914−
915−# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
916−# special comment blocks from generated source code fragments. Normal C, C++ and
917−# Fortran comments will always remain visible.
918−# The default value is: YES.
919−
920−STRIP_CODE_COMMENTS = NO
921−
922−# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
923−# function all documented functions referencing it will be listed.
924−# The default value is: NO.
925−
926−REFERENCED_BY_RELATION = YES
927−
928−# If the REFERENCES_RELATION tag is set to YES then for each documented function
929−# all documented entities called/used by that function will be listed.
930−# The default value is: NO.
931−
932−REFERENCES_RELATION = YES
933−
934−# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
935−# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
936−# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
937−# link to the documentation.
938−# The default value is: YES.
939−
940−REFERENCES_LINK_SOURCE = YES
941−
942−# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
943−# source code will show a tooltip with additional information such as prototype,
944−# brief description and links to the definition and documentation. Since this
945−# will make the HTML file larger and loading of large files a bit slower, you
946−# can opt to disable this feature.
947−# The default value is: YES.
948−# This tag requires that the tag SOURCE_BROWSER is set to YES.
949−
950−SOURCE_TOOLTIPS = YES
951−
952−# If the USE_HTAGS tag is set to YES then the references to source code will
953−# point to the HTML generated by the htags(1) tool instead of doxygen built-in
954−# source browser. The htags tool is part of GNU's global source tagging system
955−# (see http://www.gnu.org/software/global/global.html). You will need version
956−# 4.8.6 or higher.
957−#
958−# To use it do the following:
959−# - Install the latest version of global
960−# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
961−# - Make sure the INPUT points to the root of the source tree
962−# - Run doxygen as normal
963−#
964−# Doxygen will invoke htags (and that will in turn invoke gtags), so these
965−# tools must be available from the command line (i.e. in the search path).
966−#
967−# The result: instead of the source browser generated by doxygen, the links to
968−# source code will now point to the output of htags.
969−# The default value is: NO.
970−# This tag requires that the tag SOURCE_BROWSER is set to YES.
971−
972−USE_HTAGS = NO
973−
974−# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
975−# verbatim copy of the header file for each class for which an include is
976−# specified. Set to NO to disable this.
977−# See also: Section \class.
978−# The default value is: YES.
979−
980−VERBATIM_HEADERS = YES
981−
982−# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
983−# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
984−# cost of reduced performance. This can be particularly helpful with template
985−# rich C++ code for which doxygen's built-in parser lacks the necessary type
986−# information.
987−# Note: The availability of this option depends on whether or not doxygen was
988−# compiled with the --with-libclang option.
989−# The default value is: NO.
990−
991−CLANG_ASSISTED_PARSING = NO
992−
993−# If clang assisted parsing is enabled you can provide the compiler with command
994−# line options that you would normally use when invoking the compiler. Note that
995−# the include paths will already be set by doxygen for the files and directories
996−# specified with INPUT and INCLUDE_PATH.
997−# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
998−
999−CLANG_OPTIONS =
1000−
1001−#---------------------------------------------------------------------------
1002−# Configuration options related to the alphabetical class index
1003−#---------------------------------------------------------------------------
1004−
1005−# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
1006−# compounds will be generated. Enable this if the project contains a lot of
1007−# classes, structs, unions or interfaces.
1008−# The default value is: YES.
1009−
1010−ALPHABETICAL_INDEX = NO
1011−
1012−# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
1013−# which the alphabetical index list will be split.
1014−# Minimum value: 1, maximum value: 20, default value: 5.
1015−# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1016−
1017−COLS_IN_ALPHA_INDEX = 5
1018−
1019−# In case all classes in a project start with a common prefix, all classes will
1020−# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
1021−# can be used to specify a prefix (or a list of prefixes) that should be ignored
1022−# while generating the index headers.
1023−# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1024−
1025−IGNORE_PREFIX =
1026−
1027−#---------------------------------------------------------------------------
1028−# Configuration options related to the HTML output
1029−#---------------------------------------------------------------------------
1030−
1031−# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
1032−# The default value is: YES.
1033−
1034−GENERATE_HTML = YES
1035−
1036−# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
1037−# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1038−# it.
1039−# The default directory is: html.
1040−# This tag requires that the tag GENERATE_HTML is set to YES.
1041−
1042−HTML_OUTPUT = html
1043−
1044−# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
1045−# generated HTML page (for example: .htm, .php, .asp).
1046−# The default value is: .html.
1047−# This tag requires that the tag GENERATE_HTML is set to YES.
1048−
1049−HTML_FILE_EXTENSION = .html
1050−
1051−# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
1052−# each generated HTML page. If the tag is left blank doxygen will generate a
1053−# standard header.
1054−#
1055−# To get valid HTML the header file that includes any scripts and style sheets
1056−# that doxygen needs, which is dependent on the configuration options used (e.g.
1057−# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
1058−# default header using
1059−# doxygen -w html new_header.html new_footer.html new_stylesheet.css
1060−# YourConfigFile
1061−# and then modify the file new_header.html. See also section "Doxygen usage"
1062−# for information on how to generate the default header that doxygen normally
1063−# uses.
1064−# Note: The header is subject to change so you typically have to regenerate the
1065−# default header when upgrading to a newer version of doxygen. For a description
1066−# of the possible markers and block names see the documentation.
1067−# This tag requires that the tag GENERATE_HTML is set to YES.
1068−
1069−HTML_HEADER =
1070−
1071−# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
1072−# generated HTML page. If the tag is left blank doxygen will generate a standard
1073−# footer. See HTML_HEADER for more information on how to generate a default
1074−# footer and what special commands can be used inside the footer. See also
1075−# section "Doxygen usage" for information on how to generate the default footer
1076−# that doxygen normally uses.
1077−# This tag requires that the tag GENERATE_HTML is set to YES.
1078−
1079−HTML_FOOTER =
1080−
1081−# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
1082−# sheet that is used by each HTML page. It can be used to fine-tune the look of
1083−# the HTML output. If left blank doxygen will generate a default style sheet.
1084−# See also section "Doxygen usage" for information on how to generate the style
1085−# sheet that doxygen normally uses.
1086−# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
1087−# it is more robust and this tag (HTML_STYLESHEET) will in the future become
1088−# obsolete.
1089−# This tag requires that the tag GENERATE_HTML is set to YES.
1090−
1091−HTML_STYLESHEET =
1092−
1093−# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1094−# cascading style sheets that are included after the standard style sheets
1095−# created by doxygen. Using this option one can overrule certain style aspects.
1096−# This is preferred over using HTML_STYLESHEET since it does not replace the
1097−# standard style sheet and is therefor more robust against future updates.
1098−# Doxygen will copy the style sheet files to the output directory.
1099−# Note: The order of the extra stylesheet files is of importance (e.g. the last
1100−# stylesheet in the list overrules the setting of the previous ones in the
1101−# list). For an example see the documentation.
1102−# This tag requires that the tag GENERATE_HTML is set to YES.
1103−
1104−HTML_EXTRA_STYLESHEET =
1105−
1106−# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1107−# other source files which should be copied to the HTML output directory. Note
1108−# that these files will be copied to the base HTML output directory. Use the
1109−# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
1110−# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
1111−# files will be copied as-is; there are no commands or markers available.
1112−# This tag requires that the tag GENERATE_HTML is set to YES.
1113−
1114−HTML_EXTRA_FILES =
1115−
1116−# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1117−# will adjust the colors in the stylesheet and background images according to
1118−# this color. Hue is specified as an angle on a colorwheel, see
1119−# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
1120−# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
1121−# purple, and 360 is red again.
1122−# Minimum value: 0, maximum value: 359, default value: 220.
1123−# This tag requires that the tag GENERATE_HTML is set to YES.
1124−
1125−HTML_COLORSTYLE_HUE = 220
1126−
1127−# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
1128−# in the HTML output. For a value of 0 the output will use grayscales only. A
1129−# value of 255 will produce the most vivid colors.
1130−# Minimum value: 0, maximum value: 255, default value: 100.
1131−# This tag requires that the tag GENERATE_HTML is set to YES.
1132−
1133−HTML_COLORSTYLE_SAT = 100
1134−
1135−# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
1136−# luminance component of the colors in the HTML output. Values below 100
1137−# gradually make the output lighter, whereas values above 100 make the output
1138−# darker. The value divided by 100 is the actual gamma applied, so 80 represents
1139−# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
1140−# change the gamma.
1141−# Minimum value: 40, maximum value: 240, default value: 80.
1142−# This tag requires that the tag GENERATE_HTML is set to YES.
1143−
1144−HTML_COLORSTYLE_GAMMA = 80
1145−
1146−# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1147−# page will contain the date and time when the page was generated. Setting this
1148−# to NO can help when comparing the output of multiple runs.
1149−# The default value is: YES.
1150−# This tag requires that the tag GENERATE_HTML is set to YES.
1151−
1152−HTML_TIMESTAMP = NO
1153−
1154−# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
1155−# documentation will contain sections that can be hidden and shown after the
1156−# page has loaded.
1157−# The default value is: NO.
1158−# This tag requires that the tag GENERATE_HTML is set to YES.
1159−
1160−HTML_DYNAMIC_SECTIONS = NO
1161−
1162−# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
1163−# shown in the various tree structured indices initially; the user can expand
1164−# and collapse entries dynamically later on. Doxygen will expand the tree to
1165−# such a level that at most the specified number of entries are visible (unless
1166−# a fully collapsed tree already exceeds this amount). So setting the number of
1167−# entries 1 will produce a full collapsed tree by default. 0 is a special value
1168−# representing an infinite number of entries and will result in a full expanded
1169−# tree by default.
1170−# Minimum value: 0, maximum value: 9999, default value: 100.
1171−# This tag requires that the tag GENERATE_HTML is set to YES.
1172−
1173−HTML_INDEX_NUM_ENTRIES = 100
1174−
1175−# If the GENERATE_DOCSET tag is set to YES, additional index files will be
1176−# generated that can be used as input for Apple's Xcode 3 integrated development
1177−# environment (see: http://developer.apple.com/tools/xcode/), introduced with
1178−# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
1179−# Makefile in the HTML output directory. Running make will produce the docset in
1180−# that directory and running make install will install the docset in
1181−# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
1182−# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
1183−# for more information.
1184−# The default value is: NO.
1185−# This tag requires that the tag GENERATE_HTML is set to YES.
1186−
1187−GENERATE_DOCSET = NO
1188−
1189−# This tag determines the name of the docset feed. A documentation feed provides
1190−# an umbrella under which multiple documentation sets from a single provider
1191−# (such as a company or product suite) can be grouped.
1192−# The default value is: Doxygen generated docs.
1193−# This tag requires that the tag GENERATE_DOCSET is set to YES.
1194−
1195−DOCSET_FEEDNAME = "Doxygen generated docs"
1196−
1197−# This tag specifies a string that should uniquely identify the documentation
1198−# set bundle. This should be a reverse domain-name style string, e.g.
1199−# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
1200−# The default value is: org.doxygen.Project.
1201−# This tag requires that the tag GENERATE_DOCSET is set to YES.
1202−
1203−DOCSET_BUNDLE_ID = org.aubio.aubio
1204−
1205−# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
1206−# the documentation publisher. This should be a reverse domain-name style
1207−# string, e.g. com.mycompany.MyDocSet.documentation.
1208−# The default value is: org.doxygen.Publisher.
1209−# This tag requires that the tag GENERATE_DOCSET is set to YES.
1210−
1211−DOCSET_PUBLISHER_ID = org.aubio.aubio.Maintainer
1212−
1213−# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
1214−# The default value is: Publisher.
1215−# This tag requires that the tag GENERATE_DOCSET is set to YES.
1216−
1217−DOCSET_PUBLISHER_NAME = Publisher
1218−
1219−# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
1220−# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
1221−# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
1222−# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
1223−# Windows.
1224−#
1225−# The HTML Help Workshop contains a compiler that can convert all HTML output
1226−# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
1227−# files are now used as the Windows 98 help format, and will replace the old
1228−# Windows help format (.hlp) on all Windows platforms in the future. Compressed
1229−# HTML files also contain an index, a table of contents, and you can search for
1230−# words in the documentation. The HTML workshop also contains a viewer for
1231−# compressed HTML files.
1232−# The default value is: NO.
1233−# This tag requires that the tag GENERATE_HTML is set to YES.
1234−
1235−GENERATE_HTMLHELP = NO
1236−
1237−# The CHM_FILE tag can be used to specify the file name of the resulting .chm
1238−# file. You can add a path in front of the file if the result should not be
1239−# written to the html output directory.
1240−# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1241−
1242−CHM_FILE =
1243−
1244−# The HHC_LOCATION tag can be used to specify the location (absolute path
1245−# including file name) of the HTML help compiler ( hhc.exe). If non-empty
1246−# doxygen will try to run the HTML help compiler on the generated index.hhp.
1247−# The file has to be specified with full path.
1248−# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1249−
1250−HHC_LOCATION =
1251−
1252−# The GENERATE_CHI flag controls if a separate .chi index file is generated (
1253−# YES) or that it should be included in the master .chm file ( NO).
1254−# The default value is: NO.
1255−# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1256−
1257−GENERATE_CHI = NO
1258−
1259−# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
1260−# and project file content.
1261−# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1262−
1263−CHM_INDEX_ENCODING =
1264−
1265−# The BINARY_TOC flag controls whether a binary table of contents is generated (
1266−# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
1267−# enables the Previous and Next buttons.
1268−# The default value is: NO.
1269−# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1270−
1271−BINARY_TOC = NO
1272−
1273−# The TOC_EXPAND flag can be set to YES to add extra items for group members to
1274−# the table of contents of the HTML help documentation and to the tree view.
1275−# The default value is: NO.
1276−# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1277−
1278−TOC_EXPAND = NO
1279−
1280−# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
1281−# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
1282−# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
1283−# (.qch) of the generated HTML documentation.
1284−# The default value is: NO.
1285−# This tag requires that the tag GENERATE_HTML is set to YES.
1286−
1287−GENERATE_QHP = NO
1288−
1289−# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
1290−# the file name of the resulting .qch file. The path specified is relative to
1291−# the HTML output folder.
1292−# This tag requires that the tag GENERATE_QHP is set to YES.
1293−
1294−QCH_FILE =
1295−
1296−# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
1297−# Project output. For more information please see Qt Help Project / Namespace
1298−# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
1299−# The default value is: org.doxygen.Project.
1300−# This tag requires that the tag GENERATE_QHP is set to YES.
1301−
1302−QHP_NAMESPACE =
1303−
1304−# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
1305−# Help Project output. For more information please see Qt Help Project / Virtual
1306−# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
1307−# folders).
1308−# The default value is: doc.
1309−# This tag requires that the tag GENERATE_QHP is set to YES.
1310−
1311−QHP_VIRTUAL_FOLDER = doc
1312−
1313−# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
1314−# filter to add. For more information please see Qt Help Project / Custom
1315−# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1316−# filters).
1317−# This tag requires that the tag GENERATE_QHP is set to YES.
1318−
1319−QHP_CUST_FILTER_NAME =
1320−
1321−# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
1322−# custom filter to add. For more information please see Qt Help Project / Custom
1323−# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1324−# filters).
1325−# This tag requires that the tag GENERATE_QHP is set to YES.
1326−
1327−QHP_CUST_FILTER_ATTRS =
1328−
1329−# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
1330−# project's filter section matches. Qt Help Project / Filter Attributes (see:
1331−# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
1332−# This tag requires that the tag GENERATE_QHP is set to YES.
1333−
1334−QHP_SECT_FILTER_ATTRS =
1335−
1336−# The QHG_LOCATION tag can be used to specify the location of Qt's
1337−# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
1338−# generated .qhp file.
1339−# This tag requires that the tag GENERATE_QHP is set to YES.
1340−
1341−QHG_LOCATION =
1342−
1343−# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
1344−# generated, together with the HTML files, they form an Eclipse help plugin. To
1345−# install this plugin and make it available under the help contents menu in
1346−# Eclipse, the contents of the directory containing the HTML and XML files needs
1347−# to be copied into the plugins directory of eclipse. The name of the directory
1348−# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
1349−# After copying Eclipse needs to be restarted before the help appears.
1350−# The default value is: NO.
1351−# This tag requires that the tag GENERATE_HTML is set to YES.
1352−
1353−GENERATE_ECLIPSEHELP = NO
1354−
1355−# A unique identifier for the Eclipse help plugin. When installing the plugin
1356−# the directory name containing the HTML and XML files should also have this
1357−# name. Each documentation set should have its own identifier.
1358−# The default value is: org.doxygen.Project.
1359−# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
1360−
1361−ECLIPSE_DOC_ID = org.aubio.aubio
1362−
1363−# If you want full control over the layout of the generated HTML pages it might
1364−# be necessary to disable the index and replace it with your own. The
1365−# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
1366−# of each HTML page. A value of NO enables the index and the value YES disables
1367−# it. Since the tabs in the index contain the same information as the navigation
1368−# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
1369−# The default value is: NO.
1370−# This tag requires that the tag GENERATE_HTML is set to YES.
1371−
1372−DISABLE_INDEX = NO
1373−
1374−# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1375−# structure should be generated to display hierarchical information. If the tag
1376−# value is set to YES, a side panel will be generated containing a tree-like
1377−# index structure (just like the one that is generated for HTML Help). For this
1378−# to work a browser that supports JavaScript, DHTML, CSS and frames is required
1379−# (i.e. any modern browser). Windows users are probably better off using the
1380−# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
1381−# further fine-tune the look of the index. As an example, the default style
1382−# sheet generated by doxygen has an example that shows how to put an image at
1383−# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
1384−# the same information as the tab index, you could consider setting
1385−# DISABLE_INDEX to YES when enabling this option.
1386−# The default value is: NO.
1387−# This tag requires that the tag GENERATE_HTML is set to YES.
1388−
1389−GENERATE_TREEVIEW = NO
1390−
1391−# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
1392−# doxygen will group on one line in the generated HTML documentation.
1393−#
1394−# Note that a value of 0 will completely suppress the enum values from appearing
1395−# in the overview section.
1396−# Minimum value: 0, maximum value: 20, default value: 4.
1397−# This tag requires that the tag GENERATE_HTML is set to YES.
1398−
1399−ENUM_VALUES_PER_LINE = 4
1400−
1401−# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
1402−# to set the initial width (in pixels) of the frame in which the tree is shown.
1403−# Minimum value: 0, maximum value: 1500, default value: 250.
1404−# This tag requires that the tag GENERATE_HTML is set to YES.
1405−
1406−TREEVIEW_WIDTH = 250
1407−
1408−# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
1409−# external symbols imported via tag files in a separate window.
1410−# The default value is: NO.
1411−# This tag requires that the tag GENERATE_HTML is set to YES.
1412−
1413−EXT_LINKS_IN_WINDOW = NO
1414−
1415−# Use this tag to change the font size of LaTeX formulas included as images in
1416−# the HTML documentation. When you change the font size after a successful
1417−# doxygen run you need to manually remove any form_*.png images from the HTML
1418−# output directory to force them to be regenerated.
1419−# Minimum value: 8, maximum value: 50, default value: 10.
1420−# This tag requires that the tag GENERATE_HTML is set to YES.
1421−
1422−FORMULA_FONTSIZE = 10
1423−
1424−# Use the FORMULA_TRANPARENT tag to determine whether or not the images
1425−# generated for formulas are transparent PNGs. Transparent PNGs are not
1426−# supported properly for IE 6.0, but are supported on all modern browsers.
1427−#
1428−# Note that when changing this option you need to delete any form_*.png files in
1429−# the HTML output directory before the changes have effect.
1430−# The default value is: YES.
1431−# This tag requires that the tag GENERATE_HTML is set to YES.
1432−
1433−FORMULA_TRANSPARENT = YES
1434−
1435−# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1436−# http://www.mathjax.org) which uses client side Javascript for the rendering
1437−# instead of using prerendered bitmaps. Use this if you do not have LaTeX
1438−# installed or if you want to formulas look prettier in the HTML output. When
1439−# enabled you may also need to install MathJax separately and configure the path
1440−# to it using the MATHJAX_RELPATH option.
1441−# The default value is: NO.
1442−# This tag requires that the tag GENERATE_HTML is set to YES.
1443−
1444−USE_MATHJAX = YES
1445−
1446−# When MathJax is enabled you can set the default output format to be used for
1447−# the MathJax output. See the MathJax site (see:
1448−# http://docs.mathjax.org/en/latest/output.html) for more details.
1449−# Possible values are: HTML-CSS (which is slower, but has the best
1450−# compatibility), NativeMML (i.e. MathML) and SVG.
1451−# The default value is: HTML-CSS.
1452−# This tag requires that the tag USE_MATHJAX is set to YES.
1453−
1454−MATHJAX_FORMAT = HTML-CSS
1455−
1456−# When MathJax is enabled you need to specify the location relative to the HTML
1457−# output directory using the MATHJAX_RELPATH option. The destination directory
1458−# should contain the MathJax.js script. For instance, if the mathjax directory
1459−# is located at the same level as the HTML output directory, then
1460−# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
1461−# Content Delivery Network so you can quickly see the result without installing
1462−# MathJax. However, it is strongly recommended to install a local copy of
1463−# MathJax from http://www.mathjax.org before deployment.
1464−# The default value is: http://cdn.mathjax.org/mathjax/latest.
1465−# This tag requires that the tag USE_MATHJAX is set to YES.
1466−
1467−MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
1468−
1469−# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1470−# extension names that should be enabled during MathJax rendering. For example
1471−# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
1472−# This tag requires that the tag USE_MATHJAX is set to YES.
1473−
1474−MATHJAX_EXTENSIONS =
1475−
1476−# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
1477−# of code that will be used on startup of the MathJax code. See the MathJax site
1478−# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
1479−# example see the documentation.
1480−# This tag requires that the tag USE_MATHJAX is set to YES.
1481−
1482−MATHJAX_CODEFILE =
1483−
1484−# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
1485−# the HTML output. The underlying search engine uses javascript and DHTML and
1486−# should work on any modern browser. Note that when using HTML help
1487−# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
1488−# there is already a search function so this one should typically be disabled.
1489−# For large projects the javascript based search engine can be slow, then
1490−# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
1491−# search using the keyboard; to jump to the search box use <access key> + S
1492−# (what the <access key> is depends on the OS and browser, but it is typically
1493−# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
1494−# key> to jump into the search results window, the results can be navigated
1495−# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
1496−# the search. The filter options can be selected when the cursor is inside the
1497−# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
1498−# to select a filter and <Enter> or <escape> to activate or cancel the filter
1499−# option.
1500−# The default value is: YES.
1501−# This tag requires that the tag GENERATE_HTML is set to YES.
1502−
1503−SEARCHENGINE = YES
1504−
1505−# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
1506−# implemented using a web server instead of a web client using Javascript. There
1507−# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
1508−# setting. When disabled, doxygen will generate a PHP script for searching and
1509−# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
1510−# and searching needs to be provided by external tools. See the section
1511−# "External Indexing and Searching" for details.
1512−# The default value is: NO.
1513−# This tag requires that the tag SEARCHENGINE is set to YES.
1514−
1515−SERVER_BASED_SEARCH = NO
1516−
1517−# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
1518−# script for searching. Instead the search results are written to an XML file
1519−# which needs to be processed by an external indexer. Doxygen will invoke an
1520−# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1521−# search results.
1522−#
1523−# Doxygen ships with an example indexer ( doxyindexer) and search engine
1524−# (doxysearch.cgi) which are based on the open source search engine library
1525−# Xapian (see: http://xapian.org/).
1526−#
1527−# See the section "External Indexing and Searching" for details.
1528−# The default value is: NO.
1529−# This tag requires that the tag SEARCHENGINE is set to YES.
1530−
1531−EXTERNAL_SEARCH = NO
1532−
1533−# The SEARCHENGINE_URL should point to a search engine hosted by a web server
1534−# which will return the search results when EXTERNAL_SEARCH is enabled.
1535−#
1536−# Doxygen ships with an example indexer ( doxyindexer) and search engine
1537−# (doxysearch.cgi) which are based on the open source search engine library
1538−# Xapian (see: http://xapian.org/). See the section "External Indexing and
1539−# Searching" for details.
1540−# This tag requires that the tag SEARCHENGINE is set to YES.
1541−
1542−SEARCHENGINE_URL =
1543−
1544−# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
1545−# search data is written to a file for indexing by an external tool. With the
1546−# SEARCHDATA_FILE tag the name of this file can be specified.
1547−# The default file is: searchdata.xml.
1548−# This tag requires that the tag SEARCHENGINE is set to YES.
1549−
1550−SEARCHDATA_FILE = searchdata.xml
1551−
1552−# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
1553−# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
1554−# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
1555−# projects and redirect the results back to the right project.
1556−# This tag requires that the tag SEARCHENGINE is set to YES.
1557−
1558−EXTERNAL_SEARCH_ID =
1559−
1560−# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
1561−# projects other than the one defined by this configuration file, but that are
1562−# all added to the same external search index. Each project needs to have a
1563−# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
1564−# to a relative location where the documentation can be found. The format is:
1565−# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
1566−# This tag requires that the tag SEARCHENGINE is set to YES.
1567−
1568−EXTRA_SEARCH_MAPPINGS =
1569−
1570−#---------------------------------------------------------------------------
1571−# Configuration options related to the LaTeX output
1572−#---------------------------------------------------------------------------
1573−
1574−# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
1575−# The default value is: YES.
1576−
1577−GENERATE_LATEX = NO
1578−
1579−# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
1580−# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1581−# it.
1582−# The default directory is: latex.
1583−# This tag requires that the tag GENERATE_LATEX is set to YES.
1584−
1585−LATEX_OUTPUT = latex
1586−
1587−# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1588−# invoked.
1589−#
1590−# Note that when enabling USE_PDFLATEX this option is only used for generating
1591−# bitmaps for formulas in the HTML output, but not in the Makefile that is
1592−# written to the output directory.
1593−# The default file is: latex.
1594−# This tag requires that the tag GENERATE_LATEX is set to YES.
1595−
1596−LATEX_CMD_NAME = latex
1597−
1598−# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
1599−# index for LaTeX.
1600−# The default file is: makeindex.
1601−# This tag requires that the tag GENERATE_LATEX is set to YES.
1602−
1603−MAKEINDEX_CMD_NAME = makeindex
1604−
1605−# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
1606−# documents. This may be useful for small projects and may help to save some
1607−# trees in general.
1608−# The default value is: NO.
1609−# This tag requires that the tag GENERATE_LATEX is set to YES.
1610−
1611−COMPACT_LATEX = NO
1612−
1613−# The PAPER_TYPE tag can be used to set the paper type that is used by the
1614−# printer.
1615−# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
1616−# 14 inches) and executive (7.25 x 10.5 inches).
1617−# The default value is: a4.
1618−# This tag requires that the tag GENERATE_LATEX is set to YES.
1619−
1620−PAPER_TYPE = a4
1621−
1622−# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1623−# that should be included in the LaTeX output. To get the times font for
1624−# instance you can specify
1625−# EXTRA_PACKAGES=times
1626−# If left blank no extra packages will be included.
1627−# This tag requires that the tag GENERATE_LATEX is set to YES.
1628−
1629−EXTRA_PACKAGES =
1630−
1631−# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
1632−# generated LaTeX document. The header should contain everything until the first
1633−# chapter. If it is left blank doxygen will generate a standard header. See
1634−# section "Doxygen usage" for information on how to let doxygen write the
1635−# default header to a separate file.
1636−#
1637−# Note: Only use a user-defined header if you know what you are doing! The
1638−# following commands have a special meaning inside the header: $title,
1639−# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1640−# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
1641−# for the replacement values of the other commands the user is refered to
1642−# HTML_HEADER.
1643−# This tag requires that the tag GENERATE_LATEX is set to YES.
1644−
1645−LATEX_HEADER =
1646−
1647−# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
1648−# generated LaTeX document. The footer should contain everything after the last
1649−# chapter. If it is left blank doxygen will generate a standard footer. See
1650−# LATEX_HEADER for more information on how to generate a default footer and what
1651−# special commands can be used inside the footer.
1652−#
1653−# Note: Only use a user-defined footer if you know what you are doing!
1654−# This tag requires that the tag GENERATE_LATEX is set to YES.
1655−
1656−LATEX_FOOTER =
1657−
1658−# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1659−# other source files which should be copied to the LATEX_OUTPUT output
1660−# directory. Note that the files will be copied as-is; there are no commands or
1661−# markers available.
1662−# This tag requires that the tag GENERATE_LATEX is set to YES.
1663−
1664−LATEX_EXTRA_FILES =
1665−
1666−# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
1667−# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
1668−# contain links (just like the HTML output) instead of page references. This
1669−# makes the output suitable for online browsing using a PDF viewer.
1670−# The default value is: YES.
1671−# This tag requires that the tag GENERATE_LATEX is set to YES.
1672−
1673−PDF_HYPERLINKS = YES
1674−
1675−# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
1676−# the PDF file directly from the LaTeX files. Set this option to YES to get a
1677−# higher quality PDF documentation.
1678−# The default value is: YES.
1679−# This tag requires that the tag GENERATE_LATEX is set to YES.
1680−
1681−USE_PDFLATEX = YES
1682−
1683−# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
1684−# command to the generated LaTeX files. This will instruct LaTeX to keep running
1685−# if errors occur, instead of asking the user for help. This option is also used
1686−# when generating formulas in HTML.
1687−# The default value is: NO.
1688−# This tag requires that the tag GENERATE_LATEX is set to YES.
1689−
1690−LATEX_BATCHMODE = NO
1691−
1692−# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
1693−# index chapters (such as File Index, Compound Index, etc.) in the output.
1694−# The default value is: NO.
1695−# This tag requires that the tag GENERATE_LATEX is set to YES.
1696−
1697−LATEX_HIDE_INDICES = NO
1698−
1699−# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
1700−# code with syntax highlighting in the LaTeX output.
1701−#
1702−# Note that which sources are shown also depends on other settings such as
1703−# SOURCE_BROWSER.
1704−# The default value is: NO.
1705−# This tag requires that the tag GENERATE_LATEX is set to YES.
1706−
1707−LATEX_SOURCE_CODE = NO
1708−
1709−# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
1710−# bibliography, e.g. plainnat, or ieeetr. See
1711−# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
1712−# The default value is: plain.
1713−# This tag requires that the tag GENERATE_LATEX is set to YES.
1714−
1715−LATEX_BIB_STYLE = plain
1716−
1717−#---------------------------------------------------------------------------
1718−# Configuration options related to the RTF output
1719−#---------------------------------------------------------------------------
1720−
1721−# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
1722−# RTF output is optimized for Word 97 and may not look too pretty with other RTF
1723−# readers/editors.
1724−# The default value is: NO.
1725−
1726−GENERATE_RTF = NO
1727−
1728−# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
1729−# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1730−# it.
1731−# The default directory is: rtf.
1732−# This tag requires that the tag GENERATE_RTF is set to YES.
1733−
1734−RTF_OUTPUT = rtf
1735−
1736−# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
1737−# documents. This may be useful for small projects and may help to save some
1738−# trees in general.
1739−# The default value is: NO.
1740−# This tag requires that the tag GENERATE_RTF is set to YES.
1741−
1742−COMPACT_RTF = NO
1743−
1744−# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
1745−# contain hyperlink fields. The RTF file will contain links (just like the HTML
1746−# output) instead of page references. This makes the output suitable for online
1747−# browsing using Word or some other Word compatible readers that support those
1748−# fields.
1749−#
1750−# Note: WordPad (write) and others do not support links.
1751−# The default value is: NO.
1752−# This tag requires that the tag GENERATE_RTF is set to YES.
1753−
1754−RTF_HYPERLINKS = NO
1755−
1756−# Load stylesheet definitions from file. Syntax is similar to doxygen's config
1757−# file, i.e. a series of assignments. You only have to provide replacements,
1758−# missing definitions are set to their default value.
1759−#
1760−# See also section "Doxygen usage" for information on how to generate the
1761−# default style sheet that doxygen normally uses.
1762−# This tag requires that the tag GENERATE_RTF is set to YES.
1763−
1764−RTF_STYLESHEET_FILE =
1765−
1766−# Set optional variables used in the generation of an RTF document. Syntax is
1767−# similar to doxygen's config file. A template extensions file can be generated
1768−# using doxygen -e rtf extensionFile.
1769−# This tag requires that the tag GENERATE_RTF is set to YES.
1770−
1771−RTF_EXTENSIONS_FILE =
1772−
1773−#---------------------------------------------------------------------------
1774−# Configuration options related to the man page output
1775−#---------------------------------------------------------------------------
1776−
1777−# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
1778−# classes and files.
1779−# The default value is: NO.
1780−
1781−GENERATE_MAN = NO
1782−
1783−# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
1784−# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1785−# it. A directory man3 will be created inside the directory specified by
1786−# MAN_OUTPUT.
1787−# The default directory is: man.
1788−# This tag requires that the tag GENERATE_MAN is set to YES.
1789−
1790−MAN_OUTPUT = man
1791−
1792−# The MAN_EXTENSION tag determines the extension that is added to the generated
1793−# man pages. In case the manual section does not start with a number, the number
1794−# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
1795−# optional.
1796−# The default value is: .3.
1797−# This tag requires that the tag GENERATE_MAN is set to YES.
1798−
1799−MAN_EXTENSION = .3
1800−
1801−# The MAN_SUBDIR tag determines the name of the directory created within
1802−# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
1803−# MAN_EXTENSION with the initial . removed.
1804−# This tag requires that the tag GENERATE_MAN is set to YES.
1805−
1806−MAN_SUBDIR =
1807−
1808−# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
1809−# will generate one additional man file for each entity documented in the real
1810−# man page(s). These additional files only source the real man page, but without
1811−# them the man command would be unable to find the correct page.
1812−# The default value is: NO.
1813−# This tag requires that the tag GENERATE_MAN is set to YES.
1814−
1815−MAN_LINKS = NO
1816−
1817−#---------------------------------------------------------------------------
1818−# Configuration options related to the XML output
1819−#---------------------------------------------------------------------------
1820−
1821−# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
1822−# captures the structure of the code including all documentation.
1823−# The default value is: NO.
1824−
1825−GENERATE_XML = NO
1826−
1827−# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
1828−# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1829−# it.
1830−# The default directory is: xml.
1831−# This tag requires that the tag GENERATE_XML is set to YES.
1832−
1833−XML_OUTPUT = xml
1834−
1835−# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
1836−# listings (including syntax highlighting and cross-referencing information) to
1837−# the XML output. Note that enabling this will significantly increase the size
1838−# of the XML output.
1839−# The default value is: YES.
1840−# This tag requires that the tag GENERATE_XML is set to YES.
1841−
1842−XML_PROGRAMLISTING = YES
1843−
1844−#---------------------------------------------------------------------------
1845−# Configuration options related to the DOCBOOK output
1846−#---------------------------------------------------------------------------
1847−
1848−# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
1849−# that can be used to generate PDF.
1850−# The default value is: NO.
1851−
1852−GENERATE_DOCBOOK = NO
1853−
1854−# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
1855−# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
1856−# front of it.
1857−# The default directory is: docbook.
1858−# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1859−
1860−DOCBOOK_OUTPUT = docbook
1861−
1862−# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
1863−# program listings (including syntax highlighting and cross-referencing
1864−# information) to the DOCBOOK output. Note that enabling this will significantly
1865−# increase the size of the DOCBOOK output.
1866−# The default value is: NO.
1867−# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1868−
1869−DOCBOOK_PROGRAMLISTING = NO
1870−
1871−#---------------------------------------------------------------------------
1872−# Configuration options for the AutoGen Definitions output
1873−#---------------------------------------------------------------------------
1874−
1875−# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
1876−# Definitions (see http://autogen.sf.net) file that captures the structure of
1877−# the code including all documentation. Note that this feature is still
1878−# experimental and incomplete at the moment.
1879−# The default value is: NO.
1880−
1881−GENERATE_AUTOGEN_DEF = NO
1882−
1883−#---------------------------------------------------------------------------
1884−# Configuration options related to the Perl module output
1885−#---------------------------------------------------------------------------
1886−
1887−# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
1888−# file that captures the structure of the code including all documentation.
1889−#
1890−# Note that this feature is still experimental and incomplete at the moment.
1891−# The default value is: NO.
1892−
1893−GENERATE_PERLMOD = NO
1894−
1895−# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
1896−# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
1897−# output from the Perl module output.
1898−# The default value is: NO.
1899−# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1900−
1901−PERLMOD_LATEX = NO
1902−
1903−# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
1904−# formatted so it can be parsed by a human reader. This is useful if you want to
1905−# understand what is going on. On the other hand, if this tag is set to NO the
1906−# size of the Perl module output will be much smaller and Perl will parse it
1907−# just the same.
1908−# The default value is: YES.
1909−# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1910−
1911−PERLMOD_PRETTY = YES
1912−
1913−# The names of the make variables in the generated doxyrules.make file are
1914−# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
1915−# so different doxyrules.make files included by the same Makefile don't
1916−# overwrite each other's variables.
1917−# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1918−
1919−PERLMOD_MAKEVAR_PREFIX =
1920−
1921−#---------------------------------------------------------------------------
1922−# Configuration options related to the preprocessor
1923−#---------------------------------------------------------------------------
1924−
1925−# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
1926−# C-preprocessor directives found in the sources and include files.
1927−# The default value is: YES.
1928−
1929−ENABLE_PREPROCESSING = YES
1930−
1931−# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
1932−# in the source code. If set to NO only conditional compilation will be
1933−# performed. Macro expansion can be done in a controlled way by setting
1934−# EXPAND_ONLY_PREDEF to YES.
1935−# The default value is: NO.
1936−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1937−
1938−MACRO_EXPANSION = NO
1939−
1940−# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
1941−# the macro expansion is limited to the macros specified with the PREDEFINED and
1942−# EXPAND_AS_DEFINED tags.
1943−# The default value is: NO.
1944−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1945−
1946−EXPAND_ONLY_PREDEF = NO
1947−
1948−# If the SEARCH_INCLUDES tag is set to YES the includes files in the
1949−# INCLUDE_PATH will be searched if a #include is found.
1950−# The default value is: YES.
1951−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1952−
1953−SEARCH_INCLUDES = YES
1954−
1955−# The INCLUDE_PATH tag can be used to specify one or more directories that
1956−# contain include files that are not input files but should be processed by the
1957−# preprocessor.
1958−# This tag requires that the tag SEARCH_INCLUDES is set to YES.
1959−
1960−INCLUDE_PATH =
1961−
1962−# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
1963−# patterns (like *.h and *.hpp) to filter out the header-files in the
1964−# directories. If left blank, the patterns specified with FILE_PATTERNS will be
1965−# used.
1966−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1967−
196810 INCLUDE_FILE_PATTERNS =
1969−
1970−# The PREDEFINED tag can be used to specify one or more macro names that are
1971−# defined before the preprocessor is started (similar to the -D option of e.g.
1972−# gcc). The argument of the tag is a list of macros of the form: name or
1973−# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
1974−# is assumed. To prevent a macro definition from being undefined via #undef or
1975−# recursively expanded use the := operator instead of the = operator.
1976−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1977−
1978−PREDEFINED =
1979−
1980−# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
1981−# tag can be used to specify a list of macro names that should be expanded. The
1982−# macro definition that is found in the sources will be used. Use the PREDEFINED
1983−# tag if you want to use a different macro definition that overrules the
1984−# definition found in the source code.
1985−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1986−
1987−EXPAND_AS_DEFINED =
1988−
1989−# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
1990−# remove all references to function-like macros that are alone on a line, have
1991−# an all uppercase name, and do not end with a semicolon. Such function macros
1992−# are typically used for boiler-plate code, and will confuse the parser if not
1993−# removed.
1994−# The default value is: YES.
1995−# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1996−
1997−SKIP_FUNCTION_MACROS = YES
1998−
1999−#---------------------------------------------------------------------------
2000−# Configuration options related to external references
2001−#---------------------------------------------------------------------------
2002−
2003−# The TAGFILES tag can be used to specify one or more tag files. For each tag
2004−# file the location of the external documentation should be added. The format of
2005−# a tag file without this location is as follows:
2006−# TAGFILES = file1 file2 ...
2007−# Adding location for the tag files is done as follows:
2008−# TAGFILES = file1=loc1 "file2 = loc2" ...
2009−# where loc1 and loc2 can be relative or absolute paths or URLs. See the
2010−# section "Linking to external documentation" for more information about the use
2011−# of tag files.
2012−# Note: Each tag file must have a unique name (where the name does NOT include
2013−# the path). If a tag file is not located in the directory in which doxygen is
2014−# run, you must also specify the path to the tagfile here.
2015−
2016−TAGFILES =
2017−
2018−# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
2019−# tag file that is based on the input files it reads. See section "Linking to
2020−# external documentation" for more information about the usage of tag files.
2021−
2022−GENERATE_TAGFILE =
2023−
2024−# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
2025−# class index. If set to NO only the inherited external classes will be listed.
2026−# The default value is: NO.
2027−
2028−ALLEXTERNALS = NO
2029−
2030−# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
2031−# the modules index. If set to NO, only the current project's groups will be
2032−# listed.
2033−# The default value is: YES.
2034−
2035−EXTERNAL_GROUPS = YES
2036−
2037−# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
2038−# the related pages index. If set to NO, only the current project's pages will
2039−# be listed.
2040−# The default value is: YES.
2041−
2042−EXTERNAL_PAGES = YES
2043−
2044−# The PERL_PATH should be the absolute path and name of the perl script
2045−# interpreter (i.e. the result of 'which perl').
2046−# The default file (with absolute path) is: /usr/bin/perl.
2047−
2048−PERL_PATH = /usr/bin/perl
2049−
2050−#---------------------------------------------------------------------------
2051−# Configuration options related to the dot tool
2052−#---------------------------------------------------------------------------
2053−
2054−# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
2055−# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
2056−# NO turns the diagrams off. Note that this option also works with HAVE_DOT
2057−# disabled, but it is recommended to install and use dot, since it yields more
2058−# powerful graphs.
2059−# The default value is: YES.
2060−
2061−CLASS_DIAGRAMS = YES
2062−
2063−# You can define message sequence charts within doxygen comments using the \msc
2064−# command. Doxygen will then run the mscgen tool (see:
2065−# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
2066−# documentation. The MSCGEN_PATH tag allows you to specify the directory where
2067−# the mscgen tool resides. If left empty the tool is assumed to be found in the
2068−# default search path.
2069−
2070−MSCGEN_PATH =
2071−
2072−# You can include diagrams made with dia in doxygen documentation. Doxygen will
2073−# then run dia to produce the diagram and insert it in the documentation. The
2074−# DIA_PATH tag allows you to specify the directory where the dia binary resides.
2075−# If left empty dia is assumed to be found in the default search path.
2076−
2077−DIA_PATH =
2078−
2079−# If set to YES, the inheritance and collaboration graphs will hide inheritance
2080−# and usage relations if the target is undocumented or is not a class.
2081−# The default value is: YES.
2082−
208311 HIDE_UNDOC_RELATIONS = NO
2084−
2085−# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
2086−# available from the path. This tool is part of Graphviz (see:
2087−# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
2088−# Bell Labs. The other options in this section have no effect if this option is
2089−# set to NO
2090−# The default value is: YES.
2091−
2092−HAVE_DOT = NO
2093−
2094−# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
2095−# to run in parallel. When set to 0 doxygen will base this on the number of
2096−# processors available in the system. You can set it explicitly to a value
2097−# larger than 0 to get control over the balance between CPU load and processing
2098−# speed.
2099−# Minimum value: 0, maximum value: 32, default value: 0.
2100−# This tag requires that the tag HAVE_DOT is set to YES.
2101−
2102−DOT_NUM_THREADS = 0
2103−
2104−# When you want a differently looking font in the dot files that doxygen
2105−# generates you can specify the font name using DOT_FONTNAME. You need to make
2106−# sure dot is able to find the font, which can be done by putting it in a
2107−# standard location or by setting the DOTFONTPATH environment variable or by
2108−# setting DOT_FONTPATH to the directory containing the font.
2109−# The default value is: Helvetica.
2110−# This tag requires that the tag HAVE_DOT is set to YES.
2111−
2112−DOT_FONTNAME =
2113−
2114−# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
2115−# dot graphs.
2116−# Minimum value: 4, maximum value: 24, default value: 10.
2117−# This tag requires that the tag HAVE_DOT is set to YES.
2118−
2119−DOT_FONTSIZE = 10
2120−
2121−# By default doxygen will tell dot to use the default font as specified with
2122−# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
2123−# the path where dot can find it using this tag.
2124−# This tag requires that the tag HAVE_DOT is set to YES.
2125−
2126−DOT_FONTPATH =
2127−
2128−# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
2129−# each documented class showing the direct and indirect inheritance relations.
2130−# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
2131−# The default value is: YES.
2132−# This tag requires that the tag HAVE_DOT is set to YES.
2133−
2134−CLASS_GRAPH = YES
2135−
2136−# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
2137−# graph for each documented class showing the direct and indirect implementation
2138−# dependencies (inheritance, containment, and class references variables) of the
2139−# class with other documented classes.
2140−# The default value is: YES.
2141−# This tag requires that the tag HAVE_DOT is set to YES.
2142−
2143−COLLABORATION_GRAPH = YES
2144−
2145−# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
2146−# groups, showing the direct groups dependencies.
2147−# The default value is: YES.
2148−# This tag requires that the tag HAVE_DOT is set to YES.
2149−
2150−GROUP_GRAPHS = YES
2151−
2152−# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
2153−# collaboration diagrams in a style similar to the OMG's Unified Modeling
2154−# Language.
2155−# The default value is: NO.
2156−# This tag requires that the tag HAVE_DOT is set to YES.
2157−
2158−UML_LOOK = NO
2159−
2160−# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
2161−# class node. If there are many fields or methods and many nodes the graph may
2162−# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
2163−# number of items for each type to make the size more manageable. Set this to 0
2164−# for no limit. Note that the threshold may be exceeded by 50% before the limit
2165−# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
2166−# but if the number exceeds 15, the total amount of fields shown is limited to
2167−# 10.
2168−# Minimum value: 0, maximum value: 100, default value: 10.
2169−# This tag requires that the tag HAVE_DOT is set to YES.
2170−
2171−UML_LIMIT_NUM_FIELDS = 10
2172−
2173−# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
2174−# collaboration graphs will show the relations between templates and their
2175−# instances.
2176−# The default value is: NO.
2177−# This tag requires that the tag HAVE_DOT is set to YES.
2178−
2179−TEMPLATE_RELATIONS = NO
2180−
2181−# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
2182−# YES then doxygen will generate a graph for each documented file showing the
2183−# direct and indirect include dependencies of the file with other documented
2184−# files.
2185−# The default value is: YES.
2186−# This tag requires that the tag HAVE_DOT is set to YES.
2187−
2188−INCLUDE_GRAPH = YES
2189−
2190−# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
2191−# set to YES then doxygen will generate a graph for each documented file showing
2192−# the direct and indirect include dependencies of the file with other documented
2193−# files.
2194−# The default value is: YES.
2195−# This tag requires that the tag HAVE_DOT is set to YES.
2196−
2197−INCLUDED_BY_GRAPH = YES
2198−
2199−# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
2200−# dependency graph for every global function or class method.
2201−#
2202−# Note that enabling this option will significantly increase the time of a run.
2203−# So in most cases it will be better to enable call graphs for selected
2204−# functions only using the \callgraph command.
2205−# The default value is: NO.
2206−# This tag requires that the tag HAVE_DOT is set to YES.
2207−
2208−CALL_GRAPH = NO
2209−
2210−# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
2211−# dependency graph for every global function or class method.
2212−#
2213−# Note that enabling this option will significantly increase the time of a run.
2214−# So in most cases it will be better to enable caller graphs for selected
2215−# functions only using the \callergraph command.
2216−# The default value is: NO.
2217−# This tag requires that the tag HAVE_DOT is set to YES.
2218−
2219−CALLER_GRAPH = NO
2220−
2221−# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
2222−# hierarchy of all classes instead of a textual one.
2223−# The default value is: YES.
2224−# This tag requires that the tag HAVE_DOT is set to YES.
2225−
2226−GRAPHICAL_HIERARCHY = YES
2227−
2228−# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
2229−# dependencies a directory has on other directories in a graphical way. The
2230−# dependency relations are determined by the #include relations between the
2231−# files in the directories.
2232−# The default value is: YES.
2233−# This tag requires that the tag HAVE_DOT is set to YES.
2234−
2235−DIRECTORY_GRAPH = YES
2236−
2237−# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
2238−# generated by dot.
2239−# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2240−# to make the SVG files visible in IE 9+ (other browsers do not have this
2241−# requirement).
2242−# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
2243−# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
2244−# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
2245−# The default value is: png.
2246−# This tag requires that the tag HAVE_DOT is set to YES.
2247−
2248−DOT_IMAGE_FORMAT = png
2249−
2250−# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
2251−# enable generation of interactive SVG images that allow zooming and panning.
2252−#
2253−# Note that this requires a modern browser other than Internet Explorer. Tested
2254−# and working are Firefox, Chrome, Safari, and Opera.
2255−# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
2256−# the SVG files visible. Older versions of IE do not have SVG support.
2257−# The default value is: NO.
2258−# This tag requires that the tag HAVE_DOT is set to YES.
2259−
2260−INTERACTIVE_SVG = NO
2261−
2262−# The DOT_PATH tag can be used to specify the path where the dot tool can be
2263−# found. If left blank, it is assumed the dot tool can be found in the path.
2264−# This tag requires that the tag HAVE_DOT is set to YES.
2265−
2266−DOT_PATH =
2267−
2268−# The DOTFILE_DIRS tag can be used to specify one or more directories that
2269−# contain dot files that are included in the documentation (see the \dotfile
2270−# command).
2271−# This tag requires that the tag HAVE_DOT is set to YES.
2272−
2273−DOTFILE_DIRS =
2274−
2275−# The MSCFILE_DIRS tag can be used to specify one or more directories that
2276−# contain msc files that are included in the documentation (see the \mscfile
2277−# command).
2278−
2279−MSCFILE_DIRS =
2280−
2281−# The DIAFILE_DIRS tag can be used to specify one or more directories that
2282−# contain dia files that are included in the documentation (see the \diafile
2283−# command).
2284−
2285−DIAFILE_DIRS =
2286−
2287−# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
2288−# path where java can find the plantuml.jar file. If left blank, it is assumed
2289−# PlantUML is not used or called during a preprocessing step. Doxygen will
2290−# generate a warning when it encounters a \startuml command in this case and
2291−# will not generate output for the diagram.
2292−# This tag requires that the tag HAVE_DOT is set to YES.
2293−
2294−PLANTUML_JAR_PATH =
2295−
2296−# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2297−# that will be shown in the graph. If the number of nodes in a graph becomes
2298−# larger than this value, doxygen will truncate the graph, which is visualized
2299−# by representing a node as a red box. Note that doxygen if the number of direct
2300−# children of the root node in a graph is already larger than
2301−# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
2302−# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2303−# Minimum value: 0, maximum value: 10000, default value: 50.
2304−# This tag requires that the tag HAVE_DOT is set to YES.
2305−
2306−DOT_GRAPH_MAX_NODES = 50
2307−
2308−# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
2309−# generated by dot. A depth value of 3 means that only nodes reachable from the
2310−# root by following a path via at most 3 edges will be shown. Nodes that lay
2311−# further from the root node will be omitted. Note that setting this option to 1
2312−# or 2 may greatly reduce the computation time needed for large code bases. Also
2313−# note that the size of a graph can be further restricted by
2314−# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
2315−# Minimum value: 0, maximum value: 1000, default value: 0.
2316−# This tag requires that the tag HAVE_DOT is set to YES.
2317−
2318−MAX_DOT_GRAPH_DEPTH = 0
2319−
2320−# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
2321−# background. This is disabled by default, because dot on Windows does not seem
2322−# to support this out of the box.
2323−#
2324−# Warning: Depending on the platform used, enabling this option may lead to
2325−# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
2326−# read).
2327−# The default value is: NO.
2328−# This tag requires that the tag HAVE_DOT is set to YES.
2329−
2330−DOT_TRANSPARENT = NO
2331−
2332−# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
2333−# files in one run (i.e. multiple -o and -T options on the command line). This
2334−# makes dot run faster, but since only newer versions of dot (>1.8.10) support
2335−# this, this feature is disabled by default.
2336−# The default value is: NO.
2337−# This tag requires that the tag HAVE_DOT is set to YES.
2338−
2339−DOT_MULTI_TARGETS = NO
2340−
2341−# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
2342−# explaining the meaning of the various boxes and arrows in the dot generated
2343−# graphs.
2344−# The default value is: YES.
2345−# This tag requires that the tag HAVE_DOT is set to YES.
2346−
2347−GENERATE_LEGEND = YES
2348−
2349−# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
2350−# files that are used to generate the various graphs.
2351−# The default value is: YES.
2352−# This tag requires that the tag HAVE_DOT is set to YES.
2353−
2354−DOT_CLEANUP = YES
doc/index.rst+35−60
@@ -10,6 +10,38 @@ aubio features include segmenting a sound file before each of its attacks, · 9 unmodified lines
1010 performing pitch detection, tapping the beat and producing midi streams from
1111 live audio.
1212
13+Quick links
14+===========
15+
16+* :ref:`python`
17+* :ref:`manpages`
18+* :ref:`develop`
19+* :ref:`building`
20+
21+.. only:: devel
22+
23+ .. include:: statuslinks.rst
24+
25+Project pages
26+=============
27+
28+* `Project homepage`_: https://aubio.org
29+* `aubio on github`_: https://github.com/aubio/aubio
30+* `aubio on pypi`_: https://pypi.python.org/pypi/aubio
31+* `Doxygen documentation`_: https://aubio.org/doc/latest/
32+* `Mailing lists`_: https://lists.aubio.org
33+
34+.. _Project homepage: https://aubio.org
35+.. _aubio on github: https://github.com/aubio/aubio
36+.. _aubio on pypi: https://pypi.python.org/pypi/aubio
37+.. _Doxygen documentation: https://aubio.org/doc/latest/
38+.. _Mailing lists: https://lists.aubio.org/
39+
40+* `Travis Continuous integration page <https://travis-ci.org/aubio/aubio>`_
41+* `Appveyor Continuous integration page <https://ci.appveyor.com/project/piem/aubio>`_
42+* `Landscape python code validation <https://landscape.io/github/aubio/aubio/master>`_
43+* `ReadTheDocs documentation <https://aubio.readthedocs.io/en/latest/>`_
44+
1345 Features
1446 ========
1547
@@ -37,65 +69,8 @@ Content · 21 unmodified lines
3769 :maxdepth: 2
3870
3971 installing
40− cli
4172 python_module
73+ python
74+ cli
4275 develop
43−
44−Project pages
45−=============
46−
47−* `Project homepage`_: https://aubio.org
48−* `aubio on github`_: https://github.com/aubio/aubio
49−* `aubio on pypi`_: https://pypi.python.org/pypi/aubio
50−* `Doxygen documentation`_: https://aubio.org/doc/latest/
51−* `Mailing lists`_: https://lists.aubio.org
52−
53−.. _Project homepage: https://aubio.org
54−.. _aubio on github: https://github.com/aubio/aubio
55−.. _aubio on pypi: https://pypi.python.org/pypi/aubio
56−.. _Doxygen documentation: https://aubio.org/doc/latest/
57−.. _Mailing lists: https://lists.aubio.org/
58−
59−Current status
60−==============
61−
62−.. image:: https://travis-ci.org/aubio/aubio.svg?branch=master
63− :target: https://travis-ci.org/aubio/aubio
64− :alt: Travis build status
65−
66−.. image:: https://ci.appveyor.com/api/projects/status/f3lhy3a57rkgn5yi?svg=true
67− :target: https://ci.appveyor.com/project/piem/aubio/
68− :alt: Appveyor build status
69−
70−.. image:: https://landscape.io/github/aubio/aubio/master/landscape.svg?style=flat
71− :target: https://landscape.io/github/aubio/aubio/master
72− :alt: Landscape code health
73−
74−.. image:: https://readthedocs.org/projects/aubio/badge/?version=latest
75− :target: http://aubio.readthedocs.io/en/latest/?badge=latest
76− :alt: Documentation status
77−
78−.. image:: https://img.shields.io/github/commits-since/aubio/aubio/0.4.3.svg?maxAge=2592000
79− :target: https://github.com/aubio/aubio
80− :alt: Commits since last release
81−
82−* `Travis Continuous integration page <https://travis-ci.org/aubio/aubio>`_
83−* `Appveyor Continuous integration page <https://ci.appveyor.com/project/piem/aubio>`_
84−* `Landscape python code validation <https://landscape.io/github/aubio/aubio/master>`_
85−* `ReadTheDocs documentation <http://aubio.readthedocs.io/en/latest/>`_
86−
87−Copyright and License
88−=====================
89−
90−Copyright © 2003-2016 Paul Brossier <piem@aubio.org>
91−
92−aubio is a `free <http://www.debian.org/intro/free>`_ and `open source
93−<http://www.opensource.org/docs/definition.php>`_ software; **you** can
94−redistribute it and/or modify it under the terms of the `GNU
95−<http://www.gnu.org/>`_ `General Public License
96−<https://www.gnu.org/licenses/gpl.html>`_ as published by the `Free Software
97−Foundation <https://fsf.org>`_, either version 3 of the License, or (at your
98−option) any later version.
99−
100−.. Note:: aubio is not MIT or BSD licensed. Contact the author if you need it
101− in your commercial product.
76+ about
doc/installing.rst+69−9
@@ -4,16 +4,76 @@ Installing aubio · 3 unmodified lines
44 aubio runs on Linux, Windows, macOS, iOS, Android, and probably a few others
55 operating systems.
66
7−To download a pre-compiled version of the library, head to :ref:`download`.
7+Aubio is available as a C library and as a python module.
88
9−To install the python extension, head to :ref:`python`.
9+Cheat sheet
10+-----------
1011
11−To compile aubio form source, first check the :ref:`requirements`, then read
12−:ref:`building`.
12+- :ref:`get aubio latest source code <building>`::
1313
14−.. toctree::
15− :maxdepth: 2
14+ # official repo
15+ git clone https://git.aubio.org/aubio/aubio
16+ # mirror
17+ git clone https://github.com/aubio/aubio
18+ # latest release
19+ wget https://aubio.org/pub/aubio-<version>.tar.gz
1620
17− download
18− requirements
19− building
21+
22+- :ref:`build aubio from source <building>`::
23+
24+ # 1. simple
25+ cd aubio
26+ make
27+
28+ # 2. step by step
29+ ./scripts/get_waf.sh
30+ ./waf configure
31+ ./waf build
32+ sudo ./waf install
33+
34+- :ref:`install python-aubio from source <python-install>`::
35+
36+ # from git
37+ pip install git+https://git.aubio.org/aubio/aubio/
38+ # mirror
39+ pip install git+https://github.com/aubio/aubio/
40+ # from latest release
41+ pip install https://aubio.org/pub/aubio-latest.tar.bz2
42+ # from pypi
43+ pip install aubio
44+ # from source directory
45+ cd aubio
46+ pip install -v .
47+
48+- :ref:`install python-aubio from a pre-compiled binary <python-install>`::
49+
50+ # conda [osx, linux, win]
51+ conda install -c conda-forge aubio
52+ # .deb (debian, ubuntu) [linux]
53+ sudo apt-get install python3-aubio python-aubio aubio-tools
54+ # brew [osx]
55+ brew install aubio --with-python
56+
57+- :ref:`get a pre-compiled version of libaubio <download>`::
58+
59+ # .deb (linux) WARNING: old version
60+ sudo apt-get install aubio-tools
61+
62+ # python module
63+ ./setup.py install
64+ # using pip
65+ pip install .
66+
67+- :ref:`check the list of optional dependencies <requirements>`::
68+
69+ # debian / ubuntu
70+ dpkg -l libavcodec-dev libavutil-dev libavformat-dev \
71+ libswresample-dev libavresample-dev \
72+ libsamplerate-dev libsndfile-dev \
73+ txt2man doxygen
74+
75+.. include:: download.rst
76+
77+.. include:: building.rst
78+
79+.. include:: requirements.rst
doc/py_datatypes.rst+43−0
@@ -0,0 +1,43 @@
1+.. default-domain:: py
2+.. currentmodule:: aubio
3+
4+Data-types
5+----------
6+
7+This section contains the documentation for :data:`float_type`,
8+:class:`fvec`, and :class:`cvec`.
9+
10+.. defined in rst only
11+
12+.. data:: float_type
13+
14+ A string constant describing the floating-point representation used in
15+ :class:`fvec`, :class:`cvec`, and elsewhere in this module.
16+
17+ Defaults to `"float32"`.
18+
19+ If `aubio` was built specifically with the option `--enable-double`, this
20+ string will be defined to `"float64"`. See :ref:`py-doubleprecision` in
21+ :ref:`python-install` for more details on building aubio in double
22+ precision mode.
23+
24+ .. rubric:: Examples
25+
26+ >>> aubio.float_type
27+ 'float32'
28+ >>> numpy.zeros(10).dtype
29+ 'float64'
30+ >>> aubio.fvec(10).dtype
31+ 'float32'
32+ >>> np.arange(10, dtype=aubio.float_type).dtype
33+ 'float32'
34+
35+.. defined in `python/lib/aubio/__init__.py`
36+
37+.. autoclass:: fvec
38+ :members:
39+
40+.. defined in `python/ext/py-cvec.h`
41+
42+.. autoclass:: cvec
43+ :members:
doc/py_examples.rst+42−0
@@ -0,0 +1,42 @@
1+.. default-domain:: py
2+.. currentmodule:: aubio
3+
4+Examples
5+--------
6+
7+Below is a short selection of examples using the aubio module.
8+
9+Read a sound file
10+.................
11+
12+Here is a simple script, :download:`demo_source_simple.py
13+<../python/demos/demo_source_simple.py>` that reads all the samples from a
14+media file using :class:`source`:
15+
16+.. literalinclude:: ../python/demos/demo_source_simple.py
17+ :language: python
18+
19+Filter a sound file
20+...................
21+
22+Here is another example, :download:`demo_filter.py
23+<../python/demos/demo_filter.py>`, which applies a filter to a sound file
24+and writes the filtered signal in another file:
25+
26+* read audio samples from a file with :class:`source`
27+
28+* filter them using an `A-weighting <https://en.wikipedia.org/wiki/A-weighting>`_
29+ filter using :class:`digital_filter`
30+
31+* write the filtered samples to a new file with :class:`sink`.
32+
33+.. literalinclude:: ../python/demos/demo_filter.py
34+ :language: python
35+
36+More examples
37+.............
38+
39+For more examples showing how to use other components of the module, see
40+the `python demos folder`_.
41+
42+.. _python demos folder: https://github.com/aubio/aubio/blob/master/python/demos
doc/py_io.rst+118−0
@@ -0,0 +1,118 @@
1+.. currentmodule:: aubio
2+.. default-domain:: py
3+
4+Input/Output
5+------------
6+
7+This section contains the documentation for two classes:
8+:class:`source`, to read audio samples from files, and :class:`sink`,
9+to write audio samples to disk.
10+
11+.. defined in `python/ext`
12+
13+..
14+ Note: __call__ docstrings of objects defined in C must be written
15+ specifically in RST, since there is no known way to add them to
16+ their C implementation.
17+
18+..
19+ TODO: remove special-members documentation
20+
21+.. defined in py-source.c
22+
23+.. autoclass:: source
24+ :members:
25+ :special-members: __enter__
26+ :no-special-members:
27+
28+ .. function:: __call__()
29+
30+ Read at most `hop_size` new samples from self, return them in
31+ a tuple with the number of samples actually read.
32+
33+ The returned tuple contains:
34+
35+ - a vector of shape `(hop_size,)`, filled with the `read` next
36+ samples available, zero-padded if `read < hop_size`
37+ - `read`, an integer indicating the number of samples read
38+
39+ If opened with more than one channel, the frames will be
40+ down-mixed to produce the new samples.
41+
42+ :returns: A tuple of one array of samples and one integer.
43+ :rtype: (array, int)
44+
45+ .. seealso:: :meth:`__next__`
46+
47+ .. rubric:: Example
48+
49+ >>> src = aubio.source('stereo.wav')
50+ >>> while True:
51+ ... samples, read = src()
52+ ... if read < src.hop_size:
53+ ... break
54+
55+ .. function:: __next__()
56+
57+ Read at most `hop_size` new frames from self, return them in
58+ an array.
59+
60+ If source was opened with one channel, next(self) returns
61+ an array of shape `(read,)`, where `read` is the actual
62+ number of frames read (`0 <= read <= hop_size`).
63+
64+ If `source` was opened with more then one channel, the
65+ returned arrays will be of shape `(channels, read)`, where
66+ `read` is the actual number of frames read (`0 <= read <=
67+ hop_size`).
68+
69+ :return: A tuple of one array of frames and one integer.
70+ :rtype: (array, int)
71+
72+ .. seealso:: :meth:`__call__`
73+
74+ .. rubric:: Example
75+
76+ >>> for frames in aubio.source('song.flac')
77+ ... print(samples.shape)
78+
79+ .. function:: __iter__()
80+
81+ Implement iter(self).
82+
83+ .. seealso:: :meth:`__next__`
84+
85+ .. function:: __enter__()
86+
87+ Implement context manager interface. The file will be opened
88+ upon entering the context. See `with` statement.
89+
90+ .. rubric:: Example
91+
92+ >>> with aubio.source('loop.ogg') as src:
93+ ... src.uri, src.samplerate, src.channels
94+
95+ .. function:: __exit__()
96+
97+ Implement context manager interface. The file will be closed
98+ before exiting the context. See `with` statement.
99+
100+ .. seealso:: :meth:`__enter__`
101+
102+.. py-sink.c
103+ TODO: remove special-members documentation
104+
105+.. autoclass:: aubio.sink
106+ :members:
107+
108+ .. function:: __call__(vec, length)
109+
110+ Write `length` samples from `vec`.
111+
112+ :param array vec: input vector to write from
113+ :param int length: number of samples to write
114+ :example:
115+
116+ >>> with aubio.sink('foo.wav') as snk:
117+ ... snk(aubio.fvec(1025), 1025)
118+
doc/py_utils.rst+84−0
@@ -0,0 +1,84 @@
1+.. default-domain:: py
2+.. currentmodule:: aubio
3+
4+Utilities
5+---------
6+
7+This section documents various helper functions included in the aubio library.
8+
9+Note name conversion
10+....................
11+
12+.. midiconv.py
13+
14+.. autofunction:: note2midi
15+
16+.. autofunction:: midi2note
17+
18+.. autofunction:: freq2note
19+
20+.. autofunction:: note2freq
21+
22+Frequency conversion
23+....................
24+
25+.. python/ext/ufuncs.c
26+
27+.. autofunction:: freqtomidi
28+
29+.. autofunction:: miditofreq
30+
31+.. python/ext/py-musicutils.h
32+
33+.. autofunction:: meltohz
34+
35+.. autofunction:: hztomel
36+
37+.. python/ext/aubiomodule.c
38+
39+.. autofunction:: bintomidi
40+.. autofunction:: miditobin
41+.. autofunction:: bintofreq
42+.. autofunction:: freqtobin
43+
44+Audio file slicing
45+..................
46+
47+.. slicing.py
48+
49+.. autofunction:: slice_source_at_stamps
50+
51+Windowing
52+.........
53+
54+.. python/ext/py-musicutils.h
55+
56+.. autofunction:: window
57+
58+Audio level detection
59+.....................
60+
61+.. python/ext/py-musicutils.h
62+
63+.. autofunction:: level_lin
64+.. autofunction:: db_spl
65+.. autofunction:: silence_detection
66+.. autofunction:: level_detection
67+
68+Vector utilities
69+................
70+
71+.. python/ext/aubiomodule.c
72+
73+.. autofunction:: alpha_norm
74+.. autofunction:: zero_crossing_rate
75+.. autofunction:: min_removal
76+
77+.. python/ext/py-musicutils.h
78+
79+.. autofunction:: shift
80+.. autofunction:: ishift
81+
82+.. python/ext/ufuncs.c
83+
84+.. autofunction:: unwrap2pi
doc/python.rst+55−0
@@ -0,0 +1,55 @@
1+.. make sure our default-domain is python here
2+.. default-domain:: py
3+
4+.. set current module
5+.. currentmodule:: aubio
6+
7+..
8+ we follow numpy type docstrings, see:
9+ https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
10+..
11+ note: we do not import aubio's docstring, which will be displayed from an
12+ interpreter.
13+
14+.. .. automodule:: aubio
15+
16+
17+.. _python:
18+
19+Python documentation
20+====================
21+
22+This module provides a number of classes and functions for the analysis of
23+music and audio signals.
24+
25+Contents
26+--------
27+
28+.. toctree::
29+ :maxdepth: 1
30+
31+ py_datatypes
32+ py_io
33+ py_utils
34+ py_examples
35+
36+Introduction
37+------------
38+
39+This document provides a reference guide. For documentation on how to
40+install aubio, see :ref:`python-install`.
41+
42+Examples included in this guide and within the code are written assuming
43+both `aubio` and `numpy`_ have been imported:
44+
45+.. code-block:: python
46+
47+ >>> import aubio
48+ >>> import numpy as np
49+
50+`Changed in 0.4.8` : Prior to this version, almost no documentation was
51+provided with the python module. This version adds documentation for some
52+classes, including :class:`fvec`, :class:`cvec`, :class:`source`, and
53+:class:`sink`.
54+
55+.. _numpy: https://www.numpy.org
doc/python_module.rst+69−40
@@ -1,73 +1,102 @@
1−.. _python:
1+.. _python-install:
22
3−Python module
4−=============
3+Installing aubio for Python
4+===========================
55
6−The aubio extension for Python is available for Python 2.7 and Python 3.
6+aubio is available as a package for Python 2.7 and Python 3. The aubio
7+extension is written C using the `Python/C`_ and the `Numpy/C`_ APIs.
8+
9+.. _Python/C: https://docs.python.org/c-api/index.html
10+.. _Numpy/C: https://docs.scipy.org/doc/numpy/reference/c-api.html
11+
12+For general documentation on how to install Python packages, see `Installing
13+Packages`_.
714
815 Installing aubio with pip
916 -------------------------
1017
11−aubio can now be installed using ``pip``:
18+aubio can be installed from `PyPI`_ using ``pip``:
1219
13−.. code-block:: bash
20+.. code-block:: console
1421
1522 $ pip install aubio
1623
17−Building the module
18−-------------------
24+See also `Installing from PyPI`_ for general documentation.
1925
20−From ``aubio`` source directory, run the following:
26+.. note::
2127
22−.. code-block:: bash
28+ aubio is currently a `source only`_ package, so you will need a compiler to
29+ install it from `PyPI`_. See also `Installing aubio with conda`_ for
30+ pre-compiled binaries.
2331
24− $ ./setup.py clean
25− $ ./setup.py build
26− $ sudo ./setup.py install
32+.. _PyPI: https://pypi.python.org/pypi/aubio
33+.. _Installing Packages: https://packaging.python.org/tutorials/installing-packages/
34+.. _Installing from PyPI: https://packaging.python.org/tutorials/installing-packages/#installing-from-pypi
35+.. _source only: https://packaging.python.org/tutorials/installing-packages/#source-distributions-vs-wheels
36+
37+Installing aubio with conda
38+---------------------------
2739
28−Using aubio in python
29−---------------------
40+`Conda packages`_ are available through the `conda-forge`_ channel for Linux,
41+macOS, and Windows:
3042
31−Once you have python-aubio installed, you should be able to run ``python -c
32−"import aubio"``.
43+.. code-block:: console
3344
34−A simple example
35−................
45+ $ conda config --add channels conda-forge
46+ $ conda install -c conda-forge aubio
3647
37−Here is a :download:`simple script <../python/demos/demo_source_simple.py>`
38−that reads all the samples from a media file:
48+.. _Conda packages: https://anaconda.org/conda-forge/aubio
49+.. _conda-forge: https://conda-forge.org/
3950
40−.. literalinclude:: ../python/demos/demo_source_simple.py
41− :language: python
51+.. _py-doubleprecision:
4252
43−Filtering an input sound file
44−.............................
53+Double precision
54+----------------
4555
46−Here is a more complete example, :download:`demo_filter.py
47−<../python/demos/demo_filter.py>`. This files executes the following:
56+This module can be compiled in double-precision mode, in which case the
57+default type for floating-point samples will be 64-bit. The default is
58+single precision mode (32-bit, recommended).
59+
60+To build the aubio module with double precision, use the option
61+`--enable-double` of the `build_ext` subcommand:
62+
63+.. code:: bash
64+
65+ $ ./setup.py clean
66+ $ ./setup.py build_ext --enable-double
67+ $ pip install -v .
4868
49−* read an input media file (``aubio.source``)
69+**Note**: If linking against `libaubio`, make sure the library was also
70+compiled in :ref:`doubleprecision` mode.
5071
51−* filter it using an `A-weighting <https://en.wikipedia.org/wiki/A-weighting>`_
52− filter (``aubio.digital_filter``)
5372
54−* write result to a new file (``aubio.sink``)
73+Checking your installation
74+--------------------------
5575
56−.. literalinclude:: ../python/demos/demo_filter.py
57− :language: python
76+Once the python module is installed, its version can be checked with:
5877
59−More demos
60−..........
78+.. code-block:: console
79+
80+ $ python -c "import aubio; print(aubio.version, aubio.float_type)"
81+
82+The command line `aubio` is also installed:
83+
84+.. code-block:: console
85+
86+ $ aubio -h
6187
62−Check out the `python demos folder`_ for more examples.
6388
6489 Python tests
6590 ------------
6691
67−A number of `python tests`_ are provided. To run them, use
68−``python/tests/run_all_tests``.
92+A number of Python tests are provided in the `python tests`_. To run them,
93+install `nose2`_ and run the script ``python/tests/run_all_tests``:
94+
95+.. code-block:: console
96+
97+ $ pip install nose2
98+ $ ./python/tests/run_all_tests
6999
70−.. _python demos folder: https://github.com/aubio/aubio/blob/master/python/demos
71100 .. _demo_filter.py: https://github.com/aubio/aubio/blob/master/python/demos/demo_filter.py
72101 .. _python tests: https://github.com/aubio/aubio/blob/master/python/tests
73−
102+.. _nose2: https://github.com/nose-devs/nose2
doc/requirements.rst+256−81
@@ -1,10 +1,196 @@
11 .. _requirements:
22
3−Requirements
4−============
3+Build options
4+=============
5+
6+If built without any external dependencies aubio can be somewhat useful, for
7+instance to read, process, and write simple wav files.
8+
9+To support more media input formats and add more features to aubio, you can use
10+one or all of the following `external libraries`_.
11+
12+You may also want to know more about the `other options`_ and the `platform
13+notes`_
14+
15+The configure script will automatically for these extra libraries. To make sure
16+the library or feature is used, pass the `--enable-flag` to waf. To disable
17+this feature, use `--disable-feature`.
18+
19+To find out more about the build commands, use the `--verbose` option.
20+
21+External libraries
22+------------------
23+
24+External libraries are checked for using ``pkg-config``. Set the
25+``PKG_CONFIG_PATH`` environment variable if you have them installed in an
26+unusual location.
27+
28+
29+.. note::
30+
31+ If ``pkg-config`` is not found in ``PATH``, the configure step will
32+ succeed, but none of the external libraries will be used.
33+
34+Media libraries
35+---------------
36+
37+libav
38+.....
39+
40+ `libav.org <https://libav.org/>`_, open source audio and video processing
41+ tools.
42+
43+If all of the following libraries are found, they will be used to compile
44+``aubio_source_avcodec``. so that ``aubio_source`` will be able to decode audio
45+from all formats supported by `libav
46+<https://libav.org/documentation/general.html#Audio-Codecs>`_.
47+
48+* libavcodec
49+* libavformat
50+* libavutil
51+* libavresample
52+
53+To enable this option, configure with ``--enable-avcodec``. The build will then
54+failed if the required libraries are not found. To disable this option,
55+configure with ``--disable-avcodec``
56+
57+
58+libsndfile
59+..........
60+
61+ `libsndfile <http://www.mega-nerd.com/libsndfile/>`_, a C library for reading
62+ and writing sampled sound files.
63+
64+With libsndfile built in, ``aubio_source_sndfile`` will be built in and used by
65+``aubio_source``.
66+
67+To enable this option, configure with ``--enable-sndfile``. The build will then
68+fail if the required library is not found. To disable this option, configure
69+with ``--disable-sndfile``
70+
71+libsamplerate
72+.............
73+
74+ `libsamplerate <http://www.mega-nerd.com/SRC/>`_, a sample rate converter for
75+ audio.
76+
77+With libsamplerate built in, ``aubio_source_sndfile`` will support resampling,
78+and ``aubio_resample`` will be fully functional.
79+
80+To enable this option, configure with ``--enable-samplerate``. The build will
81+then fail if the required library is not found. To disable this option,
82+configure with ``--disable-samplerate``
83+
84+Optimisation libraries
85+----------------------
86+
87+libfftw3
88+........
89+
90+ `FFTW <http://fftw.org/>`_, a C subroutine for computing the discrete Fourier
91+ transform
92+
93+With libfftw3 built in, ``aubio_fft`` will use `FFTW`_ to
94+compute Fast Fourier Transform (FFT), allowing aubio to compute FFT on length
95+that are not a power of 2.
96+
97+To enable this option, configure with ``--enable-fftw3``. The build will
98+then fail if the required library is not found. To disable this option,
99+configure with ``--disable-fftw3``
100+
101+blas
102+....
103+
104+On macOs/iOS, `blas
105+<https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms>`_ are made
106+available through the Accelerate framework.
107+
108+On Linux, they can be enabled with ``--enable-blas``. On Debian (etch),
109+`atlas`_, `openblas`_, and `libblas`_ have been successfully tested.
110+
111+When enabled, ``waf`` will check for the current blas configuration by running
112+``pkg-config --libs blas``. Depending of the library path returned by
113+``pkg-config``, different headers will be searched for.
114+
115+.. note::
116+
117+ On Debian systems, `multiple versions of BLAS and LAPACK
118+ <https://wiki.debian.org/DebianScience/LinearAlgebraLibraries>`_ can be
119+ installed. To configure which libblas is being used:
120+
121+ .. code-block:: console
122+
123+ $ sudo update-alternatives --config libblas.so
124+
125+..
126+ Expected pkg-config output for each alternative:
127+ /usr/lib/atlas-base/atlas/libblas.so
128+ -L/usr/lib/atlas-base/atlas -lblas
129+ /usr/lib/openblas-base/libblas.so
130+ -L/usr/lib/openblas-base -lblas
131+ /usr/lib/libblas/libblas.so
132+ -lblas
133+
134+atlas
135+.....
136+
137+`ATLAS BLAS APIs <http://math-atlas.sourceforge.net/>`_ will be used the path
138+returned by ``pkg-config --libs blas`` contains ``atlas``.
139+
140+..
141+ ``<atlas/cblas.h>`` will be included.
142+
143+Example:
144+
145+.. code-block:: console
146+
147+ $ pkg-config --libs blas
148+ -L/usr/lib/atlas-base/atlas -lblas
149+ $ ./waf configure --enable-atlas
150+ [...]
151+ Checking for 'blas' : yes
152+ Checking for header atlas/cblas.h : yes
153+
154+openblas
155+........
156+
157+`OpenBlas libraries <https://www.openblas.net/>`_ will be used when the output
158+of ``pkg-config --libs blas`` contains 'openblas',
159+
160+..
161+ ``<openblas/cblas.h>`` will be included.
162+
163+Example:
164+
165+.. code-block:: console
166+
167+ $ pkg-config --libs blas
168+ -L/usr/lib/openblas-base -lblas
169+ $ ./waf configure --enable-atlas
170+ [...]
171+ Checking for 'blas' : yes
172+ Checking for header openblas/cblas.h : yes
173+
174+libblas
175+.......
176+
177+`Netlib's libblas (LAPACK) <https://www.netlib.org/lapack/>`_ will be used if
178+no specific library path is specified by ``pkg-config``
179+
180+..
181+ ``<cblas.h>`` will be included.
182+
183+Example:
184+
185+.. code-block:: console
186+
187+ $ pkg-config --libs blas
188+ -lblas
189+ $ ./waf configure --enable-atlas
190+ [...]
191+ Checking for 'blas' : yes
192+ Checking for header cblas.h : yes
5193
6−While aubio can be built without any external dependencies, we **recommend** to
7−use at least some of the following libraries.
8194
9195 Platform notes
10196 --------------
@@ -41,6 +227,9 @@ The following system frameworks will be used on Mac OS X systems: · 30 unmodified lines
41227 The following `External libraries`_ will also be checked: `libav`_,
42228 `libsamplerate`_, `libsndfile`_, `libfftw3`_.
43229
230+To build a fat binary on a darwin like system (macOS, tvOS, appleOS, ...)
231+platforms, configure with ``--enable-fat``.
232+
44233 Windows
45234 .......
46235
@@ -86,7 +275,7 @@ and on iOS Simulator: · 39 unmodified lines
86275 Set ``CFLAGS`` and ``LINKFLAGS`` to change these default values, or edit
87276 ``wscript`` directly.
88277
89−Build options
278+Other options
90279 -------------
91280
92281 Some additional options can be passed to the configure step. For the complete
@@ -94,105 +283,91 @@ list of options, run: · 1 unmodified line
94283
95284 .. code:: bash
96285
97− $ ./waf configure --help
98−
99−Double precision
100−................
101−
102−To compile aubio in double precision mode, configure with ``--enable-double``.
103−
104−To compile aubio in single precision mode, use ``--disable-double`` (default).
105−
106−Fat binary
107−..........
108−
109−To build a fat binary on Mac OS platforms, configure with ``--enable-fat``.
110−
111−External libraries
112−------------------
113−
114−External libraries are checked for using ``pkg-config``. Set the
115−``PKG_CONFIG_PATH`` environment variable if you have them installed in an
116−unusual location.
286+ $ ./waf --help
117287
288+Here is an example of a custom command:
118289
119−.. note::
120−
121− If ``pkg-config`` is not found in ``PATH``, the configure step will
122− succeed, but none of the external libraries will be used.
123−
124−libav
125−.....
126−
127− `libav.org <https://libav.org/>`_, open source audio and video processing
128− tools.
129−
130−If all of the following libraries are found, they will be used to compile
131−``aubio_source_avcodec``. so that ``aubio_source`` will be able to decode audio
132−from all formats supported by `libav
133−<https://libav.org/documentation/general.html#Audio-Codecs>`_.
134−
135−* libavcodec
136−* libavformat
137−* libavutil
138−* libavresample
139−
140−To enable this option, configure with ``--enable-avcodec``. The build will then
141−failed if the required libraries are not found. To disable this option,
142−configure with ``--disable-avcodec``
290+.. code:: bash
143291
292+ $ ./waf --verbose configure build install \
293+ --enable-avcodec --enable-wavread --disable-wavwrite \
294+ --enable-sndfile --enable-samplerate --enable-docs \
295+ --destdir $PWD/build/destdir --testcmd="echo %s" \
296+ --prefix=/opt --libdir=/opt/lib/multiarch \
297+ --manpagesdir=/opt/share/man \
298+ uninstall clean distclean dist distcheck
144299
145−libsndfile
146−..........
300+.. _doubleprecision:
147301
148− `libsndfile <http://www.mega-nerd.com/libsndfile/>`_, a C library for reading
149− and writing sampled sound files.
302+Double precision
303+................
150304
151−With libsndfile built in, ``aubio_source_sndfile`` will be built in and used by
152−``aubio_source``.
305+The datatype used to store real numbers in aubio is named `smpl_t`. By default,
306+`smpl_t` is defined as `float`, a `single-precision format
307+<https://en.wikipedia.org/wiki/Single-precision_floating-point_format>`_
308+(32-bit). Some algorithms require a floating point representation with a
309+higher precision, for instance to prevent arithmetic underflow in recursive
310+filters. In aubio, these special samples are named `lsmp_t` and defined as
311+`double` by default (64-bit).
312+
313+Sometimes it may be useful to compile aubio in `double-precision`, for instance
314+to reproduce numerical results obtained with 64-bit routines. In this case,
315+`smpl_t` will be defined as `double`.
316+
317+The following table shows how `smpl_t` and `lsmp_t` are defined in single- and
318+double-precision modes:
319+
320+.. list-table:: Single and double-precision modes
321+ :align: center
322+
323+ * -
324+ - single
325+ - double
326+ * - `smpl_t`
327+ - ``float``
328+ - ``double``
329+ * - `lsmp_t`
330+ - ``double``
331+ - ``long double``
153332
154−To enable this option, configure with ``--enable-sndfile``. The build will then
155−fail if the required library is not found. To disable this option, configure
156−with ``--disable-sndfile``
333+To compile aubio in double precision mode, configure with ``--enable-double``.
157334
158−libsamplerate
159−.............
335+To compile in single-precision mode (default), use ``--disable-double`` (or
336+simply none of these two options).
160337
161− `libsamplerate <http://www.mega-nerd.com/SRC/>`_, a sample rate converter for
162− audio.
338+Disabling the tests
339+...................
163340
164−With libsamplerate built in, ``aubio_source_sndfile`` will support resampling,
165−and ``aubio_resample`` will be fully functional.
341+In some case, for instance when cross-compiling, unit tests should not be run.
342+Option ``--notests`` can be used for this purpose. The tests will not be
343+executed, but the binaries will be compiled, ensuring that linking against
344+libaubio works as expected.
166345
167−To enable this option, configure with ``--enable-samplerate``. The build will
168−then fail if the required library is not found. To disable this option,
169−configure with ``--disable-samplerate``
346+.. note::
170347
171−libfftw3
172−........
348+ The ``--notests`` option should be passed to both ``build`` and ``install``
349+ targets, otherwise waf will try to run them.
173350
174− `FFTW <http://fftw.org/>`_, a C subroutine for computing the discrete Fourier
175− transform
351+Edit wscript
352+............
176353
177−With libfftw3 built in, ``aubio_fft`` will use `FFTW`_ to
178−compute Fast Fourier Transform (FFT), allowing aubio to compute FFT on length
179−that are not a power of 2.
354+Many of the options are gathered in the file `wscript`. a good starting point
355+when looking for additional options.
180356
181−To enable this option, configure with ``--enable-fftw3``. The build will
182−then fail if the required library is not found. To disable this option,
183−configure with ``--disable-fftw3``
357+.. _build_docs:
184358
185−External tools
186−--------------
359+Building the docs
360+-----------------
187361
188−If the following tools are found, additional documentations are built:
362+If the following command line tools are found, the documentation will be built
363+built:
189364
190365 - `doxygen <http://doxygen.org>`_ to build the :ref:`doxygen-documentation`.
191366 - `txt2man <https://github.com/mvertes/txt2man>`_ to build the :ref:`manpages`
367+ - `sphinx <http://sphinx-doc.org>`_ to build this document
192368
193369 These tools are searched for in the current ``PATH`` environment variable.
194370 By default, the documentation is built only if the tools are found.
195371
196372 To disable the documentation, configure with ``--disable-docs``. To build with
197373 the documentation, configure with ``--enable-docs``.
198−
doc/statuslinks.rst+24−0
@@ -0,0 +1,24 @@
1+Current status
2+==============
3+
4+.. image:: https://travis-ci.org/aubio/aubio.svg?branch=master
5+ :target: https://travis-ci.org/aubio/aubio
6+ :alt: Travis build status
7+
8+.. image:: https://ci.appveyor.com/api/projects/status/f3lhy3a57rkgn5yi?svg=true
9+ :target: https://ci.appveyor.com/project/piem/aubio/
10+ :alt: Appveyor build status
11+
12+.. image:: https://landscape.io/github/aubio/aubio/master/landscape.svg?style=flat
13+ :target: https://landscape.io/github/aubio/aubio/master
14+ :alt: Landscape code health
15+
16+.. image:: https://readthedocs.org/projects/aubio/badge/?version=latest
17+ :target: https://aubio.readthedocs.io/en/latest/?badge=latest
18+ :alt: Documentation status
19+
20+.. image:: https://img.shields.io/github/commits-since/aubio/aubio/latest.svg
21+ :target: https://github.com/aubio/aubio
22+ :alt: Commits since last release
23+
24+
doc/web.cfg+211−120
@@ -1,4 +1,4 @@
1−# Doxyfile 1.8.8
1+# Doxyfile 1.8.13
22
33 # This file describes the settings to be used by the documentation system
44 # doxygen (www.doxygen.org) for a project.
@@ -38,7 +38,7 @@ PROJECT_NAME = aubio · 33 unmodified lines
3838 # could be handy for archiving the generated documentation or if some version
3939 # control system is used.
4040
41−PROJECT_NUMBER = "0.4.2~alpha"
41+PROJECT_NUMBER = "latest"
4242
4343 # Using the PROJECT_BRIEF tag one can provide an optional one line description
4444 # for a project that appears at the top of each page and should give viewer a
@@ -46,10 +46,10 @@ PROJECT_NUMBER = "0.4.2~alpha" · 1 unmodified line
4646
4747 PROJECT_BRIEF =
4848
49−# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
50−# the documentation. The maximum height of the logo should not exceed 55 pixels
51−# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
52−# to the output directory.
49+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
50+# in the documentation. The maximum height of the logo should not exceed 55
51+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
52+# the logo to the output directory.
5353
5454 PROJECT_LOGO =
5555
@@ -60,7 +60,7 @@ PROJECT_LOGO = · 4 unmodified lines
6060
6161 OUTPUT_DIRECTORY = web
6262
63−# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
63+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
6464 # directories (in 2 levels) under the output directory of each output format and
6565 # will distribute the generated files over these directories. Enabling this
6666 # option can be useful when feeding doxygen a huge amount of source files, where
@@ -93,14 +93,14 @@ ALLOW_UNICODE_NAMES = NO · 26 unmodified lines
9393
9494 OUTPUT_LANGUAGE = English
9595
96−# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
96+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
9797 # descriptions after the members that are listed in the file and class
9898 # documentation (similar to Javadoc). Set to NO to disable this.
9999 # The default value is: YES.
100100
101101 BRIEF_MEMBER_DESC = YES
102102
103−# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
103+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
104104 # description of a member or function before the detailed description
105105 #
106106 # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@@ -135,7 +135,7 @@ ALWAYS_DETAILED_SEC = NO · 28 unmodified lines
135135
136136 INLINE_INHERITED_MEMB = NO
137137
138−# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
138+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
139139 # before files name in the file list and in the header files. If set to NO the
140140 # shortest path that makes the file name unique will be used
141141 # The default value is: YES.
@@ -205,9 +205,9 @@ MULTILINE_CPP_IS_BRIEF = NO · 63 unmodified lines
205205
206206 INHERIT_DOCS = YES
207207
208−# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
209−# new page for each member. If set to NO, the documentation of a member will be
210−# part of the file/class/namespace that contains it.
208+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
209+# page for each member. If set to NO, the documentation of a member will be part
210+# of the file/class/namespace that contains it.
211211 # The default value is: NO.
212212
213213 SEPARATE_MEMBER_PAGES = NO
@@ -276,7 +276,7 @@ OPTIMIZE_OUTPUT_VHDL = NO · 62 unmodified lines
276276 # instance to make doxygen treat .inc files as Fortran files (default is PHP),
277277 # and .f files as C (default is Fortran), use: inc=Fortran f=C.
278278 #
279−# Note For files without extension you can use no_extension as a placeholder.
279+# Note: For files without extension you can use no_extension as a placeholder.
280280 #
281281 # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
282282 # the files are not read by doxygen.
@@ -293,10 +293,19 @@ EXTENSION_MAPPING = · 10 unmodified lines
293293
294294 MARKDOWN_SUPPORT = YES
295295
296+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
297+# to that level are automatically included in the table of contents, even if
298+# they do not have an id attribute.
299+# Note: This feature currently applies only to Markdown headings.
300+# Minimum value: 0, maximum value: 99, default value: 0.
301+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
302+
303+TOC_INCLUDE_HEADINGS = 0
304+
296305 # When enabled doxygen tries to link words that correspond to documented
297306 # classes, or namespaces to their corresponding documentation. Such a link can
298−# be prevented in individual cases by by putting a % sign in front of the word
299−# or globally by setting AUTOLINK_SUPPORT to NO.
307+# be prevented in individual cases by putting a % sign in front of the word or
308+# globally by setting AUTOLINK_SUPPORT to NO.
300309 # The default value is: YES.
301310
302311 AUTOLINK_SUPPORT = YES
@@ -336,13 +345,20 @@ SIP_SUPPORT = NO · 33 unmodified lines
336345 IDL_PROPERTY_SUPPORT = YES
337346
338347 # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
339−# tag is set to YES, then doxygen will reuse the documentation of the first
348+# tag is set to YES then doxygen will reuse the documentation of the first
340349 # member in the group (if any) for the other members of the group. By default
341350 # all members of a group must be documented explicitly.
342351 # The default value is: NO.
343352
344353 DISTRIBUTE_GROUP_DOC = NO
345354
355+# If one adds a struct or class to a group and this option is enabled, then also
356+# any nested class or struct is added to the same group. By default this option
357+# is disabled and one has to add nested compounds explicitly via \ingroup.
358+# The default value is: NO.
359+
360+GROUP_NESTED_COMPOUNDS = NO
361+
346362 # Set the SUBGROUPING tag to YES to allow class member groups of the same type
347363 # (for instance a group of public functions) to be put as a subgroup of that
348364 # type (e.g. under the Public Functions section). Set it to NO to prevent
@@ -401,7 +417,7 @@ LOOKUP_CACHE_SIZE = 0 · 52 unmodified lines
401417 # Build related configuration options
402418 #---------------------------------------------------------------------------
403419
404−# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
420+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
405421 # documentation are documented, even if no documentation was available. Private
406422 # class members and static file members will be hidden unless the
407423 # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -411,35 +427,35 @@ LOOKUP_CACHE_SIZE = 0 · 3 unmodified lines
411427
412428 EXTRACT_ALL = NO
413429
414−# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
430+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
415431 # be included in the documentation.
416432 # The default value is: NO.
417433
418434 EXTRACT_PRIVATE = NO
419435
420−# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
436+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
421437 # scope will be included in the documentation.
422438 # The default value is: NO.
423439
424440 EXTRACT_PACKAGE = NO
425441
426−# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
442+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
427443 # included in the documentation.
428444 # The default value is: NO.
429445
430446 EXTRACT_STATIC = NO
431447
432−# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
433−# locally in source files will be included in the documentation. If set to NO
448+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
449+# locally in source files will be included in the documentation. If set to NO,
434450 # only classes defined in header files are included. Does not have any effect
435451 # for Java sources.
436452 # The default value is: YES.
437453
438454 EXTRACT_LOCAL_CLASSES = YES
439455
440−# This flag is only useful for Objective-C code. When set to YES local methods,
456+# This flag is only useful for Objective-C code. If set to YES, local methods,
441457 # which are defined in the implementation section but not in the interface are
442−# included in the documentation. If set to NO only methods in the interface are
458+# included in the documentation. If set to NO, only methods in the interface are
443459 # included.
444460 # The default value is: NO.
445461
@@ -464,21 +480,21 @@ HIDE_UNDOC_MEMBERS = NO · 18 unmodified lines
464480
465481 # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
466482 # undocumented classes that are normally visible in the class hierarchy. If set
467−# to NO these classes will be included in the various overviews. This option has
468−# no effect if EXTRACT_ALL is enabled.
483+# to NO, these classes will be included in the various overviews. This option
484+# has no effect if EXTRACT_ALL is enabled.
469485 # The default value is: NO.
470486
471487 HIDE_UNDOC_CLASSES = NO
472488
473489 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
474−# (class|struct|union) declarations. If set to NO these declarations will be
490+# (class|struct|union) declarations. If set to NO, these declarations will be
475491 # included in the documentation.
476492 # The default value is: NO.
477493
478494 HIDE_FRIEND_COMPOUNDS = NO
479495
480496 # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
481−# documentation blocks found inside the body of a function. If set to NO these
497+# documentation blocks found inside the body of a function. If set to NO, these
482498 # blocks will be appended to the function's detailed documentation block.
483499 # The default value is: NO.
484500
@@ -492,7 +508,7 @@ HIDE_IN_BODY_DOCS = NO · 7 unmodified lines
492508 INTERNAL_DOCS = NO
493509
494510 # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
495−# names in lower-case letters. If set to YES upper-case letters are also
511+# names in lower-case letters. If set to YES, upper-case letters are also
496512 # allowed. This is useful if you have classes or files whose names only differ
497513 # in case and if your file system supports case sensitive file names. Windows
498514 # and Mac users are advised to set this option to NO.
@@ -501,12 +517,19 @@ INTERNAL_DOCS = NO · 2 unmodified lines
501517 CASE_SENSE_NAMES = NO
502518
503519 # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
504−# their full class and namespace scopes in the documentation. If set to YES the
520+# their full class and namespace scopes in the documentation. If set to YES, the
505521 # scope will be hidden.
506522 # The default value is: NO.
507523
508524 HIDE_SCOPE_NAMES = NO
509525
526+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
527+# append additional text to a page's title, such as Class Reference. If set to
528+# YES the compound reference will be hidden.
529+# The default value is: NO.
530+
531+HIDE_COMPOUND_REFERENCE= NO
532+
510533 # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
511534 # the files that are included by a file in the documentation of that file.
512535 # The default value is: YES.
@@ -534,14 +557,14 @@ INLINE_INFO = YES · 21 unmodified lines
534557
535558 # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
536559 # (detailed) documentation of file and class members alphabetically by member
537−# name. If set to NO the members will appear in declaration order.
560+# name. If set to NO, the members will appear in declaration order.
538561 # The default value is: YES.
539562
540563 SORT_MEMBER_DOCS = YES
541564
542565 # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
543566 # descriptions of file, namespace and class members alphabetically by member
544−# name. If set to NO the members will appear in declaration order. Note that
567+# name. If set to NO, the members will appear in declaration order. Note that
545568 # this will also influence the order of the classes in the class list.
546569 # The default value is: NO.
547570
@@ -586,27 +609,25 @@ SORT_BY_SCOPE_NAME = NO · 38 unmodified lines
586609
587610 STRICT_PROTO_MATCHING = NO
588611
589−# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
590−# todo list. This list is created by putting \todo commands in the
591−# documentation.
612+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
613+# list. This list is created by putting \todo commands in the documentation.
592614 # The default value is: YES.
593615
594616 GENERATE_TODOLIST = YES
595617
596−# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
597−# test list. This list is created by putting \test commands in the
598−# documentation.
618+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
619+# list. This list is created by putting \test commands in the documentation.
599620 # The default value is: YES.
600621
601622 GENERATE_TESTLIST = YES
602623
603−# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
624+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
604625 # list. This list is created by putting \bug commands in the documentation.
605626 # The default value is: YES.
606627
607628 GENERATE_BUGLIST = YES
608629
609−# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
630+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
610631 # the deprecated list. This list is created by putting \deprecated commands in
611632 # the documentation.
612633 # The default value is: YES.
@@ -631,8 +652,8 @@ ENABLED_SECTIONS = · 18 unmodified lines
631652 MAX_INITIALIZER_LINES = 30
632653
633654 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
634−# the bottom of the documentation of classes and structs. If set to YES the list
635−# will mention the files that were used to generate the documentation.
655+# the bottom of the documentation of classes and structs. If set to YES, the
656+# list will mention the files that were used to generate the documentation.
636657 # The default value is: YES.
637658
638659 SHOW_USED_FILES = YES
@@ -696,7 +717,7 @@ CITE_BIB_FILES = · 57 unmodified lines
696717 QUIET = NO
697718
698719 # The WARNINGS tag can be used to turn on/off the warning messages that are
699−# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
720+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
700721 # this implies that the warnings are on.
701722 #
702723 # Tip: Turn warnings on while writing the documentation.
@@ -704,7 +725,7 @@ QUIET = NO · 1 unmodified line
704725
705726 WARNINGS = YES
706727
707−# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
728+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
708729 # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
709730 # will automatically be disabled.
710731 # The default value is: YES.
@@ -721,12 +742,18 @@ WARN_IF_DOC_ERROR = YES · 10 unmodified lines
721742
722743 # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
723744 # are documented, but have no documentation for their parameters or return
724−# value. If set to NO doxygen will only warn about wrong or incomplete parameter
725−# documentation, but not about the absence of documentation.
745+# value. If set to NO, doxygen will only warn about wrong or incomplete
746+# parameter documentation, but not about the absence of documentation.
726747 # The default value is: NO.
727748
728749 WARN_NO_PARAMDOC = NO
729750
751+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
752+# a warning is encountered.
753+# The default value is: NO.
754+
755+WARN_AS_ERROR = NO
756+
730757 # The WARN_FORMAT tag determines the format of the warning messages that doxygen
731758 # can produce. The string should contain the $file, $line, and $text tags, which
732759 # will be replaced by the file and line number from which the warning originated
@@ -750,7 +777,7 @@ WARN_LOGFILE = · 17 unmodified lines
750777 # The INPUT tag is used to specify the files and/or directories that contain
751778 # documented source files. You may enter file names like myfile.cpp or
752779 # directories like /usr/src/myproject. Separate the files or directories with
753−# spaces.
780+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
754781 # Note: If this tag is empty the current directory is searched.
755782
756783 INPUT = ../src
@@ -766,12 +793,17 @@ INPUT_ENCODING = UTF-8 · 9 unmodified lines
766793
767794 # If the value of the INPUT tag contains directories, you can use the
768795 # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
769−# *.h) to filter out the source-files in the directories. If left blank the
770−# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
771−# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
772−# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
773−# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
774−# *.qsf, *.as and *.js.
796+# *.h) to filter out the source-files in the directories.
797+#
798+# Note that for custom extensions or not directly supported extensions you also
799+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
800+# read by doxygen.
801+#
802+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
803+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
804+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
805+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
806+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
775807
776808 FILE_PATTERNS = *.h
777809
@@ -790,6 +822,7 @@ RECURSIVE = YES · 12 unmodified lines
790822
791823 EXCLUDE = ../src/aubio_priv.h \
792824 ../src/mathutils.h \
825+ ../src/io/ioutils.h \
793826 ../src/io/audio_unit.h \
794827 ../src/io/source_sndfile.h \
795828 ../src/io/source_apple_audio.h \
@@ -802,6 +835,7 @@ EXCLUDE = ../src/aubio_priv.h \ · 6 unmodified lines
802835 ../src/pitch/pitchmcomb.h \
803836 ../src/pitch/pitchyin.h \
804837 ../src/pitch/pitchyinfft.h \
838+ ../src/pitch/pitchyinfast.h \
805839 ../src/pitch/pitchschmitt.h \
806840 ../src/pitch/pitchfcomb.h \
807841 ../src/pitch/pitchspecacf.h \
@@ -878,6 +912,10 @@ IMAGE_PATH = · 70 unmodified lines
878912 # Note that the filter must not add or remove lines; it is applied before the
879913 # code is scanned, but not when the output code is generated. If lines are added
880914 # or removed, the anchors will not be placed correctly.
915+#
916+# Note that for custom extensions or not directly supported extensions you also
917+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
918+# properly processed by doxygen.
881919
882920 INPUT_FILTER =
883921
@@ -887,11 +925,15 @@ INPUT_FILTER = · 3 unmodified lines
887925 # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
888926 # filters are used. If the FILTER_PATTERNS tag is empty or if none of the
889927 # patterns match the file name, INPUT_FILTER is applied.
928+#
929+# Note that for custom extensions or not directly supported extensions you also
930+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
931+# properly processed by doxygen.
890932
891933 FILTER_PATTERNS =
892934
893935 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
894−# INPUT_FILTER ) will also be used to filter the input files that are used for
936+# INPUT_FILTER) will also be used to filter the input files that are used for
895937 # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
896938 # The default value is: NO.
897939
@@ -951,7 +993,7 @@ REFERENCED_BY_RELATION = YES · 53 unmodified lines
951993 REFERENCES_RELATION = YES
952994
953995 # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
954−# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
996+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
955997 # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
956998 # link to the documentation.
957999 # The default value is: YES.
@@ -998,13 +1040,13 @@ USE_HTAGS = NO · 40 unmodified lines
9981040
9991041 VERBATIM_HEADERS = YES
10001042
1001−# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
1043+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
10021044 # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
10031045 # cost of reduced performance. This can be particularly helpful with template
10041046 # rich C++ code for which doxygen's built-in parser lacks the necessary type
10051047 # information.
10061048 # Note: The availability of this option depends on whether or not doxygen was
1007−# compiled with the --with-libclang option.
1049+# generated with the -Duse-libclang=ON option for CMake.
10081050 # The default value is: NO.
10091051
10101052 CLANG_ASSISTED_PARSING = NO
@@ -1047,7 +1089,7 @@ IGNORE_PREFIX = · 36 unmodified lines
10471089 # Configuration options related to the HTML output
10481090 #---------------------------------------------------------------------------
10491091
1050−# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
1092+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
10511093 # The default value is: YES.
10521094
10531095 GENERATE_HTML = YES
@@ -1113,10 +1155,10 @@ HTML_STYLESHEET = · 59 unmodified lines
11131155 # cascading style sheets that are included after the standard style sheets
11141156 # created by doxygen. Using this option one can overrule certain style aspects.
11151157 # This is preferred over using HTML_STYLESHEET since it does not replace the
1116−# standard style sheet and is therefor more robust against future updates.
1158+# standard style sheet and is therefore more robust against future updates.
11171159 # Doxygen will copy the style sheet files to the output directory.
1118−# Note: The order of the extra stylesheet files is of importance (e.g. the last
1119−# stylesheet in the list overrules the setting of the previous ones in the
1160+# Note: The order of the extra style sheet files is of importance (e.g. the last
1161+# style sheet in the list overrules the setting of the previous ones in the
11201162 # list). For an example see the documentation.
11211163 # This tag requires that the tag GENERATE_HTML is set to YES.
11221164
@@ -1133,7 +1175,7 @@ HTML_EXTRA_STYLESHEET = · 10 unmodified lines
11331175 HTML_EXTRA_FILES =
11341176
11351177 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1136−# will adjust the colors in the stylesheet and background images according to
1178+# will adjust the colors in the style sheet and background images according to
11371179 # this color. Hue is specified as an angle on a colorwheel, see
11381180 # http://en.wikipedia.org/wiki/Hue for more information. For instance the value
11391181 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
@@ -1164,8 +1206,9 @@ HTML_COLORSTYLE_GAMMA = 80 · 24 unmodified lines
11641206
11651207 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
11661208 # page will contain the date and time when the page was generated. Setting this
1167−# to NO can help when comparing the output of multiple runs.
1168−# The default value is: YES.
1209+# to YES can help to show when doxygen was last run and thus if the
1210+# documentation is up to date.
1211+# The default value is: NO.
11691212 # This tag requires that the tag GENERATE_HTML is set to YES.
11701213
11711214 HTML_TIMESTAMP = NO
@@ -1261,28 +1304,28 @@ GENERATE_HTMLHELP = NO · 89 unmodified lines
12611304 CHM_FILE =
12621305
12631306 # The HHC_LOCATION tag can be used to specify the location (absolute path
1264−# including file name) of the HTML help compiler ( hhc.exe). If non-empty
1307+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
12651308 # doxygen will try to run the HTML help compiler on the generated index.hhp.
12661309 # The file has to be specified with full path.
12671310 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
12681311
12691312 HHC_LOCATION =
12701313
1271−# The GENERATE_CHI flag controls if a separate .chi index file is generated (
1272−# YES) or that it should be included in the master .chm file ( NO).
1314+# The GENERATE_CHI flag controls if a separate .chi index file is generated
1315+# (YES) or that it should be included in the master .chm file (NO).
12731316 # The default value is: NO.
12741317 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
12751318
12761319 GENERATE_CHI = NO
12771320
1278−# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
1321+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
12791322 # and project file content.
12801323 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
12811324
12821325 CHM_INDEX_ENCODING =
12831326
1284−# The BINARY_TOC flag controls whether a binary table of contents is generated (
1285−# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
1327+# The BINARY_TOC flag controls whether a binary table of contents is generated
1328+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
12861329 # enables the Previous and Next buttons.
12871330 # The default value is: NO.
12881331 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1396,7 +1439,7 @@ DISABLE_INDEX = NO · 107 unmodified lines
13961439 # index structure (just like the one that is generated for HTML Help). For this
13971440 # to work a browser that supports JavaScript, DHTML, CSS and frames is required
13981441 # (i.e. any modern browser). Windows users are probably better off using the
1399−# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
1442+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
14001443 # further fine-tune the look of the index. As an example, the default style
14011444 # sheet generated by doxygen has an example that shows how to put an image at
14021445 # the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@@ -1424,7 +1467,7 @@ ENUM_VALUES_PER_LINE = 4 · 21 unmodified lines
14241467
14251468 TREEVIEW_WIDTH = 250
14261469
1427−# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
1470+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
14281471 # external symbols imported via tag files in a separate window.
14291472 # The default value is: NO.
14301473 # This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1453,7 +1496,7 @@ FORMULA_TRANSPARENT = YES · 22 unmodified lines
14531496
14541497 # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
14551498 # http://www.mathjax.org) which uses client side Javascript for the rendering
1456−# instead of using prerendered bitmaps. Use this if you do not have LaTeX
1499+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
14571500 # installed or if you want to formulas look prettier in the HTML output. When
14581501 # enabled you may also need to install MathJax separately and configure the path
14591502 # to it using the MATHJAX_RELPATH option.
@@ -1483,7 +1526,7 @@ MATHJAX_FORMAT = HTML-CSS · 23 unmodified lines
14831526 # The default value is: http://cdn.mathjax.org/mathjax/latest.
14841527 # This tag requires that the tag USE_MATHJAX is set to YES.
14851528
1486−MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
1529+MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
14871530
14881531 # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
14891532 # extension names that should be enabled during MathJax rendering. For example
@@ -1539,7 +1582,7 @@ SERVER_BASED_SEARCH = NO · 49 unmodified lines
15391582 # external search engine pointed to by the SEARCHENGINE_URL option to obtain the
15401583 # search results.
15411584 #
1542−# Doxygen ships with an example indexer ( doxyindexer) and search engine
1585+# Doxygen ships with an example indexer (doxyindexer) and search engine
15431586 # (doxysearch.cgi) which are based on the open source search engine library
15441587 # Xapian (see: http://xapian.org/).
15451588 #
@@ -1552,7 +1595,7 @@ EXTERNAL_SEARCH = NO · 6 unmodified lines
15521595 # The SEARCHENGINE_URL should point to a search engine hosted by a web server
15531596 # which will return the search results when EXTERNAL_SEARCH is enabled.
15541597 #
1555−# Doxygen ships with an example indexer ( doxyindexer) and search engine
1598+# Doxygen ships with an example indexer (doxyindexer) and search engine
15561599 # (doxysearch.cgi) which are based on the open source search engine library
15571600 # Xapian (see: http://xapian.org/). See the section "External Indexing and
15581601 # Searching" for details.
@@ -1590,7 +1633,7 @@ EXTRA_SEARCH_MAPPINGS = · 31 unmodified lines
15901633 # Configuration options related to the LaTeX output
15911634 #---------------------------------------------------------------------------
15921635
1593−# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
1636+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
15941637 # The default value is: YES.
15951638
15961639 GENERATE_LATEX = NO
@@ -1621,7 +1664,7 @@ LATEX_CMD_NAME = latex · 24 unmodified lines
16211664
16221665 MAKEINDEX_CMD_NAME = makeindex
16231666
1624−# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
1667+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
16251668 # documents. This may be useful for small projects and may help to save some
16261669 # trees in general.
16271670 # The default value is: NO.
@@ -1639,9 +1682,12 @@ COMPACT_LATEX = NO · 11 unmodified lines
16391682 PAPER_TYPE = a4
16401683
16411684 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1642−# that should be included in the LaTeX output. To get the times font for
1643−# instance you can specify
1644−# EXTRA_PACKAGES=times
1685+# that should be included in the LaTeX output. The package can be specified just
1686+# by its name or with the correct syntax as to be used with the LaTeX
1687+# \usepackage command. To get the times font for instance you can specify :
1688+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
1689+# To use the option intlimits with the amsmath package you can specify:
1690+# EXTRA_PACKAGES=[intlimits]{amsmath}
16451691 # If left blank no extra packages will be included.
16461692 # This tag requires that the tag GENERATE_LATEX is set to YES.
16471693
@@ -1656,9 +1702,9 @@ EXTRA_PACKAGES = · 8 unmodified lines
16561702 # Note: Only use a user-defined header if you know what you are doing! The
16571703 # following commands have a special meaning inside the header: $title,
16581704 # $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1659−# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
1660−# for the replacement values of the other commands the user is refered to
1661−# HTML_HEADER.
1705+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
1706+# string, for the replacement values of the other commands the user is referred
1707+# to HTML_HEADER.
16621708 # This tag requires that the tag GENERATE_LATEX is set to YES.
16631709
16641710 LATEX_HEADER =
@@ -1674,6 +1720,17 @@ LATEX_HEADER = · 9 unmodified lines
16741720
16751721 LATEX_FOOTER =
16761722
1723+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1724+# LaTeX style sheets that are included after the standard style sheets created
1725+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
1726+# will copy the style sheet files to the output directory.
1727+# Note: The order of the extra style sheet files is of importance (e.g. the last
1728+# style sheet in the list overrules the setting of the previous ones in the
1729+# list).
1730+# This tag requires that the tag GENERATE_LATEX is set to YES.
1731+
1732+LATEX_EXTRA_STYLESHEET =
1733+
16771734 # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
16781735 # other source files which should be copied to the LATEX_OUTPUT output
16791736 # directory. Note that the files will be copied as-is; there are no commands or
@@ -1692,7 +1749,7 @@ LATEX_EXTRA_FILES = · 12 unmodified lines
16921749 PDF_HYPERLINKS = YES
16931750
16941751 # If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
1695−# the PDF file directly from the LaTeX files. Set this option to YES to get a
1752+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
16961753 # higher quality PDF documentation.
16971754 # The default value is: YES.
16981755 # This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1733,11 +1790,19 @@ LATEX_SOURCE_CODE = NO · 34 unmodified lines
17331790
17341791 LATEX_BIB_STYLE = plain
17351792
1793+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
1794+# page will contain the date and time when the page was generated. Setting this
1795+# to NO can help when comparing the output of multiple runs.
1796+# The default value is: NO.
1797+# This tag requires that the tag GENERATE_LATEX is set to YES.
1798+
1799+LATEX_TIMESTAMP = NO
1800+
17361801 #---------------------------------------------------------------------------
17371802 # Configuration options related to the RTF output
17381803 #---------------------------------------------------------------------------
17391804
1740−# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
1805+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
17411806 # RTF output is optimized for Word 97 and may not look too pretty with other RTF
17421807 # readers/editors.
17431808 # The default value is: NO.
@@ -1752,7 +1817,7 @@ GENERATE_RTF = NO · 8 unmodified lines
17521817
17531818 RTF_OUTPUT = rtf
17541819
1755−# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
1820+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
17561821 # documents. This may be useful for small projects and may help to save some
17571822 # trees in general.
17581823 # The default value is: NO.
@@ -1789,11 +1854,21 @@ RTF_STYLESHEET_FILE = · 30 unmodified lines
17891854
17901855 RTF_EXTENSIONS_FILE =
17911856
1857+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
1858+# with syntax highlighting in the RTF output.
1859+#
1860+# Note that which sources are shown also depends on other settings such as
1861+# SOURCE_BROWSER.
1862+# The default value is: NO.
1863+# This tag requires that the tag GENERATE_RTF is set to YES.
1864+
1865+RTF_SOURCE_CODE = NO
1866+
17921867 #---------------------------------------------------------------------------
17931868 # Configuration options related to the man page output
17941869 #---------------------------------------------------------------------------
17951870
1796−# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
1871+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
17971872 # classes and files.
17981873 # The default value is: NO.
17991874
@@ -1837,7 +1912,7 @@ MAN_LINKS = NO · 37 unmodified lines
18371912 # Configuration options related to the XML output
18381913 #---------------------------------------------------------------------------
18391914
1840−# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
1915+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
18411916 # captures the structure of the code including all documentation.
18421917 # The default value is: NO.
18431918
@@ -1851,7 +1926,7 @@ GENERATE_XML = NO · 7 unmodified lines
18511926
18521927 XML_OUTPUT = xml
18531928
1854−# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
1929+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
18551930 # listings (including syntax highlighting and cross-referencing information) to
18561931 # the XML output. Note that enabling this will significantly increase the size
18571932 # of the XML output.
@@ -1864,7 +1939,7 @@ XML_PROGRAMLISTING = YES · 6 unmodified lines
18641939 # Configuration options related to the DOCBOOK output
18651940 #---------------------------------------------------------------------------
18661941
1867−# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
1942+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
18681943 # that can be used to generate PDF.
18691944 # The default value is: NO.
18701945
@@ -1878,7 +1953,7 @@ GENERATE_DOCBOOK = NO · 7 unmodified lines
18781953
18791954 DOCBOOK_OUTPUT = docbook
18801955
1881−# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
1956+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
18821957 # program listings (including syntax highlighting and cross-referencing
18831958 # information) to the DOCBOOK output. Note that enabling this will significantly
18841959 # increase the size of the DOCBOOK output.
@@ -1891,10 +1966,10 @@ DOCBOOK_PROGRAMLISTING = NO · 6 unmodified lines
18911966 # Configuration options for the AutoGen Definitions output
18921967 #---------------------------------------------------------------------------
18931968
1894−# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
1895−# Definitions (see http://autogen.sf.net) file that captures the structure of
1896−# the code including all documentation. Note that this feature is still
1897−# experimental and incomplete at the moment.
1969+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
1970+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
1971+# structure of the code including all documentation. Note that this feature is
1972+# still experimental and incomplete at the moment.
18981973 # The default value is: NO.
18991974
19001975 GENERATE_AUTOGEN_DEF = NO
@@ -1903,7 +1978,7 @@ GENERATE_AUTOGEN_DEF = NO · 2 unmodified lines
19031978 # Configuration options related to the Perl module output
19041979 #---------------------------------------------------------------------------
19051980
1906−# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
1981+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
19071982 # file that captures the structure of the code including all documentation.
19081983 #
19091984 # Note that this feature is still experimental and incomplete at the moment.
@@ -1911,7 +1986,7 @@ GENERATE_AUTOGEN_DEF = NO · 1 unmodified line
19111986
19121987 GENERATE_PERLMOD = NO
19131988
1914−# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
1989+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
19151990 # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
19161991 # output from the Perl module output.
19171992 # The default value is: NO.
@@ -1919,9 +1994,9 @@ GENERATE_PERLMOD = NO · 1 unmodified line
19191994
19201995 PERLMOD_LATEX = NO
19211996
1922−# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
1997+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
19231998 # formatted so it can be parsed by a human reader. This is useful if you want to
1924−# understand what is going on. On the other hand, if this tag is set to NO the
1999+# understand what is going on. On the other hand, if this tag is set to NO, the
19252000 # size of the Perl module output will be much smaller and Perl will parse it
19262001 # just the same.
19272002 # The default value is: YES.
@@ -1941,14 +2016,14 @@ PERLMOD_MAKEVAR_PREFIX = · 13 unmodified lines
19412016 # Configuration options related to the preprocessor
19422017 #---------------------------------------------------------------------------
19432018
1944−# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
2019+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
19452020 # C-preprocessor directives found in the sources and include files.
19462021 # The default value is: YES.
19472022
19482023 ENABLE_PREPROCESSING = YES
19492024
1950−# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
1951−# in the source code. If set to NO only conditional compilation will be
2025+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
2026+# in the source code. If set to NO, only conditional compilation will be
19522027 # performed. Macro expansion can be done in a controlled way by setting
19532028 # EXPAND_ONLY_PREDEF to YES.
19542029 # The default value is: NO.
@@ -1964,7 +2039,7 @@ MACRO_EXPANSION = NO · 9 unmodified lines
19642039
19652040 EXPAND_ONLY_PREDEF = NO
19662041
1967−# If the SEARCH_INCLUDES tag is set to YES the includes files in the
2042+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
19682043 # INCLUDE_PATH will be searched if a #include is found.
19692044 # The default value is: YES.
19702045 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2040,20 +2115,21 @@ TAGFILES = · 69 unmodified lines
20402115
20412116 GENERATE_TAGFILE =
20422117
2043−# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
2044−# class index. If set to NO only the inherited external classes will be listed.
2118+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
2119+# the class index. If set to NO, only the inherited external classes will be
2120+# listed.
20452121 # The default value is: NO.
20462122
20472123 ALLEXTERNALS = NO
20482124
2049−# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
2050−# the modules index. If set to NO, only the current project's groups will be
2125+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
2126+# in the modules index. If set to NO, only the current project's groups will be
20512127 # listed.
20522128 # The default value is: YES.
20532129
20542130 EXTERNAL_GROUPS = YES
20552131
2056−# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
2132+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
20572133 # the related pages index. If set to NO, only the current project's pages will
20582134 # be listed.
20592135 # The default value is: YES.
@@ -2070,7 +2146,7 @@ PERL_PATH = /usr/bin/perl · 10 unmodified lines
20702146 # Configuration options related to the dot tool
20712147 #---------------------------------------------------------------------------
20722148
2073−# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
2149+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
20742150 # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
20752151 # NO turns the diagrams off. Note that this option also works with HAVE_DOT
20762152 # disabled, but it is recommended to install and use dot, since it yields more
@@ -2095,7 +2171,7 @@ MSCGEN_PATH = · 18 unmodified lines
20952171
20962172 DIA_PATH =
20972173
2098−# If set to YES, the inheritance and collaboration graphs will hide inheritance
2174+# If set to YES the inheritance and collaboration graphs will hide inheritance
20992175 # and usage relations if the target is undocumented or is not a class.
21002176 # The default value is: YES.
21012177
@@ -2168,7 +2244,7 @@ COLLABORATION_GRAPH = YES · 66 unmodified lines
21682244
21692245 GROUP_GRAPHS = YES
21702246
2171−# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
2247+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
21722248 # collaboration diagrams in a style similar to the OMG's Unified Modeling
21732249 # Language.
21742250 # The default value is: NO.
@@ -2220,7 +2296,8 @@ INCLUDED_BY_GRAPH = YES · 45 unmodified lines
22202296 #
22212297 # Note that enabling this option will significantly increase the time of a run.
22222298 # So in most cases it will be better to enable call graphs for selected
2223−# functions only using the \callgraph command.
2299+# functions only using the \callgraph command. Disabling a call graph can be
2300+# accomplished by means of the command \hidecallgraph.
22242301 # The default value is: NO.
22252302 # This tag requires that the tag HAVE_DOT is set to YES.
22262303
@@ -2231,7 +2308,8 @@ CALL_GRAPH = NO · 4 unmodified lines
22312308 #
22322309 # Note that enabling this option will significantly increase the time of a run.
22332310 # So in most cases it will be better to enable caller graphs for selected
2234−# functions only using the \callergraph command.
2311+# functions only using the \callergraph command. Disabling a caller graph can be
2312+# accomplished by means of the command \hidecallergraph.
22352313 # The default value is: NO.
22362314 # This tag requires that the tag HAVE_DOT is set to YES.
22372315
@@ -2254,13 +2332,17 @@ GRAPHICAL_HIERARCHY = YES · 16 unmodified lines
22542332 DIRECTORY_GRAPH = YES
22552333
22562334 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
2257−# generated by dot.
2335+# generated by dot. For an explanation of the image formats see the section
2336+# output formats in the documentation of the dot tool (Graphviz (see:
2337+# http://www.graphviz.org/)).
22582338 # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
22592339 # to make the SVG files visible in IE 9+ (other browsers do not have this
22602340 # requirement).
22612341 # Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
22622342 # png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
2263−# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
2343+# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
2344+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
2345+# png:gdiplus:gdiplus.
22642346 # The default value is: png.
22652347 # This tag requires that the tag HAVE_DOT is set to YES.
22662348
@@ -2308,10 +2390,19 @@ DIAFILE_DIRS = · 41 unmodified lines
23082390 # PlantUML is not used or called during a preprocessing step. Doxygen will
23092391 # generate a warning when it encounters a \startuml command in this case and
23102392 # will not generate output for the diagram.
2311−# This tag requires that the tag HAVE_DOT is set to YES.
23122393
23132394 PLANTUML_JAR_PATH =
23142395
2396+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
2397+# configuration file for plantuml.
2398+
2399+PLANTUML_CFG_FILE =
2400+
2401+# When using plantuml, the specified paths are searched for files specified by
2402+# the !include statement in a plantuml block.
2403+
2404+PLANTUML_INCLUDE_PATH =
2405+
23152406 # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
23162407 # that will be shown in the graph. If the number of nodes in a graph becomes
23172408 # larger than this value, doxygen will truncate the graph, which is visualized
@@ -2348,7 +2439,7 @@ MAX_DOT_GRAPH_DEPTH = 0 · 30 unmodified lines
23482439
23492440 DOT_TRANSPARENT = NO
23502441
2351−# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
2442+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
23522443 # files in one run (i.e. multiple -o and -T options on the command line). This
23532444 # makes dot run faster, but since only newer versions of dot (>1.8.10) support
23542445 # this, this feature is disabled by default.
@@ -2365,7 +2456,7 @@ DOT_MULTI_TARGETS = NO · 10 unmodified lines
23652456
23662457 GENERATE_LEGEND = YES
23672458
2368−# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
2459+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
23692460 # files that are used to generate the various graphs.
23702461 # The default value is: YES.
23712462 # This tag requires that the tag HAVE_DOT is set to YES.
doc/xcode_frameworks.rst+37−5
@@ -1,7 +1,5 @@
1−.. _xcode-frameworks-label:
2−
3−Using aubio frameworks in Xcode
4−-------------------------------
1+Frameworks for Xcode
2+--------------------
53
64 `Binary frameworks`_ are available and ready to use in your XCode project, for
75 `iOS`_ and `macOS`_.
@@ -34,7 +32,41 @@ Using aubio frameworks in Xcode · 26 unmodified lines
3432
3533 import aubio
3634
35+Using aubio from swift
36+----------------------
37+
38+Once you have downloaded and installed :ref:`aubio.framework
39+<xcode-frameworks-label>`, you sould be able to use aubio from C, Obj-C, and
40+Swift source files.
41+
42+
43+Here is a short example showing how to read a sound file in swift:
44+
45+
46+ .. code-block:: swift
47+
48+ import aubio
49+
50+ let path = Bundle.main.path(forResource: "example", ofType: "mp4")
51+ if (path != nil) {
52+ let hop_size : uint_t = 512
53+ let a = new_fvec(hop_size)
54+ let b = new_aubio_source(path, 0, hop_size)
55+ var read: uint_t = 0
56+ var total_frames : uint_t = 0
57+ while (true) {
58+ aubio_source_do(b, a, &read)
59+ total_frames += read
60+ if (read < hop_size) { break }
61+ }
62+ print("read", total_frames, "frames at", aubio_source_get_samplerate(b), "Hz")
63+ del_aubio_source(b)
64+ del_fvec(a)
65+ } else {
66+ print("could not find file")
67+ }
68+
69+
3770 .. _Binary frameworks: https://aubio.org/download
3871 .. _iOS: https://aubio.org/download#ios
3972 .. _macOS: https://aubio.org/download#osx
40−.. _Download: https://aubio.org/download
examples/aubiomfcc.c+7−2
@@ -48,6 +48,7 @@ void process_print (void) · 47 unmodified lines
4848 }
4949
5050 int main(int argc, char **argv) {
51+ int ret = 0;
5152 // change some default params
5253 buffer_size = 512;
5354 hop_size = 256;
@@ -62,6 +63,10 @@ int main(int argc, char **argv) { · 8 unmodified lines
6263 fftgrain = new_cvec (buffer_size);
6364 mfcc = new_aubio_mfcc(buffer_size, n_filters, n_coefs, samplerate);
6465 mfcc_out = new_fvec(n_coefs);
66+ if (pv == NULL || fftgrain == NULL || mfcc == NULL || mfcc_out == NULL) {
67+ ret = 1;
68+ goto beach;
69+ }
6570
6671 examples_common_process((aubio_process_func_t)process_block, process_print);
6772
@@ -70,7 +75,7 @@ int main(int argc, char **argv) { · 2 unmodified lines
7075 del_aubio_mfcc(mfcc);
7176 del_fvec(mfcc_out);
7277
78+beach:
7379 examples_common_del();
74− return 0;
80+ return ret;
7581 }
76−
examples/aubionotes.c+33−6
@@ -21,6 +21,8 @@ · 20 unmodified lines
2121 #include "utils.h"
2222 #define PROG_HAS_PITCH 1
2323 #define PROG_HAS_ONSET 1
24+#define PROG_HAS_NOTES 1
25+#define PROG_HAS_SILENCE 1
2426 #define PROG_HAS_JACK 1
2527 // TODO add PROG_HAS_OUTPUT
2628 #include "parse_args.h"
@@ -33,12 +35,12 @@ void process_block (fvec_t *ibuf, fvec_t *obuf) · 6 unmodified lines
3335 aubio_notes_do (notes, ibuf, obuf);
3436 // did we get a note off?
3537 if (obuf->data[2] != 0) {
36− lastmidi = aubio_freqtomidi (obuf->data[2]) + .5;
38+ lastmidi = obuf->data[2];
3739 send_noteon(lastmidi, 0);
3840 }
3941 // did we get a note on?
4042 if (obuf->data[0] != 0) {
41− lastmidi = aubio_freqtomidi (obuf->data[0]) + .5;
43+ lastmidi = obuf->data[0];
4244 send_noteon(lastmidi, obuf->data[1]);
4345 }
4446 }
@@ -49,6 +51,8 @@ void process_print (void) · 4 unmodified lines
4951 }
5052
5153 int main(int argc, char **argv) {
54+ int ret = 0;
55+
5256 examples_common_init(argc,argv);
5357
5458 verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
@@ -64,15 +68,38 @@ int main(int argc, char **argv) { · 9 unmodified lines
6468 verbmsg ("tolerance: %f\n", pitch_tolerance);
6569
6670 notes = new_aubio_notes ("default", buffer_size, hop_size, samplerate);
71+ if (notes == NULL) { ret = 1; goto beach; }
72+
73+ if (onset_minioi != 0.) {
74+ aubio_notes_set_minioi_ms(notes, onset_minioi);
75+ }
76+ if (onset_threshold != 0.) {
77+ errmsg ("warning: onset threshold not supported yet\n");
78+ //aubio_onset_set_threshold(aubio_notes_get_aubio_onset(o), onset_threshold);
79+ }
80+ if (silence_threshold != -90.) {
81+ if (aubio_notes_set_silence (notes, silence_threshold) != 0) {
82+ errmsg ("failed setting notes silence threshold to %.2f\n",
83+ silence_threshold);
84+ }
85+ }
86+ if (release_drop != 10.) {
87+ if (aubio_notes_set_release_drop (notes, release_drop) != 0) {
88+ errmsg ("failed setting notes release drop to %.2f\n",
89+ release_drop);
90+ }
91+ }
6792
6893 examples_common_process((aubio_process_func_t)process_block, process_print);
6994
70− // send a last note off
71− send_noteon (lastmidi, 0);
95+ // send a last note off if required
96+ if (lastmidi) {
97+ send_noteon (lastmidi, 0);
98+ }
7299
73100 del_aubio_notes (notes);
74101
102+beach:
75103 examples_common_del();
76− return 0;
104+ return ret;
77105 }
78−
examples/aubioonset.c+22−11
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "utils.h"
2222 #define PROG_HAS_ONSET 1
2323 #define PROG_HAS_OUTPUT 1
24+#define PROG_HAS_SILENCE 1
2425 #define PROG_HAS_JACK 1
2526 #include "parse_args.h"
2627
@@ -42,10 +43,11 @@ void process_block(fvec_t *ibuf, fvec_t *obuf) · 15 unmodified lines
4243 } else {
4344 aubio_wavetable_stop ( wavetable );
4445 }
45− if (mix_input)
46+ if (mix_input) {
4647 aubio_wavetable_do (wavetable, ibuf, obuf);
47− else
48+ } else {
4849 aubio_wavetable_do (wavetable, obuf, obuf);
50+ }
4951 }
5052
5153 void process_print (void)
@@ -57,20 +59,26 @@ void process_print (void) · 5 unmodified lines
5759 }
5860
5961 int main(int argc, char **argv) {
62+ int ret = 0;
6063 examples_common_init(argc,argv);
6164
62− verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
63− verbmsg ("onset method: %s, ", onset_method);
64− verbmsg ("buffer_size: %d, ", buffer_size);
65− verbmsg ("hop_size: %d, ", hop_size);
66− verbmsg ("silence: %f, ", silence_threshold);
67− verbmsg ("threshold: %f\n", onset_threshold);
68−
6965 o = new_aubio_onset (onset_method, buffer_size, hop_size, samplerate);
66+ if (o == NULL) { ret = 1; goto beach; }
7067 if (onset_threshold != 0.)
7168 aubio_onset_set_threshold (o, onset_threshold);
7269 if (silence_threshold != -90.)
7370 aubio_onset_set_silence (o, silence_threshold);
71+ if (onset_minioi != 0.)
72+ aubio_onset_set_minioi_s (o, onset_minioi);
73+
74+ verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
75+ verbmsg ("onset method: %s, ", onset_method);
76+ verbmsg ("buffer_size: %d, ", buffer_size);
77+ verbmsg ("hop_size: %d, ", hop_size);
78+ verbmsg ("silence: %f, ", aubio_onset_get_silence(o));
79+ verbmsg ("threshold: %f, ", aubio_onset_get_threshold(o));
80+ verbmsg ("awhitening: %f, ", aubio_onset_get_awhitening(o));
81+ verbmsg ("compression: %f\n", aubio_onset_get_compression(o));
7482
7583 onset = new_fvec (1);
7684
@@ -81,12 +89,15 @@ int main(int argc, char **argv) { · 4 unmodified lines
8189 examples_common_process((aubio_process_func_t)process_block, process_print);
8290
8391 // send a last note off
84− send_noteon (miditap_note, 0);
92+ if (usejack) {
93+ send_noteon (miditap_note, 0);
94+ }
8595
8696 del_aubio_onset (o);
8797 del_aubio_wavetable (wavetable);
8898 del_fvec (onset);
8999
100+beach:
90101 examples_common_del();
91− return 0;
102+ return ret;
92103 }
examples/aubiopitch.c+5−2
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "utils.h"
2222 #define PROG_HAS_PITCH 1
2323 #define PROG_HAS_OUTPUT 1
24+#define PROG_HAS_SILENCE 1
2425 #define PROG_HAS_JACK 1
2526 #include "parse_args.h"
2627
@@ -51,6 +52,7 @@ void process_print (void) · 24 unmodified lines
5152 }
5253
5354 int main(int argc, char **argv) {
55+ int ret = 0;
5456
5557 buffer_size = 2048;
5658
@@ -64,6 +66,7 @@ int main(int argc, char **argv) { · 7 unmodified lines
6466 verbmsg ("tolerance: %f\n", pitch_tolerance);
6567
6668 o = new_aubio_pitch (pitch_method, buffer_size, hop_size, samplerate);
69+ if (o == NULL) { ret = 1; goto beach; }
6770 if (pitch_tolerance != 0.)
6871 aubio_pitch_set_tolerance (o, pitch_tolerance);
6972 if (silence_threshold != -90.)
@@ -82,7 +85,7 @@ int main(int argc, char **argv) { · 12 unmodified lines
8285 del_aubio_wavetable (wavetable);
8386 del_fvec (pitch);
8487
88+beach:
8589 examples_common_del();
86− return 0;
90+ return ret;
8791 }
88−
examples/aubioquiet.c+1−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 */
2020
2121 #include "utils.h"
22+#define PROG_HAS_SILENCE 1
2223 #include "parse_args.h"
2324
2425 sint_t wassilence = 1, issilence;
examples/aubiotrack.c+12−5
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "utils.h"
2222 #define PROG_HAS_TEMPO 1
2323 #define PROG_HAS_ONSET 1
24+#define PROG_HAS_SILENCE 1
2425 #define PROG_HAS_OUTPUT 1
2526 #define PROG_HAS_JACK 1
2627 #include "parse_args.h"
@@ -45,10 +46,11 @@ void process_block(fvec_t * ibuf, fvec_t *obuf) { · 18 unmodified lines
4546 } else {
4647 aubio_wavetable_stop ( wavetable );
4748 }
48− if (mix_input)
49+ if (mix_input) {
4950 aubio_wavetable_do (wavetable, ibuf, obuf);
50− else
51+ } else {
5152 aubio_wavetable_do (wavetable, obuf, obuf);
53+ }
5254 }
5355
5456 void process_print (void) {
@@ -59,6 +61,7 @@ void process_print (void) { · 4 unmodified lines
5961 }
6062
6163 int main(int argc, char **argv) {
64+ int ret = 0;
6265 // override general settings from utils.c
6366 buffer_size = 1024;
6467 hop_size = 512;
@@ -74,9 +77,11 @@ int main(int argc, char **argv) { · 9 unmodified lines
7477
7578 tempo_out = new_fvec(2);
7679 tempo = new_aubio_tempo(tempo_method, buffer_size, hop_size, samplerate);
80+ if (tempo == NULL) { ret = 1; goto beach; }
7781 // set silence threshold very low to output beats even during silence
7882 // aubio_tempo_set_silence(tempo, -1000.);
7983 if (onset_threshold != 0.) aubio_tempo_set_threshold (tempo, onset_threshold);
84+ if (onset_minioi != 0.) errmsg ("warning: minioio not supported yet\n");
8085
8186 wavetable = new_aubio_wavetable (samplerate, hop_size);
8287 aubio_wavetable_set_freq ( wavetable, 2450.);
@@ -85,13 +90,15 @@ int main(int argc, char **argv) { · 2 unmodified lines
8590 examples_common_process((aubio_process_func_t)process_block,process_print);
8691
8792 // send a last note off
88− send_noteon (miditap_note, 0);
93+ if (usejack) {
94+ send_noteon (miditap_note, 0);
95+ }
8996
9097 del_aubio_tempo(tempo);
9198 del_aubio_wavetable (wavetable);
9299 del_fvec(tempo_out);
93100
101+beach:
94102 examples_common_del();
95− return 0;
103+ return ret;
96104 }
97−
examples/parse_args.h+62−11
@@ -36,6 +36,7 @@ extern uint_t hop_size; · 35 unmodified lines
3636 // onset stuff
3737 extern char_t * onset_method;
3838 extern smpl_t onset_threshold;
39+extern smpl_t onset_minioi;
3940 // pitch stuff
4041 extern char_t * pitch_method;
4142 extern char_t * pitch_unit;
@@ -46,6 +47,7 @@ extern uint_t time_format; · 4 unmodified lines
4647 extern char_t * tempo_method;
4748 // more general stuff
4849 extern smpl_t silence_threshold;
50+extern smpl_t release_drop;
4951 extern uint_t mix_input;
5052 // midi tap
5153 extern smpl_t miditap_note;
@@ -63,8 +65,8 @@ int parse_args (int argc, char **argv); · 11 unmodified lines
6365 // internal stuff
6466 extern int blocks;
6567
66−extern fvec_t *ibuf;
67−extern fvec_t *obuf;
68+extern fvec_t *input_buffer;
69+extern fvec_t *output_buffer;
6870
6971 const char *prog_name;
7072
@@ -91,17 +93,25 @@ void usage (FILE * stream, int exit_code) · 20 unmodified lines
9193 " default=hfc\n"
9294 " -t --onset-threshold set onset detection threshold\n"
9395 " a value between 0.1 (more detections) and 1 (less); default=0.3\n"
96+ " -M --minioi set minimum inter-onset interval\n"
97+ " a value in second; default=0.012\n"
9498 #endif /* PROG_HAS_ONSET */
9599 #ifdef PROG_HAS_PITCH
96100 " -p --pitch select pitch detection algorithm\n"
97− " <default|yinfft|yin|mcomb|fcomb|schmitt>; default=yinfft\n"
101+ " <default|yinfft|yinfast|yin|mcomb|fcomb|schmitt>; default=yinfft\n"
98102 " -u --pitch-unit select pitch output unit\n"
99103 " <default|freq|hertz|Hz|midi|cent|bin>; default=freq\n"
100104 " -l --pitch-tolerance select pitch tolerance\n"
101105 " (yin, yinfft only) a value between 0.1 and 0.7; default=0.3\n"
102106 #endif /* PROG_HAS_PITCH */
107+#ifdef PROG_HAS_SILENCE
103108 " -s --silence select silence threshold\n"
104109 " a value in dB, for instance -70, or -100; default=-90\n"
110+#endif /* PROG_HAS_SILENCE */
111+#ifdef PROG_HAS_NOTES
112+ " -d --release-drop select release drop threshold\n"
113+ " a positive value in dB; default=10\n"
114+#endif
105115 " -T --time-format select time values output format\n"
106116 " (samples, ms, seconds) default=seconds\n"
107117 #ifdef PROG_HAS_OUTPUT
@@ -109,10 +119,14 @@ void usage (FILE * stream, int exit_code) · 1 unmodified line
109119 " input signal will be added to output synthesis\n"
110120 " -f --force-overwrite overwrite output file if needed\n"
111121 " do not fail if output file already exists\n"
112−#endif
113−#ifdef PROG_HAS_JACK
122+#endif /* PROG_HAS_OUTPUT */
123+#if defined(PROG_HAS_JACK) && defined(HAVE_JACK)
114124 " -j --jack use Jack\n"
115−#endif
125+#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
126+ " -N --miditap-note MIDI note; default=69.\n"
127+ " -V --miditap-velo MIDI velocity; default=65.\n"
128+#endif /* defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH) */
129+#endif /* defined(PROG_HAS_JACK) && defined(HAVE_JACK) */
116130 " -v --verbose be verbose\n"
117131 " -h --help display this message\n"
118132 );
@@ -131,18 +145,30 @@ parse_args (int argc, char **argv) · 12 unmodified lines
131145 "i:r:B:H:"
132146 #ifdef PROG_HAS_JACK
133147 "j"
148+#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
149+ "N:V:"
150+#endif /* defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH) */
134151 #endif /* PROG_HAS_JACK */
135152 #ifdef PROG_HAS_OUTPUT
136153 "o:"
137154 #endif /* PROG_HAS_OUTPUT */
138155 #ifdef PROG_HAS_ONSET
139− "O:t:"
156+ "O:t:M:"
140157 #endif /* PROG_HAS_ONSET */
141158 #ifdef PROG_HAS_PITCH
142159 "p:u:l:"
143160 #endif /* PROG_HAS_PITCH */
144161 "T:"
145− "s:mf";
162+#ifdef PROG_HAS_SILENCE
163+ "s:"
164+#endif /* PROG_HAS_SILENCE */
165+#ifdef PROG_HAS_NOTES
166+ "d:"
167+#endif /* PROG_HAS_SILENCE */
168+#ifdef PROG_HAS_OUTPUT
169+ "mf"
170+#endif /* PROG_HAS_OUTPUT */
171+ ;
146172 int next_option;
147173 struct option long_options[] = {
148174 {"help", 0, NULL, 'h'},
@@ -153,6 +179,10 @@ parse_args (int argc, char **argv) · 4 unmodified lines
153179 {"hopsize", 1, NULL, 'H'},
154180 #ifdef PROG_HAS_JACK
155181 {"jack", 0, NULL, 'j'},
182+#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
183+ {"miditap-note", 1, NULL, 'N'},
184+ {"miditap-velo", 1, NULL, 'V'},
185+#endif /* PROG_HAS_ONSET !PROG_HAS_PITCH */
156186 #endif /* PROG_HAS_JACK */
157187 #ifdef PROG_HAS_OUTPUT
158188 {"output", 1, NULL, 'o'},
@@ -160,24 +190,32 @@ parse_args (int argc, char **argv) · 1 unmodified line
160190 #ifdef PROG_HAS_ONSET
161191 {"onset", 1, NULL, 'O'},
162192 {"onset-threshold", 1, NULL, 't'},
193+ {"onset-minioi", 1, NULL, 'M'},
163194 #endif /* PROG_HAS_ONSET */
164195 #ifdef PROG_HAS_PITCH
165196 {"pitch", 1, NULL, 'p'},
166197 {"pitch-unit", 1, NULL, 'u'},
167198 {"pitch-tolerance", 1, NULL, 'l'},
168199 #endif /* PROG_HAS_PITCH */
200+#ifdef PROG_HAS_SILENCE
169201 {"silence", 1, NULL, 's'},
202+#endif /* PROG_HAS_SILENCE */
203+#ifdef PROG_HAS_NOTES
204+ {"release-drop", 1, NULL, 'd'},
205+#endif /* PROG_HAS_NOTES */
170206 {"time-format", 1, NULL, 'T'},
207+#ifdef PROG_HAS_OUTPUT
171208 {"mix-input", 0, NULL, 'm'},
172209 {"force-overwrite", 0, NULL, 'f'},
210+#endif /* PROG_HAS_OUTPUT */
173211 {NULL, 0, NULL, 0}
174212 };
175213 #endif /* HAVE_GETOPT_H */
176− prog_name = argv[0];
214+ // better safe than sorry
177215 if (argc < 1) {
178216 usage (stderr, 1);
179− return -1;
180217 }
218+ prog_name = argv[0];
181219 #ifdef HAVE_GETOPT_H
182220 do {
183221 next_option = getopt_long (argc, argv, options, long_options, NULL);
@@ -191,6 +229,12 @@ parse_args (int argc, char **argv) · 7 unmodified lines
191229 case 'j':
192230 usejack = 1;
193231 break;
232+ case 'N':
233+ miditap_note = (smpl_t) atoi (optarg);
234+ break;
235+ case 'V':
236+ miditap_velo = (smpl_t) atoi (optarg);
237+ break;
194238 case 'i':
195239 source_uri = optarg;
196240 break;
@@ -215,6 +259,9 @@ parse_args (int argc, char **argv) · 18 unmodified lines
215259 case 't': /* threshold value for onset */
216260 onset_threshold = (smpl_t) atof (optarg);
217261 break;
262+ case 'M': /* minimum inter-onset-interval */
263+ onset_minioi = (smpl_t) atof (optarg);
264+ break;
218265 case 'p':
219266 pitch_method = optarg;
220267 break;
@@ -238,6 +285,9 @@ parse_args (int argc, char **argv) · 17 unmodified lines
238285 case 's': /* silence threshold */
239286 silence_threshold = (smpl_t) atof (optarg);
240287 break;
288+ case 'd': /* release-drop threshold */
289+ release_drop = (smpl_t) atof (optarg);
290+ break;
241291 case 'm': /* mix_input flag */
242292 mix_input = 1;
243293 break;
@@ -277,7 +327,8 @@ parse_args (int argc, char **argv) · 33 unmodified lines
277327 usejack = 1;
278328 #else
279329 errmsg("Error: no arguments given (and no available audio input)\n");
280− usage ( stderr, 1 );
330+ errmsg(" consider recompiling with jack support (--enable-jack)\n");
331+ exit ( 1 );
281332 #endif /* HAVE_JACK */
282333 #else
283334 errmsg("Error: no arguments given\n");
examples/utils.c+22−13
@@ -43,6 +43,7 @@ uint_t hop_size = 256; · 42 unmodified lines
4343 // onset stuff
4444 char_t * onset_method = "default";
4545 smpl_t onset_threshold = 0.0; // will be set if != 0.
46+smpl_t onset_minioi = 0.0; // will be set if != 0.
4647 // pitch stuff
4748 char_t * pitch_unit = "default";
4849 char_t * pitch_method = "default";
@@ -53,6 +54,7 @@ uint_t time_format = 0; // for "seconds", 1 for "ms", 2 for "samples" · 4 unmodified lines
5354 char_t * tempo_method = "default";
5455 // more general stuff
5556 smpl_t silence_threshold = -90.;
57+smpl_t release_drop = 10.;
5658 uint_t mix_input = 0;
5759
5860 uint_t force_overwrite = 0;
@@ -61,8 +63,8 @@ uint_t force_overwrite = 0; · 2 unmodified lines
6163 // internal memory stuff
6264 aubio_source_t *this_source = NULL;
6365 aubio_sink_t *this_sink = NULL;
64−fvec_t *ibuf;
65−fvec_t *obuf;
66+fvec_t *input_buffer;
67+fvec_t *output_buffer;
6668
6769 smpl_t miditap_note = 69.;
6870 smpl_t miditap_velo = 65.;
@@ -74,7 +76,12 @@ extern void usage (FILE * stream, int exit_code); · 5 unmodified lines
7476 extern int parse_args (int argc, char **argv);
7577
7678 #if HAVE_JACK
79+#define MAX_MIDI_EVENTS 128
80+#define MAX_MIDI_EVENT_SIZE 3
7781 aubio_jack_t *jack_setup;
82+jack_midi_event_t ev;
83+jack_midi_data_t midi_data[MAX_MIDI_EVENTS * MAX_MIDI_EVENT_SIZE];
84+size_t midi_event_count = 0;
7885 #endif /* HAVE_JACK */
7986
8087 void examples_common_init (int argc, char **argv);
@@ -119,15 +126,15 @@ void examples_common_init (int argc, char **argv) · 38 unmodified lines
119126 source_uri = "jack";
120127 #endif /* HAVE_JACK */
121128 }
122− ibuf = new_fvec (hop_size);
123− obuf = new_fvec (hop_size);
129+ input_buffer = new_fvec (hop_size);
130+ output_buffer = new_fvec (hop_size);
124131
125132 }
126133
127134 void examples_common_del (void)
128135 {
129− del_fvec (ibuf);
130− del_fvec (obuf);
136+ del_fvec (input_buffer);
137+ del_fvec (output_buffer);
131138 aubio_cleanup ();
132139 fflush(stderr);
133140 fflush(stdout);
@@ -141,6 +148,8 @@ void examples_common_process (aubio_process_func_t process_func, · 7 unmodified lines
141148 if (usejack) {
142149
143150 #ifdef HAVE_JACK
151+ ev.size = MAX_MIDI_EVENT_SIZE;
152+ ev.time = 0; // send it now
144153 debug ("Jack activation ...\n");
145154 aubio_jack_activate (jack_setup, process_func);
146155 debug ("Processing (Ctrl+C to quit) ...\n");
@@ -157,14 +166,14 @@ void examples_common_process (aubio_process_func_t process_func, · 10 unmodified lines
157166 blocks = 0;
158167
159168 do {
160− aubio_source_do (this_source, ibuf, &read);
161− process_func (ibuf, obuf);
169+ aubio_source_do (this_source, input_buffer, &read);
170+ process_func (input_buffer, output_buffer);
162171 // print to console if verbose or no output given
163172 if (verbose || sink_uri == NULL) {
164173 print();
165174 }
166175 if (this_sink) {
167− aubio_sink_do (this_sink, obuf, hop_size);
176+ aubio_sink_do (this_sink, output_buffer, hop_size);
168177 }
169178 blocks++;
170179 total_read += read;
@@ -184,11 +193,11 @@ void · 13 unmodified lines
184193 send_noteon (smpl_t pitch, smpl_t velo)
185194 {
186195 #ifdef HAVE_JACK
187− jack_midi_event_t ev;
188− ev.size = 3;
189− ev.buffer = malloc (3 * sizeof (jack_midi_data_t)); // FIXME
190− ev.time = 0;
191196 if (usejack) {
197+ ev.buffer = midi_data + midi_event_count++ * MAX_MIDI_EVENT_SIZE;
198+ if (midi_event_count >= MAX_MIDI_EVENTS) {
199+ midi_event_count = 0;
200+ }
192201 ev.buffer[2] = velo;
193202 ev.buffer[1] = pitch;
194203 if (velo == 0) {
examples/utils.h+1−1
@@ -66,7 +66,7 @@ typedef void (aubio_print_func_t) (void); · 65 unmodified lines
6666 void send_noteon (smpl_t pitch, smpl_t velo);
6767
6868 /** common process function */
69−typedef int (*aubio_process_func_t) (fvec_t * input, fvec_t * output);
69+typedef void (*aubio_process_func_t) (fvec_t * input, fvec_t * output);
7070
7171 void process_block (fvec_t *ibuf, fvec_t *obuf);
7272 void process_print (void);
python/README.md+88−79
@@ -1,100 +1,109 @@
1−Python aubio module
2−===================
1+aubio
2+=====
33
4−This module wraps the aubio library for Python using the numpy module.
4+aubio is a collection of tools for music and audio analysis.
55
6−Using the Python aubio module
7−-----------------------------
6+This package integrates the aubio library with [NumPy] to provide a set of
7+efficient tools to process and analyse audio signals, including:
88
9−After installing python-aubio, you will be able to import the aubio module:
9+- read audio from any media file, including videos and remote streams
10+- high quality phase vocoder, spectral filterbanks, and linear filters
11+- Mel-Frequency Cepstrum Coefficients and standard spectral descriptors
12+- detection of note attacks (onset)
13+- pitch tracking (fundamental frequency estimation)
14+- beat detection and tempo tracking
1015
11− $ python
12− [...]
13− >>> import aubio
14− >>> help(aubio.miditofreq)
16+aubio works with both Python 2 and Python 3.
1517
16−Finding some inspiration
17−------------------------
18+Links
19+-----
1820
19−Some examples are available in the `python/demos` directory. These scripts are
20−small programs written in python and using python-aubio.
21+- [module documentation][doc_python]
22+- [installation instructions][doc_python_install]
23+- [aubio manual][manual]
24+- [aubio homepage][homepage]
25+- [issue tracker][bugtracker]
2126
22−For instance, `demo_source.py` reads a media file.
27+Demos
28+-----
2329
24− $ ./python/demos/demo_source.py /path/to/sound/sample.wav
30+Some examples are available in the [`python/demos`][demos_dir] folder. Each
31+script is a command line program which accepts one ore more argument.
2532
26−and `demo_timestretch_online.py` stretches the original file into a new one:
33+**Notes**: installing additional modules is required to run some of the demos.
2734
28− $ ./python/demo/demo_timestretch_online.py loop.wav stretched_loop.wav 0.92`
35+### Analysis
2936
30−Note: you might need to install additional modules to run some of the demos.
31−Some demos use [matplotlib](http://matplotlib.org/) to draw plots, others use
32−[PySoundCard](https://github.com/bastibe/PySoundCard) to play and record
33−sounds.
37+- `demo_source.py` uses aubio to read audio samples from media files
38+- `demo_onset_plot.py` detects attacks in a sound file and plots the results
39+ using [matplotlib]
40+- `demo_pitch.py` looks for fundamental frequency in a sound file and plots the
41+ results using [matplotlib]
42+- `demo_spectrogram.py`, `demo_specdesc.py`, `demo_mfcc.py` for spectral
43+ analysis.
3444
35−Testing the Python module
36−-------------------------
45+### Real-time
3746
38−To run the all the python tests, use the script:
47+- `demo_pyaudio.py` and `demo_tapthebeat.py` use [pyaudio]
48+- `demo_pysoundcard_play.py`, `demo_pysoundcard.py` use [PySoundCard]
49+- `demo_alsa.py` uses [pyalsaaudio]
3950
40− $ ./python/tests/run_all_tests
51+### Others
4152
42−Each test script can also be called one at a time. For instance:
53+- `demo_timestretch.py` can change the duration of an input file and write the
54+ new sound to disk,
55+- `demo_wav2midi.py` detects the notes in a file and uses [mido] to write the
56+ results into a MIDI file
4357
44− $ ./python/tests/test_note2midi.py -v
58+### Example
4559
46−Install in a virtualenv
47−-----------------------
60+Use `demo_timestretch_online.py` to slow down `loop.wav`, write the results in
61+`stretched_loop.wav`:
4862
49−You should be able to install python-aubio directly from the top source
50−directory of aubio.
63+ $ python demo_timestretch_online.py loop.wav stretched_loop.wav 0.92
5164
52−First, create a virtualenv to hold the required python module:
53−
54− $ virtualenv pyaubio
55− $ source pyaubio/bin/activate
56−
57−Now install and build the python extension using:
58−
59− $ pip install .
60−
61−Install requirements
62−--------------------
63−
64−Before compiling this module, you must have compiled libaubio.
65−
66−A simple way to do this is with pip:
67−
68− $ pip install -r requirements.txt
69−
70−For more information about how this module works, please refer to the [Python/C
71−API Reference Manual] (http://docs.python.org/c-api/index.html) and the
72−[Numpy/C API Reference](http://docs.scipy.org/doc/numpy/reference/c-api.html).
73−
74−Compiling python aubio
75−----------------------
76−
77−To build the aubio Python module, run the following command from the top source
78−directory of aubio:
79−
80− $ ./setup.py build
81−
82−Note: if libaubio was previously built using waf, the script will use it.
83−Otherwise, the entire library will be built inside the python extension.
84−
85−To find out more about `setup.py` options:
86−
87− $ ./setup.py --help
88−
89−Installing
65+Built with
9066 ----------
9167
92−To install the Python module:
93−
94− $ ./setup.py install
95−
96−Alternatively, you may want to use the Python module without installing it by
97−setting your PYTHONPATH, for instance as follows:
98−
99− $ export PYTHONPATH=$PYTHONPATH:$PWD/`ls -rtd build/lib.* | head -1`:$PWD/tests
100−
68+The core of aubio is written in C for portability and speed. In addition to
69+[NumPy], aubio can be optionally built to use one or more of the following
70+libraries:
71+
72+- media file reading:
73+
74+ - [ffmpeg] / [avcodec] to decode and read audio from almost any format,
75+ - [libsndfile] to read audio from uncompressed sound files,
76+ - [libsamplerate] to re-sample audio signals,
77+ - [CoreAudio] to read all media formats supported by macOS, iOS, and tvOS.
78+
79+- hardware acceleration:
80+
81+ - [Atlas] and [Blas], for accelerated vector and matrix computations,
82+ - [fftw3], to compute fast Fourier Transforms of any size,
83+ - [Accelerate] for accelerated FFT and matrix computations (macOS/iOS),
84+ - [Intel IPP], accelerated vector computation and FFT implementation.
85+
86+[ffmpeg]: https://ffmpeg.org
87+[avcodec]: https://libav.org
88+[libsndfile]: http://www.mega-nerd.com/libsndfile/
89+[libsamplerate]: http://www.mega-nerd.com/SRC/
90+[CoreAudio]: https://developer.apple.com/reference/coreaudio
91+[Atlas]: http://math-atlas.sourceforge.net/
92+[Blas]: https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms
93+[fftw3]: http://fftw.org
94+[Accelerate]: https://developer.apple.com/reference/accelerate
95+[Intel IPP]: https://software.intel.com/en-us/intel-ipp
96+
97+[demos_dir]:https://github.com/aubio/aubio/tree/master/python/demos
98+[pyaudio]:https://people.csail.mit.edu/hubert/pyaudio/
99+[PySoundCard]:https://github.com/bastibe/PySoundCard
100+[pyalsaaudio]:https://larsimmisch.github.io/pyalsaaudio/
101+[mido]:https://mido.readthedocs.io
102+
103+[manual]: https://aubio.org/manual/latest/
104+[doc_python]: https://aubio.org/manual/latest/python.html
105+[doc_python_install]: https://aubio.org/manual/latest/python_module.html
106+[homepage]: https://aubio.org
107+[NumPy]: https://www.numpy.org
108+[bugtracker]: https://github.com/aubio/aubio/issues
109+[matplotlib]:https://matplotlib.org/
python/__init__.py+0−0

Empty file deleted.

python/demos/demo_alsa.py+45−0
@@ -0,0 +1,45 @@
1+#! /usr/bin/env python
2+
3+import alsaaudio
4+import numpy as np
5+import aubio
6+
7+# constants
8+samplerate = 44100
9+win_s = 2048
10+hop_s = win_s // 2
11+framesize = hop_s
12+
13+# set up audio input
14+recorder = alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE)
15+recorder.setperiodsize(framesize)
16+recorder.setrate(samplerate)
17+recorder.setformat(alsaaudio.PCM_FORMAT_FLOAT_LE)
18+recorder.setchannels(1)
19+
20+# create aubio pitch detection (first argument is method, "default" is
21+# "yinfft", can also be "yin", "mcomb", fcomb", "schmitt").
22+pitcher = aubio.pitch("default", win_s, hop_s, samplerate)
23+# set output unit (can be 'midi', 'cent', 'Hz', ...)
24+pitcher.set_unit("Hz")
25+# ignore frames under this level (dB)
26+pitcher.set_silence(-40)
27+
28+print("Starting to listen, press Ctrl+C to stop")
29+
30+# main loop
31+while True:
32+ try:
33+ # read data from audio input
34+ _, data = recorder.read()
35+ # convert data to aubio float samples
36+ samples = np.fromstring(data, dtype=aubio.float_type)
37+ # pitch of current frame
38+ freq = pitcher(samples)[0]
39+ # compute energy of current block
40+ energy = np.sum(samples**2)/len(samples)
41+ # do something with the results
42+ print("{:10.4f} {:10.4f}".format(freq,energy))
43+ except KeyboardInterrupt:
44+ print("Ctrl+C pressed, exiting")
45+ break
python/demos/demo_bench_yin.py+50−0
@@ -0,0 +1,50 @@
1+#! /usr/bin/env python
2+
3+import numpy as np
4+from aubio import pitch
5+import pylab as plt
6+
7+buf_size = 2048 * 1
8+hop_size = buf_size // 4
9+
10+samplerate = 44100
11+minfreq = 40
12+maxfreq = 6000
13+
14+def sinewave(freq, duration, samplerate = samplerate):
15+ """ generate a sinewave """
16+ length = hop_size
17+ while length < duration * samplerate:
18+ length += hop_size
19+ return np.sin( 2. * np.pi * np.arange(length) * freq / samplerate ).astype("float32")
20+
21+def get_stats_for_pitch_method(method, freqs, samplerate = samplerate):
22+ """ for a given pitch method and a list of frequency, generate a sinewave
23+ and get mean deviation """
24+ means = np.zeros(len(freqs))
25+ medians = np.zeros(len(freqs))
26+ for freq, fn in zip(freqs, range(len(freqs))):
27+ s = sinewave(freq, .50).reshape(-1, hop_size)
28+ #s = (sinewave(freq, .50) + .0*sinewave(freq/2., .50)).reshape(-1, hop_size)
29+ p = pitch(method, buf_size, hop_size, samplerate = samplerate)
30+ candidates = np.zeros(len(s))
31+ #samples = np.zeros(buf_size)
32+ for frame, i in zip(s, range(len(s))):
33+ candidates[i] = p(frame)[0]
34+ # skip first few candidates
35+ candidates = candidates[4:]
36+ means[fn] = np.mean(candidates[candidates != 0] - freq)
37+ medians[fn] = np.median(candidates[candidates != 0] - freq)
38+ print (freq, means[fn], medians[fn])
39+ return means, medians
40+
41+if __name__ == '__main__':
42+ freqs = np.arange(minfreq, maxfreq, 1.)
43+ modes = ["yin", "yinfft"]
44+ for mode in modes:
45+ means, medians = get_stats_for_pitch_method(mode, freqs)
46+ plt.figure()
47+ plt.plot(freqs, means, 'g-')
48+ plt.plot(freqs, medians, 'r--')
49+ #plt.savefig(mode + '_deviations_test.png', dpi=300)
50+ plt.show()
python/demos/demo_bpm_extract.py+44−27
@@ -3,26 +3,33 @@ · 2 unmodified lines
33 from aubio import source, tempo
44 from numpy import median, diff
55
6−def get_file_bpm(path, params = None):
6+def get_file_bpm(path, params=None):
77 """ Calculate the beats per minute (bpm) of a given file.
88 path: path to the file
99 param: dictionary of parameters
1010 """
1111 if params is None:
1212 params = {}
13− try:
14− win_s = params['win_s']
15− samplerate = params['samplerate']
16− hop_s = params['hop_s']
17− except KeyError:
18− """
19− # super fast
20− samplerate, win_s, hop_s = 4000, 128, 64
21− # fast
22− samplerate, win_s, hop_s = 8000, 512, 128
23− """
24− # default:
25− samplerate, win_s, hop_s = 44100, 1024, 512
13+ # default:
14+ samplerate, win_s, hop_s = 44100, 1024, 512
15+ if 'mode' in params:
16+ if params.mode in ['super-fast']:
17+ # super fast
18+ samplerate, win_s, hop_s = 4000, 128, 64
19+ elif params.mode in ['fast']:
20+ # fast
21+ samplerate, win_s, hop_s = 8000, 512, 128
22+ elif params.mode in ['default']:
23+ pass
24+ else:
25+ raise ValueError("unknown mode {:s}".format(params.mode))
26+ # manual settings
27+ if 'samplerate' in params:
28+ samplerate = params.samplerate
29+ if 'win_s' in params:
30+ win_s = params.win_s
31+ if 'hop_s' in params:
32+ hop_s = params.hop_s
2633
2734 s = source(path, samplerate, hop_s)
2835 samplerate = s.samplerate
@@ -44,19 +51,29 @@ def get_file_bpm(path, params = None): · 15 unmodified lines
4451 if read < hop_s:
4552 break
4653
47− # Convert to periods and to bpm
48− if len(beats) > 1:
49− if len(beats) < 4:
50− print("few beats found in {:s}".format(path))
51− bpms = 60./diff(beats)
52− b = median(bpms)
53− else:
54− b = 0
55− print("not enough beats found in {:s}".format(path))
56− return b
54+ def beats_to_bpm(beats, path):
55+ # if enough beats are found, convert to periods then to bpm
56+ if len(beats) > 1:
57+ if len(beats) < 4:
58+ print("few beats found in {:s}".format(path))
59+ bpms = 60./diff(beats)
60+ return median(bpms)
61+ else:
62+ print("not enough beats found in {:s}".format(path))
63+ return 0
64+
65+ return beats_to_bpm(beats, path)
5766
5867 if __name__ == '__main__':
59− import sys
60− for f in sys.argv[1:]:
61− bpm = get_file_bpm(f)
68+ import argparse
69+ parser = argparse.ArgumentParser()
70+ parser.add_argument('-m', '--mode',
71+ help="mode [default|fast|super-fast]",
72+ dest="mode", default='default')
73+ parser.add_argument('sources',
74+ nargs='+',
75+ help="input_files")
76+ args = parser.parse_args()
77+ for f in args.sources:
78+ bpm = get_file_bpm(f, params = args)
6279 print("{:6s} {:s}".format("{:2f}".format(bpm), f))
python/demos/demo_filter.py+31−14
@@ -1,36 +1,53 @@
11 #! /usr/bin/env python
22
3+import sys
4+import os.path
5+import aubio
36
4−def apply_filter(path):
5− from aubio import source, sink, digital_filter
6− from os.path import basename, splitext
77
8+def apply_filter(path, target):
89 # open input file, get its samplerate
9− s = source(path)
10+ s = aubio.source(path)
1011 samplerate = s.samplerate
1112
1213 # create an A-weighting filter
13− f = digital_filter(7)
14+ f = aubio.digital_filter(7)
1415 f.set_a_weighting(samplerate)
15− # alternatively, apply another filter
1616
1717 # create output file
18− o = sink("filtered_" + splitext(basename(path))[0] + ".wav", samplerate)
18+ o = aubio.sink(target, samplerate)
1919
2020 total_frames = 0
2121 while True:
22+ # read from source
2223 samples, read = s()
24+ # filter samples
2325 filtered_samples = f(samples)
26+ # write to sink
2427 o(filtered_samples, read)
28+ # count frames read
2529 total_frames += read
26− if read < s.hop_size: break
30+ # end of file reached
31+ if read < s.hop_size:
32+ break
2733
34+ # print some info
2835 duration = total_frames / float(samplerate)
29− print ("read {:s}".format(s.uri))
30− print ("applied A-weighting filtered ({:d} Hz)".format(samplerate))
31− print ("wrote {:s} ({:.2f} s)".format(o.uri, duration))
36+ input_str = "input: {:s} ({:.2f} s, {:d} Hz)"
37+ output_str = "output: {:s}, A-weighting filtered ({:d} frames total)"
38+ print(input_str.format(s.uri, duration, samplerate))
39+ print(output_str.format(o.uri, total_frames))
3240
3341 if __name__ == '__main__':
34− import sys
35− for f in sys.argv[1:]:
36− apply_filter(f)
42+ usage = "{:s} <input_file> [output_file]".format(sys.argv[0])
43+ if not 1 < len(sys.argv) < 4:
44+ print(usage)
45+ sys.exit(1)
46+ if len(sys.argv) < 3:
47+ input_path = sys.argv[1]
48+ basename = os.path.splitext(os.path.basename(input_path))[0] + ".wav"
49+ output_path = "filtered_" + basename
50+ else:
51+ input_path, output_path = sys.argv[1:]
52+ # run function
53+ apply_filter(input_path, output_path)
python/demos/demo_filterbank.py+31−17
@@ -1,30 +1,44 @@
11 #! /usr/bin/env python
22
3−from aubio import filterbank, fvec
4−from pylab import loglog, show, xlim, ylim, xlabel, ylabel, title
5−from numpy import vstack, arange
3+"""Create a filterbank from a list of frequencies.
64
7−win_s = 2048
5+This demo uses `aubio.filterbank.set_triangle_bands` to build a set of
6+triangular filters from a list of frequencies.
7+
8+The filterbank coefficients are then modified before being displayed."""
9+
10+import aubio
11+import numpy as np
12+import matplotlib.pyplot as plt
13+
14+# sampling rate and size of the fft
815 samplerate = 48000
16+win_s = 2048
917
18+# define a list of custom frequency
1019 freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000]
20+# number of filters to create
1121 n_filters = len(freq_list) - 2
1222
13−f = filterbank(n_filters, win_s)
14−freqs = fvec(freq_list)
23+# create a new filterbank
24+f = aubio.filterbank(n_filters, win_s)
25+freqs = aubio.fvec(freq_list)
1526 f.set_triangle_bands(freqs, samplerate)
1627
28+# get the coefficients from the filterbank
1729 coeffs = f.get_coeffs()
18−coeffs[4] *= 5.
19−
30+# apply a gain to fifth band
31+coeffs[4] *= 6.
32+# load the modified coeffs into the filterbank
2033 f.set_coeffs(coeffs)
2134
22−times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
23−title('Bank of filters built using a simple list of boundaries\nThe middle band has been amplified by 2.')
24−loglog(times.T, f.get_coeffs().T, '.-')
25−xlim([50, samplerate/2])
26−ylim([1.0e-6, 2.0e-2])
27−xlabel('log frequency (Hz)')
28−ylabel('log amplitude')
29−
30−show()
35+# display the band gains in a loglog plot
36+freqs = np.vstack([np.arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
37+plt.title('filterbank built from a list of frequencies\n'
38+ 'The 5th band has been amplified by a factor 6.')
39+plt.loglog(freqs.T, f.get_coeffs().T, '.-')
40+plt.xlim([50, samplerate/2])
41+plt.ylim([1.0e-6, 2.0e-2])
42+plt.xlabel('log frequency (Hz)')
43+plt.ylabel('log amplitude')
44+plt.show()
python/demos/demo_notes.py+37−0
@@ -0,0 +1,37 @@
1+#! /usr/bin/env python
2+
3+import sys
4+from aubio import source, notes
5+
6+if len(sys.argv) < 2:
7+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
8+ sys.exit(1)
9+
10+filename = sys.argv[1]
11+
12+downsample = 1
13+samplerate = 44100 // downsample
14+if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
15+
16+win_s = 512 // downsample # fft size
17+hop_s = 256 // downsample # hop size
18+
19+s = source(filename, samplerate, hop_s)
20+samplerate = s.samplerate
21+
22+tolerance = 0.8
23+
24+notes_o = notes("default", win_s, hop_s, samplerate)
25+
26+print("%8s" % "time","[ start","vel","last ]")
27+
28+# total number of frames read
29+total_frames = 0
30+while True:
31+ samples, read = s()
32+ new_note = notes_o(samples)
33+ if (new_note[0] != 0):
34+ note_str = ' '.join(["%.2f" % i for i in new_note])
35+ print("%.6f" % (total_frames/float(samplerate)), new_note)
36+ total_frames += read
37+ if read < hop_s: break
python/demos/demo_pitch_sinusoid.py+1−1
@@ -37,7 +37,7 @@ freqs[ pointer : pointer + partition ] = 1480 · 36 unmodified lines
3737
3838 pointer += partition
3939 pointer += partition
40−freqs[ pointer : pointer + partition ] = 400 + 5 * np.random.random(sin_length/8)
40+freqs[ pointer : pointer + partition ] = 400 + 5 * np.random.random(sin_length//8)
4141
4242 a = build_sinusoid(sin_length, freqs, samplerate)
4343
python/demos/demo_pyaudio.py+75−0
@@ -0,0 +1,75 @@
1+#! /usr/bin/env python
2+
3+# Use pyaudio to open the microphone and run aubio.pitch on the stream of
4+# incoming samples. If a filename is given as the first argument, it will
5+# record 5 seconds of audio to this location. Otherwise, the script will
6+# run until Ctrl+C is pressed.
7+
8+# Examples:
9+# $ ./python/demos/demo_pyaudio.py
10+# $ ./python/demos/demo_pyaudio.py /tmp/recording.wav
11+
12+import pyaudio
13+import sys
14+import numpy as np
15+import aubio
16+
17+# initialise pyaudio
18+p = pyaudio.PyAudio()
19+
20+# open stream
21+buffer_size = 1024
22+pyaudio_format = pyaudio.paFloat32
23+n_channels = 1
24+samplerate = 44100
25+stream = p.open(format=pyaudio_format,
26+ channels=n_channels,
27+ rate=samplerate,
28+ input=True,
29+ frames_per_buffer=buffer_size)
30+
31+if len(sys.argv) > 1:
32+ # record 5 seconds
33+ output_filename = sys.argv[1]
34+ record_duration = 5 # exit 1
35+ outputsink = aubio.sink(sys.argv[1], samplerate)
36+ total_frames = 0
37+else:
38+ # run forever
39+ outputsink = None
40+ record_duration = None
41+
42+# setup pitch
43+tolerance = 0.8
44+win_s = 4096 # fft size
45+hop_s = buffer_size # hop size
46+pitch_o = aubio.pitch("default", win_s, hop_s, samplerate)
47+pitch_o.set_unit("midi")
48+pitch_o.set_tolerance(tolerance)
49+
50+print("*** starting recording")
51+while True:
52+ try:
53+ audiobuffer = stream.read(buffer_size)
54+ signal = np.fromstring(audiobuffer, dtype=np.float32)
55+
56+ pitch = pitch_o(signal)[0]
57+ confidence = pitch_o.get_confidence()
58+
59+ print("{} / {}".format(pitch,confidence))
60+
61+ if outputsink:
62+ outputsink(signal, len(signal))
63+
64+ if record_duration:
65+ total_frames += len(signal)
66+ if record_duration * samplerate < total_frames:
67+ break
68+ except KeyboardInterrupt:
69+ print("*** Ctrl+C pressed, exiting")
70+ break
71+
72+print("*** done recording")
73+stream.stop_stream()
74+stream.close()
75+p.terminate()
python/demos/demo_source_simple.py+13−9
@@ -1,16 +1,20 @@
11 #! /usr/bin/env python
2−import sys, aubio
2+
3+"""A simple example using aubio.source."""
4+
5+import sys
6+import aubio
37
48 samplerate = 0 # use original source samplerate
5−hop_size = 256 # number of frames to read in one block
6−s = aubio.source(sys.argv[1], samplerate, hop_size)
9+hop_size = 256 # number of frames to read in one block
10+src = aubio.source(sys.argv[1], samplerate, hop_size)
711 total_frames = 0
812
9−while True: # reading loop
10− samples, read = s()
11− total_frames += read
12− if read < hop_size: break # end of file reached
13+while True:
14+ samples, read = src() # read hop_size new samples from source
15+ total_frames += read # increment total number of frames
16+ if read < hop_size: # end of file reached
17+ break
1318
1419 fmt_string = "read {:d} frames at {:d}Hz from {:s}"
15−print (fmt_string.format(total_frames, s.samplerate, sys.argv[1]))
16−
20+print(fmt_string.format(total_frames, src.samplerate, src.uri))
python/demos/demo_tapthebeat.py+78−0
@@ -0,0 +1,78 @@
1+#! /usr/bin/env python
2+
3+""" A simple demo using aubio and pyaudio to play beats in real time
4+
5+Note you will need to have pyaudio installed: `pip install pyaudio`.
6+
7+Examples:
8+ ./demo_tapthebeat.py ~/Music/track1.ogg
9+
10+When compiled with ffmpeg/libav, you should be able to open remote streams. For
11+instance using youtube-dl (`pip install youtube-dl`):
12+
13+ ./demo_tapthebeat.py `youtube-dl -xg https://youtu.be/zZbM9n9j3_g`
14+
15+"""
16+
17+import sys
18+import time
19+import pyaudio
20+import aubio
21+import numpy as np
22+
23+win_s = 1024 # fft size
24+hop_s = win_s // 2 # hop size
25+
26+# parse command line arguments
27+if len(sys.argv) < 2:
28+ print("Usage: %s <filename> [samplerate]" % sys.argv[0])
29+ sys.exit(1)
30+
31+filename = sys.argv[1]
32+
33+samplerate = 0
34+if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
35+
36+# create aubio source
37+a_source = aubio.source(filename, samplerate, hop_s)
38+samplerate = a_source.samplerate
39+
40+# create aubio tempo detection
41+a_tempo = aubio.tempo("default", win_s, hop_s, samplerate)
42+
43+# create a simple click sound
44+click = 0.7 * np.sin(2. * np.pi * np.arange(hop_s) / hop_s * samplerate / 3000.)
45+
46+# pyaudio callback
47+def pyaudio_callback(_in_data, _frame_count, _time_info, _status):
48+ samples, read = a_source()
49+ is_beat = a_tempo(samples)
50+ if is_beat:
51+ samples += click
52+ #print ('tick') # avoid print in audio callback
53+ audiobuf = samples.tobytes()
54+ if read < hop_s:
55+ return (audiobuf, pyaudio.paComplete)
56+ return (audiobuf, pyaudio.paContinue)
57+
58+# create pyaudio stream with frames_per_buffer=hop_s and format=paFloat32
59+p = pyaudio.PyAudio()
60+pyaudio_format = pyaudio.paFloat32
61+frames_per_buffer = hop_s
62+n_channels = 1
63+stream = p.open(format=pyaudio_format, channels=n_channels, rate=samplerate,
64+ output=True, frames_per_buffer=frames_per_buffer,
65+ stream_callback=pyaudio_callback)
66+
67+# start pyaudio stream
68+stream.start_stream()
69+
70+# wait for stream to finish
71+while stream.is_active():
72+ time.sleep(0.1)
73+
74+# stop pyaudio stream
75+stream.stop_stream()
76+stream.close()
77+# close pyaudio
78+p.terminate()
python/demos/demo_timestretch.py+1−1
@@ -12,7 +12,7 @@ from aubio import unwrap2pi, float_type · 11 unmodified lines
1212 import numpy as np
1313
1414 win_s = 1024
15−hop_s = win_s / 8 # 87.5 % overlap
15+hop_s = win_s // 8 # 87.5 % overlap
1616
1717 warmup = win_s // hop_s - 1
1818
python/demos/demo_timestretch_online.py+5−3
@@ -11,8 +11,8 @@ from aubio import source, sink, pvoc, cvec · 10 unmodified lines
1111 from aubio import unwrap2pi, float_type
1212 import numpy as np
1313
14−win_s = 1024
15−hop_s = win_s / 8 # 87.5 % overlap
14+win_s = 512
15+hop_s = win_s // 8 # 87.5 % overlap
1616
1717 warmup = win_s // hop_s - 1
1818
@@ -92,8 +92,10 @@ while True: · 73 unmodified lines
9292 old_grain.norm = np.copy(cur_grain.norm)
9393 old_grain.phas = np.copy(cur_grain.phas)
9494
95− block_read += 1
95+ # until end of file
9696 if read < hop_s: break
97+ # increment block counter
98+ block_read += 1
9799
98100 for t in range(warmup + 2): # purge the last frames from the phase vocoder
99101 new_grain.norm[:] = 0
python/demos/demo_wav2midi.py+77−0
@@ -0,0 +1,77 @@
1+#! /usr/bin/env python
2+
3+# Simple demo to extract notes from a sound file, and store them in a midi file
4+# using mido.
5+#
6+# Install mido: `pip instal mido`
7+#
8+# Documentation: https://mido.readthedocs.io/
9+
10+import sys
11+from aubio import source, notes
12+from mido import Message, MetaMessage, MidiFile, MidiTrack, second2tick, bpm2tempo
13+
14+if len(sys.argv) < 3:
15+ print("Usage: %s <filename> <output> [samplerate]" % sys.argv[0])
16+ sys.exit(1)
17+
18+filename = sys.argv[1]
19+midioutput = sys.argv[2]
20+
21+downsample = 1
22+samplerate = 44100 // downsample
23+if len( sys.argv ) > 3: samplerate = int(sys.argv[3])
24+
25+win_s = 512 // downsample # fft size
26+hop_s = 256 // downsample # hop size
27+
28+s = source(filename, samplerate, hop_s)
29+samplerate = s.samplerate
30+
31+tolerance = 0.8
32+
33+notes_o = notes("default", win_s, hop_s, samplerate)
34+
35+print("%8s" % "time","[ start","vel","last ]")
36+
37+# create a midi file
38+mid = MidiFile()
39+track = MidiTrack()
40+mid.tracks.append(track)
41+
42+ticks_per_beat = mid.ticks_per_beat # default: 480
43+bpm = 120 # default midi tempo
44+
45+tempo = bpm2tempo(bpm)
46+track.append(MetaMessage('set_tempo', tempo=tempo))
47+track.append(MetaMessage('time_signature', numerator=4, denominator=4))
48+
49+def frames2tick(frames, samplerate=samplerate):
50+ sec = frames / float(samplerate)
51+ return int(second2tick(sec, ticks_per_beat, tempo))
52+
53+last_time = 0
54+
55+# total number of frames read
56+total_frames = 0
57+while True:
58+ samples, read = s()
59+ new_note = notes_o(samples)
60+ if (new_note[0] != 0):
61+ note_str = ' '.join(["%.2f" % i for i in new_note])
62+ print("%.6f" % (total_frames/float(samplerate)), new_note)
63+ delta = frames2tick(total_frames) - last_time
64+ if new_note[2] > 0:
65+ track.append(Message('note_off', note=int(new_note[2]),
66+ velocity=127, time=0)
67+ )
68+ track.append(Message('note_on',
69+ note=int(new_note[0]),
70+ velocity=int(new_note[1]),
71+ time=delta)
72+ )
73+ last_time = frames2tick(total_frames)
74+ total_frames += read
75+ if read < hop_s: break
76+
77+mid.save(midioutput)
python/demos/demo_yin_compare.py+175−0
@@ -0,0 +1,175 @@
1+#! /usr/bin/env python
2+# -*- coding: utf8 -*-
3+
4+""" Pure python implementation of the sum of squared difference
5+
6+ sqd_yin: original sum of squared difference [0]
7+ d_t(tau) = x ⊗ kernel
8+ sqd_yinfast: sum of squared diff using complex domain [0]
9+ sqd_yinfftslow: tappered squared diff [1]
10+ sqd_yinfft: modified squared diff using complex domain [1]
11+
12+[0]:http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf
13+[1]:https://aubio.org/phd/
14+"""
15+
16+import sys
17+import numpy as np
18+import matplotlib.pyplot as plt
19+
20+def sqd_yin(samples):
21+ """ compute original sum of squared difference
22+
23+ Brute-force computation (cost o(N**2), slow)."""
24+ B = len(samples)
25+ W = B//2
26+ yin = np.zeros(W)
27+ for j in range(W):
28+ for tau in range(1, W):
29+ yin[tau] += (samples[j] - samples[j+tau])**2
30+ return yin
31+
32+def sqd_yinfast(samples):
33+ """ compute approximate sum of squared difference
34+
35+ Using complex convolution (fast, cost o(n*log(n)) )"""
36+ # yin_t(tau) = (r_t(0) + r_(t+tau)(0)) - 2r_t(tau)
37+ B = len(samples)
38+ W = B//2
39+ yin = np.zeros(W)
40+ sqdiff = np.zeros(W)
41+ kernel = np.zeros(B)
42+ # compute r_(t+tau)(0)
43+ squares = samples**2
44+ for tau in range(W):
45+ sqdiff[tau] = squares[tau:tau+W].sum()
46+ # add r_t(0)
47+ sqdiff += sqdiff[0]
48+ # compute r_t(tau) using kernel convolution in complex domain
49+ samples_fft = np.fft.fft(samples)
50+ kernel[1:W+1] = samples[W-1::-1] # first half, reversed
51+ kernel_fft = np.fft.fft(kernel)
52+ r_t_tau = np.fft.ifft(samples_fft * kernel_fft).real[W:]
53+ # compute yin_t(tau)
54+ yin = sqdiff - 2 * r_t_tau
55+ return yin
56+
57+def sqd_yintapered(samples):
58+ """ compute tappered sum of squared difference
59+
60+ Brute-force computation (cost o(N**2), slow)."""
61+ B = len(samples)
62+ W = B//2
63+ yin = np.zeros(W)
64+ for tau in range(1, W):
65+ for j in range(W - tau):
66+ yin[tau] += (samples[j] - samples[j+tau])**2
67+ return yin
68+
69+def sqd_yinfft(samples):
70+ """ compute yinfft modified sum of squared differences
71+
72+ Very fast, improved performance in transients.
73+
74+ FIXME: biased."""
75+ B = len(samples)
76+ W = B//2
77+ yin = np.zeros(W)
78+ def hanningz(W):
79+ return .5 * (1. - np.cos(2. * np.pi * np.arange(W) / W))
80+ #win = np.ones(B)
81+ win = hanningz(B)
82+ sqrmag = np.zeros(B)
83+ fftout = np.fft.fft(win*samples)
84+ sqrmag[0] = fftout[0].real**2
85+ for l in range(1, W):
86+ sqrmag[l] = fftout[l].real**2 + fftout[l].imag**2
87+ sqrmag[B-l] = sqrmag[l]
88+ sqrmag[W] = fftout[W].real**2
89+ fftout = np.fft.fft(sqrmag)
90+ sqrsum = 2.*sqrmag[:W + 1].sum()
91+ yin[0] = 0
92+ yin[1:] = sqrsum - fftout.real[1:W]
93+ return yin / B
94+
95+def cumdiff(yin):
96+ """ compute the cumulative mean normalized difference """
97+ W = len(yin)
98+ yin[0] = 1.
99+ cumsum = 0.
100+ for tau in range(1, W):
101+ cumsum += yin[tau]
102+ if cumsum != 0:
103+ yin[tau] *= tau/cumsum
104+ else:
105+ yin[tau] = 1
106+ return yin
107+
108+def compute_all(x):
109+ import time
110+ now = time.time()
111+
112+ yin = sqd_yin(x)
113+ t1 = time.time()
114+ print ("yin took %.2fms" % ((t1-now) * 1000.))
115+
116+ yinfast = sqd_yinfast(x)
117+ t2 = time.time()
118+ print ("yinfast took: %.2fms" % ((t2-t1) * 1000.))
119+
120+ yintapered = sqd_yintapered(x)
121+ t3 = time.time()
122+ print ("yintapered took: %.2fms" % ((t3-t2) * 1000.))
123+
124+ yinfft = sqd_yinfft(x)
125+ t4 = time.time()
126+ print ("yinfft took: %.2fms" % ((t4-t3) * 1000.))
127+
128+ return yin, yinfast, yintapered, yinfft
129+
130+def plot_all(yin, yinfast, yintapered, yinfft):
131+ fig, axes = plt.subplots(nrows=2, ncols=2, sharex=True, sharey='col')
132+
133+ axes[0, 0].plot(yin, label='yin')
134+ axes[0, 0].plot(yintapered, label='yintapered')
135+ axes[0, 0].set_ylim(bottom=0)
136+ axes[0, 0].legend()
137+ axes[1, 0].plot(yinfast, '-', label='yinfast')
138+ axes[1, 0].plot(yinfft, label='yinfft')
139+ axes[1, 0].legend()
140+
141+ axes[0, 1].plot(cumdiff(yin), label='yin')
142+ axes[0, 1].plot(cumdiff(yintapered), label='yin tapered')
143+ axes[0, 1].set_ylim(bottom=0)
144+ axes[0, 1].legend()
145+ axes[1, 1].plot(cumdiff(yinfast), '-', label='yinfast')
146+ axes[1, 1].plot(cumdiff(yinfft), label='yinfft')
147+ axes[1, 1].legend()
148+
149+ fig.tight_layout()
150+
151+testfreqs = [441., 800., 10000., 40.]
152+
153+if len(sys.argv) > 1:
154+ testfreqs = map(float,sys.argv[1:])
155+
156+for f in testfreqs:
157+ print ("Comparing yin implementations for sine wave at %.fHz" % f)
158+ samplerate = 44100.
159+ win_s = 4096
160+
161+ x = np.cos(2.*np.pi * np.arange(win_s) * f / samplerate)
162+
163+ n_times = 1#00
164+ for n in range(n_times):
165+ yin, yinfast, yinfftslow, yinfft = compute_all(x)
166+ if 0: # plot difference
167+ plt.plot(yin-yinfast)
168+ plt.tight_layout()
169+ plt.show()
170+ if 1:
171+ plt.plot(yinfftslow-yinfft)
172+ plt.tight_layout()
173+ plt.show()
174+ plot_all(yin, yinfast, yinfftslow, yinfft)
175+plt.show()
python/ext/aubio-types.h+9−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
2727 #ifdef USE_LOCAL_AUBIO
2828 #include "aubio.h"
2929 #else
30−#include "aubio/aubio.h"
30+#include <aubio/aubio.h>
3131 #endif
3232
3333 #define Py_default_vector_length 1024
@@ -46,6 +46,14 @@ · 12 unmodified lines
4646 #define AUBIO_NPY_SMPL_CHR "f"
4747 #endif
4848
49+#ifndef PATH_MAX
50+#ifdef MAX_PATH
51+#define PATH_MAX MAX_PATH
52+#else
53+#define PATH_MAX 1024
54+#endif
55+#endif
56+
4957 // compat with Python < 2.6
5058 #ifndef Py_TYPE
5159 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
python/ext/aubiomodule.c+167−27
@@ -2,77 +2,202 @@ · 1 unmodified line
22 #include "aubio-types.h"
33 #include "py-musicutils.h"
44
5+// this dummy macro is used to convince windows that a string passed as -D flag
6+// is just that, a string, and not a double.
7+#define REDEFINESTRING(x) #x
8+#define DEFINEDSTRING(x) REDEFINESTRING(x)
9+
510 static char aubio_module_doc[] = "Python module for the aubio library";
611
712 static char Py_alpha_norm_doc[] = ""
8−"alpha_norm(fvec, integer) -> float\n"
13+"alpha_norm(vec, alpha)\n"
14+"\n"
15+"Compute `alpha` normalisation factor of vector `vec`.\n"
916 "\n"
10−"Compute alpha normalisation factor on vector, given alpha\n"
17+"Parameters\n"
18+"----------\n"
19+"vec : fvec\n"
20+" input vector\n"
21+"alpha : float\n"
22+" norm factor\n"
23+"\n"
24+"Returns\n"
25+"-------\n"
26+"float\n"
27+" p-norm of the input vector, where `p=alpha`\n"
1128 "\n"
1229 "Example\n"
1330 "-------\n"
1431 "\n"
15−">>> b = alpha_norm(a, 9)";
32+">>> a = aubio.fvec(np.arange(10)); alpha = 2\n"
33+">>> aubio.alpha_norm(a, alpha), (sum(a**alpha)/len(a))**(1./alpha)\n"
34+"(5.338539123535156, 5.338539126015656)\n"
35+"\n"
36+"Note\n"
37+"----\n"
38+"Computed as:\n"
39+"\n"
40+".. math::\n"
41+" l_{\\alpha} = \n"
42+" \\|\\frac{\\sum_{n=0}^{N-1}{{x_n}^{\\alpha}}}{N}\\|^{1/\\alpha}\n"
43+"";
1644
1745 static char Py_bintomidi_doc[] = ""
18−"bintomidi(float, samplerate = integer, fftsize = integer) -> float\n"
46+"bintomidi(fftbin, samplerate, fftsize)\n"
47+"\n"
48+"Convert FFT bin to frequency in midi note, given the sampling rate\n"
49+"and the size of the FFT.\n"
1950 "\n"
20−"Convert bin (float) to midi (float), given the sampling rate and the FFT size\n"
51+"Parameters\n"
52+"----------\n"
53+"fftbin : float\n"
54+" input frequency bin\n"
55+"samplerate : float\n"
56+" sampling rate of the signal\n"
57+"fftsize : float\n"
58+" size of the FFT\n"
59+"\n"
60+"Returns\n"
61+"-------\n"
62+"float\n"
63+" Frequency converted to midi note.\n"
2164 "\n"
2265 "Example\n"
2366 "-------\n"
2467 "\n"
25−">>> midi = bintomidi(float, samplerate = 44100, fftsize = 1024)";
68+">>> aubio.bintomidi(10, 44100, 1024)\n"
69+"68.62871551513672\n"
70+"";
2671
2772 static char Py_miditobin_doc[] = ""
28−"miditobin(float, samplerate = integer, fftsize = integer) -> float\n"
73+"miditobin(midi, samplerate, fftsize)\n"
2974 "\n"
30−"Convert midi (float) to bin (float), given the sampling rate and the FFT size\n"
75+"Convert frequency in midi note to FFT bin, given the sampling rate\n"
76+"and the size of the FFT.\n"
3177 "\n"
32−"Example\n"
78+"Parameters\n"
79+"----------\n"
80+"midi : float\n"
81+" input frequency, in midi note\n"
82+"samplerate : float\n"
83+" sampling rate of the signal\n"
84+"fftsize : float\n"
85+" size of the FFT\n"
86+"\n"
87+"Returns\n"
3388 "-------\n"
89+"float\n"
90+" Frequency converted to FFT bin.\n"
91+"\n"
92+"Examples\n"
93+"--------\n"
3494 "\n"
35−">>> bin = miditobin(midi, samplerate = 44100, fftsize = 1024)";
95+">>> aubio.miditobin(69, 44100, 1024)\n"
96+"10.216779708862305\n"
97+">>> aubio.miditobin(75.08, 32000, 512)\n"
98+"10.002175331115723\n"
99+"";
36100
37101 static char Py_bintofreq_doc[] = ""
38−"bintofreq(float, samplerate = integer, fftsize = integer) -> float\n"
102+"bintofreq(fftbin, samplerate, fftsize)\n"
103+"\n"
104+"Convert FFT bin to frequency in Hz, given the sampling rate\n"
105+"and the size of the FFT.\n"
39106 "\n"
40−"Convert bin number (float) in frequency (Hz), given the sampling rate and the FFT size\n"
107+"Parameters\n"
108+"----------\n"
109+"fftbin : float\n"
110+" input frequency bin\n"
111+"samplerate : float\n"
112+" sampling rate of the signal\n"
113+"fftsize : float\n"
114+" size of the FFT\n"
115+"\n"
116+"Returns\n"
117+"-------\n"
118+"float\n"
119+" Frequency converted to Hz.\n"
41120 "\n"
42121 "Example\n"
43122 "-------\n"
44123 "\n"
45−">>> freq = bintofreq(bin, samplerate = 44100, fftsize = 1024)";
124+">>> aubio.bintofreq(10, 44100, 1024)\n"
125+"430.6640625\n"
126+"";
46127
47128 static char Py_freqtobin_doc[] = ""
48−"freqtobin(float, samplerate = integer, fftsize = integer) -> float\n"
129+"freqtobin(freq, samplerate, fftsize)\n"
49130 "\n"
50−"Convert frequency (Hz) in bin number (float), given the sampling rate and the FFT size\n"
131+"Convert frequency in Hz to FFT bin, given the sampling rate\n"
132+"and the size of the FFT.\n"
51133 "\n"
52−"Example\n"
134+"Parameters\n"
135+"----------\n"
136+"midi : float\n"
137+" input frequency, in midi note\n"
138+"samplerate : float\n"
139+" sampling rate of the signal\n"
140+"fftsize : float\n"
141+" size of the FFT\n"
142+"\n"
143+"Returns\n"
53144 "-------\n"
145+"float\n"
146+" Frequency converted to FFT bin.\n"
147+"\n"
148+"Examples\n"
149+"--------\n"
54150 "\n"
55−">>> bin = freqtobin(freq, samplerate = 44100, fftsize = 1024)";
151+">>> aubio.freqtobin(440, 44100, 1024)\n"
152+"10.216779708862305\n"
153+"";
56154
57155 static char Py_zero_crossing_rate_doc[] = ""
58−"zero_crossing_rate(fvec) -> float\n"
156+"zero_crossing_rate(vec)\n"
157+"\n"
158+"Compute zero-crossing rate of `vec`.\n"
59159 "\n"
60−"Compute Zero crossing rate of a vector\n"
160+"Parameters\n"
161+"----------\n"
162+"vec : fvec\n"
163+" input vector\n"
164+"\n"
165+"Returns\n"
166+"-------\n"
167+"float\n"
168+" Zero-crossing rate.\n"
61169 "\n"
62170 "Example\n"
63171 "-------\n"
64172 "\n"
65−">>> z = zero_crossing_rate(a)";
173+">>> a = np.linspace(-1., 1., 1000, dtype=aubio.float_type)\n"
174+">>> aubio.zero_crossing_rate(a), 1/1000\n"
175+"(0.0010000000474974513, 0.001)\n"
176+"";
66177
67178 static char Py_min_removal_doc[] = ""
68−"min_removal(fvec) -> float\n"
179+"min_removal(vec)\n"
180+"\n"
181+"Remove the minimum value of a vector to each of its element.\n"
69182 "\n"
70−"Remove the minimum value of a vector, in-place modification\n"
183+"Modifies the input vector in-place and returns a reference to it.\n"
184+"\n"
185+"Parameters\n"
186+"----------\n"
187+"vec : fvec\n"
188+" input vector\n"
189+"\n"
190+"Returns\n"
191+"-------\n"
192+"fvec\n"
193+" modified input vector\n"
71194 "\n"
72195 "Example\n"
73196 "-------\n"
74197 "\n"
75−">>> min_removal(a)";
198+">>> aubio.min_removal(aubio.fvec(np.arange(1,4)))\n"
199+"array([0., 1., 2.], dtype=" AUBIO_NPY_SMPL_STR ")\n"
200+"";
76201
77202 extern void add_ufuncs ( PyObject *m );
78203 extern int generated_types_ready(void);
@@ -112,7 +237,9 @@ Py_bintomidi (PyObject * self, PyObject * args) · 33 unmodified lines
112237 smpl_t input, samplerate, fftsize;
113238 smpl_t output;
114239
115− if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) {
240+ if (!PyArg_ParseTuple (args,
241+ "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR,
242+ &input, &samplerate, &fftsize)) {
116243 return NULL;
117244 }
118245
@@ -127,7 +254,9 @@ Py_miditobin (PyObject * self, PyObject * args) · 8 unmodified lines
127254 smpl_t input, samplerate, fftsize;
128255 smpl_t output;
129256
130− if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) {
257+ if (!PyArg_ParseTuple (args,
258+ "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR,
259+ &input, &samplerate, &fftsize)) {
131260 return NULL;
132261 }
133262
@@ -142,7 +271,9 @@ Py_bintofreq (PyObject * self, PyObject * args) · 8 unmodified lines
142271 smpl_t input, samplerate, fftsize;
143272 smpl_t output;
144273
145− if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) {
274+ if (!PyArg_ParseTuple (args,
275+ "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR,
276+ &input, &samplerate, &fftsize)) {
146277 return NULL;
147278 }
148279
@@ -157,7 +288,9 @@ Py_freqtobin (PyObject * self, PyObject * args) · 8 unmodified lines
157288 smpl_t input, samplerate, fftsize;
158289 smpl_t output;
159290
160− if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) {
291+ if (!PyArg_ParseTuple (args,
292+ "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR,
293+ &input, &samplerate, &fftsize)) {
161294 return NULL;
162295 }
163296
@@ -237,6 +370,12 @@ static PyMethodDef aubio_methods[] = { · 73 unmodified lines
237370 {"silence_detection", Py_aubio_silence_detection, METH_VARARGS, Py_aubio_silence_detection_doc},
238371 {"level_detection", Py_aubio_level_detection, METH_VARARGS, Py_aubio_level_detection_doc},
239372 {"window", Py_aubio_window, METH_VARARGS, Py_aubio_window_doc},
373+ {"shift", Py_aubio_shift, METH_VARARGS, Py_aubio_shift_doc},
374+ {"ishift", Py_aubio_ishift, METH_VARARGS, Py_aubio_ishift_doc},
375+ {"hztomel", Py_aubio_hztomel, METH_VARARGS|METH_KEYWORDS, Py_aubio_hztomel_doc},
376+ {"meltohz", Py_aubio_meltohz, METH_VARARGS|METH_KEYWORDS, Py_aubio_meltohz_doc},
377+ {"hztomel_htk", Py_aubio_hztomel_htk, METH_VARARGS, Py_aubio_hztomel_htk_doc},
378+ {"meltohz_htk", Py_aubio_meltohz_htk, METH_VARARGS, Py_aubio_meltohz_htk_doc},
240379 {NULL, NULL, 0, NULL} /* Sentinel */
241380 };
242381
@@ -323,6 +462,7 @@ initaubio (void) · 80 unmodified lines
323462 PyModule_AddObject (m, "sink", (PyObject *) & Py_sinkType);
324463
325464 PyModule_AddStringConstant(m, "float_type", AUBIO_NPY_SMPL_STR);
465+ PyModule_AddStringConstant(m, "__version__", DEFINEDSTRING(AUBIO_VERSION));
326466
327467 // add generated objects
328468 add_generated_objects(m);
python/ext/py-cvec.c+42−12
@@ -19,7 +19,37 @@ typedef struct · 18 unmodified lines
1919 uint_t length;
2020 } Py_cvec;
2121
22−static char Py_cvec_doc[] = "cvec object";
22+static char Py_cvec_doc[] = ""
23+"cvec(size)\n"
24+"\n"
25+"A container holding spectral data.\n"
26+"\n"
27+"Create one `cvec` to store the spectral information of a window\n"
28+"of `size` points. The data will be stored in two vectors,\n"
29+":attr:`phas` and :attr:`norm`, each of shape (:attr:`length`,),\n"
30+"with `length = size // 2 + 1`.\n"
31+"\n"
32+"Parameters\n"
33+"----------\n"
34+"size: int\n"
35+" Size of spectrum to create.\n"
36+"\n"
37+"Examples\n"
38+"--------\n"
39+">>> c = aubio.cvec(1024)\n"
40+">>> c\n"
41+"aubio cvec of 513 elements\n"
42+">>> c.length\n"
43+"513\n"
44+">>> c.norm.dtype, c.phas.dtype\n"
45+"(dtype('float32'), dtype('float32'))\n"
46+">>> c.norm.shape, c.phas.shape\n"
47+"((513,), (513,))\n"
48+"\n"
49+"See Also\n"
50+"--------\n"
51+"fvec, fft, pvoc\n"
52+"";
2353
2454
2555 PyObject *
@@ -142,14 +172,14 @@ Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure) · 116 unmodified lines
142172 {
143173 npy_intp length;
144174 if (!PyAubio_IsValidVector(input)) {
145− return 1;
175+ return -1;
146176 }
147177 length = PyArray_SIZE ((PyArrayObject *)input);
148178 if (length != vec->length) {
149179 PyErr_Format (PyExc_ValueError,
150− "input array has length %ld, but cvec has length %d", length,
180+ "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length,
151181 vec->length);
152− return 1;
182+ return -1;
153183 }
154184
155185 Py_XDECREF(vec->norm);
@@ -163,14 +193,14 @@ Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) · 7 unmodified lines
163193 {
164194 npy_intp length;
165195 if (!PyAubio_IsValidVector(input)) {
166− return 1;
196+ return -1;
167197 }
168198 length = PyArray_SIZE ((PyArrayObject *)input);
169199 if (length != vec->length) {
170200 PyErr_Format (PyExc_ValueError,
171− "input array has length %ld, but cvec has length %d", length,
201+ "input array has length %" NPY_INTP_FMT ", but cvec has length %d", length,
172202 vec->length);
173− return 1;
203+ return -1;
174204 }
175205
176206 Py_XDECREF(vec->phas);
@@ -182,7 +212,7 @@ Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) · 5 unmodified lines
182212 static PyMemberDef Py_cvec_members[] = {
183213 // TODO remove READONLY flag and define getter/setter
184214 {"length", T_INT, offsetof (Py_cvec, length), READONLY,
185− "length attribute"},
215+ "int: Length of `norm` and `phas` vectors."},
186216 {NULL} /* Sentinel */
187217 };
188218
@@ -191,11 +221,11 @@ static PyMethodDef Py_cvec_methods[] = { · 2 unmodified lines
191221 };
192222
193223 static PyGetSetDef Py_cvec_getseters[] = {
194− {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm,
195− "Numpy vector of shape (length,) containing the magnitude",
224+ {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm,
225+ "numpy.ndarray: Vector of shape `(length,)` containing the magnitude.",
196226 NULL},
197− {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas,
198− "Numpy vector of shape (length,) containing the phase",
227+ {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas,
228+ "numpy.ndarray: Vector of shape `(length,)` containing the phase.",
199229 NULL},
200230 {NULL} /* sentinel */
201231 };
python/ext/py-filterbank.c+133−9
@@ -94,7 +94,7 @@ Py_filterbank_do(Py_filterbank * self, PyObject * args) · 93 unmodified lines
9494
9595 if (self->vec.length != self->win_s / 2 + 1) {
9696 PyErr_Format(PyExc_ValueError,
97− "input cvec has length %d, but fft expects length %d",
97+ "input cvec has length %d, but filterbank expects length %d",
9898 self->vec.length, self->win_s / 2 + 1);
9999 return NULL;
100100 }
@@ -122,8 +122,8 @@ Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) · 21 unmodified lines
122122 uint_t err = 0;
123123
124124 PyObject *input;
125− uint_t samplerate;
126− if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) {
125+ smpl_t samplerate;
126+ if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR, &input, &samplerate)) {
127127 return NULL;
128128 }
129129
@@ -138,8 +138,14 @@ Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) · 8 unmodified lines
138138 err = aubio_filterbank_set_triangle_bands (self->o,
139139 &(self->freqs), samplerate);
140140 if (err > 0) {
141− PyErr_SetString (PyExc_ValueError,
142− "error when setting filter to A-weighting");
141+ if (PyErr_Occurred() == NULL) {
142+ PyErr_SetString (PyExc_ValueError, "error running set_triangle_bands");
143+ } else {
144+ // change the RuntimeError into ValueError
145+ PyObject *type, *value, *traceback;
146+ PyErr_Fetch(&type, &value, &traceback);
147+ PyErr_Restore(PyExc_ValueError, value, traceback);
148+ }
143149 return NULL;
144150 }
145151 Py_RETURN_NONE;
@@ -150,15 +156,79 @@ Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) · 4 unmodified lines
150156 {
151157 uint_t err = 0;
152158
153− uint_t samplerate;
154− if (!PyArg_ParseTuple (args, "I", &samplerate)) {
159+ smpl_t samplerate;
160+ if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &samplerate)) {
155161 return NULL;
156162 }
157163
158164 err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate);
159165 if (err > 0) {
160− PyErr_SetString (PyExc_ValueError,
161− "error when setting filter to A-weighting");
166+ if (PyErr_Occurred() == NULL) {
167+ PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs_slaney");
168+ } else {
169+ // change the RuntimeError into ValueError
170+ PyObject *type, *value, *traceback;
171+ PyErr_Fetch(&type, &value, &traceback);
172+ PyErr_Restore(PyExc_ValueError, value, traceback);
173+ }
174+ return NULL;
175+ }
176+ Py_RETURN_NONE;
177+}
178+
179+static PyObject *
180+Py_filterbank_set_mel_coeffs (Py_filterbank * self, PyObject *args)
181+{
182+ uint_t err = 0;
183+
184+ smpl_t samplerate;
185+ smpl_t freq_min;
186+ smpl_t freq_max;
187+ if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR
188+ AUBIO_NPY_SMPL_CHR, &samplerate, &freq_min, &freq_max)) {
189+ return NULL;
190+ }
191+
192+ err = aubio_filterbank_set_mel_coeffs (self->o, samplerate,
193+ freq_min, freq_max);
194+ if (err > 0) {
195+ if (PyErr_Occurred() == NULL) {
196+ PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs");
197+ } else {
198+ // change the RuntimeError into ValueError
199+ PyObject *type, *value, *traceback;
200+ PyErr_Fetch(&type, &value, &traceback);
201+ PyErr_Restore(PyExc_ValueError, value, traceback);
202+ }
203+ return NULL;
204+ }
205+ Py_RETURN_NONE;
206+}
207+
208+static PyObject *
209+Py_filterbank_set_mel_coeffs_htk (Py_filterbank * self, PyObject *args)
210+{
211+ uint_t err = 0;
212+
213+ smpl_t samplerate;
214+ smpl_t freq_min;
215+ smpl_t freq_max;
216+ if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR
217+ AUBIO_NPY_SMPL_CHR, &samplerate, &freq_min, &freq_max)) {
218+ return NULL;
219+ }
220+
221+ err = aubio_filterbank_set_mel_coeffs_htk (self->o, samplerate,
222+ freq_min, freq_max);
223+ if (err > 0) {
224+ if (PyErr_Occurred() == NULL) {
225+ PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs_htk");
226+ } else {
227+ // change the RuntimeError into ValueError
228+ PyObject *type, *value, *traceback;
229+ PyErr_Fetch(&type, &value, &traceback);
230+ PyErr_Restore(PyExc_ValueError, value, traceback);
231+ }
162232 return NULL;
163233 }
164234 Py_RETURN_NONE;
@@ -195,15 +265,69 @@ Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused) · 30 unmodified lines
195265 aubio_filterbank_get_coeffs (self->o) );
196266 }
197267
268+static PyObject *
269+Py_filterbank_set_power(Py_filterbank *self, PyObject *args)
270+{
271+ smpl_t power;
272+
273+ if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &power)) {
274+ return NULL;
275+ }
276+ if(aubio_filterbank_set_power (self->o, power)) {
277+ if (PyErr_Occurred() == NULL) {
278+ PyErr_SetString (PyExc_ValueError,
279+ "error running filterbank.set_power");
280+ } else {
281+ // change the RuntimeError into ValueError
282+ PyObject *type, *value, *traceback;
283+ PyErr_Fetch(&type, &value, &traceback);
284+ PyErr_Restore(PyExc_ValueError, value, traceback);
285+ }
286+ return NULL;
287+ }
288+ Py_RETURN_NONE;
289+}
290+
291+static PyObject *
292+Py_filterbank_set_norm(Py_filterbank *self, PyObject *args)
293+{
294+ smpl_t norm;
295+
296+ if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &norm)) {
297+ return NULL;
298+ }
299+ if(aubio_filterbank_set_norm (self->o, norm)) {
300+ if (PyErr_Occurred() == NULL) {
301+ PyErr_SetString (PyExc_ValueError,
302+ "error running filterbank.set_power");
303+ } else {
304+ // change the RuntimeError into ValueError
305+ PyObject *type, *value, *traceback;
306+ PyErr_Fetch(&type, &value, &traceback);
307+ PyErr_Restore(PyExc_ValueError, value, traceback);
308+ }
309+ return NULL;
310+ }
311+ Py_RETURN_NONE;
312+}
313+
198314 static PyMethodDef Py_filterbank_methods[] = {
199315 {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands,
200316 METH_VARARGS, "set coefficients of filterbanks"},
201317 {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney,
202318 METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"},
319+ {"set_mel_coeffs", (PyCFunction) Py_filterbank_set_mel_coeffs,
320+ METH_VARARGS, "set coefficients of filterbank to linearly spaced mel scale"},
321+ {"set_mel_coeffs_htk", (PyCFunction) Py_filterbank_set_mel_coeffs_htk,
322+ METH_VARARGS, "set coefficients of filterbank to linearly spaced mel scale"},
203323 {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs,
204324 METH_NOARGS, "get coefficients of filterbank"},
205325 {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs,
206326 METH_VARARGS, "set coefficients of filterbank"},
327+ {"set_power", (PyCFunction) Py_filterbank_set_power,
328+ METH_VARARGS, "set power applied to filterbank input spectrum"},
329+ {"set_norm", (PyCFunction) Py_filterbank_set_norm,
330+ METH_VARARGS, "set norm applied to filterbank input spectrum"},
207331 {NULL}
208332 };
209333
python/ext/py-musicutils.c+102−0
@@ -133,3 +133,105 @@ Py_aubio_level_detection(PyObject *self, PyObject *args) · 132 unmodified lines
133133
134134 return level_detection;
135135 }
136+
137+PyObject *
138+Py_aubio_shift(PyObject *self, PyObject *args)
139+{
140+ PyObject *input;
141+ fvec_t vec;
142+
143+ if (!PyArg_ParseTuple (args, "O:shift", &input)) {
144+ return NULL;
145+ }
146+
147+ if (input == NULL) {
148+ return NULL;
149+ }
150+
151+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
152+ return NULL;
153+ }
154+
155+ fvec_shift(&vec);
156+
157+ //Py_RETURN_NONE;
158+ return (PyObject *) PyAubio_CFvecToArray(&vec);
159+}
160+
161+PyObject *
162+Py_aubio_ishift(PyObject *self, PyObject *args)
163+{
164+ PyObject *input;
165+ fvec_t vec;
166+
167+ if (!PyArg_ParseTuple (args, "O:shift", &input)) {
168+ return NULL;
169+ }
170+
171+ if (input == NULL) {
172+ return NULL;
173+ }
174+
175+ if (!PyAubio_ArrayToCFvec(input, &vec)) {
176+ return NULL;
177+ }
178+
179+ fvec_ishift(&vec);
180+
181+ //Py_RETURN_NONE;
182+ return (PyObject *) PyAubio_CFvecToArray(&vec);
183+}
184+
185+PyObject*
186+Py_aubio_hztomel(PyObject *self, PyObject *args, PyObject *kwds)
187+{
188+ smpl_t v;
189+ PyObject *htk = NULL;
190+ static char *kwlist[] = {"f", "htk", NULL};
191+ if (!PyArg_ParseTupleAndKeywords(args, kwds, AUBIO_NPY_SMPL_CHR "|O",
192+ kwlist, &v, &htk))
193+ {
194+ return NULL;
195+ }
196+ if (htk != NULL && PyObject_IsTrue(htk) == 1)
197+ return Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_hztomel_htk(v));
198+ else
199+ return Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_hztomel(v));
200+}
201+
202+PyObject*
203+Py_aubio_meltohz(PyObject *self, PyObject *args, PyObject *kwds)
204+{
205+ smpl_t v;
206+ PyObject *htk = NULL;
207+ static char *kwlist[] = {"m", "htk", NULL};
208+ if (!PyArg_ParseTupleAndKeywords(args, kwds, AUBIO_NPY_SMPL_CHR "|O",
209+ kwlist, &v, &htk))
210+ {
211+ return NULL;
212+ }
213+ if (htk != NULL && PyObject_IsTrue(htk) == 1)
214+ return Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_meltohz_htk(v));
215+ else
216+ return Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_meltohz(v));
217+}
218+
219+PyObject*
220+Py_aubio_hztomel_htk(PyObject *self, PyObject *args)
221+{
222+ smpl_t v;
223+ if (!PyArg_ParseTuple(args, AUBIO_NPY_SMPL_CHR, &v)) {
224+ return NULL;
225+ }
226+ return Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_hztomel_htk(v));
227+}
228+
229+PyObject*
230+Py_aubio_meltohz_htk(PyObject *self, PyObject *args)
231+{
232+ smpl_t v;
233+ if (!PyArg_ParseTuple(args, AUBIO_NPY_SMPL_CHR, &v)) {
234+ return NULL;
235+ }
236+ return Py_BuildValue(AUBIO_NPY_SMPL_CHR, aubio_meltohz_htk(v));
237+}
python/ext/py-musicutils.h+322−25
@@ -2,73 +2,370 @@ · 1 unmodified line
22 #define PY_AUBIO_MUSICUTILS_H
33
44 static char Py_aubio_window_doc[] = ""
5−"window(string, integer) -> fvec\n"
5+"window(window_type, size)\n"
66 "\n"
7−"Create a window\n"
7+"Create a window of length `size`. `window_type` should be one\n"
8+"of the following:\n"
89 "\n"
9−"Example\n"
10+"- `default` (same as `hanningz`).\n"
11+"- `ones`\n"
12+"- `rectangle`\n"
13+"- `hamming`\n"
14+"- `hanning`\n"
15+"- `hanningz` [1]_\n"
16+"- `blackman`\n"
17+"- `blackman_harris`\n"
18+"- `gaussian`\n"
19+"- `welch`\n"
20+"- `parzen`\n"
21+"\n"
22+"Parameters\n"
23+"----------\n"
24+"window_type : str\n"
25+" Type of window.\n"
26+"size : int\n"
27+" Length of window.\n"
28+"\n"
29+"Returns\n"
1030 "-------\n"
31+"fvec\n"
32+" Array of shape `(length,)` containing the new window.\n"
33+"\n"
34+"See Also\n"
35+"--------\n"
36+"pvoc, fft\n"
37+"\n"
38+"Examples\n"
39+"--------\n"
40+"Compute a zero-phase Hann window on `1024` points:\n"
1141 "\n"
12−">>> window('hanningz', 1024)\n"
42+">>> aubio.window('hanningz', 1024)\n"
1343 "array([ 0.00000000e+00, 9.41753387e-06, 3.76403332e-05, ...,\n"
14−" 8.46982002e-05, 3.76403332e-05, 9.41753387e-06], dtype=float32)";
44+" 8.46982002e-05, 3.76403332e-05, 9.41753387e-06], dtype=float32)\n"
45+"\n"
46+"Plot different window types with `matplotlib <https://matplotlib.org/>`_:\n"
47+"\n"
48+">>> import matplotlib.pyplot as plt\n"
49+">>> modes = ['default', 'ones', 'rectangle', 'hamming', 'hanning',\n"
50+"... 'hanningz', 'blackman', 'blackman_harris', 'gaussian',\n"
51+"... 'welch', 'parzen']; n = 2048\n"
52+">>> for m in modes: plt.plot(aubio.window(m, n), label=m)\n"
53+"...\n"
54+">>> plt.legend(); plt.show()\n"
55+"\n"
56+"Note\n"
57+"----\n"
58+"The following examples contain the equivalent source code to compute\n"
59+"each type of window with `NumPy <https://numpy.org>`_:\n"
60+"\n"
61+">>> n = 1024; x = np.arange(n, dtype=aubio.float_type)\n"
62+">>> ones = np.ones(n).astype(aubio.float_type)\n"
63+">>> rectangle = 0.5 * ones\n"
64+">>> hanning = 0.5 - 0.5 * np.cos(2 * np.pi * x / n)\n"
65+">>> hanningz = 0.5 * (1 - np.cos(2 * np.pi * x / n))\n"
66+">>> hamming = 0.54 - 0.46 * np.cos(2.*np.pi * x / (n - 1))\n"
67+">>> blackman = 0.42 \\\n"
68+"... - 0.50 * np.cos(2 * np.pi * x / (n - 1)) \\\n"
69+"... + 0.08 * np.cos(4 * np.pi * x / (n - 1))\n"
70+">>> blackman_harris = 0.35875 \\\n"
71+"... - 0.48829 * np.cos(2 * np.pi * x / (n - 1)) \\\n"
72+"... + 0.14128 * np.cos(4 * np.pi * x / (n - 1)) \\\n"
73+"... + 0.01168 * np.cos(6 * np.pi * x / (n - 1))\n"
74+">>> gaussian = np.exp( - 0.5 * ((x - 0.5 * (n - 1)) \\\n"
75+"... / (0.25 * (n - 1)) )**2 )\n"
76+">>> welch = 1 - ((2 * x - n) / (n + 1))**2\n"
77+">>> parzen = 1 - np.abs((2 * x - n) / (n + 1))\n"
78+">>> default = hanningz\n"
79+"References\n"
80+"----------\n"
81+#if 0
82+"`Window function <https://en.wikipedia.org/wiki/Window_function>`_ on\n"
83+"Wikipedia.\n"
84+"\n"
85+#endif
86+".. [1] Amalia de Götzen, Nicolas Bernardini, and Daniel Arfib. Traditional\n"
87+" (?) implementations of a phase vocoder: the tricks of the trade.\n"
88+" In *Proceedings of the International Conference on Digital Audio\n"
89+" Effects* (DAFx-00), pages 37–44, University of Verona, Italy, 2000.\n"
90+" (`online version <"
91+"https://www.cs.princeton.edu/courses/archive/spr09/cos325/Bernardini.pdf"
92+">`_).\n"
93+"";
1594
1695 PyObject * Py_aubio_window(PyObject *self, PyObject *args);
1796
1897 static char Py_aubio_level_lin_doc[] = ""
19−"level_lin(fvec) -> fvec\n"
98+"level_lin(x)\n"
2099 "\n"
21−"Compute sound level on a linear scale.\n"
100+"Compute sound pressure level of `x`, on a linear scale.\n"
22101 "\n"
23−"This gives the average of the square amplitudes.\n"
102+"Parameters\n"
103+"----------\n"
104+"x : fvec\n"
105+" input vector\n"
106+"\n"
107+"Returns\n"
108+"-------\n"
109+"float\n"
110+" Linear level of `x`.\n"
24111 "\n"
25112 "Example\n"
26113 "-------\n"
27114 "\n"
28−">>> level_Lin(numpy.ones(1024))\n"
29−"1.0";
115+">>> aubio.level_lin(aubio.fvec(numpy.ones(1024)))\n"
116+"1.0\n"
117+"\n"
118+"Note\n"
119+"----\n"
120+"Computed as the average of the squared amplitudes:\n"
121+"\n"
122+".. math:: L = \\frac {\\sum_{n=0}^{N-1} {x_n}^2} {N}\n"
123+"\n"
124+"See Also\n"
125+"--------\n"
126+"db_spl, silence_detection, level_detection\n"
127+"";
30128
31129 PyObject * Py_aubio_level_lin(PyObject *self, PyObject *args);
32130
33131 static char Py_aubio_db_spl_doc[] = ""
34−"Compute sound pressure level (SPL) in dB\n"
132+"db_spl(x)\n"
35133 "\n"
36−"This quantity is often wrongly called 'loudness'.\n"
134+"Compute Sound Pressure Level (SPL) of `x`, in dB.\n"
37135 "\n"
38−"This gives ten times the log10 of the average of the square amplitudes.\n"
136+"Parameters\n"
137+"----------\n"
138+"x : fvec\n"
139+" input vector\n"
140+"\n"
141+"Returns\n"
142+"-------\n"
143+"float\n"
144+" Level of `x`, in dB SPL.\n"
39145 "\n"
40146 "Example\n"
41147 "-------\n"
42148 "\n"
43−">>> db_spl(numpy.ones(1024))\n"
44−"1.0";
149+">>> aubio.db_spl(aubio.fvec(np.ones(1024)))\n"
150+"1.0\n"
151+">>> aubio.db_spl(0.7*aubio.fvec(np.ones(32)))\n"
152+"-3.098040819168091\n"
153+"\n"
154+"Note\n"
155+"----\n"
156+"Computed as `log10` of :py:func:`level_lin`:\n"
157+"\n"
158+".. math::\n"
159+"\n"
160+" {SPL}_{dB} = log10{\\frac {\\sum_{n=0}^{N-1}{x_n}^2} {N}}\n"
161+"\n"
162+"This quantity is often incorrectly called 'loudness'.\n"
163+"\n"
164+"See Also\n"
165+"--------\n"
166+"level_lin, silence_detection, level_detection\n"
167+"";
45168
46169 PyObject * Py_aubio_db_spl(PyObject *self, PyObject *args);
47170
48171 static char Py_aubio_silence_detection_doc[] = ""
49−"Check if buffer level in dB SPL is under a given threshold\n"
172+"silence_detection(vec, level)\n"
50173 "\n"
51−"Return 0 if level is under the given threshold, 1 otherwise.\n"
174+"Check if level of `vec`, in dB SPL, is under a given threshold.\n"
52175 "\n"
53−"Example\n"
176+"Parameters\n"
177+"----------\n"
178+"vec : fvec\n"
179+" input vector\n"
180+"level : float\n"
181+" level threshold, in dB SPL\n"
182+"\n"
183+"Returns\n"
54184 "-------\n"
185+"int\n"
186+" `1` if level of `vec`, in dB SPL, is under `level`,\n"
187+" `0` otherwise.\n"
55188 "\n"
56−">>> import numpy\n"""
57−">>> silence_detection(numpy.ones(1024, dtype=\"float32\"), -80)\n"
58−"0";
189+"Examples\n"
190+"--------\n"
191+"\n"
192+">>> aubio.silence_detection(aubio.fvec(32), -100.)\n"
193+"1\n"
194+">>> aubio.silence_detection(aubio.fvec(np.ones(32)), 0.)\n"
195+"0\n"
196+"\n"
197+"See Also\n"
198+"--------\n"
199+"level_detection, db_spl, level_lin\n"
200+"";
59201
60202 PyObject * Py_aubio_silence_detection(PyObject *self, PyObject *args);
61203
62204 static char Py_aubio_level_detection_doc[] = ""
63−"Get buffer level in dB SPL if over a given threshold, 1. otherwise.\n"
205+"level_detection(vec, level)\n"
206+"\n"
207+"Check if `vec` is above threshold `level`, in dB SPL.\n"
208+"\n"
209+"Parameters\n"
210+"----------\n"
211+"vec : fvec\n"
212+" input vector\n"
213+"level : float\n"
214+" level threshold, in dB SPL\n"
215+"\n"
216+"Returns\n"
217+"-------\n"
218+"float\n"
219+" `1.0` if level of `vec` in dB SPL is under `level`,\n"
220+" `db_spl(vec)` otherwise.\n"
64221 "\n"
65222 "Example\n"
66223 "-------\n"
67224 "\n"
68−">>> import numpy\n"""
69−">>> level_detection(0.7*numpy.ones(1024, dtype=\"float32\"), -80)\n"
70−"0";
225+">>> aubio.level_detection(0.7*aubio.fvec(np.ones(1024)), -3.)\n"
226+"1.0\n"
227+">>> aubio.level_detection(0.7*aubio.fvec(np.ones(1024)), -4.)\n"
228+"-3.0980708599090576\n"
229+"\n"
230+"See Also\n"
231+"--------\n"
232+"silence_detection, db_spl, level_lin\n"
233+"";
71234
72235 PyObject * Py_aubio_level_detection(PyObject *self, PyObject *args);
73236
237+static char Py_aubio_shift_doc[] = ""
238+"shift(vec)\n"
239+"\n"
240+"Swap left and right partitions of a vector, in-place.\n"
241+"\n"
242+"Parameters\n"
243+"----------\n"
244+"vec : fvec\n"
245+" input vector to shift\n"
246+"\n"
247+"Returns\n"
248+"-------\n"
249+"fvec\n"
250+" The swapped vector.\n"
251+"\n"
252+"Notes\n"
253+"-----\n"
254+"The input vector is also modified.\n"
255+"\n"
256+"For a vector of length N, the partition is split at index N - N//2.\n"
257+"\n"
258+"Example\n"
259+"-------\n"
260+"\n"
261+">>> aubio.shift(aubio.fvec(np.arange(3)))\n"
262+"array([2., 0., 1.], dtype=" AUBIO_NPY_SMPL_STR ")\n"
263+"\n"
264+"See Also\n"
265+"--------\n"
266+"ishift\n"
267+"";
268+PyObject * Py_aubio_shift(PyObject *self, PyObject *args);
269+
270+static char Py_aubio_ishift_doc[] = ""
271+"ishift(vec)\n"
272+"\n"
273+"Swap right and left partitions of a vector, in-place.\n"
274+"\n"
275+"Parameters\n"
276+"----------\n"
277+"vec : fvec\n"
278+" input vector to shift\n"
279+"\n"
280+"Returns\n"
281+"-------\n"
282+"fvec\n"
283+" The swapped vector.\n"
284+"\n"
285+"Notes\n"
286+"-----\n"
287+"The input vector is also modified.\n"
288+"\n"
289+"Unlike with :py:func:`shift`, the partition is split at index N//2.\n"
290+"\n"
291+"Example\n"
292+"-------\n"
293+"\n"
294+">>> aubio.ishift(aubio.fvec(np.arange(3)))\n"
295+"array([1., 2., 0.], dtype=" AUBIO_NPY_SMPL_STR ")\n"
296+"\n"
297+"See Also\n"
298+"--------\n"
299+"shift\n"
300+"";
301+PyObject * Py_aubio_ishift(PyObject *self, PyObject *args);
302+
303+static char Py_aubio_hztomel_doc[] = ""
304+"hztomel(f, htk=False)\n"
305+"\n"
306+"Convert a scalar from frequency to mel scale.\n"
307+"\n"
308+"Parameters\n"
309+"----------\n"
310+"m : float\n"
311+" input frequency, in Hz\n"
312+"htk : bool\n"
313+" if `True`, use Htk mel scale instead of Slaney.\n"
314+"\n"
315+"Returns\n"
316+"-------\n"
317+"float\n"
318+" output mel\n"
319+"\n"
320+"See Also\n"
321+"--------\n"
322+"meltohz\n"
323+"";
324+PyObject * Py_aubio_hztomel(PyObject *self, PyObject *args);
325+
326+static char Py_aubio_meltohz_doc[] = ""
327+"meltohz(m, htk=False)\n"
328+"\n"
329+"Convert a scalar from mel scale to frequency.\n"
330+"\n"
331+"Parameters\n"
332+"----------\n"
333+"m : float\n"
334+" input mel\n"
335+"htk : bool\n"
336+" if `True`, use Htk mel scale instead of Slaney.\n"
337+"\n"
338+"Returns\n"
339+"-------\n"
340+"float\n"
341+" output frequency, in Hz\n"
342+"\n"
343+"See Also\n"
344+"--------\n"
345+"hztomel\n"
346+"";
347+PyObject * Py_aubio_meltohz(PyObject *self, PyObject *args);
348+
349+static char Py_aubio_hztomel_htk_doc[] = ""
350+"hztomel_htk(m)\n"
351+"\n"
352+"Same as `hztomel(m, htk=True)`\n"
353+"\n"
354+"See Also\n"
355+"--------\n"
356+"hztomel\n"
357+"";
358+PyObject * Py_aubio_hztomel_htk(PyObject *self, PyObject *args);
359+
360+static char Py_aubio_meltohz_htk_doc[] = ""
361+"meltohz_htk(m)\n"
362+"\n"
363+"Same as `meltohz(m, htk=True)`\n"
364+"\n"
365+"See Also\n"
366+"--------\n"
367+"meltohz\n"
368+"";
369+PyObject * Py_aubio_meltohz_htk(PyObject *self, PyObject *args);
370+
74371 #endif /* PY_AUBIO_MUSICUTILS_H */
python/ext/py-phasevoc.c+116−8
@@ -1,6 +1,58 @@
11 #include "aubio-types.h"
22
3−static char Py_pvoc_doc[] = "pvoc object";
3+static char Py_pvoc_doc[] = ""
4+"pvoc(win_s=512, hop_s=256)\n"
5+"\n"
6+"Phase vocoder.\n"
7+"\n"
8+"`pvoc` creates callable object implements a phase vocoder [1]_,\n"
9+"using the tricks detailed in [2]_.\n"
10+"\n"
11+"The call function takes one input of type `fvec` and of size\n"
12+"`hop_s`, and returns a `cvec` of length `win_s//2+1`.\n"
13+"\n"
14+"Parameters\n"
15+"----------\n"
16+"win_s : int\n"
17+" number of channels in the phase-vocoder.\n"
18+"hop_s : int\n"
19+" number of samples expected between each call\n"
20+"\n"
21+"Examples\n"
22+"--------\n"
23+">>> x = aubio.fvec(256)\n"
24+">>> pv = aubio.pvoc(512, 256)\n"
25+">>> pv(x)\n"
26+"aubio cvec of 257 elements\n"
27+"\n"
28+"Default values for hop_s and win_s are provided:\n"
29+"\n"
30+">>> pv = aubio.pvoc()\n"
31+">>> pv.win_s, pv.hop_s\n"
32+"512, 256\n"
33+"\n"
34+"A `cvec` can be resynthesised using `rdo()`:\n"
35+"\n"
36+">>> pv = aubio.pvoc(512, 256)\n"
37+">>> y = aubio.cvec(512)\n"
38+">>> x_reconstructed = pv.rdo(y)\n"
39+">>> x_reconstructed.shape\n"
40+"(256,)\n"
41+"\n"
42+"References\n"
43+"----------\n"
44+".. [1] James A. Moorer. The use of the phase vocoder in computer music\n"
45+" applications. `Journal of the Audio Engineering Society`,\n"
46+" 26(1/2):42–45, 1978.\n"
47+".. [2] Amalia de Götzen, Nicolas Bernardini, and Daniel Arfib. Traditional\n"
48+" (?) implementations of a phase vocoder: the tricks of the trade.\n"
49+" In `Proceedings of the International Conference on Digital Audio\n"
50+" Effects` (DAFx-00), pages 37–44, University of Verona, Italy, 2000.\n"
51+" (`online version <"
52+"https://www.cs.princeton.edu/courses/archive/spr09/cos325/Bernardini.pdf"
53+">`_).\n"
54+"";
55+
456
557 typedef struct
658 {
@@ -38,10 +90,6 @@ Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) · 31 unmodified lines
3890 self->win_s = Py_default_vector_length;
3991 self->hop_s = Py_default_vector_length/2;
4092
41− if (self == NULL) {
42− return NULL;
43− }
44−
4593 if (win_s > 0) {
4694 self->win_s = win_s;
4795 } else if (win_s < 0) {
@@ -121,9 +169,11 @@ Py_pvoc_do(Py_pvoc * self, PyObject * args) · 73 unmodified lines
121169
122170 static PyMemberDef Py_pvoc_members[] = {
123171 {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY,
124− "size of the window"},
172+ "int: Size of phase vocoder analysis windows, in samples.\n"
173+ ""},
125174 {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY,
126− "size of the hop"},
175+ "int: Interval between two analysis, in samples.\n"
176+ ""},
127177 { NULL } // sentinel
128178 };
129179
@@ -155,9 +205,67 @@ Py_pvoc_rdo(Py_pvoc * self, PyObject * args) · 25 unmodified lines
155205 return self->routput;
156206 }
157207
208+static PyObject *
209+Pyaubio_pvoc_set_window (Py_pvoc *self, PyObject *args)
210+{
211+ uint_t err = 0;
212+ char_t *window = NULL;
213+
214+ if (!PyArg_ParseTuple (args, "s", &window)) {
215+ return NULL;
216+ }
217+ err = aubio_pvoc_set_window (self->o, window);
218+
219+ if (err > 0) {
220+ PyErr_SetString (PyExc_ValueError, "error running aubio_pvoc_set_window");
221+ return NULL;
222+ }
223+ Py_RETURN_NONE;
224+}
225+
158226 static PyMethodDef Py_pvoc_methods[] = {
159227 {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS,
160− "synthesis of spectral grain"},
228+ "rdo(fftgrain)\n"
229+ "\n"
230+ "Read a new spectral grain and resynthesise the next `hop_s`\n"
231+ "output samples.\n"
232+ "\n"
233+ "Parameters\n"
234+ "----------\n"
235+ "fftgrain : cvec\n"
236+ " new input `cvec` to synthesize from, should be of size `win_s/2+1`\n"
237+ "\n"
238+ "Returns\n"
239+ "-------\n"
240+ "fvec\n"
241+ " re-synthesised output of shape `(hop_s,)`\n"
242+ "\n"
243+ "Example\n"
244+ "-------\n"
245+ ">>> pv = aubio.pvoc(2048, 512)\n"
246+ ">>> out = pv.rdo(aubio.cvec(2048))\n"
247+ ">>> out.shape\n"
248+ "(512,)\n"
249+ ""},
250+ {"set_window", (PyCFunction) Pyaubio_pvoc_set_window, METH_VARARGS,
251+ "set_window(window_type)\n"
252+ "\n"
253+ "Set window function\n"
254+ "\n"
255+ "Parameters\n"
256+ "----------\n"
257+ "window_type : str\n"
258+ " the window type to use for this phase vocoder\n"
259+ "\n"
260+ "Raises\n"
261+ "------\n"
262+ "ValueError\n"
263+ " If an unknown window type was given.\n"
264+ "\n"
265+ "See Also\n"
266+ "--------\n"
267+ "window : create a window.\n"
268+ ""},
161269 {NULL}
162270 };
163271
python/ext/py-sink.c+89−50
@@ -12,53 +12,78 @@ typedef struct · 11 unmodified lines
1212 } Py_sink;
1313
1414 static char Py_sink_doc[] = ""
15−" __new__(path, samplerate = 44100, channels = 1)\n"
15+"sink(path, samplerate=44100, channels=1)\n"
1616 "\n"
17−" Create a new sink, opening the given path for writing.\n"
17+"Write audio samples to file.\n"
1818 "\n"
19−" Examples\n"
20−" --------\n"
19+"Parameters\n"
20+"----------\n"
21+"path : str\n"
22+" Pathname of the file to be opened for writing.\n"
23+"samplerate : int\n"
24+" Sampling rate of the file, in Hz.\n"
25+"channels : int\n"
26+" Number of channels to create the file with.\n"
2127 "\n"
22−" Create a new sink at 44100Hz, mono:\n"
28+"Examples\n"
29+"--------\n"
2330 "\n"
24−" >>> sink('/tmp/t.wav')\n"
31+"Create a new sink at 44100Hz, mono:\n"
2532 "\n"
26−" Create a new sink at 8000Hz, mono:\n"
33+">>> snk = aubio.sink('out.wav')\n"
2734 "\n"
28−" >>> sink('/tmp/t.wav', samplerate = 8000)\n"
35+"Create a new sink at 32000Hz, stereo, write 100 samples into it:\n"
2936 "\n"
30−" Create a new sink at 32000Hz, stereo:\n"
37+">>> snk = aubio.sink('out.wav', samplerate=16000, channels=3)\n"
38+">>> snk(aubio.fvec(100), 100)\n"
3139 "\n"
32−" >>> sink('/tmp/t.wav', samplerate = 32000, channels = 2)\n"
40+"Open a new sink at 48000Hz, stereo, write `1234` samples into it:\n"
3341 "\n"
34−" Create a new sink at 32000Hz, 5 channels:\n"
42+">>> with aubio.sink('out.wav', samplerate=48000, channels=2) as src:\n"
43+"... snk(aubio.fvec(1024), 1024)\n"
44+"... snk(aubio.fvec(210), 210)\n"
45+"...\n"
3546 "\n"
36−" >>> sink('/tmp/t.wav', channels = 5, samplerate = 32000)\n"
37−"\n"
38−" __call__(vec, write)\n"
39−" x(vec,write) <==> x.do(vec, write)\n"
40−"\n"
41−" Write vector to sink.\n"
42−"\n"
43−" See also\n"
44−" --------\n"
45−" aubio.sink.do\n"
47+"See also\n"
48+"--------\n"
49+"source: read audio samples from a file.\n"
4650 "\n";
4751
4852 static char Py_sink_do_doc[] = ""
49−"x.do(vec, write) <==> x(vec, write)\n"
53+"do(vec, write)\n"
5054 "\n"
51−"write monophonic vector to sink";
55+"Write a single channel vector to sink.\n"
56+"\n"
57+"Parameters\n"
58+"----------\n"
59+"vec : fvec\n"
60+" input vector `(n,)` where `n >= 0`.\n"
61+"write : int\n"
62+" Number of samples to write.\n"
63+"";
5264
5365 static char Py_sink_do_multi_doc[] = ""
54−"x.do_multi(mat, write)\n"
66+"do_multi(mat, write)\n"
67+"\n"
68+"Write a matrix containing vectors from multiple channels to sink.\n"
5569 "\n"
56−"write polyphonic vector to sink";
70+"Parameters\n"
71+"----------\n"
72+"mat : numpy.ndarray\n"
73+" input matrix of shape `(channels, n)`, where `n >= 0`.\n"
74+"write : int\n"
75+" Number of frames to write.\n"
76+"";
5777
5878 static char Py_sink_close_doc[] = ""
59−"x.close()\n"
79+"close()\n"
6080 "\n"
61−"close this sink now";
81+"Close this sink now.\n"
82+"\n"
83+"By default, the sink will be closed before being deleted.\n"
84+"Explicitely closing a sink can be useful to control the number\n"
85+"of files simultaneously opened.\n"
86+"";
6287
6388 static PyObject *
6489 Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
@@ -80,27 +105,20 @@ Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) · 15 unmodified lines
80105 return NULL;
81106 }
82107
83− self->uri = "none";
108+ self->uri = NULL;
84109 if (uri != NULL) {
85− self->uri = uri;
110+ self->uri = (char_t *)malloc(sizeof(char_t) * (strnlen(uri, PATH_MAX) + 1));
111+ strncpy(self->uri, uri, strnlen(uri, PATH_MAX) + 1);
86112 }
87113
88114 self->samplerate = Py_aubio_default_samplerate;
89− if ((sint_t)samplerate > 0) {
115+ if (samplerate != 0) {
90116 self->samplerate = samplerate;
91− } else if ((sint_t)samplerate < 0) {
92− PyErr_SetString (PyExc_ValueError,
93− "can not use negative value for samplerate");
94− return NULL;
95117 }
96118
97119 self->channels = 1;
98− if ((sint_t)channels > 0) {
120+ if (channels != 0) {
99121 self->channels = channels;
100− } else if ((sint_t)channels < 0) {
101− PyErr_SetString (PyExc_ValueError,
102− "can not use negative or null value for channels");
103− return NULL;
104122 }
105123
106124 return (PyObject *) self;
@@ -109,17 +127,20 @@ Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) · 2 unmodified lines
109127 static int
110128 Py_sink_init (Py_sink * self, PyObject * args, PyObject * kwds)
111129 {
112− if (self->channels == 1) {
113− self->o = new_aubio_sink ( self->uri, self->samplerate );
114− } else {
115− self->o = new_aubio_sink ( self->uri, 0 );
116− aubio_sink_preset_channels ( self->o, self->channels );
117− aubio_sink_preset_samplerate ( self->o, self->samplerate );
118− }
130+ self->o = new_aubio_sink ( self->uri, 0 );
119131 if (self->o == NULL) {
120− PyErr_SetString (PyExc_RuntimeError, "error creating sink with this uri");
132+ // error string was set in new_aubio_sink
121133 return -1;
122134 }
135+ if (aubio_sink_preset_channels(self->o, self->channels) != 0) {
136+ // error string was set in aubio_sink_preset_channels
137+ return -1;
138+ }
139+ if (aubio_sink_preset_samplerate(self->o, self->samplerate) != 0) {
140+ // error string was set in aubio_sink_preset_samplerate
141+ return -1;
142+ }
143+
123144 self->samplerate = aubio_sink_get_samplerate ( self->o );
124145 self->channels = aubio_sink_get_channels ( self->o );
125146
@@ -131,6 +152,9 @@ Py_sink_del (Py_sink *self, PyObject *unused) · 5 unmodified lines
131152 {
132153 del_aubio_sink(self->o);
133154 free(self->mwrite_data.data);
155+ if (self->uri) {
156+ free(self->uri);
157+ }
134158 Py_TYPE(self)->tp_free((PyObject *) self);
135159 }
136160
@@ -189,11 +213,11 @@ Py_sink_do_multi(Py_sink * self, PyObject * args) · 52 unmodified lines
189213
190214 static PyMemberDef Py_sink_members[] = {
191215 {"uri", T_STRING, offsetof (Py_sink, uri), READONLY,
192− "path at which the sink was created"},
216+ "str (read-only): Path at which the sink was created."},
193217 {"samplerate", T_INT, offsetof (Py_sink, samplerate), READONLY,
194− "samplerate at which the sink was created"},
218+ "int (read-only): Samplerate at which the sink was created."},
195219 {"channels", T_INT, offsetof (Py_sink, channels), READONLY,
196− "number of channels with which the sink was created"},
220+ "int (read-only): Number of channels with which the sink was created."},
197221 { NULL } // sentinel
198222 };
199223
@@ -204,10 +228,25 @@ Pyaubio_sink_close (Py_sink *self, PyObject *unused) · 4 unmodified lines
204228 Py_RETURN_NONE;
205229 }
206230
231+static char Pyaubio_sink_enter_doc[] = "";
232+static PyObject* Pyaubio_sink_enter(Py_sink *self, PyObject *unused) {
233+ Py_INCREF(self);
234+ return (PyObject*)self;
235+}
236+
237+static char Pyaubio_sink_exit_doc[] = "";
238+static PyObject* Pyaubio_sink_exit(Py_sink *self, PyObject *unused) {
239+ return Pyaubio_sink_close(self, unused);
240+}
241+
207242 static PyMethodDef Py_sink_methods[] = {
208243 {"do", (PyCFunction) Py_sink_do, METH_VARARGS, Py_sink_do_doc},
209244 {"do_multi", (PyCFunction) Py_sink_do_multi, METH_VARARGS, Py_sink_do_multi_doc},
210245 {"close", (PyCFunction) Pyaubio_sink_close, METH_NOARGS, Py_sink_close_doc},
246+ {"__enter__", (PyCFunction)Pyaubio_sink_enter, METH_NOARGS,
247+ Pyaubio_sink_enter_doc},
248+ {"__exit__", (PyCFunction)Pyaubio_sink_exit, METH_VARARGS,
249+ Pyaubio_sink_exit_doc},
211250 {NULL} /* sentinel */
212251 };
213252
python/ext/py-source.c+370−41
@@ -16,68 +16,316 @@ typedef struct · 15 unmodified lines
1616 } Py_source;
1717
1818 static char Py_source_doc[] = ""
19−" __new__(path, samplerate = 0, hop_size = 512, channels = 1)\n"
19+"source(path, samplerate=0, hop_size=512, channels=0)\n"
2020 "\n"
21−" Create a new source, opening the given path for reading.\n"
21+"Read audio samples from a media file.\n"
2222 "\n"
23−" Examples\n"
24−" --------\n"
23+"`source` open the file specified in `path` and creates a callable\n"
24+"returning `hop_size` new audio samples at each invocation.\n"
2525 "\n"
26−" Create a new source, using the original samplerate, with hop_size = 512:\n"
26+"If `samplerate=0` (default), the original sampling rate of `path`\n"
27+"will be used. Otherwise, the output audio samples will be\n"
28+"resampled at the desired sampling-rate.\n"
2729 "\n"
28−" >>> source('/tmp/t.wav')\n"
30+"If `channels=0` (default), the original number of channels\n"
31+"in `path` will be used. Otherwise, the output audio samples\n"
32+"will be down-mixed or up-mixed to the desired number of\n"
33+"channels.\n"
2934 "\n"
30−" Create a new source, resampling the original to 8000Hz:\n"
35+"If `path` is a URL, a remote connection will be attempted to\n"
36+"open the resource and stream data from it.\n"
3137 "\n"
32−" >>> source('/tmp/t.wav', samplerate = 8000)\n"
38+"The parameter `hop_size` determines how many samples should be\n"
39+"read at each consecutive calls.\n"
3340 "\n"
34−" Create a new source, resampling it at 32000Hz, hop_size = 32:\n"
41+"Parameters\n"
42+"----------\n"
43+"path : str\n"
44+" pathname (or URL) of the file to be opened for reading\n"
45+"samplerate : int, optional\n"
46+" sampling rate of the file\n"
47+"hop_size : int, optional\n"
48+" number of samples to be read per iteration\n"
49+"channels : int, optional\n"
50+" number of channels of the file\n"
3551 "\n"
36−" >>> source('/tmp/t.wav', samplerate = 32000, hop_size = 32)\n"
52+"Examples\n"
53+"--------\n"
54+"By default, when only `path` is given, the file will be opened\n"
55+"with its original sampling rate and channel:\n"
3756 "\n"
38−" Create a new source, using its original samplerate:\n"
57+">>> src = aubio.source('stereo.wav')\n"
58+">>> src.uri, src.samplerate, src.channels, src.duration\n"
59+"('stereo.wav', 48000, 2, 86833)\n"
3960 "\n"
40−" >>> source('/tmp/t.wav', samplerate = 0)\n"
61+"A typical loop to read all samples from a local file could\n"
62+"look like this:\n"
4163 "\n"
42−" __call__()\n"
43−" vec, read = x() <==> vec, read = x.do()\n"
64+">>> src = aubio.source('stereo.wav')\n"
65+">>> total_read = 0\n"
66+">>> while True:\n"
67+"... samples, read = src()\n"
68+"... # do something with samples\n"
69+"... total_read += read\n"
70+"... if read < src.hop_size:\n"
71+"... break\n"
72+"...\n"
4473 "\n"
45−" Read vector from source.\n"
74+"In a more Pythonic way, it can also look like this:\n"
4675 "\n"
47−" See also\n"
48−" --------\n"
49−" aubio.source.do\n"
50−"\n";
76+">>> total_read = 0\n"
77+">>> with aubio.source('stereo.wav') as src:\n"
78+"... for frames in src:\n"
79+"... total_read += samples.shape[-1]\n"
80+"...\n"
81+"\n"
82+".. rubric:: Basic interface\n"
83+"\n"
84+"`source` is a **callable**; its :meth:`__call__` method\n"
85+"returns a tuple containing:\n"
86+"\n"
87+"- a vector of shape `(hop_size,)`, filled with the `read` next\n"
88+" samples available, zero-padded if `read < hop_size`\n"
89+"- `read`, an integer indicating the number of samples read\n"
90+"\n"
91+"To read the first `hop_size` samples from the source, simply call\n"
92+"the instance itself, with no argument:\n"
93+"\n"
94+">>> src = aubio.source('song.ogg')\n"
95+">>> samples, read = src()\n"
96+">>> samples.shape, read, src.hop_size\n"
97+"((512,), 512, 512)\n"
98+"\n"
99+"The first call returned the slice of samples `[0 : hop_size]`.\n"
100+"The next call will return samples `[hop_size: 2*hop_size]`.\n"
101+"\n"
102+"After several invocations of :meth:`__call__`, when reaching the end\n"
103+"of the opened stream, `read` might become less than `hop_size`:\n"
104+"\n"
105+">>> samples, read = src()\n"
106+">>> samples.shape, read\n"
107+"((512,), 354)\n"
108+"\n"
109+"The end of the vector `samples` is filled with zeros.\n"
110+"\n"
111+"After the end of the stream, `read` will be `0` since no more\n"
112+"samples are available:\n"
113+"\n"
114+">>> samples, read = src()\n"
115+">>> samples.shape, read\n"
116+"((512,), 0)\n"
117+"\n"
118+"**Note**: when the source has more than one channels, they\n"
119+"are be down-mixed to mono when invoking :meth:`__call__`.\n"
120+"To read from each individual channel, see :meth:`__next__`.\n"
121+"\n"
122+".. rubric:: ``for`` statements\n"
123+"\n"
124+"The `source` objects are **iterables**. This allows using them\n"
125+"directly in a ``for`` loop, which calls :meth:`__next__` until\n"
126+"the end of the stream is reached:\n"
127+"\n"
128+">>> src = aubio.source('stereo.wav')\n"
129+">>> for frames in src:\n"
130+">>> print (frames.shape)\n"
131+"...\n"
132+"(2, 512)\n"
133+"(2, 512)\n"
134+"(2, 230)\n"
135+"\n"
136+"**Note**: When `next(self)` is called on a source with multiple\n"
137+"channels, an array of shape `(channels, read)` is returned,\n"
138+"unlike with :meth:`__call__` which always returns the down-mixed\n"
139+"channels.\n"
140+"\n"
141+"If the file is opened with a single channel, `next(self)` returns\n"
142+"an array of shape `(read,)`:\n"
143+"\n"
144+">>> src = aubio.source('stereo.wav', channels=1)\n"
145+">>> next(src).shape\n"
146+"(512,)\n"
147+"\n"
148+".. rubric:: ``with`` statements\n"
149+"\n"
150+"The `source` objects are **context managers**, which allows using\n"
151+"them in ``with`` statements:\n"
152+"\n"
153+">>> with aubio.source('audiotrack.wav') as source:\n"
154+"... n_frames=0\n"
155+"... for samples in source:\n"
156+"... n_frames += len(samples)\n"
157+"... print('read', n_frames, 'samples in', samples.shape[0], 'channels',\n"
158+"... 'from file \"%%s\"' %% source.uri)\n"
159+"...\n"
160+"read 239334 samples in 2 channels from file \"audiotrack.wav\"\n"
161+"\n"
162+"The file will be closed before exiting the statement.\n"
163+"\n"
164+"See also the methods implementing the context manager,\n"
165+":meth:`__enter__` and :meth:`__exit__`.\n"
166+"\n"
167+".. rubric:: Seeking and closing\n"
168+"\n"
169+"At any time, :meth:`seek` can be used to move to any position in\n"
170+"the file. For instance, to rewind to the start of the stream:\n"
171+"\n"
172+">>> src.seek(0)\n"
173+"\n"
174+"The opened file will be automatically closed when the object falls\n"
175+"out of scope and is scheduled for garbage collection.\n"
176+"\n"
177+"In some cases, it is useful to manually :meth:`close` a given source,\n"
178+"for instance to limit the number of simultaneously opened files:\n"
179+"\n"
180+">>> src.close()\n"
181+"\n"
182+".. rubric:: Input formats\n"
183+"\n"
184+"Depending on how aubio was compiled, :class:`source` may or may not\n"
185+"open certain **files format**. Below are some examples that assume\n"
186+"support for compressed files and remote urls was compiled in:\n"
187+"\n"
188+"- open a local file using its original sampling rate and channels,\n"
189+" and with the default hop size:\n"
190+"\n"
191+">>> s = aubio.source('sample.wav')\n"
192+">>> s.uri, s.samplerate, s.channels, s.hop_size\n"
193+"('sample.wav', 44100, 2, 512)\n"
194+"\n"
195+"- open a local compressed audio file, resampling to 32000Hz if needed:\n"
196+"\n"
197+">>> s = aubio.source('song.mp3', samplerate=32000)\n"
198+">>> s.uri, s.samplerate, s.channels, s.hop_size\n"
199+"('song.mp3', 32000, 2, 512)\n"
200+"\n"
201+"- open a local video file, down-mixing and resampling it to 16kHz:\n"
202+"\n"
203+">>> s = aubio.source('movie.mp4', samplerate=16000, channels=1)\n"
204+">>> s.uri, s.samplerate, s.channels, s.hop_size\n"
205+"('movie.mp4', 16000, 1, 512)\n"
206+"\n"
207+"- open a remote resource, with hop_size = 1024:\n"
208+"\n"
209+">>> s = aubio.source('https://aubio.org/drum.ogg', hop_size=1024)\n"
210+">>> s.uri, s.samplerate, s.channels, s.hop_size\n"
211+"('https://aubio.org/drum.ogg', 48000, 2, 1024)\n"
212+"\n"
213+"See Also\n"
214+"--------\n"
215+"sink: write audio samples to a file.\n"
216+"";
51217
52218 static char Py_source_get_samplerate_doc[] = ""
53−"x.get_samplerate() -> source samplerate\n"
219+"get_samplerate()\n"
220+"\n"
221+"Get sampling rate of source.\n"
54222 "\n"
55−"Get samplerate of source.";
223+"Returns\n"
224+"-------\n"
225+"int\n"
226+" Sampling rate, in Hz.\n"
227+"";
56228
57229 static char Py_source_get_channels_doc[] = ""
58−"x.get_channels() -> number of channels\n"
230+"get_channels()\n"
59231 "\n"
60−"Get number of channels in source.";
232+"Get number of channels in source.\n"
233+"\n"
234+"Returns\n"
235+"-------\n"
236+"int\n"
237+" Number of channels.\n"
238+"";
61239
62240 static char Py_source_do_doc[] = ""
63−"vec, read = x.do() <==> vec, read = x()\n"
241+"source.do()\n"
242+"\n"
243+"Read vector of audio samples.\n"
244+"\n"
245+"If the audio stream in the source has more than one channel,\n"
246+"the channels will be down-mixed.\n"
247+"\n"
248+"Returns\n"
249+"-------\n"
250+"samples : numpy.ndarray\n"
251+" `fvec` of size `hop_size` containing the new samples.\n"
252+"read : int\n"
253+" Number of samples read from the source, equals to `hop_size`\n"
254+" before the end-of-file is reached, less when it is reached,\n"
255+" and `0` after.\n"
64256 "\n"
65−"Read monophonic vector from source.";
257+"See Also\n"
258+"--------\n"
259+"do_multi\n"
260+"\n"
261+"Examples\n"
262+"--------\n"
263+">>> src = aubio.source('sample.wav', hop_size=1024)\n"
264+">>> src.do()\n"
265+"(array([-0.00123001, -0.00036685, 0.00097106, ..., -0.2031033 ,\n"
266+" -0.2025854 , -0.20221856], dtype=" AUBIO_NPY_SMPL_STR "), 1024)\n"
267+"";
66268
67269 static char Py_source_do_multi_doc[] = ""
68−"mat, read = x.do_multi()\n"
270+"do_multi()\n"
271+"\n"
272+"Read multiple channels of audio samples.\n"
273+"\n"
274+"If the source was opened with the same number of channels\n"
275+"found in the stream, each channel will be read individually.\n"
276+"\n"
277+"If the source was opened with less channels than the number\n"
278+"of channels in the stream, only the first channels will be read.\n"
279+"\n"
280+"If the source was opened with more channels than the number\n"
281+"of channel in the original stream, the first channels will\n"
282+"be duplicated on the additional output channel.\n"
69283 "\n"
70−"Read polyphonic vector from source.";
284+"Returns\n"
285+"-------\n"
286+"samples : numpy.ndarray\n"
287+" NumPy array of shape `(hop_size, channels)` containing the new\n"
288+" audio samples.\n"
289+"read : int\n"
290+" Number of samples read from the source, equals to `hop_size`\n"
291+" before the end-of-file is reached, less when it is reached,\n"
292+" and `0` after.\n"
293+"\n"
294+"See Also\n"
295+"--------\n"
296+"do\n"
297+"\n"
298+"Examples\n"
299+"--------\n"
300+">>> src = aubio.source('sample.wav')\n"
301+">>> src.do_multi()\n"
302+"(array([[ 0.00668335, 0.0067749 , 0.00714111, ..., -0.05737305,\n"
303+" -0.05856323, -0.06018066],\n"
304+" [-0.00842285, -0.0072937 , -0.00576782, ..., -0.09405518,\n"
305+" -0.09558105, -0.09725952]], dtype=" AUBIO_NPY_SMPL_STR "), 512)\n"
306+"";
71307
72308 static char Py_source_close_doc[] = ""
73−"x.close()\n"
309+"close()\n"
74310 "\n"
75−"Close this source now.";
311+"Close this source now.\n"
312+"\n"
313+".. note:: Closing twice a source will **not** raise any exception.\n"
314+"";
76315
77316 static char Py_source_seek_doc[] = ""
78−"x.seek(position)\n"
317+"seek(position)\n"
318+"\n"
319+"Seek to position in file.\n"
79320 "\n"
80−"Seek to resampled frame position.";
321+"If the source was not opened with its original sampling-rate,\n"
322+"`position` corresponds to the position in the re-sampled file.\n"
323+"\n"
324+"Parameters\n"
325+"----------\n"
326+"position : str\n"
327+" position to seek to, in samples\n"
328+"";
81329
82330 static PyObject *
83331 Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
@@ -100,9 +348,10 @@ Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) · 16 unmodified lines
100348 return NULL;
101349 }
102350
103− self->uri = "none";
351+ self->uri = NULL;
104352 if (uri != NULL) {
105− self->uri = uri;
353+ self->uri = (char_t *)malloc(sizeof(char_t) * (strnlen(uri, PATH_MAX) + 1));
354+ strncpy(self->uri, uri, strnlen(uri, PATH_MAX) + 1);
106355 }
107356
108357 self->samplerate = 0;
@@ -163,6 +412,9 @@ Py_source_del (Py_source *self, PyObject *unused) · 54 unmodified lines
163412 del_aubio_source(self->o);
164413 free(self->c_mread_to.data);
165414 }
415+ if (self->uri) {
416+ free(self->uri);
417+ }
166418 Py_XDECREF(self->read_to);
167419 Py_XDECREF(self->mread_to);
168420 Py_TYPE(self)->tp_free((PyObject *) self);
@@ -213,15 +465,29 @@ Py_source_do_multi(Py_source * self, PyObject * args) · 44 unmodified lines
213465
214466 static PyMemberDef Py_source_members[] = {
215467 {"uri", T_STRING, offsetof (Py_source, uri), READONLY,
216− "path at which the source was created"},
468+ "str (read-only): pathname or URL"},
217469 {"samplerate", T_INT, offsetof (Py_source, samplerate), READONLY,
218− "samplerate at which the source is viewed"},
470+ "int (read-only): sampling rate"},
219471 {"channels", T_INT, offsetof (Py_source, channels), READONLY,
220− "number of channels found in the source"},
472+ "int (read-only): number of channels"},
221473 {"hop_size", T_INT, offsetof (Py_source, hop_size), READONLY,
222− "number of consecutive frames that will be read at each do or do_multi call"},
474+ "int (read-only): number of samples read per iteration"},
223475 {"duration", T_INT, offsetof (Py_source, duration), READONLY,
224− "total number of frames in the source (estimated)"},
476+ "int (read-only): total number of frames in the source\n"
477+ "\n"
478+ "Can be estimated, for instance if the opened stream is\n"
479+ "a compressed media or a remote resource.\n"
480+ "\n"
481+ "Example\n"
482+ "-------\n"
483+ ">>> n = 0\n"
484+ ">>> src = aubio.source('track1.mp3')\n"
485+ ">>> for samples in src:\n"
486+ "... n += samples.shape[-1]\n"
487+ "...\n"
488+ ">>> n, src.duration\n"
489+ "(9638784, 9616561)\n"
490+ ""},
225491 { NULL } // sentinel
226492 };
227493
@@ -242,7 +508,7 @@ Pyaubio_source_get_channels (Py_source *self, PyObject *unused) · 14 unmodified lines
242508 static PyObject *
243509 Pyaubio_source_close (Py_source *self, PyObject *unused)
244510 {
245− aubio_source_close (self->o);
511+ if (aubio_source_close(self->o) != 0) return NULL;
246512 Py_RETURN_NONE;
247513 }
248514
@@ -272,6 +538,65 @@ Pyaubio_source_seek (Py_source *self, PyObject *args) · 23 unmodified lines
272538 Py_RETURN_NONE;
273539 }
274540
541+static char Pyaubio_source_enter_doc[] = "";
542+static PyObject* Pyaubio_source_enter(Py_source *self, PyObject *unused) {
543+ Py_INCREF(self);
544+ return (PyObject*)self;
545+}
546+
547+static char Pyaubio_source_exit_doc[] = "";
548+static PyObject* Pyaubio_source_exit(Py_source *self, PyObject *unused) {
549+ return Pyaubio_source_close(self, unused);
550+}
551+
552+static PyObject* Pyaubio_source_iter(PyObject *self) {
553+ Py_INCREF(self);
554+ return (PyObject*)self;
555+}
556+
557+static PyObject* Pyaubio_source_iter_next(Py_source *self) {
558+ PyObject *done, *size;
559+ if (self->channels == 1) {
560+ done = Py_source_do(self, NULL);
561+ } else {
562+ done = Py_source_do_multi(self, NULL);
563+ }
564+ if (!PyTuple_Check(done)) {
565+ PyErr_Format(PyExc_ValueError,
566+ "error when reading source: not opened?");
567+ return NULL;
568+ }
569+ size = PyTuple_GetItem(done, 1);
570+ if (size != NULL && PyLong_Check(size)) {
571+ if (PyLong_AsLong(size) == (long)self->hop_size) {
572+ PyObject *vec = PyTuple_GetItem(done, 0);
573+ return vec;
574+ } else if (PyLong_AsLong(size) > 0) {
575+ // short read, return a shorter array
576+ PyArrayObject *shortread = (PyArrayObject*)PyTuple_GetItem(done, 0);
577+ PyArray_Dims newdims;
578+ PyObject *reshaped;
579+ newdims.len = PyArray_NDIM(shortread);
580+ newdims.ptr = PyArray_DIMS(shortread);
581+ // mono or multiple channels?
582+ if (newdims.len == 1) {
583+ newdims.ptr[0] = PyLong_AsLong(size);
584+ } else {
585+ newdims.ptr[1] = PyLong_AsLong(size);
586+ }
587+ reshaped = PyArray_Newshape(shortread, &newdims, NPY_CORDER);
588+ Py_DECREF(shortread);
589+ return reshaped;
590+ } else {
591+ PyErr_SetNone(PyExc_StopIteration);
592+ return NULL;
593+ }
594+ } else {
595+ PyErr_SetNone(PyExc_StopIteration);
596+ return NULL;
597+ }
598+}
599+
275600 static PyMethodDef Py_source_methods[] = {
276601 {"get_samplerate", (PyCFunction) Pyaubio_source_get_samplerate,
277602 METH_NOARGS, Py_source_get_samplerate_doc},
@@ -285,6 +610,10 @@ static PyMethodDef Py_source_methods[] = { · 7 unmodified lines
285610 METH_NOARGS, Py_source_close_doc},
286611 {"seek", (PyCFunction) Pyaubio_source_seek,
287612 METH_VARARGS, Py_source_seek_doc},
613+ {"__enter__", (PyCFunction)Pyaubio_source_enter, METH_NOARGS,
614+ Pyaubio_source_enter_doc},
615+ {"__exit__", (PyCFunction)Pyaubio_source_exit, METH_VARARGS,
616+ Pyaubio_source_exit_doc},
288617 {NULL} /* sentinel */
289618 };
290619
@@ -314,8 +643,8 @@ PyTypeObject Py_sourceType = { · 23 unmodified lines
314643 0,
315644 0,
316645 0,
317− 0,
318− 0,
646+ Pyaubio_source_iter,
647+ (unaryfunc)Pyaubio_source_iter_next,
319648 Py_source_methods,
320649 Py_source_members,
321650 0,
python/ext/ufuncs.c+44−3
@@ -58,7 +58,22 @@ static char Py_aubio_unary_types[] = { · 57 unmodified lines
5858 //NPY_OBJECT, NPY_OBJECT,
5959 };
6060
61−static char Py_unwrap2pi_doc[] = "map angle to unit circle [-pi, pi[";
61+// Note: these docstrings should *not* include the function signatures
62+
63+static char Py_unwrap2pi_doc[] = ""
64+"\n"
65+"Map angle to unit circle :math:`[-\\pi, \\pi[`.\n"
66+"\n"
67+"Parameters\n"
68+"----------\n"
69+"x : numpy.ndarray\n"
70+" input array\n"
71+"\n"
72+"Returns\n"
73+"-------\n"
74+"numpy.ndarray\n"
75+" values clamped to the unit circle :math:`[-\\pi, \\pi[`\n"
76+"";
6277
6378 static void* Py_unwrap2pi_data[] = {
6479 (void *)aubio_unwrap2pi,
@@ -67,14 +82,40 @@ static void* Py_unwrap2pi_data[] = { · 2 unmodified lines
6782 //(void *)unwrap2pio,
6883 };
6984
70−static char Py_freqtomidi_doc[] = "convert frequency to midi";
85+static char Py_freqtomidi_doc[] = ""
86+"\n"
87+"Convert frequency `[0; 23000[` to midi `[0; 128[`.\n"
88+"\n"
89+"Parameters\n"
90+"----------\n"
91+"x : numpy.ndarray\n"
92+" Array of frequencies, in Hz.\n"
93+"\n"
94+"Returns\n"
95+"-------\n"
96+"numpy.ndarray\n"
97+" Converted frequencies, in midi note.\n"
98+"";
7199
72100 static void* Py_freqtomidi_data[] = {
73101 (void *)aubio_freqtomidi,
74102 (void *)aubio_freqtomidi,
75103 };
76104
77−static char Py_miditofreq_doc[] = "convert midi to frequency";
105+static char Py_miditofreq_doc[] = ""
106+"\n"
107+"Convert midi `[0; 128[` to frequency `[0, 23000]`.\n"
108+"\n"
109+"Parameters\n"
110+"----------\n"
111+"x : numpy.ndarray\n"
112+" Array of frequencies, in midi note.\n"
113+"\n"
114+"Returns\n"
115+"-------\n"
116+"numpy.ndarray\n"
117+" Converted frequencies, in Hz\n"
118+"";
78119
79120 static void* Py_miditofreq_data[] = {
80121 (void *)aubio_miditofreq,
python/lib/__init__.py+0−0

Empty file deleted.

python/lib/aubio/__init__.py+72−5
@@ -1,18 +1,85 @@
11 #! /usr/bin/env python
2+# -*- coding: utf8 -*-
3+
4+"""
5+aubio
6+=====
7+
8+Provides a number of classes and functions for music and audio signal
9+analysis.
10+
11+How to use the documentation
12+----------------------------
13+
14+Documentation of the python module is available as docstrings provided
15+within the code, and a reference guide available online from `the
16+aubio homepage <https://aubio.org/documentation>`_.
17+
18+The docstrings examples are written assuming `aubio` and `numpy` have been
19+imported with:
20+
21+>>> import aubio
22+>>> import numpy as np
23+"""
224
325 import numpy
4−from ._aubio import *
26+from ._aubio import __version__ as version
527 from ._aubio import float_type
28+from ._aubio import *
629 from .midiconv import *
730 from .slicing import *
831
32+
933 class fvec(numpy.ndarray):
10− """a numpy vector holding audio samples"""
34+ """fvec(input_arg=1024)
35+ A vector holding float samples.
36+
37+ If `input_arg` is an `int`, a 1-dimensional vector of length `input_arg`
38+ will be created and filled with zeros. Otherwise, if `input_arg` is an
39+ `array_like` object, it will be converted to a 1-dimensional vector of
40+ type :data:`float_type`.
41+
42+ Parameters
43+ ----------
44+ input_arg : `int` or `array_like`
45+ Can be a positive integer, or any object that can be converted to
46+ a numpy array with :func:`numpy.array`.
47+
48+ Examples
49+ --------
50+ >>> aubio.fvec(10)
51+ array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)
52+ >>> aubio.fvec([0,1,2])
53+ array([0., 1., 2.], dtype=float32)
54+ >>> a = np.arange(10); type(a), type(aubio.fvec(a))
55+ (<class 'numpy.ndarray'>, <class 'numpy.ndarray'>)
56+ >>> a.dtype, aubio.fvec(a).dtype
57+ (dtype('int64'), dtype('float32'))
1158
12− def __new__(cls, input_arg=1024, **kwargs):
59+ Notes
60+ -----
61+
62+ In the Python world, `fvec` is simply a subclass of
63+ :class:`numpy.ndarray`. In practice, any 1-dimensional `numpy.ndarray` of
64+ `dtype` :data:`float_type` may be passed to methods accepting
65+ `fvec` as parameter. For instance, `sink()` or `pvoc()`.
66+
67+ See Also
68+ --------
69+ cvec : a container holding spectral data
70+ numpy.ndarray : parent class of :class:`fvec`
71+ numpy.zeros : create a numpy array filled with zeros
72+ numpy.array : create a numpy array from an existing object
73+ """
74+ def __new__(cls, input_arg=1024):
1375 if isinstance(input_arg, int):
1476 if input_arg == 0:
1577 raise ValueError("vector length of 1 or more expected")
16− return numpy.zeros(input_arg, dtype=float_type, **kwargs)
78+ return numpy.zeros(input_arg, dtype=float_type, order='C')
1779 else:
18− return numpy.array(input_arg, dtype=float_type, **kwargs)
80+ np_input = numpy.array(input_arg, dtype=float_type, order='C')
81+ if len(np_input.shape) != 1:
82+ raise ValueError("input_arg should have shape (n,)")
83+ if np_input.shape[0] == 0:
84+ raise ValueError("vector length of 1 or more expected")
85+ return np_input
python/lib/aubio/cmd.py+623−0
@@ -0,0 +1,623 @@
1+#! /usr/bin/env python
2+# -*- coding: utf-8 -*-
3+
4+"""aubio command line tool
5+
6+This file was written by Paul Brossier <piem@aubio.org> and is released under
7+the GNU/GPL v3.
8+
9+Note: this script is mostly about parsing command line arguments. For more
10+readable code examples, check out the `python/demos` folder."""
11+
12+import sys
13+import argparse
14+import warnings
15+import aubio
16+
17+def aubio_parser():
18+ epilog = 'use "%(prog)s <command> --help" for more info about each command'
19+ parser = argparse.ArgumentParser(epilog=epilog)
20+ parser.add_argument('-V', '--version', help="show version",
21+ action="store_true", dest="show_version")
22+
23+ subparsers = parser.add_subparsers(title='commands', dest='command',
24+ parser_class= AubioArgumentParser,
25+ metavar="")
26+
27+ parser_add_subcommand_help(subparsers)
28+
29+ parser_add_subcommand_onset(subparsers)
30+ parser_add_subcommand_pitch(subparsers)
31+ parser_add_subcommand_beat(subparsers)
32+ parser_add_subcommand_tempo(subparsers)
33+ parser_add_subcommand_notes(subparsers)
34+ parser_add_subcommand_mfcc(subparsers)
35+ parser_add_subcommand_melbands(subparsers)
36+ parser_add_subcommand_quiet(subparsers)
37+ parser_add_subcommand_cut(subparsers)
38+
39+ return parser
40+
41+def parser_add_subcommand_help(subparsers):
42+ # global help subcommand
43+ subparsers.add_parser('help',
44+ help='show help message',
45+ formatter_class = argparse.ArgumentDefaultsHelpFormatter)
46+
47+def parser_add_subcommand_onset(subparsers):
48+ # onset subcommand
49+ subparser = subparsers.add_parser('onset',
50+ help='estimate time of onsets (beginning of sound event)',
51+ formatter_class = argparse.ArgumentDefaultsHelpFormatter)
52+ subparser.add_input()
53+ subparser.add_buf_hop_size()
54+ helpstr = "onset novelty function"
55+ helpstr += " <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux>"
56+ subparser.add_method(helpstr=helpstr)
57+ subparser.add_threshold()
58+ subparser.add_silence()
59+ subparser.add_minioi()
60+ subparser.add_time_format()
61+ subparser.add_verbose_help()
62+ subparser.set_defaults(process=process_onset)
63+
64+def parser_add_subcommand_pitch(subparsers):
65+ # pitch subcommand
66+ subparser = subparsers.add_parser('pitch',
67+ help='estimate fundamental frequency (monophonic)')
68+ subparser.add_input()
69+ subparser.add_buf_hop_size(buf_size=2048)
70+ helpstr = "pitch detection method <default|yinfft|yin|mcomb|fcomb|schmitt>"
71+ subparser.add_method(helpstr=helpstr)
72+ subparser.add_threshold()
73+ subparser.add_pitch_unit()
74+ subparser.add_silence()
75+ subparser.add_time_format()
76+ subparser.add_verbose_help()
77+ subparser.set_defaults(process=process_pitch)
78+
79+def parser_add_subcommand_beat(subparsers):
80+ # beat subcommand
81+ subparser = subparsers.add_parser('beat',
82+ help='estimate location of beats')
83+ subparser.add_input()
84+ subparser.add_buf_hop_size(buf_size=1024, hop_size=512)
85+ subparser.add_time_format()
86+ subparser.add_verbose_help()
87+ subparser.set_defaults(process=process_beat)
88+
89+def parser_add_subcommand_tempo(subparsers):
90+ # tempo subcommand
91+ subparser = subparsers.add_parser('tempo',
92+ help='estimate overall tempo in bpm')
93+ subparser.add_input()
94+ subparser.add_buf_hop_size(buf_size=1024, hop_size=512)
95+ subparser.add_time_format()
96+ subparser.add_verbose_help()
97+ subparser.set_defaults(process=process_tempo)
98+
99+def parser_add_subcommand_notes(subparsers):
100+ # notes subcommand
101+ subparser = subparsers.add_parser('notes',
102+ help='estimate midi-like notes (monophonic)')
103+ subparser.add_input()
104+ subparser.add_buf_hop_size()
105+ subparser.add_silence()
106+ subparser.add_release_drop()
107+ subparser.add_time_format()
108+ subparser.add_verbose_help()
109+ subparser.set_defaults(process=process_notes)
110+
111+def parser_add_subcommand_mfcc(subparsers):
112+ # mfcc subcommand
113+ subparser = subparsers.add_parser('mfcc',
114+ help='extract Mel-Frequency Cepstrum Coefficients')
115+ subparser.add_input()
116+ subparser.add_buf_hop_size()
117+ subparser.add_time_format()
118+ subparser.add_verbose_help()
119+ subparser.set_defaults(process=process_mfcc)
120+
121+def parser_add_subcommand_melbands(subparsers):
122+ # melbands subcommand
123+ subparser = subparsers.add_parser('melbands',
124+ help='extract energies in Mel-frequency bands')
125+ subparser.add_input()
126+ subparser.add_buf_hop_size()
127+ subparser.add_time_format()
128+ subparser.add_verbose_help()
129+ subparser.set_defaults(process=process_melbands)
130+
131+def parser_add_subcommand_quiet(subparsers):
132+ # quiet subcommand
133+ subparser = subparsers.add_parser('quiet',
134+ help='extract timestamps of quiet and loud regions')
135+ subparser.add_input()
136+ subparser.add_hop_size()
137+ subparser.add_silence()
138+ subparser.add_time_format()
139+ subparser.add_verbose_help()
140+ subparser.set_defaults(process=process_quiet)
141+
142+def parser_add_subcommand_cut(subparsers):
143+ # cut subcommand
144+ subparser = subparsers.add_parser('cut',
145+ help='slice at timestamps')
146+ subparser.add_input()
147+ helpstr = "onset novelty function"
148+ helpstr += " <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux>"
149+ subparser.add_method(helpstr=helpstr)
150+ subparser.add_buf_hop_size()
151+ subparser.add_silence()
152+ subparser.add_threshold(default=0.3)
153+ subparser.add_minioi()
154+ subparser.add_slicer_options()
155+ subparser.add_time_format()
156+ subparser.add_verbose_help()
157+ subparser.set_defaults(process=process_cut)
158+
159+class AubioArgumentParser(argparse.ArgumentParser):
160+
161+ def add_input(self):
162+ self.add_argument("source_uri", default=None, nargs='?',
163+ help="input sound file to analyse", metavar = "<source_uri>")
164+ self.add_argument("-i", "--input", dest = "source_uri2",
165+ help="input sound file to analyse", metavar = "<source_uri>")
166+ self.add_argument("-r", "--samplerate",
167+ metavar = "<freq>", type=int,
168+ action="store", dest="samplerate", default=0,
169+ help="samplerate at which the file should be represented")
170+
171+ def add_verbose_help(self):
172+ self.add_argument("-v", "--verbose",
173+ action="count", dest="verbose", default=1,
174+ help="make lots of noise [default]")
175+ self.add_argument("-q", "--quiet",
176+ action="store_const", dest="verbose", const=0,
177+ help="be quiet")
178+
179+ def add_buf_hop_size(self, buf_size=512, hop_size=256):
180+ self.add_buf_size(buf_size=buf_size)
181+ self.add_hop_size(hop_size=hop_size)
182+
183+ def add_buf_size(self, buf_size=512):
184+ self.add_argument("-B", "--bufsize",
185+ action="store", dest="buf_size", default=buf_size,
186+ metavar = "<size>", type=int,
187+ help="buffer size [default=%d]" % buf_size)
188+
189+ def add_hop_size(self, hop_size=256):
190+ self.add_argument("-H", "--hopsize",
191+ metavar = "<size>", type=int,
192+ action="store", dest="hop_size", default=hop_size,
193+ help="overlap size [default=%d]" % hop_size)
194+
195+ def add_method(self, method='default', helpstr='method'):
196+ self.add_argument("-m", "--method",
197+ metavar = "<method>", type=str,
198+ action="store", dest="method", default=method,
199+ help="%s [default=%s]" % (helpstr, method))
200+
201+ def add_threshold(self, default=None):
202+ self.add_argument("-t", "--threshold",
203+ metavar = "<threshold>", type=float,
204+ action="store", dest="threshold", default=default,
205+ help="threshold [default=%s]" % default)
206+
207+ def add_silence(self):
208+ self.add_argument("-s", "--silence",
209+ metavar = "<value>", type=float,
210+ action="store", dest="silence", default=-70,
211+ help="silence threshold")
212+
213+ def add_release_drop(self):
214+ self.add_argument("-d", "--release-drop",
215+ metavar = "<value>", type=float,
216+ action="store", dest="release_drop", default=10,
217+ help="release drop threshold")
218+
219+ def add_minioi(self, default="12ms"):
220+ self.add_argument("-M", "--minioi",
221+ metavar = "<value>", type=str,
222+ action="store", dest="minioi", default=default,
223+ help="minimum Inter-Onset Interval [default=%s]" % default)
224+
225+ def add_pitch_unit(self, default="Hz"):
226+ help_str = "frequency unit, should be one of Hz, midi, bin, cent"
227+ help_str += " [default=%s]" % default
228+ self.add_argument("-u", "--pitch-unit",
229+ metavar = "<value>", type=str,
230+ action="store", dest="pitch_unit", default=default,
231+ help=help_str)
232+
233+ def add_time_format(self):
234+ helpstr = "select time values output format (samples, ms, seconds)"
235+ helpstr += " [default=seconds]"
236+ self.add_argument("-T", "--time-format",
237+ metavar='format',
238+ dest="time_format",
239+ default=None,
240+ help=helpstr)
241+
242+ def add_slicer_options(self):
243+ self.add_argument("-o", "--output", type = str,
244+ metavar = "<outputdir>",
245+ action="store", dest="output_directory", default=None,
246+ help="specify path where slices of the original file should"
247+ " be created")
248+ self.add_argument("--cut-until-nsamples", type = int,
249+ metavar = "<samples>",
250+ action = "store", dest = "cut_until_nsamples", default = None,
251+ help="how many extra samples should be added at the end of"
252+ " each slice")
253+ self.add_argument("--cut-every-nslices", type = int,
254+ metavar = "<samples>",
255+ action = "store", dest = "cut_every_nslices", default = None,
256+ help="how many slices should be groupped together at each cut")
257+ self.add_argument("--cut-until-nslices", type = int,
258+ metavar = "<slices>",
259+ action = "store", dest = "cut_until_nslices", default = None,
260+ help="how many extra slices should be added at the end of"
261+ " each slice")
262+ self.add_argument("--create-first",
263+ action = "store_true", dest = "create_first", default = False,
264+ help="always include first slice")
265+
266+# some utilities
267+
268+def samples2seconds(n_frames, samplerate):
269+ return "%f\t" % (n_frames / float(samplerate))
270+
271+def samples2milliseconds(n_frames, samplerate):
272+ return "%f\t" % (1000. * n_frames / float(samplerate))
273+
274+def samples2samples(n_frames, _samplerate):
275+ return "%d\t" % n_frames
276+
277+def timefunc(mode):
278+ if mode is None or mode == 'seconds' or mode == 's':
279+ return samples2seconds
280+ elif mode == 'ms' or mode == 'milliseconds':
281+ return samples2milliseconds
282+ elif mode == 'samples':
283+ return samples2samples
284+ else:
285+ raise ValueError("invalid time format '%s'" % mode)
286+
287+# definition of processing classes
288+
289+class default_process(object):
290+ def __init__(self, args):
291+ if 'time_format' in args:
292+ self.time2string = timefunc(args.time_format)
293+ if args.verbose > 2 and hasattr(self, 'options'):
294+ name = type(self).__name__.split('_')[1]
295+ optstr = ' '.join(['running', name, 'with options',
296+ repr(self.options), '\n'])
297+ sys.stderr.write(optstr)
298+ def flush(self, frames_read, samplerate):
299+ # optionally called at the end of process
300+ pass
301+
302+ def parse_options(self, args, valid_opts):
303+ # get any valid options found in a dictionnary of arguments
304+ options = {k: v for k, v in vars(args).items() if k in valid_opts}
305+ self.options = options
306+
307+ def remap_pvoc_options(self, options):
308+ # FIXME: we need to remap buf_size to win_s, hop_size to hop_s
309+ # adjust python/ext/py-phasevoc.c to understand buf_size/hop_size
310+ if 'buf_size' in options:
311+ options['win_s'] = options['buf_size']
312+ del options['buf_size']
313+ if 'hop_size' in options:
314+ options['hop_s'] = options['hop_size']
315+ del options['hop_size']
316+ self.options = options
317+
318+class process_onset(default_process):
319+ valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
320+ def __init__(self, args):
321+ self.parse_options(args, self.valid_opts)
322+ self.onset = aubio.onset(**self.options)
323+ if args.threshold is not None:
324+ self.onset.set_threshold(args.threshold)
325+ if args.minioi:
326+ if args.minioi.endswith('ms'):
327+ self.onset.set_minioi_ms(float(args.minioi[:-2]))
328+ elif args.minioi.endswith('s'):
329+ self.onset.set_minioi_s(float(args.minioi[:-1]))
330+ else:
331+ self.onset.set_minioi(int(args.minioi))
332+ if args.silence:
333+ self.onset.set_silence(args.silence)
334+ super(process_onset, self).__init__(args)
335+ def __call__(self, block):
336+ return self.onset(block)
337+ def repr_res(self, res, _frames_read, samplerate):
338+ if res[0] != 0:
339+ outstr = self.time2string(self.onset.get_last(), samplerate)
340+ sys.stdout.write(outstr + '\n')
341+
342+class process_pitch(default_process):
343+ valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
344+ def __init__(self, args):
345+ self.parse_options(args, self.valid_opts)
346+ self.pitch = aubio.pitch(**self.options)
347+ if args.pitch_unit is not None:
348+ self.pitch.set_unit(args.pitch_unit)
349+ if args.threshold is not None:
350+ self.pitch.set_tolerance(args.threshold)
351+ if args.silence is not None:
352+ self.pitch.set_silence(args.silence)
353+ super(process_pitch, self).__init__(args)
354+ def __call__(self, block):
355+ return self.pitch(block)
356+ def repr_res(self, res, frames_read, samplerate):
357+ fmt_out = self.time2string(frames_read, samplerate)
358+ sys.stdout.write(fmt_out + "%.6f\n" % res[0])
359+
360+class process_beat(default_process):
361+ valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
362+ def __init__(self, args):
363+ self.parse_options(args, self.valid_opts)
364+ self.tempo = aubio.tempo(**self.options)
365+ super(process_beat, self).__init__(args)
366+ def __call__(self, block):
367+ return self.tempo(block)
368+ def repr_res(self, res, _frames_read, samplerate):
369+ if res[0] != 0:
370+ outstr = self.time2string(self.tempo.get_last(), samplerate)
371+ sys.stdout.write(outstr + '\n')
372+
373+class process_tempo(process_beat):
374+ def __init__(self, args):
375+ super(process_tempo, self).__init__(args)
376+ self.beat_locations = []
377+ def repr_res(self, res, _frames_read, samplerate):
378+ if res[0] != 0:
379+ self.beat_locations.append(self.tempo.get_last_s())
380+ def flush(self, frames_read, samplerate):
381+ import numpy as np
382+ if len(self.beat_locations) < 2:
383+ outstr = "unknown bpm"
384+ else:
385+ bpms = 60. / np.diff(self.beat_locations)
386+ median_bpm = np.mean(bpms)
387+ if len(self.beat_locations) < 10:
388+ outstr = "%.2f bpm (uncertain)" % median_bpm
389+ else:
390+ outstr = "%.2f bpm" % median_bpm
391+ sys.stdout.write(outstr + '\n')
392+
393+class process_notes(default_process):
394+ valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
395+ def __init__(self, args):
396+ self.parse_options(args, self.valid_opts)
397+ self.notes = aubio.notes(**self.options)
398+ if args.silence is not None:
399+ self.notes.set_silence(args.silence)
400+ if args.release_drop is not None:
401+ self.notes.set_release_drop(args.release_drop)
402+ super(process_notes, self).__init__(args)
403+ def __call__(self, block):
404+ return self.notes(block)
405+ def repr_res(self, res, frames_read, samplerate):
406+ if res[2] != 0: # note off
407+ fmt_out = self.time2string(frames_read, samplerate)
408+ sys.stdout.write(fmt_out + '\n')
409+ if res[0] != 0: # note on
410+ lastmidi = res[0]
411+ fmt_out = "%f\t" % lastmidi
412+ fmt_out += self.time2string(frames_read, samplerate)
413+ sys.stdout.write(fmt_out) # + '\t')
414+ def flush(self, frames_read, samplerate):
415+ eof = self.time2string(frames_read, samplerate)
416+ sys.stdout.write(eof + '\n')
417+
418+class process_mfcc(default_process):
419+ def __init__(self, args):
420+ valid_opts1 = ['hop_size', 'buf_size']
421+ self.parse_options(args, valid_opts1)
422+ self.remap_pvoc_options(self.options)
423+ self.pv = aubio.pvoc(**self.options)
424+
425+ valid_opts2 = ['buf_size', 'n_filters', 'n_coeffs', 'samplerate']
426+ self.parse_options(args, valid_opts2)
427+ self.mfcc = aubio.mfcc(**self.options)
428+
429+ # remember all options
430+ self.parse_options(args, list(set(valid_opts1 + valid_opts2)))
431+
432+ super(process_mfcc, self).__init__(args)
433+
434+ def __call__(self, block):
435+ fftgrain = self.pv(block)
436+ return self.mfcc(fftgrain)
437+ def repr_res(self, res, frames_read, samplerate):
438+ fmt_out = self.time2string(frames_read, samplerate)
439+ fmt_out += ' '.join(["% 9.7f" % f for f in res.tolist()])
440+ sys.stdout.write(fmt_out + '\n')
441+
442+class process_melbands(default_process):
443+ def __init__(self, args):
444+ self.args = args
445+ valid_opts = ['hop_size', 'buf_size']
446+ self.parse_options(args, valid_opts)
447+ self.remap_pvoc_options(self.options)
448+ self.pv = aubio.pvoc(**self.options)
449+
450+ valid_opts = ['buf_size', 'n_filters']
451+ self.parse_options(args, valid_opts)
452+ self.remap_pvoc_options(self.options)
453+ self.filterbank = aubio.filterbank(**self.options)
454+ self.filterbank.set_mel_coeffs_slaney(args.samplerate)
455+
456+ super(process_melbands, self).__init__(args)
457+ def __call__(self, block):
458+ fftgrain = self.pv(block)
459+ return self.filterbank(fftgrain)
460+ def repr_res(self, res, frames_read, samplerate):
461+ fmt_out = self.time2string(frames_read, samplerate)
462+ fmt_out += ' '.join(["% 9.7f" % f for f in res.tolist()])
463+ sys.stdout.write(fmt_out + '\n')
464+
465+class process_quiet(default_process):
466+ def __init__(self, args):
467+ self.args = args
468+ valid_opts = ['hop_size', 'silence']
469+ self.parse_options(args, valid_opts)
470+ self.wassilence = 1
471+
472+ if args.silence is not None:
473+ self.silence = args.silence
474+ super(process_quiet, self).__init__(args)
475+
476+ def __call__(self, block):
477+ if aubio.silence_detection(block, self.silence) == 1:
478+ if self.wassilence != 1:
479+ self.wassilence = 1
480+ return 2 # newly found silence
481+ return 1 # silence again
482+ else:
483+ if self.wassilence != 0:
484+ self.wassilence = 0
485+ return -1 # newly found noise
486+ return 0 # noise again
487+
488+ def repr_res(self, res, frames_read, samplerate):
489+ fmt_out = None
490+ if res == -1:
491+ fmt_out = "NOISY: "
492+ if res == 2:
493+ fmt_out = "QUIET: "
494+ if fmt_out is not None:
495+ fmt_out += self.time2string(frames_read, samplerate)
496+ sys.stdout.write(fmt_out + '\n')
497+
498+class process_cut(process_onset):
499+ def __init__(self, args):
500+ super(process_cut, self).__init__(args)
501+ self.slices = []
502+ self.options = args
503+
504+ def __call__(self, block):
505+ ret = super(process_cut, self).__call__(block)
506+ if ret:
507+ self.slices.append(self.onset.get_last())
508+ return ret
509+
510+ def flush(self, frames_read, samplerate):
511+ _cut_slice(self.options, self.slices)
512+ duration = float(frames_read) / float(samplerate)
513+ base_info = '%(source_file)s' % \
514+ {'source_file': self.options.source_uri}
515+ base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \
516+ {'duration': duration, 'samplerate': samplerate}
517+ info = "created %d slices from " % len(self.slices)
518+ info += base_info
519+ sys.stderr.write(info)
520+
521+def _cut_slice(options, timestamps):
522+ # cutting pass
523+ nstamps = len(timestamps)
524+ if nstamps > 0:
525+ # generate output files
526+ timestamps_end = None
527+ if options.cut_every_nslices:
528+ timestamps = timestamps[::options.cut_every_nslices]
529+ nstamps = len(timestamps)
530+ if options.cut_until_nslices and options.cut_until_nsamples:
531+ msg = "using cut_until_nslices, but cut_until_nsamples is set"
532+ warnings.warn(msg)
533+ if options.cut_until_nsamples:
534+ lag = options.cut_until_nsamples
535+ timestamps_end = [t + lag for t in timestamps[1:]]
536+ timestamps_end += [1e120]
537+ if options.cut_until_nslices:
538+ slice_lag = options.cut_until_nslices
539+ timestamps_end = [t for t in timestamps[1 + slice_lag:]]
540+ timestamps_end += [1e120] * (options.cut_until_nslices + 1)
541+ aubio.slice_source_at_stamps(options.source_uri,
542+ timestamps, timestamps_end = timestamps_end,
543+ output_dir = options.output_directory,
544+ samplerate = options.samplerate,
545+ create_first = options.create_first)
546+
547+def main():
548+ parser = aubio_parser()
549+ if sys.version_info[0] != 3:
550+ # on py2, create a dummy ArgumentParser to workaround the
551+ # optional subcommand issue. See https://bugs.python.org/issue9253
552+ # This ensures that:
553+ # - version string is shown when only '-V' is passed
554+ # - help is printed if '-V' is passed with any other argument
555+ # - any other argument get forwarded to the real parser
556+ parser_root = argparse.ArgumentParser(add_help=False)
557+ parser_root.add_argument('-V', '--version', help="show version",
558+ action="store_true", dest="show_version")
559+ args, extras = parser_root.parse_known_args()
560+ if not args.show_version: # no -V, forward to parser
561+ args = parser.parse_args(extras, namespace=args)
562+ elif len(extras) != 0: # -V with other arguments, print help
563+ parser.print_help()
564+ sys.exit(1)
565+ else: # in py3, we can simply use parser directly
566+ args = parser.parse_args()
567+ if 'show_version' in args and args.show_version:
568+ sys.stdout.write('aubio version ' + aubio.version + '\n')
569+ sys.exit(0)
570+ elif 'verbose' in args and args.verbose > 3:
571+ sys.stderr.write('aubio version ' + aubio.version + '\n')
572+ if 'command' not in args or args.command is None \
573+ or args.command in ['help']:
574+ # no command given, print help and return 1
575+ parser.print_help()
576+ if args.command and args.command in ['help']:
577+ sys.exit(0)
578+ else:
579+ sys.exit(1)
580+ elif not args.source_uri and not args.source_uri2:
581+ sys.stderr.write("Error: a source is required\n")
582+ parser.print_help()
583+ sys.exit(1)
584+ elif args.source_uri2 is not None:
585+ args.source_uri = args.source_uri2
586+ try:
587+ # open source_uri
588+ with aubio.source(args.source_uri, hop_size=args.hop_size,
589+ samplerate=args.samplerate) as a_source:
590+ # always update args.samplerate to native samplerate, in case
591+ # source was opened with args.samplerate=0
592+ args.samplerate = a_source.samplerate
593+ # create the processor for this subcommand
594+ processor = args.process(args)
595+ frames_read = 0
596+ while True:
597+ # read new block from source
598+ block, read = a_source()
599+ # execute processor on this block
600+ res = processor(block)
601+ # print results for this block
602+ if args.verbose > 0:
603+ processor.repr_res(res, frames_read, a_source.samplerate)
604+ # increment total number of frames read
605+ frames_read += read
606+ # exit loop at end of file
607+ if read < a_source.hop_size:
608+ break
609+ # flush the processor if needed
610+ processor.flush(frames_read, a_source.samplerate)
611+ if args.verbose > 1:
612+ fmt_string = "read {:.2f}s"
613+ fmt_string += " ({:d} samples in {:d} blocks of {:d})"
614+ fmt_string += " from {:s} at {:d}Hz\n"
615+ sys.stderr.write(fmt_string.format(
616+ frames_read / float(a_source.samplerate),
617+ frames_read,
618+ frames_read // a_source.hop_size + 1,
619+ a_source.hop_size,
620+ a_source.uri,
621+ a_source.samplerate))
622+ except KeyboardInterrupt:
623+ sys.exit(1)
python/lib/aubio/cut.py+163−0
@@ -0,0 +1,163 @@
1+#! /usr/bin/env python
2+
3+""" this file was written by Paul Brossier
4+ it is released under the GNU/GPL license.
5+"""
6+
7+import sys
8+from aubio.cmd import AubioArgumentParser, _cut_slice
9+
10+def aubio_cut_parser():
11+ parser = AubioArgumentParser()
12+ parser.add_input()
13+ parser.add_argument("-O", "--onset-method",
14+ action="store", dest="onset_method", default='default',
15+ metavar = "<onset_method>",
16+ help="onset detection method [default=default] \
17+ complexdomain|hfc|phase|specdiff|energy|kl|mkl")
18+ # cutting methods
19+ parser.add_argument("-b", "--beat",
20+ action="store_true", dest="beat", default=False,
21+ help="slice at beat locations")
22+ """
23+ parser.add_argument("-S", "--silencecut",
24+ action="store_true", dest="silencecut", default=False,
25+ help="use silence locations")
26+ parser.add_argument("-s", "--silence",
27+ metavar = "<value>",
28+ action="store", dest="silence", default=-70,
29+ help="silence threshold [default=-70]")
30+ """
31+ # algorithm parameters
32+ parser.add_buf_hop_size()
33+ parser.add_argument("-t", "--threshold", "--onset-threshold",
34+ metavar = "<threshold>", type=float,
35+ action="store", dest="threshold", default=0.3,
36+ help="onset peak picking threshold [default=0.3]")
37+ parser.add_argument("-c", "--cut",
38+ action="store_true", dest="cut", default=False,
39+ help="cut input sound file at detected labels")
40+ parser.add_minioi()
41+
42+ """
43+ parser.add_argument("-D", "--delay",
44+ action = "store", dest = "delay", type = float,
45+ metavar = "<seconds>", default=0,
46+ help="number of seconds to take back [default=system]\
47+ default system delay is 3*hopsize/samplerate")
48+ parser.add_argument("-C", "--dcthreshold",
49+ metavar = "<value>",
50+ action="store", dest="dcthreshold", default=1.,
51+ help="onset peak picking DC component [default=1.]")
52+ parser.add_argument("-L", "--localmin",
53+ action="store_true", dest="localmin", default=False,
54+ help="use local minima after peak detection")
55+ parser.add_argument("-d", "--derivate",
56+ action="store_true", dest="derivate", default=False,
57+ help="derivate onset detection function")
58+ parser.add_argument("-z", "--zerocross",
59+ metavar = "<value>",
60+ action="store", dest="zerothres", default=0.008,
61+ help="zero-crossing threshold for slicing [default=0.00008]")
62+ # plotting functions
63+ parser.add_argument("-p", "--plot",
64+ action="store_true", dest="plot", default=False,
65+ help="draw plot")
66+ parser.add_argument("-x", "--xsize",
67+ metavar = "<size>",
68+ action="store", dest="xsize", default=1.,
69+ type=float, help="define xsize for plot")
70+ parser.add_argument("-y", "--ysize",
71+ metavar = "<size>",
72+ action="store", dest="ysize", default=1.,
73+ type=float, help="define ysize for plot")
74+ parser.add_argument("-f", "--function",
75+ action="store_true", dest="func", default=False,
76+ help="print detection function")
77+ parser.add_argument("-n", "--no-onsets",
78+ action="store_true", dest="nplot", default=False,
79+ help="do not plot detected onsets")
80+ parser.add_argument("-O", "--outplot",
81+ metavar = "<output_image>",
82+ action="store", dest="outplot", default=None,
83+ help="save plot to output.{ps,png}")
84+ parser.add_argument("-F", "--spectrogram",
85+ action="store_true", dest="spectro", default=False,
86+ help="add spectrogram to the plot")
87+ """
88+ parser.add_slicer_options()
89+ parser.add_verbose_help()
90+ return parser
91+
92+
93+def _cut_analyze(options):
94+ hopsize = options.hop_size
95+ bufsize = options.buf_size
96+ samplerate = options.samplerate
97+ source_uri = options.source_uri
98+
99+ # analyze pass
100+ from aubio import onset, tempo, source
101+
102+ s = source(source_uri, samplerate, hopsize)
103+ if samplerate == 0:
104+ samplerate = s.samplerate
105+ options.samplerate = samplerate
106+
107+ if options.beat:
108+ o = tempo(options.onset_method, bufsize, hopsize,
109+ samplerate=samplerate)
110+ else:
111+ o = onset(options.onset_method, bufsize, hopsize,
112+ samplerate=samplerate)
113+ if options.minioi:
114+ if options.minioi.endswith('ms'):
115+ o.set_minioi_ms(int(options.minioi[:-2]))
116+ elif options.minioi.endswith('s'):
117+ o.set_minioi_s(int(options.minioi[:-1]))
118+ else:
119+ o.set_minioi(int(options.minioi))
120+ o.set_threshold(options.threshold)
121+
122+ timestamps = []
123+ total_frames = 0
124+ while True:
125+ samples, read = s()
126+ if o(samples):
127+ timestamps.append(o.get_last())
128+ if options.verbose:
129+ print("%.4f" % o.get_last_s())
130+ total_frames += read
131+ if read < hopsize:
132+ break
133+ del s
134+ return timestamps, total_frames
135+
136+def main():
137+ parser = aubio_cut_parser()
138+ options = parser.parse_args()
139+ if not options.source_uri and not options.source_uri2:
140+ sys.stderr.write("Error: no file name given\n")
141+ parser.print_help()
142+ sys.exit(1)
143+ elif options.source_uri2 is not None:
144+ options.source_uri = options.source_uri2
145+
146+ # analysis
147+ timestamps, total_frames = _cut_analyze(options)
148+
149+ # print some info
150+ duration = float(total_frames) / float(options.samplerate)
151+ base_info = '%(source_uri)s' % {'source_uri': options.source_uri}
152+ base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \
153+ {'duration': duration, 'samplerate': options.samplerate}
154+
155+ info = "found %d timestamps in " % len(timestamps)
156+ info += base_info
157+ sys.stderr.write(info)
158+
159+ if options.cut:
160+ _cut_slice(options, timestamps)
161+ info = "created %d slices from " % len(timestamps)
162+ info += base_info
163+ sys.stderr.write(info)
python/lib/aubio/midiconv.py+142−17
@@ -1,9 +1,11 @@
11 # -*- coding: utf-8 -*-
22 """ utilities to convert midi note number to and from note names """
33
4−__all__ = ['note2midi', 'midi2note', 'freq2note']
5−
64 import sys
5+from ._aubio import freqtomidi, miditofreq
6+
7+__all__ = ['note2midi', 'midi2note', 'freq2note', 'note2freq']
8+
79 py3 = sys.version_info[0] == 3
810 if py3:
911 str_instances = str
@@ -12,18 +14,65 @@ else: · 2 unmodified lines
1214 str_instances = (str, unicode)
1315 int_instances = (int, long)
1416
17+
1518 def note2midi(note):
16− " convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] "
17− _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
18− _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2,
19− 'b': -1, u'♭': -1, u'\ufffd': -2}
19+ """Convert note name to midi note number.
20+
21+ Input string `note` should be composed of one note root
22+ and one octave, with optionally one modifier in between.
23+
24+ List of valid components:
25+
26+ - note roots: `C`, `D`, `E`, `F`, `G`, `A`, `B`,
27+ - modifiers: `b`, `#`, as well as unicode characters
28+ `𝄫`, `♭`, `♮`, `♯` and `𝄪`,
29+ - octave numbers: `-1` -> `11`.
30+
31+ Parameters
32+ ----------
33+ note : str
34+ note name
35+
36+ Returns
37+ -------
38+ int
39+ corresponding midi note number
40+
41+ Examples
42+ --------
43+ >>> aubio.note2midi('C#4')
44+ 61
45+ >>> aubio.note2midi('B♭5')
46+ 82
47+
48+ Raises
49+ ------
50+ TypeError
51+ If `note` was not a string.
52+ ValueError
53+ If an error was found while converting `note`.
54+
55+ See Also
56+ --------
57+ midi2note, freqtomidi, miditofreq
58+ """
59+ _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7,
60+ 'A': 9, 'B': 11}
61+ _valid_modifiers = {
62+ u'𝄫': -2, # double flat
63+ u'♭': -1, 'b': -1, '\u266d': -1, # simple flat
64+ u'♮': 0, '\u266e': 0, None: 0, # natural
65+ '#': +1, u'♯': +1, '\u266f': +1, # sharp
66+ u'𝄪': +2, # double sharp
67+ }
2068 _valid_octaves = range(-1, 10)
2169 if not isinstance(note, str_instances):
22− raise TypeError("a string is required, got %s (%s)" % (note, str(type(note))))
70+ msg = "a string is required, got {:s} ({:s})"
71+ raise TypeError(msg.format(str(type(note)), repr(note)))
2372 if len(note) not in range(2, 5):
24− raise ValueError("string of 2 to 4 characters expected, got %d (%s)" \
25− % (len(note), note))
26− notename, modifier, octave = [None]*3
73+ msg = "string of 2 to 4 characters expected, got {:d} ({:s})"
74+ raise ValueError(msg.format(len(note), note))
75+ notename, modifier, octave = [None] * 3
2776
2877 if len(note) == 4:
2978 notename, modifier, octave_sign, octave = note
@@ -46,21 +95,97 @@ def note2midi(note): · 16 unmodified lines
4695 if octave not in _valid_octaves:
4796 raise ValueError("%s is not a valid octave" % octave)
4897
49− midi = 12 + octave * 12 + _valid_notenames[notename] + _valid_modifiers[modifier]
98+ midi = (octave + 1) * 12 + _valid_notenames[notename] \
99+ + _valid_modifiers[modifier]
50100 if midi > 127:
51101 raise ValueError("%s is outside of the range C-2 to G8" % note)
52102 return midi
53103
104+
54105 def midi2note(midi):
55− " convert midi note number to note name, e.g. [0, 127] -> [C-1, G9] "
106+ """Convert midi note number to note name.
107+
108+ Parameters
109+ ----------
110+ midi : int [0, 128]
111+ input midi note number
112+
113+ Returns
114+ -------
115+ str
116+ note name
117+
118+ Examples
119+ --------
120+ >>> aubio.midi2note(70)
121+ 'A#4'
122+ >>> aubio.midi2note(59)
123+ 'B3'
124+
125+ Raises
126+ ------
127+ TypeError
128+ If `midi` was not an integer.
129+ ValueError
130+ If `midi` is out of the range `[0, 128]`.
131+
132+ See Also
133+ --------
134+ note2midi, miditofreq, freqtomidi
135+ """
56136 if not isinstance(midi, int_instances):
57137 raise TypeError("an integer is required, got %s" % midi)
58138 if midi not in range(0, 128):
59− raise ValueError("an integer between 0 and 127 is excepted, got %d" % midi)
60− _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
139+ msg = "an integer between 0 and 127 is excepted, got {:d}"
140+ raise ValueError(msg.format(midi))
141+ _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#',
142+ 'A', 'A#', 'B']
61143 return _valid_notenames[midi % 12] + str(int(midi / 12) - 1)
62144
145+
63146 def freq2note(freq):
64− " convert frequency in Hz to nearest note name, e.g. [0, 22050.] -> [C-1, G9] "
65− from aubio import freqtomidi
66− return midi2note(int(freqtomidi(freq)))
147+ """Convert frequency in Hz to nearest note name.
148+
149+ Parameters
150+ ----------
151+ freq : float [0, 23000[
152+ input frequency, in Hz
153+
154+ Returns
155+ -------
156+ str
157+ name of the nearest note
158+
159+ Example
160+ -------
161+ >>> aubio.freq2note(440)
162+ 'A4'
163+ >>> aubio.freq2note(220.1)
164+ 'A3'
165+ """
166+ nearest_note = int(freqtomidi(freq) + .5)
167+ return midi2note(nearest_note)
168+
169+
170+def note2freq(note):
171+ """Convert note name to corresponding frequency, in Hz.
172+
173+ Parameters
174+ ----------
175+ note : str
176+ input note name
177+
178+ Returns
179+ -------
180+ freq : float [0, 23000[
181+ frequency, in Hz
182+
183+ Example
184+ -------
185+ >>> aubio.note2freq('A4')
186+ 440
187+ >>> aubio.note2freq('A3')
188+ 220.1
189+ """
190+ midi = note2midi(note)
191+ return miditofreq(midi)
python/lib/aubio/slicing.py+81−14
@@ -5,26 +5,91 @@ from aubio import source, sink · 4 unmodified lines
55
66 _max_timestamp = 1e120
77
8+
89 def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,
9− output_dir=None, samplerate=0, hopsize=256):
10− """ slice a sound file at given timestamps """
10+ output_dir=None, samplerate=0, hopsize=256,
11+ create_first=False):
12+ """Slice a sound file at given timestamps.
13+
14+ This function reads `source_file` and creates slices, new smaller
15+ files each starting at `t` in `timestamps`, a list of integer
16+ corresponding to time locations in `source_file`, in samples.
17+
18+ If `timestamps_end` is unspecified, the slices will end at
19+ `timestamps_end[n] = timestamps[n+1]-1`, or the end of file.
20+ Otherwise, `timestamps_end` should be a list with the same length
21+ as `timestamps` containing the locations of the end of each slice.
22+
23+ If `output_dir` is unspecified, the new slices will be written in
24+ the current directory. If `output_dir` is a string, new slices
25+ will be written in `output_dir`, after creating the directory if
26+ required.
27+
28+ The default `samplerate` is 0, meaning the original sampling rate
29+ of `source_file` will be used. When using a sampling rate
30+ different to the one of the original files, `timestamps` and
31+ `timestamps_end` should be expressed in the re-sampled signal.
32+
33+ The `hopsize` parameter simply tells :class:`source` to use this
34+ hopsize and does not change the output slices.
35+
36+ If `create_first` is True and `timestamps` does not start with `0`, the
37+ first slice from `0` to `timestamps[0] - 1` will be automatically added.
38+
39+ Parameters
40+ ----------
41+ source_file : str
42+ path of the resource to slice
43+ timestamps : :obj:`list` of :obj:`int`
44+ time stamps at which to slice, in samples
45+ timestamps_end : :obj:`list` of :obj:`int` (optional)
46+ time stamps at which to end the slices
47+ output_dir : str (optional)
48+ output directory to write the slices to
49+ samplerate : int (optional)
50+ samplerate to read the file at
51+ hopsize : int (optional)
52+ number of samples read from source per iteration
53+ create_first : bool (optional)
54+ always create the slice at the start of the file
55+
56+ Examples
57+ --------
58+ Create two slices: the first slice starts at the beginning of the
59+ input file `loop.wav` and lasts exactly one second, starting at
60+ sample `0` and ending at sample `44099`; the second slice starts
61+ at sample `44100` and lasts until the end of the input file:
62+
63+ >>> aubio.slice_source_at_stamps('loop.wav', [0, 44100])
64+
65+ Create one slice, from 1 second to 2 seconds:
66+
67+ >>> aubio.slice_source_at_stamps('loop.wav', [44100], [44100 * 2 - 1])
68+
69+ Notes
70+ -----
71+ Slices may be overlapping. If `timestamps_end` is `1` element
72+ shorter than `timestamps`, the last slice will end at the end of
73+ the file.
74+ """
1175
12− if timestamps is None or len(timestamps) == 0:
76+ if not timestamps:
1377 raise ValueError("no timestamps given")
1478
15− if timestamps[0] != 0:
79+ if timestamps[0] != 0 and create_first:
1680 timestamps = [0] + timestamps
1781 if timestamps_end is not None:
1882 timestamps_end = [timestamps[1] - 1] + timestamps_end
1983
2084 if timestamps_end is not None:
21− if len(timestamps_end) != len(timestamps):
85+ if len(timestamps_end) == len(timestamps) - 1:
86+ timestamps_end = timestamps_end + [_max_timestamp]
87+ elif len(timestamps_end) != len(timestamps):
2288 raise ValueError("len(timestamps_end) != len(timestamps)")
2389 else:
2490 timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp]
2591
2692 regions = list(zip(timestamps, timestamps_end))
27− #print regions
2893
2994 source_base_name, _ = os.path.splitext(os.path.basename(source_file))
3095 if output_dir is not None:
@@ -32,8 +97,8 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 1 unmodified line
3297 os.makedirs(output_dir)
3398 source_base_name = os.path.join(output_dir, source_base_name)
3499
35− def new_sink_name(source_base_name, timestamp, samplerate):
36− """ create a sink based on a timestamp in samples, converted in seconds """
100+ def _new_sink_name(source_base_name, timestamp, samplerate):
101+ # create name based on a timestamp in samples, converted in seconds
37102 timestamp_seconds = timestamp / float(samplerate)
38103 return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'
39104
@@ -48,16 +113,17 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 8 unmodified lines
48113 # get hopsize new samples from source
49114 vec, read = _source.do_multi()
50115 # if the total number of frames read will exceed the next region start
51− if len(regions) and total_frames + read >= regions[0][0]:
52− #print "getting", regions[0], "at", total_frames
116+ while regions and total_frames + read >= regions[0][0]:
53117 # get next region
54118 start_stamp, end_stamp = regions.pop(0)
55119 # create a name for the sink
56− new_sink_path = new_sink_name(source_base_name, start_stamp, samplerate)
120+ new_sink_path = _new_sink_name(source_base_name, start_stamp,
121+ samplerate)
57122 # create its sink
58123 _sink = sink(new_sink_path, samplerate, _source.channels)
59124 # create a dictionary containing all this
60− new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp, 'sink': _sink}
125+ new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp,
126+ 'sink': _sink}
61127 # append the dictionary to the current list of slices
62128 slices.append(new_slice)
63129
@@ -69,18 +135,19 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 5 unmodified lines
69135 start = max(start_stamp - total_frames, 0)
70136 # number of samples yet to written be until end of region
71137 remaining = end_stamp - total_frames + 1
72− #print current_slice, remaining, start
73138 # not enough frames remaining, time to split
74139 if remaining < read:
75140 if remaining > start:
76141 # write remaining samples from current region
77142 _sink.do_multi(vec[:, start:remaining], remaining - start)
78− #print "closing region", "remaining", remaining
79143 # close this file
80144 _sink.close()
81145 elif read > start:
82146 # write all the samples
83147 _sink.do_multi(vec[:, start:read], read - start)
84148 total_frames += read
149+ # remove old slices
150+ slices = list(filter(lambda s: s['end_stamp'] > total_frames,
151+ slices))
85152 if read < hopsize:
86153 break
python/lib/gen_code.py+65−23
@@ -2,6 +2,7 @@ aubiodefvalue = { · 1 unmodified line
22 # we have some clean up to do
33 'buf_size': 'Py_default_vector_length',
44 'win_s': 'Py_default_vector_length',
5+ 'size': 'Py_default_vector_length',
56 # and here too
67 'hop_size': 'Py_default_vector_length / 2',
78 'hop_s': 'Py_default_vector_length / 2',
@@ -84,6 +85,7 @@ objoutsize = { · 76 unmodified lines
8485 'filterbank': 'self->n_filters',
8586 'tss': 'self->buf_size',
8687 'pitchshift': 'self->hop_size',
88+ 'dct': 'self->size',
8789 }
8890
8991 objinputsize = {
@@ -179,6 +181,10 @@ class MappedObject(object): · 89 unmodified lines
179181 self.do_inputs = [get_params_types_names(self.do_proto)[1]]
180182 self.do_outputs = get_params_types_names(self.do_proto)[2:]
181183 struct_output_str = ["PyObject *{0[name]}; {1} c_{0[name]}".format(i, i['type'][:-1]) for i in self.do_outputs]
184+ if len(self.prototypes['rdo']):
185+ rdo_outputs = get_params_types_names(prototypes['rdo'][0])[2:]
186+ struct_output_str += ["PyObject *{0[name]}; {1} c_{0[name]}".format(i, i['type'][:-1]) for i in rdo_outputs]
187+ self.outputs += rdo_outputs
182188 self.struct_outputs = ";\n ".join(struct_output_str)
183189
184190 #print ("input_params: ", map(split_type, get_input_params(self.do_proto)))
@@ -186,17 +192,26 @@ class MappedObject(object): · 1 unmodified line
186192
187193 def gen_code(self):
188194 out = ""
189− out += self.gen_struct()
190− out += self.gen_doc()
191− out += self.gen_new()
192− out += self.gen_init()
193− out += self.gen_del()
194− out += self.gen_do()
195− out += self.gen_memberdef()
196− out += self.gen_set()
197− out += self.gen_get()
198− out += self.gen_methodef()
199− out += self.gen_typeobject()
195+ try:
196+ out += self.gen_struct()
197+ out += self.gen_doc()
198+ out += self.gen_new()
199+ out += self.gen_init()
200+ out += self.gen_del()
201+ out += self.gen_do()
202+ if len(self.prototypes['rdo']):
203+ self.do_proto = self.prototypes['rdo'][0]
204+ self.do_inputs = [get_params_types_names(self.do_proto)[1]]
205+ self.do_outputs = get_params_types_names(self.do_proto)[2:]
206+ out += self.gen_do(method='rdo')
207+ out += self.gen_memberdef()
208+ out += self.gen_set()
209+ out += self.gen_get()
210+ out += self.gen_methodef()
211+ out += self.gen_typeobject()
212+ except Exception as e:
213+ print ("Failed generating code for", self.shortname)
214+ raise
200215 return out
201216
202217 def gen_struct(self):
@@ -380,12 +395,12 @@ Py_{shortname}_del (Py_{shortname} * self, PyObject * unused) · 177 unmodified lines
380395 """.format(del_fn = del_fn)
381396 return out
382397
383− def gen_do(self):
398+ def gen_do(self, method = 'do'):
384399 out = """
385400 // do {shortname}
386401 static PyObject*
387−Py_{shortname}_do (Py_{shortname} * self, PyObject * args)
388−{{""".format(**self.__dict__)
402+Pyaubio_{shortname}_{method} (Py_{shortname} * self, PyObject * args)
403+{{""".format(method = method, **self.__dict__)
389404 input_params = self.do_inputs
390405 output_params = self.do_outputs
391406 #print input_params
@@ -461,30 +476,51 @@ Py_{shortname}_do (Py_{shortname} * self, PyObject * args) · 69 unmodified lines
461476 // {shortname} setters
462477 """.format(**self.__dict__)
463478 for set_param in self.prototypes['set']:
464− params = get_params_types_names(set_param)[1]
465− paramtype = params['type']
479+ params = get_params_types_names(set_param)[1:]
480+ param = self.shortname.split('_set_')[-1]
481+ paramdecls = "".join(["""
482+ {0} {1};""".format(p['type'], p['name']) for p in params])
466483 method_name = get_name(set_param)
467484 param = method_name.split('aubio_'+self.shortname+'_set_')[-1]
468− pyparamtype = pyargparse_chars[paramtype]
485+ refs = ", ".join(["&%s" % p['name'] for p in params])
486+ paramlist = ", ".join(["%s" % p['name'] for p in params])
487+ if len(params):
488+ paramlist = "," + paramlist
489+ pyparamtypes = ''.join([pyargparse_chars[p['type']] for p in params])
469490 out += """
470491 static PyObject *
471492 Pyaubio_{shortname}_set_{param} (Py_{shortname} *self, PyObject *args)
472493 {{
473494 uint_t err = 0;
474− {paramtype} {param};
495+ {paramdecls}
496+""".format(param = param, paramdecls = paramdecls, **self.__dict__)
497+
498+ if len(refs) and len(pyparamtypes):
499+ out += """
475500
476− if (!PyArg_ParseTuple (args, "{pyparamtype}", &{param})) {{
501+ if (!PyArg_ParseTuple (args, "{pyparamtypes}", {refs})) {{
477502 return NULL;
478503 }}
479− err = aubio_{shortname}_set_{param} (self->o, {param});
504+""".format(pyparamtypes = pyparamtypes, refs = refs)
505+
506+ out += """
507+ err = aubio_{shortname}_set_{param} (self->o {paramlist});
480508
481509 if (err > 0) {{
482− PyErr_SetString (PyExc_ValueError, "error running aubio_{shortname}_set_{param}");
510+ if (PyErr_Occurred() == NULL) {{
511+ PyErr_SetString (PyExc_ValueError, "error running aubio_{shortname}_set_{param}");
512+ }} else {{
513+ // change the RuntimeError into ValueError
514+ PyObject *type, *value, *traceback;
515+ PyErr_Fetch(&type, &value, &traceback);
516+ PyErr_Restore(PyExc_ValueError, value, traceback);
517+ }}
483518 return NULL;
484519 }}
485520 Py_RETURN_NONE;
486521 }}
487−""".format(param = param, paramtype = paramtype, pyparamtype = pyparamtype, **self.__dict__)
522+""".format(param = param, refs = refs, paramdecls = paramdecls,
523+ pyparamtypes = pyparamtypes, paramlist = paramlist, **self.__dict__)
488524 return out
489525
490526 def gen_get(self):
@@ -525,6 +561,12 @@ static PyMethodDef Py_{shortname}_methods[] = {{""".format(**self.__dict__) · 34 unmodified lines
525561 out += """
526562 {{"{shortname}", (PyCFunction) Py{name},
527563 METH_NOARGS, ""}},""".format(name = name, shortname = shortname)
564+ for m in self.prototypes['rdo']:
565+ name = get_name(m)
566+ shortname = name.replace('aubio_%s_' % self.shortname, '')
567+ out += """
568+ {{"{shortname}", (PyCFunction) Py{name},
569+ METH_VARARGS, ""}},""".format(name = name, shortname = shortname)
528570 out += """
529571 {NULL} /* sentinel */
530572 };
@@ -550,7 +592,7 @@ PyTypeObject Py_{shortname}Type = {{ · 19 unmodified lines
550592 0,
551593 0,
552594 0,
553− (ternaryfunc)Py_{shortname}_do,
595+ (ternaryfunc)Pyaubio_{shortname}_do,
554596 0,
555597 0,
556598 0,
python/lib/gen_external.py+180−89
@@ -1,5 +1,10 @@
11 import distutils.ccompiler
2−import sys, os, subprocess, glob
2+import sys
3+import os
4+import subprocess
5+import glob
6+from distutils.sysconfig import customize_compiler
7+from gen_code import MappedObject
38
49 header = os.path.join('src', 'aubio.h')
510 output_path = os.path.join('python', 'gen')
@@ -8,43 +13,44 @@ source_header = """// this file is generated! do not modify · 2 unmodified lines
813 #include "aubio-types.h"
914 """
1015
11−skip_objects = [
12− # already in ext/
13− 'fft',
14− 'pvoc',
15− 'filter',
16− 'filterbank',
17− #'resampler',
18− # AUBIO_UNSTABLE
19− 'hist',
20− 'parameter',
21− 'scale',
22− 'beattracking',
23− 'resampler',
24− 'peakpicker',
25− 'pitchfcomb',
26− 'pitchmcomb',
27− 'pitchschmitt',
28− 'pitchspecacf',
29− 'pitchyin',
30− 'pitchyinfft',
31− 'sink',
32− 'sink_apple_audio',
33− 'sink_sndfile',
34− 'sink_wavwrite',
35− #'mfcc',
36− 'source',
37− 'source_apple_audio',
38− 'source_sndfile',
39− 'source_avcodec',
40− 'source_wavread',
41− #'sampler',
42− 'audio_unit',
43− ]
16+default_skip_objects = [
17+ # already in ext/
18+ 'fft',
19+ 'pvoc',
20+ 'filter',
21+ 'filterbank',
22+ # AUBIO_UNSTABLE
23+ 'hist',
24+ 'parameter',
25+ 'scale',
26+ 'beattracking',
27+ 'resampler',
28+ 'peakpicker',
29+ 'pitchfcomb',
30+ 'pitchmcomb',
31+ 'pitchschmitt',
32+ 'pitchspecacf',
33+ 'pitchyin',
34+ 'pitchyinfft',
35+ 'pitchyinfast',
36+ 'sink',
37+ 'sink_apple_audio',
38+ 'sink_sndfile',
39+ 'sink_wavwrite',
40+ #'mfcc',
41+ 'source',
42+ 'source_apple_audio',
43+ 'source_sndfile',
44+ 'source_avcodec',
45+ 'source_wavread',
46+ #'sampler',
47+ 'audio_unit',
48+ 'spectral_whitening',
49+]
50+
4451
4552 def get_preprocessor():
4653 # findout which compiler to use
47− from distutils.sysconfig import customize_compiler
4854 compiler_name = distutils.ccompiler.get_default_compiler()
4955 compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)
5056 try:
@@ -59,26 +65,50 @@ def get_preprocessor(): · 8 unmodified lines
5965 print("Warning: failed initializing compiler ({:s})".format(repr(e)))
6066
6167 cpp_cmd = None
62− if hasattr(compiler, 'preprocessor'): # for unixccompiler
68+ if hasattr(compiler, 'preprocessor'): # for unixccompiler
6369 cpp_cmd = compiler.preprocessor
64− elif hasattr(compiler, 'compiler'): # for ccompiler
70+ elif hasattr(compiler, 'compiler'): # for ccompiler
6571 cpp_cmd = compiler.compiler.split()
6672 cpp_cmd += ['-E']
67− elif hasattr(compiler, 'cc'): # for msvccompiler
73+ elif hasattr(compiler, 'cc'): # for msvccompiler
6874 cpp_cmd = compiler.cc.split()
6975 cpp_cmd += ['-E']
7076
77+ # On win-amd64 (py3.x), the default compiler is cross-compiling, from x86
78+ # to amd64 with %WIN_SDK_ROOT%\x86_amd64\cl.exe, but using this binary as a
79+ # pre-processor generates no output, so we use %WIN_SDK_ROOT%\cl.exe
80+ # instead.
81+ if len(cpp_cmd) > 1 and 'cl.exe' in cpp_cmd[-2]:
82+ plat = os.path.basename(os.path.dirname(cpp_cmd[-2]))
83+ if plat == 'x86_amd64':
84+ print('workaround on win64 to avoid empty pre-processor output')
85+ cpp_cmd[-2] = cpp_cmd[-2].replace('x86_amd64', '')
86+ elif True in ['amd64' in f for f in cpp_cmd]:
87+ print('warning: not using workaround for', cpp_cmd[0], plat)
88+
7189 if not cpp_cmd:
7290 print("Warning: could not guess preprocessor, using env's CC")
7391 cpp_cmd = os.environ.get('CC', 'cc').split()
7492 cpp_cmd += ['-E']
75−
93+ if 'emcc' in cpp_cmd:
94+ cpp_cmd += ['-x', 'c'] # emcc defaults to c++, force C language
7695 return cpp_cmd
7796
78−def get_cpp_objects(header=header):
97+
98+def get_c_declarations(header=header, usedouble=False):
99+ ''' return a dense and preprocessed string of all c declarations implied by aubio.h
100+ '''
101+ cpp_output = get_cpp_output(header=header, usedouble=usedouble)
102+ return filter_cpp_output (cpp_output)
103+
104+
105+def get_cpp_output(header=header, usedouble=False):
106+ ''' find and run a C pre-processor on aubio.h '''
79107 cpp_cmd = get_preprocessor()
80108
81109 macros = [('AUBIO_UNSTABLE', 1)]
110+ if usedouble:
111+ macros += [('HAVE_AUBIO_DOUBLE', 1)]
82112
83113 if not os.path.isfile(header):
84114 raise Exception("could not find include file " + header)
@@ -89,56 +119,115 @@ def get_cpp_objects(header=header): · 4 unmodified lines
89119
90120 print("Running command: {:s}".format(" ".join(cpp_cmd)))
91121 proc = subprocess.Popen(cpp_cmd,
92− stderr=subprocess.PIPE,
93− stdout=subprocess.PIPE)
122+ stderr=subprocess.PIPE,
123+ stdout=subprocess.PIPE)
94124 assert proc, 'Proc was none'
95125 cpp_output = proc.stdout.read()
96126 err_output = proc.stderr.read()
127+ if err_output:
128+ print("Warning: preprocessor produced errors or warnings:\n%s" \
129+ % err_output.decode('utf8'))
97130 if not cpp_output:
98− raise Exception("preprocessor output is empty:\n%s" % err_output)
99− elif err_output:
100− print ("Warning: preprocessor produced warnings:\n%s" % err_output)
131+ raise_msg = "preprocessor output is empty! Running command " \
132+ + "\"%s\" failed" % " ".join(cpp_cmd)
133+ if err_output:
134+ raise_msg += " with stderr: \"%s\"" % err_output.decode('utf8')
135+ else:
136+ raise_msg += " with no stdout or stderr"
137+ raise Exception(raise_msg)
101138 if not isinstance(cpp_output, list):
102139 cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')]
103140
104− cpp_output = filter(lambda y: len(y) > 1, cpp_output)
141+ return cpp_output
142+
143+def filter_cpp_output(cpp_raw_output):
144+ ''' prepare cpp-output for parsing '''
145+ cpp_output = filter(lambda y: len(y) > 1, cpp_raw_output)
105146 cpp_output = list(filter(lambda y: not y.startswith('#'), cpp_output))
106147
107148 i = 1
108149 while 1:
109− if i >= len(cpp_output): break
110− if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
111− cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
112− cpp_output.pop(i-1)
150+ if i >= len(cpp_output):
151+ break
152+ if ('{' in cpp_output[i - 1]) and ('}' not in cpp_output[i - 1]) or (';' not in cpp_output[i - 1]):
153+ cpp_output[i] = cpp_output[i - 1] + ' ' + cpp_output[i]
154+ cpp_output.pop(i - 1)
155+ elif ('}' in cpp_output[i]):
156+ cpp_output[i] = cpp_output[i - 1] + ' ' + cpp_output[i]
157+ cpp_output.pop(i - 1)
113158 else:
114159 i += 1
115160
116− typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
161+ # clean pointer notations
162+ tmp = []
163+ for l in cpp_output:
164+ tmp += [l.replace(' *', ' * ')]
165+ cpp_output = tmp
117166
167+ return cpp_output
168+
169+
170+def get_cpp_objects_from_c_declarations(c_declarations, skip_objects=None):
171+ if skip_objects is None:
172+ skip_objects = default_skip_objects
173+ typedefs = filter(lambda y: y.startswith('typedef struct _aubio'), c_declarations)
118174 cpp_objects = [a.split()[3][:-1] for a in typedefs]
175+ cpp_objects_filtered = filter(lambda y: not y[6:-2] in skip_objects, cpp_objects)
176+ return cpp_objects_filtered
177+
178+
179+def get_all_func_names_from_lib(lib):
180+ ''' return flat string of all function used in lib
181+ '''
182+ res = []
183+ for _, v in lib.items():
184+ if isinstance(v, dict):
185+ res += get_all_func_names_from_lib(v)
186+ elif isinstance(v, list):
187+ for elem in v:
188+ e = elem.split('(')
189+ if len(e) < 2:
190+ continue # not a function
191+ fname_part = e[0].strip().split(' ')
192+ fname = fname_part[-1]
193+ if fname:
194+ res += [fname]
195+ else:
196+ raise NameError('gen_lib : weird function: ' + str(e))
119197
120− return cpp_output, cpp_objects
198+ return res
121199
122200
123−def analyze_cpp_output(cpp_objects, cpp_output):
201+def generate_lib_from_c_declarations(cpp_objects, c_declarations):
202+ ''' returns a lib from given cpp_object names
203+
204+ a lib is a dict grouping functions by family (onset,pitch...)
205+ each eement is itself a dict of functions grouped by puposes as :
206+ struct, new, del, do, get, set and other
207+ '''
124208 lib = {}
125209
126210 for o in cpp_objects:
127− if o[:6] != 'aubio_':
128− continue
129− shortname = o[6:-2]
130− if shortname in skip_objects:
131− continue
132− lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []}
211+ shortname = o
212+ if o[:6] == 'aubio_':
213+ shortname = o[6:-2] # without aubio_ prefix and _t suffix
214+
215+ lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'rdo': [], 'get': [], 'set': [], 'other': []}
133216 lib[shortname]['longname'] = o
134217 lib[shortname]['shortname'] = shortname
135− for fn in cpp_output:
136− if o[:-1] in fn:
137− #print "found", o[:-1], "in", fn
218+
219+ fullshortname = o[:-2] # name without _t suffix
220+
221+ for fn in c_declarations:
222+ func_name = fn.split('(')[0].strip().split(' ')[-1]
223+ if func_name.startswith(fullshortname + '_') or func_name.endswith(fullshortname):
224+ # print "found", shortname, "in", fn
138225 if 'typedef struct ' in fn:
139226 lib[shortname]['struct'].append(fn)
140227 elif '_do' in fn:
141228 lib[shortname]['do'].append(fn)
229+ elif '_rdo' in fn:
230+ lib[shortname]['rdo'].append(fn)
142231 elif 'new_' in fn:
143232 lib[shortname]['new'].append(fn)
144233 elif 'del_' in fn:
@@ -148,52 +237,52 @@ def analyze_cpp_output(cpp_objects, cpp_output): · 3 unmodified lines
148237 elif '_set_' in fn:
149238 lib[shortname]['set'].append(fn)
150239 else:
151− #print "no idea what to do about", fn
240+ # print "no idea what to do about", fn
152241 lib[shortname]['other'].append(fn)
153242 return lib
154243
155−def print_cpp_output_results(lib, cpp_output):
156− for fn in cpp_output:
244+
245+def print_c_declarations_results(lib, c_declarations):
246+ for fn in c_declarations:
157247 found = 0
158248 for o in lib:
159249 for family in lib[o]:
160250 if fn in lib[o][family]:
161251 found = 1
162252 if found == 0:
163− print ("missing", fn)
253+ print("missing", fn)
164254
165255 for o in lib:
166256 for family in lib[o]:
167257 if type(lib[o][family]) == str:
168− print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
258+ print("{:15s} {:10s} {:s}".format(o, family, lib[o][family]))
169259 elif len(lib[o][family]) == 1:
170− print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family][0] ) )
260+ print("{:15s} {:10s} {:s}".format(o, family, lib[o][family][0]))
171261 else:
172− print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
262+ print("{:15s} {:10s} {:s}".format(o, family, lib[o][family]))
173263
174264
175265 def generate_external(header=header, output_path=output_path, usedouble=False, overwrite=True):
176− if not os.path.isdir(output_path): os.mkdir(output_path)
177− elif not overwrite: return glob.glob(os.path.join(output_path, '*.c'))
266+ if not os.path.isdir(output_path):
267+ os.mkdir(output_path)
268+ elif not overwrite:
269+ return sorted(glob.glob(os.path.join(output_path, '*.c')))
178270
179− cpp_output, cpp_objects = get_cpp_objects(header)
271+ c_declarations = get_c_declarations(header, usedouble=usedouble)
272+ cpp_objects = get_cpp_objects_from_c_declarations(c_declarations)
180273
181− lib = analyze_cpp_output(cpp_objects, cpp_output)
182− # print_cpp_output_results(lib, cpp_output)
274+ lib = generate_lib_from_c_declarations(cpp_objects, c_declarations)
275+ # print_c_declarations_results(lib, c_declarations)
183276
184277 sources_list = []
185− try:
186− from .gen_code import MappedObject
187− except (SystemError, ValueError):
188− from gen_code import MappedObject
189278 for o in lib:
190279 out = source_header
191− mapped = MappedObject(lib[o], usedouble = usedouble)
280+ mapped = MappedObject(lib[o], usedouble=usedouble)
192281 out += mapped.gen_code()
193282 output_file = os.path.join(output_path, 'gen-%s.c' % o)
194283 with open(output_file, 'w') as f:
195284 f.write(out)
196− print ("wrote %s" % output_file )
285+ print("wrote %s" % output_file)
197286 sources_list.append(output_file)
198287
199288 out = source_header
@@ -205,23 +294,23 @@ int generated_types_ready (void) · 5 unmodified lines
205294 {{
206295 return ({pycheck_types});
207296 }}
208−""".format(pycheck_types = check_types)
297+""".format(pycheck_types=check_types)
209298
210299 add_types = "".join(["""
211300 Py_INCREF (&Py_{name}Type);
212− PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name = o) for o in lib])
301+ PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name=o) for o in lib])
213302 out += """
214303
215304 void add_generated_objects ( PyObject *m )
216305 {{
217306 {add_types}
218307 }}
219−""".format(add_types = add_types)
308+""".format(add_types=add_types)
220309
221310 output_file = os.path.join(output_path, 'aubio-generated.c')
222311 with open(output_file, 'w') as f:
223312 f.write(out)
224− print ("wrote %s" % output_file )
313+ print("wrote %s" % output_file)
225314 sources_list.append(output_file)
226315
227316 objlist = "".join(["extern PyTypeObject Py_%sType;\n" % p for p in lib])
@@ -239,17 +328,19 @@ void add_generated_objects ( PyObject *m ) · 11 unmodified lines
239328 {objlist}
240329 int generated_objects ( void );
241330 void add_generated_objects( PyObject *m );
242−""".format(objlist = objlist)
331+""".format(objlist=objlist)
243332
244333 output_file = os.path.join(output_path, 'aubio-generated.h')
245334 with open(output_file, 'w') as f:
246335 f.write(out)
247− print ("wrote %s" % output_file )
336+ print("wrote %s" % output_file)
248337 # no need to add header to list of sources
249338
250− return sources_list
339+ return sorted(sources_list)
251340
252341 if __name__ == '__main__':
253− if len(sys.argv) > 1: header = sys.argv[1]
254− if len(sys.argv) > 2: output_path = sys.argv[2]
342+ if len(sys.argv) > 1:
343+ header = sys.argv[1]
344+ if len(sys.argv) > 2:
345+ output_path = sys.argv[2]
255346 generate_external(header, output_path)
python/lib/moresetuptools.py+78−26
@@ -2,7 +2,9 @@ · 1 unmodified line
22 #
33 import sys, os, glob, subprocess
44 import distutils, distutils.command.clean, distutils.dir_util
5−from .gen_external import generate_external, header, output_path
5+from gen_external import generate_external, header, output_path
6+
7+from this_version import get_aubio_version
68
79 # inspired from https://gist.github.com/abergmeier/9488990
810 def add_packages(packages, ext=None, **kw):
@@ -21,6 +23,7 @@ def add_packages(packages, ext=None, **kw): · 12 unmodified lines
2123 }
2224
2325 for package in packages:
26+ print("checking for {:s}".format(package))
2427 cmd = ['pkg-config', '--libs', '--cflags', package]
2528 try:
2629 tokens = subprocess.check_output(cmd)
@@ -54,13 +57,14 @@ def add_local_aubio_lib(ext): · 27 unmodified lines
5457
5558 def add_local_aubio_sources(ext):
5659 """ build aubio inside python module instead of linking against libaubio """
57− print("Warning: libaubio was not built with waf, adding src/")
58− # create an empty header, macros will be passed on the command line
59− fake_config_header = os.path.join('python', 'ext', 'config.h')
60− distutils.file_util.write_file(fake_config_header, "")
61− aubio_sources = glob.glob(os.path.join('src', '**.c'))
62− aubio_sources += glob.glob(os.path.join('src', '*', '**.c'))
60+ print("Info: libaubio was not installed or built locally with waf, adding src/")
61+ aubio_sources = sorted(glob.glob(os.path.join('src', '**.c')))
62+ aubio_sources += sorted(glob.glob(os.path.join('src', '*', '**.c')))
6363 ext.sources += aubio_sources
64+
65+def add_local_macros(ext, usedouble = False):
66+ if usedouble:
67+ ext.define_macros += [('HAVE_AUBIO_DOUBLE', 1)]
6468 # define macros (waf puts them in build/src/config.h)
6569 for define_macro in ['HAVE_STDLIB_H', 'HAVE_STDIO_H',
6670 'HAVE_MATH_H', 'HAVE_STRING_H',
@@ -69,22 +73,31 @@ def add_local_aubio_sources(ext): · 2 unmodified lines
6973 'HAVE_MEMCPY_HACKS']:
7074 ext.define_macros += [(define_macro, 1)]
7175
76+def add_external_deps(ext, usedouble = False):
7277 # loof for additional packages
7378 print("Info: looking for *optional* additional packages")
74− packages = ['libavcodec', 'libavformat', 'libavutil', 'libavresample',
79+ packages = ['libavcodec', 'libavformat', 'libavutil',
80+ 'libswresample', 'libavresample',
7581 'jack',
76− 'sndfile', 'samplerate',
82+ 'sndfile',
7783 'rubberband',
7884 #'fftw3f',
7985 ]
86+ # samplerate only works with float
87+ if usedouble is False:
88+ packages += ['samplerate']
89+ else:
90+ print("Info: not adding libsamplerate in double precision mode")
8091 add_packages(packages, ext=ext)
8192 if 'avcodec' in ext.libraries \
8293 and 'avformat' in ext.libraries \
83− and 'avutil' in ext.libraries \
84− and 'avresample' in ext.libraries:
85− ext.define_macros += [('HAVE_LIBAV', 1)]
86− if 'jack' in ext.libraries:
87− ext.define_macros += [('HAVE_JACK', 1)]
94+ and 'avutil' in ext.libraries:
95+ if 'swresample' in ext.libraries:
96+ ext.define_macros += [('HAVE_SWRESAMPLE', 1)]
97+ elif 'avresample' in ext.libraries:
98+ ext.define_macros += [('HAVE_AVRESAMPLE', 1)]
99+ if 'swresample' in ext.libraries or 'avresample' in ext.libraries:
100+ ext.define_macros += [('HAVE_LIBAV', 1)]
88101 if 'sndfile' in ext.libraries:
89102 ext.define_macros += [('HAVE_SNDFILE', 1)]
90103 if 'samplerate' in ext.libraries:
@@ -107,39 +120,78 @@ def add_local_aubio_sources(ext): · 16 unmodified lines
107120
108121 ext.define_macros += [('HAVE_WAVWRITE', 1)]
109122 ext.define_macros += [('HAVE_WAVREAD', 1)]
110− # TODO:
111− # add cblas
123+
124+ # TODO: add cblas
112125 if 0:
113126 ext.libraries += ['cblas']
114127 ext.define_macros += [('HAVE_ATLAS_CBLAS_H', 1)]
115128
116129 def add_system_aubio(ext):
117130 # use pkg-config to find aubio's location
118− add_packages(['aubio'], ext)
131+ aubio_version = get_aubio_version()
132+ add_packages(['aubio = ' + aubio_version], ext)
119133 if 'aubio' not in ext.libraries:
120− print("Error: libaubio not found")
134+ print("Info: aubio " + aubio_version + " was not found by pkg-config")
135+ else:
136+ print("Info: using system aubio " + aubio_version + " found in " + ' '.join(ext.library_dirs))
137+
138+def add_libav_on_win(ext):
139+ """ no pkg-config on windows, simply assume these libs are available """
140+ ext.libraries += ['avformat', 'avutil', 'avcodec', 'swresample']
141+ for define_macro in ['HAVE_LIBAV', 'HAVE_SWRESAMPLE']:
142+ ext.define_macros += [(define_macro, 1)]
121143
122144 class CleanGenerated(distutils.command.clean.clean):
123145 def run(self):
124− distutils.dir_util.remove_tree(output_path)
125− distutils.command.clean.clean.run(self)
146+ if os.path.isdir(output_path):
147+ distutils.dir_util.remove_tree(output_path)
148+
149+from distutils.command.build_ext import build_ext as _build_ext
150+class build_ext(_build_ext):
126151
127−class GenerateCommand(distutils.cmd.Command):
128− description = 'generate gen/gen-*.c files from ../src/aubio.h'
129− user_options = [
152+ user_options = _build_ext.user_options + [
130153 # The format is (long option, short option, description).
131154 ('enable-double', None, 'use HAVE_AUBIO_DOUBLE=1 (default: 0)'),
132155 ]
133156
134157 def initialize_options(self):
158+ _build_ext.initialize_options(self)
135159 self.enable_double = False
136160
137161 def finalize_options(self):
162+ _build_ext.finalize_options(self)
138163 if self.enable_double:
139164 self.announce(
140165 'will generate code for aubio compiled with HAVE_AUBIO_DOUBLE=1',
141166 level=distutils.log.INFO)
142167
143− def run(self):
144− self.announce( 'Generating code', level=distutils.log.INFO)
145− generated_object_files = generate_external(header, output_path, usedouble=self.enable_double)
168+ def build_extension(self, extension):
169+ if self.enable_double or 'HAVE_AUBIO_DOUBLE' in os.environ:
170+ enable_double = True
171+ else:
172+ enable_double = False
173+ # seack for aubio headers and lib in PKG_CONFIG_PATH
174+ add_system_aubio(extension)
175+ # the lib was not installed on this system
176+ if 'aubio' not in extension.libraries:
177+ # use local src/aubio.h
178+ if os.path.isfile(os.path.join('src', 'aubio.h')):
179+ add_local_aubio_header(extension)
180+ add_local_macros(extension, usedouble=enable_double)
181+ # look for a local waf build
182+ if os.path.isfile(os.path.join('build','src', 'fvec.c.1.o')):
183+ add_local_aubio_lib(extension)
184+ else:
185+ # check for external dependencies
186+ add_external_deps(extension, usedouble=enable_double)
187+ # force adding libav on windows
188+ if os.name == 'nt' and ('WITH_LIBAV' in os.environ \
189+ or 'CONDA_PREFIX' in os.environ):
190+ add_libav_on_win(extension)
191+ # add libaubio sources and look for optional deps with pkg-config
192+ add_local_aubio_sources(extension)
193+ # generate files python/gen/*.c, python/gen/aubio-generated.h
194+ extension.include_dirs += [ output_path ]
195+ extension.sources += generate_external(header, output_path, overwrite = False,
196+ usedouble=enable_double)
197+ return _build_ext.build_extension(self, extension)
python/scripts/aubiocut+0−206
@@ -1,206 +0,0 @@
1−#! /usr/bin/env python
2−
3−""" this file was written by Paul Brossier
4− it is released under the GNU/GPL license.
5−"""
6−
7−import sys
8−#from aubio.task import *
9−
10−usage = "usage: %s [options] -i soundfile" % sys.argv[0]
11−usage += "\n help: %s -h" % sys.argv[0]
12−
13−def parse_args():
14− from optparse import OptionParser
15− parser = OptionParser(usage=usage)
16− parser.add_option("-i", "--input", action = "store", dest = "source_file",
17− help="input sound file to analyse", metavar = "<source_file>")
18− parser.add_option("-O","--onset-method",
19− action="store", dest="onset_method", default='default',
20− metavar = "<onset_method>",
21− help="onset detection method [default=default] \
22− complexdomain|hfc|phase|specdiff|energy|kl|mkl")
23− # cutting methods
24− parser.add_option("-b","--beat",
25− action="store_true", dest="beat", default=False,
26− help="use beat locations")
27− """
28− parser.add_option("-S","--silencecut",
29− action="store_true", dest="silencecut", default=False,
30− help="use silence locations")
31− parser.add_option("-s","--silence",
32− metavar = "<value>",
33− action="store", dest="silence", default=-70,
34− help="silence threshold [default=-70]")
35− """
36− # algorithm parameters
37− parser.add_option("-r", "--samplerate",
38− metavar = "<freq>", type='int',
39− action="store", dest="samplerate", default=0,
40− help="samplerate at which the file should be represented")
41− parser.add_option("-B","--bufsize",
42− action="store", dest="bufsize", default=512,
43− metavar = "<size>", type='int',
44− help="buffer size [default=512]")
45− parser.add_option("-H","--hopsize",
46− metavar = "<size>", type='int',
47− action="store", dest="hopsize", default=256,
48− help="overlap size [default=256]")
49− parser.add_option("-t","--onset-threshold",
50− metavar = "<value>", type="float",
51− action="store", dest="threshold", default=0.3,
52− help="onset peak picking threshold [default=0.3]")
53− parser.add_option("-c","--cut",
54− action="store_true", dest="cut", default=False,
55− help="cut input sound file at detected labels \
56− best used with option -L")
57−
58− # minioi
59− parser.add_option("-M","--minioi",
60− metavar = "<value>", type='string',
61− action="store", dest="minioi", default="12ms",
62− help="minimum inter onset interval [default=12ms]")
63−
64− """
65− parser.add_option("-D","--delay",
66− action = "store", dest = "delay", type = "float",
67− metavar = "<seconds>", default=0,
68− help="number of seconds to take back [default=system]\
69− default system delay is 3*hopsize/samplerate")
70− parser.add_option("-C","--dcthreshold",
71− metavar = "<value>",
72− action="store", dest="dcthreshold", default=1.,
73− help="onset peak picking DC component [default=1.]")
74− parser.add_option("-L","--localmin",
75− action="store_true", dest="localmin", default=False,
76− help="use local minima after peak detection")
77− parser.add_option("-d","--derivate",
78− action="store_true", dest="derivate", default=False,
79− help="derivate onset detection function")
80− parser.add_option("-z","--zerocross",
81− metavar = "<value>",
82− action="store", dest="zerothres", default=0.008,
83− help="zero-crossing threshold for slicing [default=0.00008]")
84− """
85− # plotting functions
86− """
87− parser.add_option("-p","--plot",
88− action="store_true", dest="plot", default=False,
89− help="draw plot")
90− parser.add_option("-x","--xsize",
91− metavar = "<size>",
92− action="store", dest="xsize", default=1.,
93− type='float', help="define xsize for plot")
94− parser.add_option("-y","--ysize",
95− metavar = "<size>",
96− action="store", dest="ysize", default=1.,
97− type='float', help="define ysize for plot")
98− parser.add_option("-f","--function",
99− action="store_true", dest="func", default=False,
100− help="print detection function")
101− parser.add_option("-n","--no-onsets",
102− action="store_true", dest="nplot", default=False,
103− help="do not plot detected onsets")
104− parser.add_option("-O","--outplot",
105− metavar = "<output_image>",
106− action="store", dest="outplot", default=None,
107− help="save plot to output.{ps,png}")
108− parser.add_option("-F","--spectrogram",
109− action="store_true", dest="spectro", default=False,
110− help="add spectrogram to the plot")
111− """
112− parser.add_option("-o","--output", type = str,
113− metavar = "<outputdir>",
114− action="store", dest="output_directory", default=None,
115− help="specify path where slices of the original file should be created")
116− parser.add_option("--cut-until-nsamples", type = int,
117− metavar = "<samples>",
118− action = "store", dest = "cut_until_nsamples", default = None,
119− help="how many extra samples should be added at the end of each slice")
120− parser.add_option("--cut-until-nslices", type = int,
121− metavar = "<slices>",
122− action = "store", dest = "cut_until_nslices", default = None,
123− help="how many extra slices should be added at the end of each slice")
124−
125− parser.add_option("-v","--verbose",
126− action="store_true", dest="verbose", default=True,
127− help="make lots of noise [default]")
128− parser.add_option("-q","--quiet",
129− action="store_false", dest="verbose", default=True,
130− help="be quiet")
131− (options, args) = parser.parse_args()
132− if not options.source_file:
133− import os.path
134− if len(args) == 1:
135− options.source_file = args[0]
136− else:
137− print ("no file name given\n" + usage)
138− sys.exit(1)
139− return options, args
140−
141−if __name__ == '__main__':
142− options, args = parse_args()
143−
144− hopsize = options.hopsize
145− bufsize = options.bufsize
146− samplerate = options.samplerate
147− source_file = options.source_file
148−
149− from aubio import onset, tempo, source, sink
150−
151− s = source(source_file, samplerate, hopsize)
152− if samplerate == 0: samplerate = s.get_samplerate()
153−
154− if options.beat:
155− o = tempo(options.onset_method, bufsize, hopsize)
156− else:
157− o = onset(options.onset_method, bufsize, hopsize)
158− if options.minioi:
159− if options.minioi.endswith('ms'):
160− o.set_minioi_ms(int(options.minioi[:-2]))
161− elif options.minioi.endswith('s'):
162− o.set_minioi_s(int(options.minioi[:-1]))
163− else:
164− o.set_minioi(int(options.minioi))
165− o.set_threshold(options.threshold)
166−
167− timestamps = []
168− total_frames = 0
169− # analyze pass
170− while True:
171− samples, read = s()
172− if o(samples):
173− timestamps.append (o.get_last())
174− if options.verbose: print ("%.4f" % o.get_last_s())
175− total_frames += read
176− if read < hopsize: break
177− del s
178− # print some info
179− nstamps = len(timestamps)
180− duration = float (total_frames) / float(samplerate)
181− info = 'found %(nstamps)d timestamps in %(source_file)s' % locals()
182− info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % locals()
183− sys.stderr.write(info)
184−
185− # cutting pass
186− if options.cut and nstamps > 0:
187− # generate output files
188− from aubio.slicing import slice_source_at_stamps
189− timestamps_end = None
190− if options.cut_until_nslices and options.cut_until_nsamples:
191− print ("warning: using cut_until_nslices, but cut_until_nsamples is set")
192− if options.cut_until_nsamples:
193− timestamps_end = [t + options.cut_until_nsamples for t in timestamps[1:]]
194− timestamps_end += [ 1e120 ]
195− if options.cut_until_nslices:
196− timestamps_end = [t for t in timestamps[1 + options.cut_until_nslices:]]
197− timestamps_end += [ 1e120 ] * (options.cut_until_nslices + 1)
198− slice_source_at_stamps(source_file, timestamps, timestamps_end = timestamps_end,
199− output_dir = options.output_directory,
200− samplerate = samplerate)
201−
202− # print some info
203− duration = float (total_frames) / float(samplerate)
204− info = 'created %(nstamps)d slices from %(source_file)s' % locals()
205− info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % locals()
206− sys.stderr.write(info)
python/tests/__init__.py+1−0
@@ -0,0 +1 @@
1+
python/tests/eval_pitch+1−1
@@ -24,7 +24,7 @@ import sys · 23 unmodified lines
2424 import time
2525 import os.path
2626 import numpy
27−from utils import array_from_text_file, array_from_yaml_file
27+from .utils import array_from_text_file, array_from_yaml_file
2828 from aubio import source, pitch, freqtomidi
2929
3030 start = time.time()
python/tests/test_aubio.py+5−0
@@ -9,6 +9,11 @@ class aubiomodule_test_case(TestCase): · 8 unmodified lines
99 """ try importing aubio """
1010 import aubio
1111
12+ def test_version(self):
13+ """ test aubio.version """
14+ import aubio
15+ self.assertEqual('0', aubio.version[0])
16+
1217 if __name__ == '__main__':
1318 main()
1419
python/tests/test_aubio_cmd.py+34−0
@@ -0,0 +1,34 @@
1+#! /usr/bin/env python
2+
3+import aubio.cmd
4+from nose2 import main
5+from numpy.testing import TestCase
6+
7+class aubio_cmd(TestCase):
8+
9+ def setUp(self):
10+ self.a_parser = aubio.cmd.aubio_parser()
11+
12+ def test_default_creation(self):
13+ try:
14+ assert self.a_parser.parse_args(['-V']).show_version
15+ except SystemExit:
16+ url = 'https://bugs.python.org/issue9253'
17+ self.skipTest('subcommand became optional in py3, see %s' % url)
18+
19+class aubio_cmd_utils(TestCase):
20+
21+ def test_samples2seconds(self):
22+ self.assertEqual(aubio.cmd.samples2seconds(3200, 32000),
23+ "0.100000\t")
24+
25+ def test_samples2milliseconds(self):
26+ self.assertEqual(aubio.cmd.samples2milliseconds(3200, 32000),
27+ "100.000000\t")
28+
29+ def test_samples2samples(self):
30+ self.assertEqual(aubio.cmd.samples2samples(3200, 32000),
31+ "3200\t")
32+
33+if __name__ == '__main__':
34+ main()
python/tests/test_aubio_cut.py+16−0
@@ -0,0 +1,16 @@
1+#! /usr/bin/env python
2+
3+import aubio.cut
4+from nose2 import main
5+from numpy.testing import TestCase
6+
7+class aubio_cut(TestCase):
8+
9+ def setUp(self):
10+ self.a_parser = aubio.cut.aubio_cut_parser()
11+
12+ def test_default_creation(self):
13+ assert self.a_parser.parse_args(['-v']).verbose
14+
15+if __name__ == '__main__':
16+ main()
python/tests/test_dct.py+68−0
@@ -0,0 +1,68 @@
1+#! /usr/bin/env python
2+
3+
4+import numpy as np
5+from numpy.testing import TestCase, assert_almost_equal
6+import aubio
7+
8+precomputed_arange = [ 9.89949512, -6.44232273, 0., -0.67345482, 0.,
9+ -0.20090288, 0., -0.05070186]
10+
11+precomputed_some_ones = [ 4.28539848, 0.2469689, -0.14625292, -0.58121818,
12+ -0.83483052, -0.75921834, -0.35168475, 0.24087936,
13+ 0.78539824, 1.06532764, 0.97632152, 0.57164496, 0.03688532,
14+ -0.39446154, -0.54619485, -0.37771079]
15+
16+class aubio_dct(TestCase):
17+
18+ def test_init(self):
19+ """ test that aubio.dct() is created with expected size """
20+ a_dct = aubio.dct()
21+ self.assertEqual(a_dct.size, 1024)
22+
23+ def test_arange(self):
24+ """ test that dct(arange(8)) is computed correctly
25+
26+ >>> from scipy.fftpack import dct
27+ >>> a_in = np.arange(8).astype(aubio.float_type)
28+ >>> precomputed = dct(a_in, norm='ortho')
29+ """
30+ N = len(precomputed_arange)
31+ a_dct = aubio.dct(8)
32+ a_in = np.arange(8).astype(aubio.float_type)
33+ a_expected = aubio.fvec(precomputed_arange)
34+ assert_almost_equal(a_dct(a_in), a_expected, decimal=5)
35+
36+ def test_some_ones(self):
37+ """ test that dct(somevector) is computed correctly """
38+ a_dct = aubio.dct(16)
39+ a_in = np.ones(16).astype(aubio.float_type)
40+ a_in[1] = 0
41+ a_in[3] = np.pi
42+ a_expected = aubio.fvec(precomputed_some_ones)
43+ assert_almost_equal(a_dct(a_in), a_expected, decimal=6)
44+
45+ def test_reconstruction(self):
46+ """ test that some_ones vector can be recontructed """
47+ a_dct = aubio.dct(16)
48+ a_in = np.ones(16).astype(aubio.float_type)
49+ a_in[1] = 0
50+ a_in[3] = np.pi
51+ a_dct_in = a_dct(a_in)
52+ a_dct_reconstructed = a_dct.rdo(a_dct_in)
53+ assert_almost_equal(a_dct_reconstructed, a_in, decimal=6)
54+
55+ def test_negative_size(self):
56+ """ test that creation fails with a negative size """
57+ with self.assertRaises(ValueError):
58+ aubio.dct(-1)
59+
60+ def test_wrong_size(self):
61+ """ test that creation fails with a non power-of-two size """
62+ # supports for non 2** fft sizes only when compiled with fftw3
63+ size = 13
64+ try:
65+ with self.assertRaises(RuntimeError):
66+ aubio.dct(size)
67+ except AssertionError:
68+ self.skipTest('creating aubio.dct with size %d did not fail' % size)
python/tests/test_fft.py+39−12
@@ -33,7 +33,14 @@ class aubio_fft_test_case(TestCase): · 32 unmodified lines
3333 f = fft (win_s)
3434 fftgrain = f (timegrain)
3535 assert_equal ( fftgrain.norm, 0 )
36− assert_equal ( fftgrain.phas, 0 )
36+ try:
37+ assert_equal ( fftgrain.phas, 0 )
38+ except AssertionError:
39+ assert_equal (fftgrain.phas[fftgrain.phas > 0], +pi)
40+ assert_equal (fftgrain.phas[fftgrain.phas < 0], -pi)
41+ assert_equal (np.abs(fftgrain.phas[np.abs(fftgrain.phas) != pi]), 0)
42+ self.skipTest('fft(fvec(%d)).phas != +0, ' % win_s \
43+ + 'This is expected when using fftw3 on powerpc.')
3744
3845 def test_impulse(self):
3946 """ check the transform of one impulse at a random place """
@@ -135,6 +142,37 @@ class aubio_fft_test_case(TestCase): · 95 unmodified lines
135142 assert_almost_equal ( r[0], impulse, decimal = 6)
136143 assert_almost_equal ( r[1:], 0)
137144
145+class aubio_fft_odd_sizes(TestCase):
146+
147+ def test_reconstruct_with_odd_size(self):
148+ win_s = 29
149+ self.recontruct(win_s, 'odd sizes not supported')
150+
151+ def test_reconstruct_with_radix15(self):
152+ win_s = 2 ** 4 * 15
153+ self.recontruct(win_s, 'radix 15 supported')
154+
155+ def test_reconstruct_with_radix5(self):
156+ win_s = 2 ** 4 * 5
157+ self.recontruct(win_s, 'radix 5 supported')
158+
159+ def test_reconstruct_with_radix3(self):
160+ win_s = 2 ** 4 * 3
161+ self.recontruct(win_s, 'radix 3 supported')
162+
163+ def recontruct(self, win_s, skipMessage):
164+ try:
165+ f = fft(win_s)
166+ except RuntimeError:
167+ self.skipTest(skipMessage)
168+ input_signal = fvec(win_s)
169+ input_signal[win_s//2] = 1
170+ c = f(input_signal)
171+ output_signal = f.rdo(c)
172+ assert_almost_equal(input_signal, output_signal)
173+
174+class aubio_fft_wrong_params(TestCase):
175+
138176 def test_large_input_timegrain(self):
139177 win_s = 1024
140178 f = fft(win_s)
@@ -163,22 +201,11 @@ class aubio_fft_test_case(TestCase): · 22 unmodified lines
163201 with self.assertRaises(ValueError):
164202 f.rdo(s)
165203
166−class aubio_fft_wrong_params(TestCase):
167−
168204 def test_wrong_buf_size(self):
169205 win_s = -1
170206 with self.assertRaises(ValueError):
171207 fft(win_s)
172208
173− def test_buf_size_not_power_of_two(self):
174− # when compiled with fftw3, aubio supports non power of two fft sizes
175− win_s = 320
176− try:
177− with self.assertRaises(RuntimeError):
178− fft(win_s)
179− except AssertionError:
180− self.skipTest('creating aubio.fft with size %d did not fail' % win_s)
181−
182209 def test_buf_size_too_small(self):
183210 win_s = 1
184211 with self.assertRaises(RuntimeError):
python/tests/test_filter.py+11−1
@@ -3,7 +3,7 @@ · 2 unmodified lines
33 from unittest import main
44 from numpy.testing import TestCase, assert_equal, assert_almost_equal
55 from aubio import fvec, digital_filter
6−from utils import array_from_text_file
6+from .utils import array_from_text_file
77
88 class aubio_filter_test_case(TestCase):
99
@@ -77,6 +77,16 @@ class aubio_filter_test_case(TestCase): · 67 unmodified lines
7777 with self.assertRaises(ValueError):
7878 f.set_biquad(0., 0., 0, 0., 0.)
7979
80+ def test_all_available_presets(self):
81+ f = digital_filter(7)
82+ for sr in [8000, 11025, 16000, 22050, 24000, 32000,
83+ 44100, 48000, 88200, 96000, 192000]:
84+ f.set_a_weighting(sr)
85+ f = digital_filter(5)
86+ for sr in [8000, 11025, 16000, 22050, 24000, 32000,
87+ 44100, 48000, 88200, 96000, 192000]:
88+ f.set_c_weighting(sr)
89+
8090 class aubio_filter_wrong_params(TestCase):
8191
8292 def test_negative_order(self):
python/tests/test_filterbank.py+12−5
@@ -1,11 +1,10 @@
11 #! /usr/bin/env python
22
3−from unittest import main
4−from numpy.testing import TestCase
5−from numpy.testing import assert_equal, assert_almost_equal
63 import numpy as np
4+from numpy.testing import TestCase, assert_equal, assert_almost_equal
5+
76 from aubio import cvec, filterbank, float_type
8−from utils import array_from_text_file
7+from .utils import array_from_text_file
98
109 class aubio_filterbank_test_case(TestCase):
1110
@@ -62,6 +61,13 @@ class aubio_filterbank_test_case(TestCase): · 50 unmodified lines
6261 f.set_mel_coeffs_slaney(16000)
6362 assert_almost_equal ( expected, f.get_coeffs() )
6463
64+ def test_mfcc_coeffs_get_coeffs(self):
65+ f = filterbank(40, 512)
66+ coeffs = f.get_coeffs()
67+ self.assertIsInstance(coeffs, np.ndarray)
68+ assert_equal (coeffs, 0)
69+ assert_equal (np.shape(coeffs), (40, 512 / 2 + 1))
70+
6571 class aubio_filterbank_wrong_values(TestCase):
6672
6773 def test_negative_window(self):
@@ -81,4 +87,5 @@ class aubio_filterbank_wrong_values(TestCase): · 13 unmodified lines
8187 f(cvec(256))
8288
8389 if __name__ == '__main__':
84− main()
90+ import nose2
91+ nose2.main()
python/tests/test_filterbank_mel.py+136−13
@@ -1,10 +1,12 @@
11 #! /usr/bin/env python
22
3−from unittest import main
4−from numpy.testing import TestCase
5−from numpy.testing import assert_equal, assert_almost_equal
6−from numpy import array, shape
7−from aubio import cvec, filterbank, float_type
3+import numpy as np
4+from numpy.testing import TestCase, assert_equal, assert_almost_equal
5+
6+from aubio import fvec, cvec, filterbank, float_type
7+
8+import warnings
9+warnings.filterwarnings('ignore', category=UserWarning, append=True)
810
911 class aubio_filterbank_mel_test_case(TestCase):
1012
@@ -12,38 +14,159 @@ class aubio_filterbank_mel_test_case(TestCase): · 1 unmodified line
1214 f = filterbank(40, 512)
1315 f.set_mel_coeffs_slaney(16000)
1416 a = f.get_coeffs()
15− assert_equal(shape (a), (40, 512/2 + 1) )
17+ assert_equal(np.shape (a), (40, 512/2 + 1) )
1618
1719 def test_other_slaney(self):
1820 f = filterbank(40, 512*2)
1921 f.set_mel_coeffs_slaney(44100)
20− _ = f.get_coeffs()
22+ self.assertIsInstance(f.get_coeffs(), np.ndarray)
2123 #print "sum is", sum(sum(a))
2224 for win_s in [256, 512, 1024, 2048, 4096]:
2325 f = filterbank(40, win_s)
2426 f.set_mel_coeffs_slaney(32000)
25− _ = f.get_coeffs()
2627 #print "sum is", sum(sum(a))
28+ self.assertIsInstance(f.get_coeffs(), np.ndarray)
2729
2830 def test_triangle_freqs_zeros(self):
2931 f = filterbank(9, 1024)
3032 freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]
31− freqs = array(freq_list, dtype = float_type)
33+ freqs = np.array(freq_list, dtype = float_type)
3234 f.set_triangle_bands(freqs, 48000)
33− _ = f.get_coeffs().T
3435 assert_equal ( f(cvec(1024)), 0)
36+ self.assertIsInstance(f.get_coeffs(), np.ndarray)
3537
3638 def test_triangle_freqs_ones(self):
3739 f = filterbank(9, 1024)
3840 freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]
39− freqs = array(freq_list, dtype = float_type)
41+ freqs = np.array(freq_list, dtype = float_type)
4042 f.set_triangle_bands(freqs, 48000)
41− _ = f.get_coeffs().T
43+ self.assertIsInstance(f.get_coeffs(), np.ndarray)
4244 spec = cvec(1024)
4345 spec.norm[:] = 1
4446 assert_almost_equal ( f(spec),
4547 [ 0.02070313, 0.02138672, 0.02127604, 0.02135417,
4648 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345])
4749
50+ def test_triangle_freqs_with_zeros(self):
51+ """make sure set_triangle_bands works when list starts with 0"""
52+ freq_list = [0, 40, 80]
53+ freqs = np.array(freq_list, dtype = float_type)
54+ f = filterbank(len(freqs)-2, 1024)
55+ f.set_triangle_bands(freqs, 48000)
56+ assert_equal ( f(cvec(1024)), 0)
57+ self.assertIsInstance(f.get_coeffs(), np.ndarray)
58+
59+ def test_triangle_freqs_with_wrong_negative(self):
60+ """make sure set_triangle_bands fails when list contains a negative"""
61+ freq_list = [-10, 0, 80]
62+ f = filterbank(len(freq_list)-2, 1024)
63+ with self.assertRaises(ValueError):
64+ f.set_triangle_bands(fvec(freq_list), 48000)
65+
66+ def test_triangle_freqs_with_wrong_ordering(self):
67+ """make sure set_triangle_bands fails when list not ordered"""
68+ freq_list = [0, 80, 40]
69+ f = filterbank(len(freq_list)-2, 1024)
70+ with self.assertRaises(ValueError):
71+ f.set_triangle_bands(fvec(freq_list), 48000)
72+
73+ def test_triangle_freqs_with_large_freq(self):
74+ """make sure set_triangle_bands warns when freq > nyquist"""
75+ samplerate = 22050
76+ freq_list = [0, samplerate//4, samplerate // 2 + 1]
77+ f = filterbank(len(freq_list)-2, 1024)
78+ # TODO add assert_warns
79+ f.set_triangle_bands(fvec(freq_list), samplerate)
80+
81+ def test_triangle_freqs_with_not_enough_filters(self):
82+ """make sure set_triangle_bands warns when not enough filters"""
83+ samplerate = 22050
84+ freq_list = [0, 100, 1000, 4000, 8000, 10000]
85+ f = filterbank(len(freq_list)-3, 1024)
86+ # TODO add assert_warns
87+ f.set_triangle_bands(fvec(freq_list), samplerate)
88+
89+ def test_triangle_freqs_with_too_many_filters(self):
90+ """make sure set_triangle_bands warns when too many filters"""
91+ samplerate = 22050
92+ freq_list = [0, 100, 1000, 4000, 8000, 10000]
93+ f = filterbank(len(freq_list)-1, 1024)
94+ # TODO add assert_warns
95+ f.set_triangle_bands(fvec(freq_list), samplerate)
96+
97+ def test_triangle_freqs_with_double_value(self):
98+ """make sure set_triangle_bands works with 2 duplicate freqs"""
99+ samplerate = 22050
100+ freq_list = [0, 100, 1000, 4000, 4000, 4000, 10000]
101+ f = filterbank(len(freq_list)-2, 1024)
102+ # TODO add assert_warns
103+ f.set_triangle_bands(fvec(freq_list), samplerate)
104+
105+ def test_triangle_freqs_with_triple(self):
106+ """make sure set_triangle_bands works with 3 duplicate freqs"""
107+ samplerate = 22050
108+ freq_list = [0, 100, 1000, 4000, 4000, 4000, 10000]
109+ f = filterbank(len(freq_list)-2, 1024)
110+ # TODO add assert_warns
111+ f.set_triangle_bands(fvec(freq_list), samplerate)
112+
113+ def test_triangle_freqs_without_norm(self):
114+ """make sure set_triangle_bands works without """
115+ samplerate = 22050
116+ freq_list = fvec([0, 100, 1000, 10000])
117+ f = filterbank(len(freq_list) - 2, 1024)
118+ f.set_norm(0)
119+ f.set_triangle_bands(freq_list, samplerate)
120+ expected = f.get_coeffs()
121+ f.set_norm(1)
122+ f.set_triangle_bands(fvec(freq_list), samplerate)
123+ assert_almost_equal(f.get_coeffs().T,
124+ expected.T * 2. / (freq_list[2:] - freq_list[:-2]))
125+
126+ def test_triangle_freqs_wrong_norm(self):
127+ f = filterbank(10, 1024)
128+ with self.assertRaises(ValueError):
129+ f.set_norm(-1)
130+
131+ def test_triangle_freqs_with_power(self):
132+ f = filterbank(9, 1024)
133+ freqs = fvec([40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000,
134+ 24000])
135+ f.set_power(2)
136+ f.set_triangle_bands(freqs, 48000)
137+ spec = cvec(1024)
138+ spec.norm[:] = .1
139+ expected = fvec([0.02070313, 0.02138672, 0.02127604, 0.02135417,
140+ 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345])
141+ expected /= 100.
142+ assert_almost_equal(f(spec), expected)
143+
144+ def test_mel_coeffs(self):
145+ f = filterbank(40, 1024)
146+ f.set_mel_coeffs(44100, 0, 44100 / 2)
147+
148+ def test_zero_fmax(self):
149+ f = filterbank(40, 1024)
150+ f.set_mel_coeffs(44100, 0, 0)
151+
152+ def test_wrong_mel_coeffs(self):
153+ f = filterbank(40, 1024)
154+ with self.assertRaises(ValueError):
155+ f.set_mel_coeffs_slaney(0)
156+ with self.assertRaises(ValueError):
157+ f.set_mel_coeffs(44100, 0, -44100 / 2)
158+ with self.assertRaises(ValueError):
159+ f.set_mel_coeffs(44100, -0.1, 44100 / 2)
160+ with self.assertRaises(ValueError):
161+ f.set_mel_coeffs(-44100, 0.1, 44100 / 2)
162+ with self.assertRaises(ValueError):
163+ f.set_mel_coeffs_htk(-1, 0, 0)
164+
165+ def test_mel_coeffs_htk(self):
166+ f = filterbank(40, 1024)
167+ f.set_mel_coeffs_htk(44100, 0, 44100 / 2)
168+
169+
48170 if __name__ == '__main__':
49− main()
171+ import nose2
172+ nose2.main()
python/tests/test_fvec.py+8−0
@@ -60,6 +60,14 @@ class aubio_fvec_wrong_values(TestCase): · 59 unmodified lines
6060 self.assertRaises(IndexError, a.__getitem__, 3)
6161 self.assertRaises(IndexError, a.__getitem__, 2)
6262
63+ def test_wrong_dimensions(self):
64+ a = np.array([[[1, 2], [3, 4]]], dtype=float_type)
65+ self.assertRaises(ValueError, fvec, a)
66+
67+ def test_wrong_size(self):
68+ a = np.ndarray([0,], dtype=float_type)
69+ self.assertRaises(ValueError, fvec, a)
70+
6371 class aubio_wrong_fvec_input(TestCase):
6472 """ uses min_removal to test PyAubio_IsValidVector """
6573
python/tests/test_fvec_shift.py+35−0
@@ -0,0 +1,35 @@
1+#! /usr/bin/env python
2+
3+import numpy as np
4+from numpy.testing import TestCase, assert_equal
5+import aubio
6+
7+class aubio_shift_test_case(TestCase):
8+
9+ def run_shift_ishift(self, n):
10+ ramp = np.arange(n, dtype=aubio.float_type)
11+ # construct expected output
12+ # even length: [5. 6. 7. 8. 9. 0. 1. 2. 3. 4.]
13+ # odd length: [4. 5. 6. 0. 1. 2. 3.]
14+ half = n - n//2
15+ expected = np.concatenate([np.arange(half, n), np.arange(half)])
16+ # shift in place, returns modified copy
17+ assert_equal(aubio.shift(ramp), expected)
18+ # check input was changed as expected
19+ assert_equal(ramp, expected)
20+ # construct expected output
21+ expected = np.arange(n)
22+ # revert shift in place, returns modifed copy
23+ assert_equal(aubio.ishift(ramp), expected)
24+ # check input was shifted back
25+ assert_equal(ramp, expected)
26+
27+ def test_can_shift_fvec(self):
28+ self.run_shift_ishift(10)
29+
30+ def test_can_shift_fvec_odd(self):
31+ self.run_shift_ishift(7)
32+
33+from unittest import main
34+if __name__ == '__main__':
35+ main()
python/tests/test_hztomel.py+109−0
@@ -0,0 +1,109 @@
1+#! /usr/bin/env python
2+
3+from unittest import main
4+from numpy.testing import TestCase
5+from numpy.testing import assert_equal, assert_almost_equal
6+import numpy as np
7+import aubio
8+
9+from aubio import hztomel, meltohz
10+from aubio import hztomel_htk, meltohz_htk
11+
12+
13+class aubio_hztomel_test_case(TestCase):
14+
15+ def test_hztomel(self):
16+ assert_equal(hztomel(0.), 0.)
17+ assert_almost_equal(hztomel(400. / 3.), 2., decimal=5)
18+ assert_almost_equal(hztomel(1000. / 3), 5.)
19+ assert_equal(hztomel(200.), 3.)
20+ assert_almost_equal(hztomel(1000.), 15)
21+ assert_almost_equal(hztomel(6400), 42)
22+ assert_almost_equal(hztomel(40960), 69)
23+
24+ for m in np.linspace(0, 1000, 100):
25+ assert_almost_equal(hztomel(meltohz(m)) - m, 0, decimal=3)
26+
27+ def test_meltohz(self):
28+ assert_equal(meltohz(0.), 0.)
29+ assert_almost_equal(meltohz(2), 400. / 3., decimal=4)
30+ assert_equal(meltohz(3.), 200.)
31+ assert_almost_equal(meltohz(5), 1000. / 3., decimal=4)
32+ assert_almost_equal(meltohz(15), 1000., decimal=4)
33+ assert_almost_equal(meltohz(42), 6400., decimal=2)
34+ assert_almost_equal(meltohz(69), 40960., decimal=1)
35+
36+ for f in np.linspace(0, 20000, 1000):
37+ assert_almost_equal(meltohz(hztomel(f)) - f, 0, decimal=1)
38+
39+ def test_meltohz_negative(self):
40+ # TODO add assert_warns
41+ assert_equal(meltohz(-1), 0)
42+
43+ def test_hztomel_negative(self):
44+ # TODO add assert_warns
45+ assert_equal(hztomel(-1), 0)
46+
47+
48+class aubio_hztomel_htk_test_case(TestCase):
49+
50+ def test_meltohz(self):
51+ assert_equal(meltohz(0, htk=True), 0)
52+ assert_almost_equal(meltohz(2595, htk=True), 6300., decimal=1)
53+
54+ def test_hztomel(self):
55+ assert_equal(hztomel(0, htk=True), 0)
56+ assert_almost_equal(hztomel(3428.7, htk=True), 2000., decimal=1)
57+ assert_almost_equal(hztomel(6300, htk=True), 2595., decimal=1)
58+
59+ def test_meltohz_negative(self):
60+ # TODO add assert_warns
61+ assert_equal(meltohz(-1, htk=True), 0)
62+ assert_almost_equal(meltohz(2000, htk=True), 3428.7, decimal=1)
63+ assert_almost_equal(meltohz(1000, htk=True), 1000., decimal=1)
64+
65+ def test_hztomel_negative(self):
66+ # TODO add assert_warns
67+ assert_equal(hztomel(-1, htk=True), 0)
68+ assert_almost_equal(hztomel(1000, htk=True), 1000., decimal=1)
69+
70+ def test_hztomel_htk(self):
71+ for f in np.linspace(0, 20000, 1000):
72+ assert_almost_equal(meltohz_htk(hztomel_htk(f)) - f, 0, decimal=1)
73+ for f in np.linspace(0, 20000, 1000):
74+ assert_almost_equal(hztomel_htk(meltohz_htk(f)) - f, 0, decimal=1)
75+
76+
77+class aubio_hztomel_wrong_values(TestCase):
78+ """ more tests to cover all branches """
79+
80+ def test_hztomel_wrong_values(self):
81+ with self.assertRaises(TypeError):
82+ hztomel('s')
83+
84+ def test_meltohz_wrong_values(self):
85+ with self.assertRaises(TypeError):
86+ meltohz(bytes('ad'))
87+
88+ def test_meltohz_no_arg(self):
89+ with self.assertRaises(TypeError):
90+ meltohz()
91+
92+ def test_meltohz_htk_no_arg(self):
93+ with self.assertRaises(TypeError):
94+ meltohz_htk()
95+
96+ def test_hztomel_htk_wrong_values(self):
97+ with self.assertRaises(TypeError):
98+ hztomel_htk('0')
99+
100+ def test_hztomel_htk_false(self):
101+ assert hztomel(120, htk=False) == hztomel(120)
102+
103+ def test_meltohz_htk_false(self):
104+ assert meltohz(12, htk=False) == meltohz(12)
105+
106+
107+if __name__ == '__main__':
108+ from unittest import main
109+ main()
python/tests/test_mfcc.py+37−0
@@ -110,5 +110,42 @@ class aubio_mfcc_all_parameters(TestCase): · 109 unmodified lines
110110 o(spec)
111111 #print coeffs
112112
113+
114+class aubio_mfcc_fb_params(TestCase):
115+
116+ def test_set_scale(self):
117+ buf_size, n_filters, n_coeffs, samplerate = 512, 20, 10, 16000
118+ m = mfcc(buf_size, n_filters, n_coeffs, samplerate)
119+ m.set_scale(10.5)
120+ assert m.get_scale() == 10.5
121+ m(cvec(buf_size))
122+
123+ def test_set_power(self):
124+ buf_size, n_filters, n_coeffs, samplerate = 512, 20, 10, 16000
125+ m = mfcc(buf_size, n_filters, n_coeffs, samplerate)
126+ m.set_power(2.5)
127+ assert m.get_power() == 2.5
128+ m(cvec(buf_size))
129+
130+ def test_set_mel_coeffs(self):
131+ buf_size, n_filters, n_coeffs, samplerate = 512, 20, 10, 16000
132+ m = mfcc(buf_size, n_filters, n_coeffs, samplerate)
133+ m.set_mel_coeffs(0., samplerate/2.)
134+ m(cvec(buf_size))
135+
136+ def test_set_mel_coeffs_htk(self):
137+ buf_size, n_filters, n_coeffs, samplerate = 512, 20, 10, 16000
138+ m = mfcc(buf_size, n_filters, n_coeffs, samplerate)
139+ m.set_mel_coeffs_htk(0., samplerate/2.)
140+ m(cvec(buf_size))
141+
142+ def test_set_mel_coeffs_slaney(self):
143+ buf_size, n_filters, n_coeffs, samplerate = 512, 40, 10, 16000
144+ m = mfcc(buf_size, n_filters, n_coeffs, samplerate)
145+ m.set_mel_coeffs_slaney()
146+ m(cvec(buf_size))
147+ assert m.get_power() == 1
148+ assert m.get_scale() == 1
149+
113150 if __name__ == '__main__':
114151 main()
python/tests/test_midi2note.py+6−4
@@ -2,6 +2,7 @@ · 1 unmodified line
22 # -*- coding: utf-8 -*-
33
44 from aubio import midi2note
5+from nose2.tools import params
56 import unittest
67
78 list_of_known_midis = (
@@ -16,10 +17,10 @@ list_of_known_midis = ( · 8 unmodified lines
1617
1718 class midi2note_good_values(unittest.TestCase):
1819
19− def test_midi2note_known_values(self):
20+ @params(*list_of_known_midis)
21+ def test_midi2note_known_values(self, midi, note):
2022 " known values are correctly converted "
21− for midi, note in list_of_known_midis:
22− self.assertEqual ( midi2note(midi), note )
23+ self.assertEqual ( midi2note(midi), note )
2324
2425 class midi2note_wrong_values(unittest.TestCase):
2526
@@ -40,4 +41,5 @@ class midi2note_wrong_values(unittest.TestCase): · 14 unmodified lines
4041 self.assertRaises(TypeError, midi2note, "a")
4142
4243 if __name__ == '__main__':
43− unittest.main()
44+ import nose2
45+ nose2.main()
python/tests/test_note2midi.py+67−7
@@ -3,7 +3,8 @@ · 2 unmodified lines
33
44 from __future__ import unicode_literals
55
6−from aubio import note2midi, freq2note
6+from aubio import note2midi, freq2note, note2freq, float_type
7+from nose2.tools import params
78 import unittest
89
910 list_of_known_notes = (
@@ -13,24 +14,57 @@ list_of_known_notes = ( · 3 unmodified lines
1314 ( 'C3', 48 ),
1415 ( 'B3', 59 ),
1516 ( 'B#3', 60 ),
17+ ( 'C♯4', 61 ),
1618 ( 'A4', 69 ),
1719 ( 'A#4', 70 ),
20+ ( 'A♯4', 70 ),
21+ ( 'A\u266f4', 70 ),
1822 ( 'Bb4', 70 ),
1923 ( 'B♭4', 70 ),
24+ ( 'B\u266d4', 70 ),
2025 ( 'G8', 115 ),
2126 ( 'G♯8', 116 ),
2227 ( 'G9', 127 ),
23− ( 'G\udd2a2', 45 ),
24− ( 'B\ufffd2', 45 ),
2528 ( 'A♮2', 45 ),
2629 )
2730
31+list_of_known_notes_with_unicode_issues = (
32+ ('C𝄪4', 62 ),
33+ ('E𝄫4', 62 ),
34+ )
35+
36+list_of_unknown_notes = (
37+ ( 'G\udd2a2' ),
38+ ( 'B\ufffd2' ),
39+ ( 'B\u266e\u266e2' ),
40+ ( 'B\u266f\u266d3' ),
41+ ( 'B33' ),
42+ ( 'C.3' ),
43+ ( 'A' ),
44+ ( '2' ),
45+ )
46+
2847 class note2midi_good_values(unittest.TestCase):
2948
30− def test_note2midi_known_values(self):
49+ @params(*list_of_known_notes)
50+ def test_note2midi_known_values(self, note, midi):
3151 " known values are correctly converted "
32− for note, midi in list_of_known_notes:
52+ self.assertEqual ( note2midi(note), midi )
53+
54+ @params(*list_of_known_notes_with_unicode_issues)
55+ def test_note2midi_known_values_with_unicode_issues(self, note, midi):
56+ " known values are correctly converted, unless decoding is expected to fail"
57+ try:
3358 self.assertEqual ( note2midi(note), midi )
59+ except UnicodeEncodeError as e:
60+ import sys
61+ strfmt = "len(u'\\U0001D12A') != 1, excpected decoding failure | {:s} | {:s} {:s}"
62+ strres = strfmt.format(e, sys.platform, sys.version)
63+ # happens with: darwin 2.7.10, windows 2.7.12
64+ if len('\U0001D12A') != 1 and sys.version[0] == '2':
65+ self.skipTest(strres + " | upgrade to Python 3 to fix")
66+ else:
67+ raise
3468
3569 class note2midi_wrong_values(unittest.TestCase):
3670
@@ -66,12 +100,38 @@ class note2midi_wrong_values(unittest.TestCase): · 29 unmodified lines
66100 " fails when passed a non-string value "
67101 self.assertRaises(TypeError, note2midi, 123)
68102
103+ def test_note2midi_wrong_data_too_long(self):
104+ " fails when passed a note with a note name longer than expected"
105+ self.assertRaises(ValueError, note2midi, 'CB+-3')
106+
107+ @params(*list_of_unknown_notes)
108+ def test_note2midi_unknown_values(self, note):
109+ " unknown values throw out an error "
110+ self.assertRaises(ValueError, note2midi, note)
69111
70112 class freq2note_simple_test(unittest.TestCase):
71113
72− def test_freq2note(self):
114+ def test_freq2note_above(self):
73115 " make sure freq2note(441) == A4 "
74116 self.assertEqual("A4", freq2note(441))
75117
118+ def test_freq2note_under(self):
119+ " make sure freq2note(439) == A4 "
120+ self.assertEqual("A4", freq2note(439))
121+
122+class note2freq_simple_test(unittest.TestCase):
123+
124+ def test_note2freq(self):
125+ " make sure note2freq('A3') == 220"
126+ self.assertEqual(220, note2freq("A3"))
127+
128+ def test_note2freq_under(self):
129+ " make sure note2freq(A4) == 440"
130+ if float_type == 'float32':
131+ self.assertEqual(440, note2freq("A4"))
132+ else:
133+ self.assertLess(abs(note2freq("A4")-440), 1.e-12)
134+
76135 if __name__ == '__main__':
77− unittest.main()
136+ import nose2
137+ nose2.main()
python/tests/test_notes.py+95−0
@@ -0,0 +1,95 @@
1+#! /usr/bin/env python
2+
3+from unittest import main
4+from numpy.testing import TestCase, assert_equal, assert_almost_equal
5+from aubio import notes
6+
7+AUBIO_DEFAULT_NOTES_SILENCE = -70.
8+AUBIO_DEFAULT_NOTES_RELEASE_DROP = 10.
9+AUBIO_DEFAULT_NOTES_MINIOI_MS = 30.
10+
11+class aubio_notes_default(TestCase):
12+
13+ def test_members(self):
14+ o = notes()
15+ assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate],
16+ [1024,512,'default',44100])
17+
18+
19+class aubio_notes_params(TestCase):
20+
21+ samplerate = 44100
22+
23+ def setUp(self):
24+ self.o = notes(samplerate = self.samplerate)
25+
26+ def test_get_minioi_ms(self):
27+ assert_equal (self.o.get_minioi_ms(), AUBIO_DEFAULT_NOTES_MINIOI_MS)
28+
29+ def test_set_minioi_ms(self):
30+ val = 40.
31+ self.o.set_minioi_ms(val)
32+ assert_almost_equal (self.o.get_minioi_ms(), val)
33+
34+ def test_get_silence(self):
35+ assert_equal (self.o.get_silence(), AUBIO_DEFAULT_NOTES_SILENCE)
36+
37+ def test_set_silence(self):
38+ val = -50
39+ self.o.set_silence(val)
40+ assert_equal (self.o.get_silence(), val)
41+
42+ def test_get_release_drop(self):
43+ assert_equal (self.o.get_release_drop(), AUBIO_DEFAULT_NOTES_RELEASE_DROP)
44+
45+ def test_set_release_drop(self):
46+ val = 50
47+ self.o.set_release_drop(val)
48+ assert_equal (self.o.get_release_drop(), val)
49+
50+ def test_set_release_drop_wrong(self):
51+ val = -10
52+ with self.assertRaises(ValueError):
53+ self.o.set_release_drop(val)
54+
55+from .utils import list_all_sounds
56+list_of_sounds = list_all_sounds('sounds')
57+
58+class aubio_notes_sinewave(TestCase):
59+
60+ def analyze_file(self, filepath, samplerate=0):
61+ from aubio import source
62+ import numpy as np
63+ win_s = 512 # fft size
64+ hop_s = 256 # hop size
65+
66+ s = source(filepath, samplerate, hop_s)
67+ samplerate = s.samplerate
68+
69+ tolerance = 0.8
70+
71+ notes_o = notes("default", win_s, hop_s, samplerate)
72+ total_frames = 0
73+
74+ results = []
75+ while True:
76+ samples, read = s()
77+ new_note = notes_o(samples)
78+ if (new_note[0] != 0):
79+ note_str = ' '.join(["%.2f" % i for i in new_note])
80+ results.append( [total_frames, np.copy(new_note)] )
81+ total_frames += read
82+ if read < hop_s: break
83+ return results
84+
85+ def test_sinewave(self):
86+ for filepath in list_of_sounds:
87+ if '44100Hz_44100f_sine441.wav' in filepath:
88+ results = self.analyze_file(filepath)
89+ assert_equal (len(results), 1)
90+ assert_equal (len(results[0]), 2)
91+ assert_equal (results[0][0], 1280)
92+ assert_equal (results[0][1], [69, 123, -1])
93+
94+if __name__ == '__main__':
95+ main()
python/tests/test_onset.py+40−8
@@ -2,7 +2,7 @@ · 1 unmodified line
22
33 from unittest import main
44 from numpy.testing import TestCase, assert_equal, assert_almost_equal
5−from aubio import onset
5+from aubio import onset, fvec
66
77 class aubio_onset_default(TestCase):
88
@@ -19,25 +19,25 @@ class aubio_onset_params(TestCase): · 10 unmodified lines
1919 self.o = onset(samplerate = self.samplerate)
2020
2121 def test_get_delay(self):
22− assert_equal (self.o.get_delay(), int(4.3 * self.o.hop_size))
22+ self.assertGreater(self.o.get_delay(), 0)
2323
2424 def test_get_delay_s(self):
25− assert_almost_equal (self.o.get_delay_s(), self.o.get_delay() / float(self.samplerate))
25+ self.assertGreater(self.o.get_delay_s(), 0.)
2626
2727 def test_get_delay_ms(self):
28− assert_almost_equal (self.o.get_delay_ms(), self.o.get_delay() * 1000. / self.samplerate, 5)
28+ self.assertGreater(self.o.get_delay_ms(), 0.)
2929
3030 def test_get_minioi(self):
31− assert_almost_equal (self.o.get_minioi(), 0.02 * self.samplerate)
31+ self.assertGreater(self.o.get_minioi(), 0)
3232
3333 def test_get_minioi_s(self):
34− assert_almost_equal (self.o.get_minioi_s(), 0.02)
34+ self.assertGreater(self.o.get_minioi_s(), 0.)
3535
3636 def test_get_minioi_ms(self):
37− assert_equal (self.o.get_minioi_ms(), 20.)
37+ self.assertGreater(self.o.get_minioi_ms(), 0.)
3838
3939 def test_get_threshold(self):
40− assert_almost_equal (self.o.get_threshold(), 0.3)
40+ self.assertGreater(self.o.get_threshold(), 0.)
4141
4242 def test_set_delay(self):
4343 val = 256
@@ -83,5 +83,37 @@ class aubio_onset_32000(aubio_onset_params): · 39 unmodified lines
8383 class aubio_onset_8000(aubio_onset_params):
8484 samplerate = 8000
8585
86+class aubio_onset_coverate(TestCase):
87+ # extra tests to execute the C routines and improve coverage
88+
89+ def test_all_methods(self):
90+ for method in ['default', 'energy', 'hfc', 'complexdomain', 'complex',
91+ 'phase', 'wphase', 'mkl', 'kl', 'specflux', 'specdiff',
92+ 'old_default']:
93+ o = onset(method=method, buf_size=512, hop_size=256)
94+ o(fvec(256))
95+
96+ def test_get_methods(self):
97+ o = onset(method='default', buf_size=512, hop_size=256)
98+
99+ assert o.get_silence() == -70
100+ o.set_silence(-20)
101+ assert_almost_equal(o.get_silence(), -20)
102+
103+ assert o.get_compression() == 1
104+ o.set_compression(.99)
105+ assert_almost_equal(o.get_compression(), .99)
106+
107+ assert o.get_awhitening() == 0
108+ o.set_awhitening(1)
109+ assert o.get_awhitening() == 1
110+
111+ o.get_last()
112+ o.get_last_ms()
113+ o.get_last_s()
114+ o.get_descriptor()
115+ o.get_thresholded_descriptor()
116+
117+
86118 if __name__ == '__main__':
87119 main()
python/tests/test_phasevoc.py+17−1
@@ -46,9 +46,25 @@ class aubio_pvoc_test_case(TestCase): · 45 unmodified lines
4646 r = f.rdo(s)
4747 assert_equal ( t, 0.)
4848 assert_equal ( s.norm, 0.)
49− assert_equal ( s.phas, 0.)
49+ try:
50+ assert_equal ( s.phas, 0 )
51+ except AssertionError:
52+ assert_equal (s.phas[s.phas > 0], +np.pi)
53+ assert_equal (s.phas[s.phas < 0], -np.pi)
54+ assert_equal (np.abs(s.phas[np.abs(s.phas) != np.pi]), 0)
55+ self.skipTest('pvoc(fvec(%d)).phas != +0, ' % win_s \
56+ + 'This is expected when using fftw3 on powerpc.')
5057 assert_equal ( r, 0.)
5158
59+ def test_no_overlap(self):
60+ win_s, hop_s = 1024, 1024
61+ f = pvoc (win_s, hop_s)
62+ t = fvec (hop_s)
63+ for _ in range(4):
64+ s = f(t)
65+ r = f.rdo(s)
66+ assert_equal ( t, 0.)
67+
5268 @params(
5369 ( 256, 8),
5470 ( 256, 4),
python/tests/test_pitch.py+2−2
@@ -70,8 +70,8 @@ class aubio_pitch_Sinusoid(TestCase): · 69 unmodified lines
7070 #print 'len(pitches), cut:', len(pitches), cut
7171 #print 'median errors: ', median(errors), 'median pitches: ', median(pitches)
7272
73−pitch_algorithms = [ "default", "yinfft", "yin", "schmitt", "mcomb", "fcomb" , "specacf" ]
74−pitch_algorithms = [ "default", "yinfft", "yin", "schmitt", "mcomb", "fcomb" ]
73+pitch_algorithms = [ "default", "yinfft", "yin", "yinfast", "schmitt", "mcomb", "fcomb" , "specacf" ]
74+pitch_algorithms = [ "default", "yinfft", "yin", "yinfast", "schmitt", "mcomb", "fcomb" ]
7575
7676 #freqs = [ 27.5, 55., 110., 220., 440., 880., 1760., 3520. ]
7777 freqs = [ 110., 220., 440., 880., 1760., 3520. ]
python/tests/test_sink.py+32−1
@@ -4,7 +4,10 @@ from nose2 import main · 3 unmodified lines
44 from nose2.tools import params
55 from numpy.testing import TestCase
66 from aubio import fvec, source, sink
7−from utils import list_all_sounds, get_tmp_sink_path, del_tmp_sink_path
7+from .utils import list_all_sounds, get_tmp_sink_path, del_tmp_sink_path
8+
9+import warnings
10+warnings.filterwarnings('ignore', category=UserWarning, append=True)
811
912 list_of_sounds = list_all_sounds('sounds')
1013 samplerates = [0, 44100, 8000, 32000]
@@ -26,6 +29,26 @@ class aubio_sink_test_case(TestCase): · 15 unmodified lines
2629 if not len(list_of_sounds):
2730 self.skipTest('add some sound files in \'python/tests/sounds\'')
2831
32+ def test_wrong_filename(self):
33+ with self.assertRaises(RuntimeError):
34+ sink('')
35+
36+ def test_wrong_samplerate(self):
37+ with self.assertRaises(RuntimeError):
38+ sink(get_tmp_sink_path(), -1)
39+
40+ def test_wrong_samplerate_too_large(self):
41+ with self.assertRaises(RuntimeError):
42+ sink(get_tmp_sink_path(), 1536001, 2)
43+
44+ def test_wrong_channels(self):
45+ with self.assertRaises(RuntimeError):
46+ sink(get_tmp_sink_path(), 44100, -1)
47+
48+ def test_wrong_channels_too_large(self):
49+ with self.assertRaises(RuntimeError):
50+ sink(get_tmp_sink_path(), 44100, 202020)
51+
2952 def test_many_sinks(self):
3053 from tempfile import mkdtemp
3154 import os.path
@@ -93,5 +116,13 @@ class aubio_sink_test_case(TestCase): · 61 unmodified lines
93116 g.close()
94117 del_tmp_sink_path(sink_path)
95118
119+ def test_read_with(self):
120+ samplerate = 44100
121+ sink_path = get_tmp_sink_path()
122+ vec = fvec(128)
123+ with sink(sink_path, samplerate) as g:
124+ for _ in range(10):
125+ g(vec, 128)
126+
96127 if __name__ == '__main__':
97128 main()
python/tests/test_slicing.py+27−6
@@ -3,8 +3,8 @@ · 2 unmodified lines
33 from unittest import main
44 from numpy.testing import TestCase, assert_equal
55 from aubio import slice_source_at_stamps
6−from utils import count_files_in_directory, get_default_test_sound
7−from utils import count_samples_in_directory, count_samples_in_file
6+from .utils import count_files_in_directory, get_default_test_sound
7+from .utils import count_samples_in_directory, count_samples_in_file
88
99 import tempfile
1010 import shutil
@@ -23,19 +23,27 @@ class aubio_slicing_test_case(TestCase): · 12 unmodified lines
2323
2424 def test_slice_start_only_no_zero(self):
2525 regions_start = [i*1000 for i in range(1, n_slices)]
26− slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir)
26+ slice_source_at_stamps(self.source_file, regions_start,
27+ output_dir = self.output_dir, create_first=True)
2728
2829 def test_slice_start_beyond_end(self):
2930 regions_start = [i*1000 for i in range(1, n_slices)]
3031 regions_start += [count_samples_in_file(self.source_file) + 1000]
31− slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir)
32+ slice_source_at_stamps(self.source_file, regions_start,
33+ output_dir = self.output_dir, create_first=True)
3234
3335 def test_slice_start_every_blocksize(self):
3436 hopsize = 200
35− regions_start = [i*hopsize for i in range(1, n_slices)]
37+ regions_start = [i*hopsize for i in range(0, n_slices)]
3638 slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir,
3739 hopsize = 200)
3840
41+ def test_slice_start_every_half_blocksize(self):
42+ hopsize = 200
43+ regions_start = [i*hopsize//2 for i in range(0, n_slices)]
44+ slice_source_at_stamps(self.source_file, regions_start,
45+ output_dir = self.output_dir, hopsize = 200)
46+
3947 def tearDown(self):
4048 original_samples = count_samples_in_file(self.source_file)
4149 written_samples = count_samples_in_directory(self.output_dir)
@@ -91,6 +99,19 @@ class aubio_slicing_with_ends_test_case(TestCase): · 49 unmodified lines
9199 assert_equal(written_samples, expected_samples,
92100 "number of samples written different from number of original samples")
93101
102+ def test_slice_start_and_ends_with_missing_end(self):
103+ regions_start = [i*1000 for i in range(n_slices)]
104+ regions_ends = [r-1 for r in regions_start[1:]]
105+ slice_source_at_stamps(self.source_file, regions_start, regions_ends,
106+ output_dir = self.output_dir)
107+ written_samples = count_samples_in_directory(self.output_dir)
108+ original_samples = count_samples_in_file(self.source_file)
109+ total_files = count_files_in_directory(self.output_dir)
110+ assert_equal(n_slices, total_files,
111+ "number of slices created different from expected")
112+ assert_equal(written_samples, original_samples,
113+ "number of samples written different from number of original samples")
114+
94115 def tearDown(self):
95116 shutil.rmtree(self.output_dir)
96117
@@ -133,7 +154,7 @@ class aubio_slicing_wrong_ends_test_case(TestCase): · 36 unmodified lines
133154 regions_start = [i*1000 for i in range(1, n_slices)]
134155 regions_end = None
135156 slice_source_at_stamps (self.source_file, regions_start, regions_end,
136− output_dir = self.output_dir)
157+ output_dir = self.output_dir, create_first=True)
137158 total_files = count_files_in_directory(self.output_dir)
138159 assert_equal(n_slices, total_files,
139160 "number of slices created different from expected")
python/tests/test_source.py+34−7
@@ -2,9 +2,9 @@ · 1 unmodified line
22
33 from nose2 import main
44 from nose2.tools import params
5−from numpy.testing import TestCase
5+from numpy.testing import TestCase, assert_equal
66 from aubio import source
7−from utils import list_all_sounds
7+from .utils import list_all_sounds
88
99 import warnings
1010 warnings.filterwarnings('ignore', category=UserWarning, append=True)
@@ -51,9 +51,11 @@ class aubio_source_read_test_case(aubio_source_test_case_base): · 40 unmodified lines
5151 def read_from_source(self, f):
5252 total_frames = 0
5353 while True:
54− _ , read = f()
54+ samples , read = f()
5555 total_frames += read
56− if read < f.hop_size: break
56+ if read < f.hop_size:
57+ assert_equal(samples[read:], 0)
58+ break
5759 #result_str = "read {:.2f}s ({:d} frames in {:d} blocks at {:d}Hz) from {:s}"
5860 #result_params = total_frames / float(f.samplerate), total_frames, total_frames//f.hop_size, f.samplerate, f.uri
5961 #print (result_str.format(*result_params))
@@ -66,7 +68,14 @@ class aubio_source_read_test_case(aubio_source_test_case_base): · 6 unmodified lines
6668 except RuntimeError as e:
6769 self.skipTest('failed opening with hop_s = {:d}, samplerate = {:d} ({:s})'.format(hop_size, samplerate, str(e)))
6870 assert f.samplerate != 0
69− self.read_from_source(f)
71+ read_frames = self.read_from_source(f)
72+ if 'f_' in soundfile and samplerate == 0:
73+ import re
74+ f = re.compile('.*_\([0:9]*f\)_.*')
75+ match_f = re.findall('([0-9]*)f_', soundfile)
76+ if len(match_f) == 1:
77+ expected_frames = int(match_f[0])
78+ self.assertEqual(expected_frames, read_frames)
7079
7180 @params(*list_of_sounds)
7281 def test_samplerate_none(self, p):
@@ -149,13 +158,31 @@ class aubio_source_readmulti_test_case(aubio_source_read_test_case): · 76 unmodified lines
149158 def read_from_source(self, f):
150159 total_frames = 0
151160 while True:
152− _, read = f.do_multi()
161+ samples, read = f.do_multi()
153162 total_frames += read
154− if read < f.hop_size: break
163+ if read < f.hop_size:
164+ assert_equal(samples[:,read:], 0)
165+ break
155166 #result_str = "read {:.2f}s ({:d} frames in {:d} channels and {:d} blocks at {:d}Hz) from {:s}"
156167 #result_params = total_frames / float(f.samplerate), total_frames, f.channels, int(total_frames/f.hop_size), f.samplerate, f.uri
157168 #print (result_str.format(*result_params))
158169 return total_frames
159170
171+class aubio_source_with(aubio_source_test_case_base):
172+
173+ #@params(*list_of_sounds)
174+ @params(*list_of_sounds)
175+ def test_read_from_mono(self, filename):
176+ total_frames = 0
177+ hop_size = 2048
178+ with source(filename, 0, hop_size) as input_source:
179+ assert_equal(input_source.hop_size, hop_size)
180+ #assert_equal(input_source.samplerate, samplerate)
181+ total_frames = 0
182+ for frames in input_source:
183+ total_frames += frames.shape[-1]
184+ # check we read as many samples as we expected
185+ assert_equal(total_frames, input_source.duration)
186+
160187 if __name__ == '__main__':
161188 main()
python/tests/test_source_channels.py+93−0
@@ -0,0 +1,93 @@
1+#! /usr/bin/env python
2+
3+"""A brute force test using `sink` to create and write samples to a stereo
4+file, then `source` to check the correct content is read from the files."""
5+
6+import os.path
7+import unittest
8+import aubio
9+import numpy as np
10+from numpy.testing import assert_equal
11+from .utils import get_tmp_sink_path
12+
13+class aubio_source_test_case(unittest.TestCase):
14+
15+ def test_read_from_mono(self):
16+ out = get_tmp_sink_path()
17+ samplerate = 44100
18+ hop_size = 256
19+ blocks = 10
20+ channels = 1
21+ write_samples = np.ones([channels, hop_size], dtype=aubio.float_type)
22+ write_samples *= .5
23+ self.check_write_and_read(samplerate, channels, hop_size, blocks,
24+ write_samples)
25+
26+ def test_read_from_stereo(self):
27+ out = get_tmp_sink_path()
28+ samplerate = 44100
29+ hop_size = 256
30+ blocks = 10
31+ channels = 1
32+ write_samples = np.ones([channels, hop_size], dtype=aubio.float_type)
33+ write_samples *= .5
34+ self.check_write_and_read(samplerate, channels, hop_size, blocks,
35+ write_samples)
36+
37+ def test_read_from_half_stereo(self):
38+ samplerate = 16000
39+ channels = 2
40+ hop_size = 512
41+ blocks = 10
42+ write_samples = np.ones([channels, hop_size], dtype=aubio.float_type)
43+ write_samples *= .5
44+ write_samples[1, :] = 0
45+ self.check_write_and_read(samplerate, channels, hop_size, blocks,
46+ write_samples)
47+
48+ def test_read_from_cancelling_channels(self):
49+ samplerate = 16000
50+ channels = 2
51+ hop_size = 512
52+ blocks = 10
53+ write_samples = np.ones([channels, hop_size], dtype=aubio.float_type)
54+ write_samples *= .5
55+ write_samples[1] *= -1
56+ self.check_write_and_read(samplerate, channels, hop_size, blocks,
57+ write_samples)
58+
59+ def test_read_from_strange_three_channels(self):
60+ samplerate = 8000
61+ channels = 3
62+ hop_size = 123
63+ blocks = 10
64+ write_samples = np.ones([channels, hop_size], dtype=aubio.float_type)
65+ write_samples *= .5
66+ write_samples[1, :] = 0
67+ self.check_write_and_read(samplerate, channels, hop_size, blocks,
68+ write_samples)
69+
70+ def check_write_and_read(self, samplerate, channels,
71+ hop_size, blocks, write_samples):
72+ expected_mono = np.sum(write_samples, axis=0)/write_samples.shape[0]
73+ out = get_tmp_sink_path()
74+ snk = aubio.sink(out, samplerate, channels=channels)
75+ for i in range(blocks):
76+ snk.do_multi(write_samples, hop_size)
77+ # close the sink before reading from it
78+ snk.close()
79+
80+ src = aubio.source(out, samplerate, hop_size)
81+ for i in range(blocks):
82+ read_samples, read = src.do_multi()
83+ assert_equal (read_samples, write_samples)
84+ assert_equal (read, hop_size)
85+
86+ src.seek(0)
87+ for i in range(blocks):
88+ read_samples, read = src()
89+ assert_equal (read, hop_size)
90+ assert_equal (read_samples, expected_mono)
91+
92+if __name__ == '__main__':
93+ unittest.main()
python/tests/test_tempo.py+91−0
@@ -0,0 +1,91 @@
1+#! /usr/bin/env python
2+
3+from unittest import main
4+from numpy.testing import TestCase, assert_equal, assert_almost_equal
5+import aubio
6+
7+class aubio_tempo_default(TestCase):
8+
9+ def test_members(self):
10+ o = aubio.tempo()
11+ assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate],
12+ [1024,512,'default',44100])
13+
14+class aubio_tempo_params(TestCase):
15+
16+ samplerate = 44100
17+
18+ def setUp(self):
19+ self.o = aubio.tempo(samplerate = self.samplerate)
20+
21+ def test_get_delay(self):
22+ self.assertEqual(self.o.get_delay(), 0)
23+
24+ def test_set_delay(self):
25+ val = 256
26+ self.o.set_delay(val)
27+ assert_equal (self.o.get_delay(), val)
28+
29+ def test_get_delay_s(self):
30+ self.assertEqual(self.o.get_delay_s(), 0.)
31+
32+ def test_set_delay_s(self):
33+ val = .05
34+ self.o.set_delay_s(val)
35+ assert_almost_equal (self.o.get_delay_s(), val)
36+
37+ def test_get_delay_ms(self):
38+ self.assertEqual(self.o.get_delay_ms(), 0.)
39+
40+ def test_set_delay_ms(self):
41+ val = 50.
42+ self.o.set_delay_ms(val)
43+ assert_almost_equal (self.o.get_delay_ms(), val)
44+
45+ def test_get_threshold(self):
46+ assert_almost_equal(self.o.get_threshold(), 0.3)
47+
48+ def test_set_threshold(self):
49+ val = .1
50+ self.o.set_threshold(val)
51+ assert_almost_equal (self.o.get_threshold(), val)
52+
53+ def test_get_silence(self):
54+ self.assertEqual(self.o.get_silence(), -90.)
55+
56+ def test_set_silence(self):
57+ val = -50.
58+ self.o.set_silence(val)
59+ assert_almost_equal (self.o.get_silence(), val)
60+
61+ def test_get_last(self):
62+ self.assertEqual(self.o.get_last(), 0.)
63+
64+ def test_get_last_s(self):
65+ self.assertEqual(self.o.get_last_s(), 0.)
66+
67+ def test_get_last_ms(self):
68+ self.assertEqual(self.o.get_last_ms(), 0.)
69+
70+ def test_get_period(self):
71+ self.assertEqual(self.o.get_period(), 0.)
72+
73+ def test_get_period_s(self):
74+ self.assertEqual(self.o.get_period_s(), 0.)
75+
76+ def test_get_last_tatum(self):
77+ self.assertEqual(self.o.get_last_tatum(), 0.)
78+
79+ def test_set_tatum_signature(self):
80+ self.o.set_tatum_signature(8)
81+ self.o.set_tatum_signature(64)
82+ self.o.set_tatum_signature(1)
83+
84+ def test_set_wrong_tatum_signature(self):
85+ with self.assertRaises(ValueError):
86+ self.o.set_tatum_signature(101)
87+ with self.assertRaises(ValueError):
88+ self.o.set_tatum_signature(0)
89+
90+if __name__ == '__main__':
91+ main()
scripts/build_android+41−0
@@ -0,0 +1,41 @@
1+#! /bin/bash
2+
3+set -e
4+set -x
5+
6+# location of android NDK
7+NDK_PATH=$PWD/../contrib/android-ndk-r12
8+
9+WAFOPTS="--disable-avcodec --disable-samplerate --disable-jack --disable-sndfile"
10+
11+# set these variables to change the default values
12+[ -z $PLATFORM ] && PLATFORM=android-19
13+[ -z $ARCH ] && ARCH=arm
14+
15+# location nof the standalone toolchains, created with
16+# $NDK_PATH/build/tools/make-standalone-toolchains.sh
17+NDK_TOOLCHAINS=$PWD/contrib
18+
19+# location of the current toolchain
20+CURRENT_TOOLCHAIN=$NDK_TOOLCHAINS/toolchain-$PLATFORM-$ARCH
21+
22+# if it does not exist, create the toolchain
23+[ -d $CURRENT_TOOLCHAIN ] || \
24+ $NDK_PATH/build/tools/make-standalone-toolchain.sh \
25+ --platform=$PLATFORM --arch=$ARCH \
26+ --install-dir=$CURRENT_TOOLCHAIN
27+
28+# aubio install destination directory
29+DESTDIR=$PWD/dist-$PLATFORM-$ARCH
30+
31+# wipe it out if it exists
32+[ -d $DESTDIR ] && rm -rf $DESTDIR
33+
34+# get the link to gcc
35+CC=`ls $CURRENT_TOOLCHAIN/*-linux-android*/bin/gcc`
36+
37+CFLAGS="-Os" \
38+ CC=$CC \
39+ ./waf distclean configure build install --destdir=$DESTDIR \
40+ --verbose \
41+ --with-target-platform=android $WAFOPTS
scripts/build_apple_frameworks+3−0
@@ -1,5 +1,8 @@
11 #! /bin/sh
22
3+# cd to aubio directory for consistency
4+cd `dirname $0`/..
5+
36 AUBIO_TMPDIR=`mktemp -d /var/tmp/aubio-build-XXXX`
47 PACKAGE=aubio
58 source VERSION
scripts/build_emscripten+4−7
@@ -1,4 +1,4 @@
1−#! /bin/sh
1+#! /bin/bash
22
33 function checkprog() {
44 type $1 >/dev/null 2>&1 || { echo >&2 "$1 required but not found, aborting."; exit 1; }
@@ -9,13 +9,10 @@ checkprog emconfigure · 4 unmodified lines
99 checkprog emmake
1010
1111 # clean
12−emmake ./waf distclean
12+./waf distclean
1313
1414 # configure
15−emconfigure ./waf configure --prefix=$EMSCRIPTEN/system/local/ --with-target-platform emscripten
15+emconfigure ./waf configure --with-target-platform emscripten $*
1616
1717 # build
18−emmake ./waf --testcmd="node %s"
19−
20−# intall
21−#emmake ./waf install
18+emmake ./waf build
scripts/build_mingw+109−18
@@ -1,28 +1,119 @@
11 #! /bin/bash
22
3−# This script cross compiles aubio for windows using mingw, both for 32 and 64
4−# bits. Built binaries will be placed in ./dist-win32 and ./dist-win64.
5−
3+# This script cross compiles aubio for windows using mingw, four times:
4+#
5+# - 32 and 64 bits with no external dependencies
6+# - 32 and 64 bits against ffmpeg
7+#
68 # On debian or ubuntu, you will want to 'apt-get install gcc-mingw-w64'
79
810 set -e
911 set -x
1012
11−WAFOPTS="-v --disable-avcodec --disable-samplerate --disable-jack --disable-sndfile"
13+python this_version.py -v
14+VERSION=`python $PWD/this_version.py -v`
15+
16+FFMPEG_BUILDS_URL="https://ffmpeg.zeranoe.com/builds"
17+FFMPEG_DEFAULT="3.3.3"
18+
19+# define some default CFLAGS
20+DEF_CFLAGS="-Os -I/usr/share/mingw-w64"
21+DEF_LDFLAGS=""
22+
23+WAFOPTS=""
24+# disable external deps to make sure we don't try to use the host package
25+WAFOPTS+=" --disable-samplerate --disable-jack --disable-sndfile"
26+# enable ffmpeg build
27+WAFOPTS+=" --disable-avcodec"
28+# install without a prefix
29+WAFOPTS+=" --prefix=/"
30+# compile the tests, but fake running them
31+# passing this option WAFOPTS fails (escaping?), added in actual waf call below
32+#WAFOPTS+=" --testcmd='echo %s'"
33+
34+# debugging
35+#WAFOPTS+=" -v"
36+#WAFOPTS+=" -j1"
37+#WAFOPTS+=" --notests"
38+
39+function fetch_ffpmeg() {
40+ ## manually add ffmpeg (no pkg-config .pc files in bins)
41+ [ -n "$FFMPEG_VERSION" ] || FFMPEG_VERSION=$FFMPEG_DEFAULT
42+ FFMPEG_TARBALL="$PWD/ffmpeg-$FFMPEG_VERSION-$TARGET-dev.zip"
43+ FFMPEG_BINARIES="${FFMPEG_TARBALL%%.zip}"
44+ if [ ! -d "$FFMPEG_BINARIES" ]
45+ then
46+ if [ ! -f "$FFMPEG_TARBALL" ]
47+ then
48+ curl -O $FFMPEG_BUILDS_URL/$TARGET/dev/ffmpeg-$FFMPEG_VERSION-$TARGET-dev.zip
49+ else
50+ echo "using $FFMPEG_TARBALL"
51+ fi
52+ unzip -x $FFMPEG_TARBALL
53+ else
54+ echo "using $FFMPEG_BINARIES"
55+ fi
56+}
57+
58+function get_cflags() {
59+ CFLAGS="$DEF_CFLAGS"
60+ LDFLAGS="$DEF_LDFLAGS"
61+ if [ -n "$WITH_FFMEG" ]
62+ then
63+ fetch_ffpmeg
64+ CFLAGS+=" -DHAVE_LIBAV=1 -DHAVE_SWRESAMPLE=1"
65+ CFLAGS+=" -I$FFMPEG_BINARIES/include"
66+ LDFLAGS+=" -lavcodec -lavformat -lavutil -lswresample"
67+ LDFLAGS+=" -L$FFMPEG_BINARIES/lib"
68+ fi
69+}
70+
71+function build_mingw() {
72+ DESTDIR="$PWD/aubio-$VERSION-$TARGET"
73+ [ -n "$WITH_FFMEG" ] && DESTDIR+="-ffmpeg"
74+ [ -f $DESTDIR.zip ] && echo "Remove existing $DESTDIR.zip first" && exit 1
75+ [ -d $DESTDIR ] && rm -rf $DESTDIR
76+ WAFOPTS_TGT="$WAFOPTS --destdir=$DESTDIR"
77+ WAFOPTS_TGT+=" --with-target-platform=$TARGET"
78+ get_cflags
79+ CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" \
80+ ./waf distclean configure build install $WAFOPTS_TGT --testcmd='echo %s'
81+ # fix dll location (see https://github.com/waf-project/waf/issues/1860)
82+ mv $DESTDIR/lib/libaubio-5.dll $DESTDIR/bin
83+ mv $DESTDIR/lib/libaubio-5.def $DESTDIR/bin
84+ zip -r $DESTDIR.zip `basename $DESTDIR`
85+ rm -rf $DESTDIR
86+ sha256sum $DESTDIR.zip > $DESTDIR.zip.sha256
87+}
88+
89+function build_mingw32() {
90+ TARGET=win32
91+ export CC=i686-w64-mingw32-gcc
92+ export NM=i686-w64-mingw32-nm
93+ build_mingw
94+}
95+
96+function build_mingw64() {
97+ TARGET=win64
98+ export CC=x86_64-w64-mingw32-gcc
99+ export NM=x86_64-w64-mingw32-nm
100+ build_mingw
101+}
102+
103+# fetch waf if needed
104+[ -f "waf" ] || make getwaf
12105
13−[ -d dist-win32 ] && rm -rf dist-win32
14−[ -d dist-win64 ] && rm -rf dist-win64
106+# first build without ffmpeg
107+build_mingw32
108+build_mingw64
15109
16−CFLAGS="-Os" \
17− LDFLAGS="" \
18− CC=x86_64-w64-mingw32-gcc \
19− ./waf distclean configure build install --destdir=$PWD/dist-win64 \
20− --testcmd="echo %s" \
21− $WAFOPTS --with-target-platform=win64
110+# then build against ffmpeg
111+WITH_FFMEG=1
112+build_mingw32
113+build_mingw64
22114
23−CFLAGS="-Os" \
24− LDFLAGS="" \
25− CC=i686-w64-mingw32-gcc \
26− ./waf distclean configure build install --destdir=$PWD/dist-win32 \
27− --testcmd="echo %s" \
28− $WAFOPTS --with-target-platform=win32
115+set +x
116+echo ""
117+echo "All done! The following files were generated:"
118+echo ""
119+ls -lart aubio*.zip*
scripts/get_waf.sh+48−4
@@ -1,10 +1,54 @@
1−#! /bin/sh
1+#! /bin/bash
22
33 set -e
4−set -x
4+#set -x
55
6−WAFURL=https://waf.io/waf-1.8.22
6+WAFVERSION=2.0.12
7+WAFTARBALL=waf-$WAFVERSION.tar.bz2
8+WAFURL=https://waf.io/$WAFTARBALL
9+WAFUPSTREAMKEY=https://gitlab.com/ita1024/waf/raw/master/utils/pubkey.asc
710
8−( which wget > /dev/null && wget -qO waf $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > waf )
11+WAFBUILDDIR=`mktemp -d`
912
13+function cleanup () {
14+ rm -rf $WAFBUILDDIR
15+}
16+
17+trap cleanup SIGINT SIGTERM
18+
19+function download () {
20+ ( [[ -n `which wget` ]] && wget -qO $1 $2 ) || ( [[ -n `which curl` ]] && curl -so $1 $2 )
21+}
22+
23+function checkwaf () {
24+ download $WAFTARBALL.asc $WAFURL.asc
25+ if [[ -z `which gpg` ]]
26+ then
27+ echo "Warning: gpg not found, not verifying signature for $WAFTARBALL"
28+ else
29+ download - $WAFUPSTREAMKEY | gpg --import
30+ gpg --verify $WAFTARBALL.asc || exit 1
31+ fi
32+}
33+
34+function fetchwaf () {
35+ download $WAFTARBALL $WAFURL
36+ checkwaf
37+}
38+
39+function buildwaf () {
40+ tar xf $WAFTARBALL
41+ pushd waf-$WAFVERSION
42+ NOCLIMB=1 python waf-light --tools=c_emscripten $*
43+ popd
44+}
45+
46+pushd $WAFBUILDDIR
47+fetchwaf
48+buildwaf
49+popd
50+
51+cp -prv $WAFBUILDDIR/waf-$WAFVERSION/waf $PWD
1052 chmod +x waf
53+
54+cleanup
scripts/setenv_local.sh+7−19
@@ -1,24 +1,15 @@
11 #! /usr/bin/env bash
22
3−# This script sets the environment to execute aubio binaries and python code
4−# directly from build/ python/build/ without installing libaubio on the system
5−
6−# Usage: $ source ./scripts/setenv_local.sh
7−
8−# WARNING: this script will *overwrite* existing (DY)LD_LIBRARY_PATH and
9−# PYTHONPATH variables.
10−
11−PYTHON_PLATFORM=`python -c "import pkg_resources, sys; print '%s-%s' % (pkg_resources.get_build_platform(), '.'.join(map(str, sys.version_info[0:2])))"`
3+# This script sets the LD_LIBRARY_PATH environment variable to ./build/src to
4+# execute aubio binaries without installing libaubio.
5+#
6+# Usage: $ source scripts/setenv_local.sh
7+#
8+# Note: on macOs, the variable is DYLD_LIBRARY_PATH
129
1310 AUBIODIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
14−AUBIOLIB=$AUBIODIR/build/src
15−AUBIOPYTHON=$AUBIODIR/build/lib.$PYTHON_PLATFORM
1611
17−if [ "$(dirname $PWD)" == "scripts" ]; then
18− AUBIODIR=$(basename $PWD)
19−else
20− AUBIODIR=$(basename $PWD)
21−fi
12+AUBIOLIB=$AUBIODIR/build/src
2213
2314 if [ "$(uname)" == "Darwin" ]; then
2415 export DYLD_LIBRARY_PATH=$AUBIOLIB
@@ -27,6 +18,3 @@ else · 2 unmodified lines
2718 export LD_LIBRARY_PATH=$AUBIOLIB
2819 echo export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
2920 fi
30−
31−export PYTHONPATH=$AUBIOPYTHON
32−echo export PYTHONPATH=$PYTHONPATH
setup.py+41−50
@@ -1,43 +1,37 @@
11 #! /usr/bin/env python
22
3−import sys, os.path, glob
3+import sys
4+import os.path
5+import glob
46 from setuptools import setup, Extension
5−from python.lib.moresetuptools import *
6−# function to generate gen/*.{c,h}
7−from python.lib.gen_external import generate_external, header, output_path
87
9−# read from VERSION
10−for l in open('VERSION').readlines(): exec (l.strip())
8+# add ./python/lib to current path
9+sys.path.append(os.path.join('python', 'lib')) # noqa
10+from moresetuptools import build_ext, CleanGenerated
1111
12−if AUBIO_MAJOR_VERSION is None or AUBIO_MINOR_VERSION is None \
13− or AUBIO_PATCH_VERSION is None:
14− raise SystemError("Failed parsing VERSION file.")
12+# function to generate gen/*.{c,h}
13+from this_version import get_aubio_version, get_aubio_pyversion
1514
16−__version__ = '.'.join(map(str, [AUBIO_MAJOR_VERSION,
17− AUBIO_MINOR_VERSION,
18− AUBIO_PATCH_VERSION]))
19−if AUBIO_VERSION_STATUS is not None:
20− if AUBIO_VERSION_STATUS.startswith('~'):
21− AUBIO_VERSION_STATUS = AUBIO_VERSION_STATUS[1:]
22− __version__ += AUBIO_VERSION_STATUS
15+__version__ = get_aubio_pyversion()
16+__aubio_version__ = get_aubio_version()
2317
2418 include_dirs = []
2519 library_dirs = []
26−define_macros = []
20+define_macros = [('AUBIO_VERSION', '%s' % __aubio_version__)]
2721 extra_link_args = []
2822
29−include_dirs += [ 'python/ext' ]
30−include_dirs += [ output_path ] # aubio-generated.h
23+include_dirs += ['python/ext']
3124 try:
3225 import numpy
33− include_dirs += [ numpy.get_include() ]
26+ include_dirs += [numpy.get_include()]
3427 except ImportError:
3528 pass
3629
3730 if sys.platform.startswith('darwin'):
38− extra_link_args += ['-framework','CoreFoundation', '-framework','AudioToolbox']
31+ extra_link_args += ['-framework', 'CoreFoundation',
32+ '-framework', 'AudioToolbox']
3933
40−sources = glob.glob(os.path.join('python', 'ext', '*.c'))
34+sources = sorted(glob.glob(os.path.join('python', 'ext', '*.c')))
4135
4236 aubio_extension = Extension("aubio._aubio",
4337 sources,
@@ -46,21 +40,11 @@ aubio_extension = Extension("aubio._aubio", · 2 unmodified lines
4640 extra_link_args = extra_link_args,
4741 define_macros = define_macros)
4842
49−if os.path.isfile('src/aubio.h'):
50− # if aubio headers are found in this directory
51− add_local_aubio_header(aubio_extension)
52− # was waf used to build the shared lib?
53− if os.path.isdir(os.path.join('build','src')):
54− # link against build/src/libaubio, built with waf
55− add_local_aubio_lib(aubio_extension)
56− else:
57− # add libaubio sources and look for optional deps with pkg-config
58− add_local_aubio_sources(aubio_extension)
59− __version__ += 'a2' # pypi version
60−else:
61− # look for aubio headers and lib using pkg-config
62− add_system_aubio(aubio_extension)
63−
43+# TODO: find a way to track if package is built against libaubio
44+# if os.path.isfile('src/aubio.h'):
45+# if not os.path.isdir(os.path.join('build','src')):
46+# pass
47+# #__version__ += 'a2' # python only version
6448
6549 classifiers = [
6650 'Development Status :: 4 - Beta',
@@ -74,38 +58,45 @@ classifiers = [ · 7 unmodified lines
7458 'Operating System :: Microsoft :: Windows',
7559 'Programming Language :: C',
7660 'Programming Language :: Python',
77− 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
61+ 'License :: OSI Approved :: '
62+ 'GNU General Public License v3 or later (GPLv3+)',
7863 ]
7964
80−from distutils.command.build_ext import build_ext as _build_ext
81−class build_ext(_build_ext):
82−
83− def build_extension(self, extension):
84− # generate files python/gen/*.c, python/gen/aubio-generated.h
85− extension.sources += generate_external(header, output_path, overwrite = False)
86− return _build_ext.build_extension(self, extension)
65+thisdir = os.path.abspath(os.path.dirname(__file__))
66+py_readme_file = os.path.join(thisdir, 'python', 'README.md')
67+with open(py_readme_file, 'r') as fp:
68+ long_description = ''.join(fp.readlines()[3:])
8769
8870 distrib = setup(name='aubio',
8971 version = __version__,
9072 packages = ['aubio'],
91− package_dir = {'aubio':'python/lib/aubio'},
92− scripts = ['python/scripts/aubiocut'],
73+ package_dir = {'aubio': 'python/lib/aubio'},
9374 ext_modules = [aubio_extension],
9475 description = 'a collection of tools for music analysis',
95− long_description = 'a collection of tools for music analysis',
76+ long_description = long_description,
77+ long_description_content_type = 'text/markdown',
9678 license = 'GNU/GPL version 3',
9779 author = 'Paul Brossier',
9880 author_email = 'piem@aubio.org',
9981 maintainer = 'Paul Brossier',
10082 maintainer_email = 'piem@aubio.org',
101− url = 'http://aubio.org/',
83+ url = 'https://aubio.org/',
10284 platforms = 'any',
10385 classifiers = classifiers,
10486 install_requires = ['numpy'],
87+ setup_requires = ['numpy'],
10588 cmdclass = {
10689 'clean': CleanGenerated,
107− 'generate': GenerateCommand,
10890 'build_ext': build_ext,
10991 },
92+ entry_points = {
93+ 'console_scripts': [
94+ 'aubio = aubio.cmd:main',
95+ 'aubiocut = aubio.cut:main',
96+ ],
97+ },
11098 test_suite = 'nose2.collector.collector',
99+ extras_require = {
100+ 'tests': ['numpy'],
101+ },
111102 )
src/aubio.h+14−9
@@ -109,14 +109,16 @@ · 108 unmodified lines
109109 \endcode
110110
111111 Several examples of C programs are available in the \p examples/ and \p tests/src
112− directories of the source tree. See more examples:
113− @ref spectral/test-fft.c
114− @ref spectral/test-phasevoc.c
115− @ref onset/test-onset.c
116− @ref pitch/test-pitch.c
117− @ref tempo/test-tempo.c
118− @ref test-fvec.c
119− @ref test-cvec.c
112+ directories of the source tree.
113+
114+ Some examples:
115+ - @ref spectral/test-fft.c
116+ - @ref spectral/test-phasevoc.c
117+ - @ref onset/test-onset.c
118+ - @ref pitch/test-pitch.c
119+ - @ref tempo/test-tempo.c
120+ - @ref test-fvec.c
121+ - @ref test-cvec.c
120122
121123 \subsection unstable_api Unstable API
122124
@@ -137,7 +139,7 @@ · 14 unmodified lines
137139 \section download Download
138140
139141 Latest versions, further documentation, examples, wiki, and mailing lists can
140− be found at http://aubio.org .
142+ be found at https://aubio.org .
141143
142144 */
143145
@@ -180,11 +182,13 @@ extern "C" · 36 unmodified lines
180182 #include "temporal/a_weighting.h"
181183 #include "temporal/c_weighting.h"
182184 #include "spectral/fft.h"
185+#include "spectral/dct.h"
183186 #include "spectral/phasevoc.h"
184187 #include "spectral/filterbank.h"
185188 #include "spectral/filterbank_mel.h"
186189 #include "spectral/mfcc.h"
187190 #include "spectral/specdesc.h"
191+#include "spectral/awhitening.h"
188192 #include "spectral/tss.h"
189193 #include "pitch/pitch.h"
190194 #include "onset/onset.h"
@@ -211,6 +215,7 @@ extern "C" · 20 unmodified lines
211215 #include "pitch/pitchmcomb.h"
212216 #include "pitch/pitchyin.h"
213217 #include "pitch/pitchyinfft.h"
218+#include "pitch/pitchyinfast.h"
214219 #include "pitch/pitchschmitt.h"
215220 #include "pitch/pitchfcomb.h"
216221 #include "pitch/pitchspecacf.h"
src/aubio_priv.h+66−12
@@ -33,7 +33,9 @@ · 32 unmodified lines
3333 *
3434 */
3535
36+#ifdef HAVE_CONFIG_H
3637 #include "config.h"
38+#endif
3739
3840 #ifdef HAVE_STDLIB_H
3941 #include <stdlib.h>
@@ -68,14 +70,20 @@ · 28 unmodified lines
6870 #include <stdarg.h>
6971 #endif
7072
71−#ifdef HAVE_ACCELERATE
73+#if defined(HAVE_ACCELERATE)
7274 #define HAVE_ATLAS 1
75+#define HAVE_BLAS 1
7376 #include <Accelerate/Accelerate.h>
7477 #elif defined(HAVE_ATLAS_CBLAS_H)
78+#elif defined(HAVE_BLAS)
79+#if defined(HAVE_ATLAS_CBLAS_H)
7580 #define HAVE_ATLAS 1
7681 #include <atlas/cblas.h>
77−#else
78−#undef HAVE_ATLAS
82+#elif defined(HAVE_OPENBLAS_CBLAS_H)
83+#include <openblas/cblas.h>
84+#elif defined(HAVE_CBLAS_H)
85+#include <cblas.h>
86+#endif
7987 #endif
8088
8189 #ifdef HAVE_ACCELERATE
@@ -83,6 +91,8 @@ · 1 unmodified line
8391 #ifndef HAVE_AUBIO_DOUBLE
8492 #define aubio_vDSP_mmov vDSP_mmov
8593 #define aubio_vDSP_vmul vDSP_vmul
94+#define aubio_vDSP_vsmul vDSP_vsmul
95+#define aubio_vDSP_vsadd vDSP_vsadd
8696 #define aubio_vDSP_vfill vDSP_vfill
8797 #define aubio_vDSP_meanv vDSP_meanv
8898 #define aubio_vDSP_sve vDSP_sve
@@ -91,9 +101,12 @@ · 2 unmodified lines
91101 #define aubio_vDSP_minv vDSP_minv
92102 #define aubio_vDSP_minvi vDSP_minvi
93103 #define aubio_vDSP_dotpr vDSP_dotpr
104+#define aubio_vDSP_vclr vDSP_vclr
94105 #else /* HAVE_AUBIO_DOUBLE */
95106 #define aubio_vDSP_mmov vDSP_mmovD
96107 #define aubio_vDSP_vmul vDSP_vmulD
108+#define aubio_vDSP_vsmul vDSP_vsmulD
109+#define aubio_vDSP_vsadd vDSP_vsaddD
97110 #define aubio_vDSP_vfill vDSP_vfillD
98111 #define aubio_vDSP_meanv vDSP_meanvD
99112 #define aubio_vDSP_sve vDSP_sveD
@@ -102,27 +115,61 @@ · 2 unmodified lines
102115 #define aubio_vDSP_minv vDSP_minvD
103116 #define aubio_vDSP_minvi vDSP_minviD
104117 #define aubio_vDSP_dotpr vDSP_dotprD
118+#define aubio_vDSP_vclr vDSP_vclrD
105119 #endif /* HAVE_AUBIO_DOUBLE */
106120 #endif /* HAVE_ACCELERATE */
107121
108−#ifdef HAVE_ATLAS
122+#if defined(HAVE_BLAS)
109123 #ifndef HAVE_AUBIO_DOUBLE
124+#ifdef HAVE_ATLAS
110125 #define aubio_catlas_set catlas_sset
126+#endif /* HAVE_ATLAS */
111127 #define aubio_cblas_copy cblas_scopy
112128 #define aubio_cblas_swap cblas_sswap
113129 #define aubio_cblas_dot cblas_sdot
114130 #else /* HAVE_AUBIO_DOUBLE */
131+#ifdef HAVE_ATLAS
115132 #define aubio_catlas_set catlas_dset
133+#endif /* HAVE_ATLAS */
116134 #define aubio_cblas_copy cblas_dcopy
117135 #define aubio_cblas_swap cblas_dswap
118136 #define aubio_cblas_dot cblas_ddot
119137 #endif /* HAVE_AUBIO_DOUBLE */
120−#endif /* HAVE_ATLAS */
138+#endif /* HAVE_BLAS */
139+
140+#if defined HAVE_INTEL_IPP
141+#include <ippcore.h>
142+#include <ippvm.h>
143+#include <ipps.h>
144+#ifndef HAVE_AUBIO_DOUBLE
145+#define aubio_ippsSet ippsSet_32f
146+#define aubio_ippsZero ippsZero_32f
147+#define aubio_ippsCopy ippsCopy_32f
148+#define aubio_ippsMul ippsMul_32f
149+#define aubio_ippsMulC ippsMulC_32f
150+#define aubio_ippsAddC ippsAddC_32f
151+#define aubio_ippsLn ippsLn_32f_A21
152+#define aubio_ippsMean(a,b,c) ippsMean_32f(a, b, c, ippAlgHintFast)
153+#define aubio_ippsSum(a,b,c) ippsSum_32f(a, b, c, ippAlgHintFast)
154+#define aubio_ippsMax ippsMax_32f
155+#define aubio_ippsMin ippsMin_32f
156+#else /* HAVE_AUBIO_DOUBLE */
157+#define aubio_ippsSet ippsSet_64f
158+#define aubio_ippsZero ippsZero_64f
159+#define aubio_ippsCopy ippsCopy_64f
160+#define aubio_ippsMul ippsMul_64f
161+#define aubio_ippsMulC ippsMulC_64f
162+#define aubio_ippsAddC ippsAddC_64f
163+#define aubio_ippsLn ippsLn_64f_A26
164+#define aubio_ippsMean ippsMean_64f
165+#define aubio_ippsSum ippsSum_64f
166+#define aubio_ippsMax ippsMax_64f
167+#define aubio_ippsMin ippsMin_64f
168+#endif /* HAVE_AUBIO_DOUBLE */
169+#endif
121170
122−#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
171+#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS) && !defined(HAVE_INTEL_IPP)
123172 #define HAVE_NOOPT 1
124−#else
125−#undef HAVE_NOOPT
126173 #endif
127174
128175 #include "types.h"
@@ -181,14 +228,16 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 52 unmodified lines
181228
182229 #ifdef HAVE_C99_VARARGS_MACROS
183230 #define AUBIO_ERR(...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " __VA_ARGS__)
231+#define AUBIO_INF(...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " __VA_ARGS__)
184232 #define AUBIO_MSG(...) aubio_log(AUBIO_LOG_MSG, __VA_ARGS__)
185233 #define AUBIO_DBG(...) aubio_log(AUBIO_LOG_DBG, __VA_ARGS__)
186234 #define AUBIO_WRN(...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " __VA_ARGS__)
187235 #else
188−#define AUBIO_ERR(format, args...) aubio_log(stderr, "AUBIO ERROR: " format , ##args)
189−#define AUBIO_MSG(format, args...) aubio_log(stdout, format , ##args)
190−#define AUBIO_DBG(format, args...) aubio_log(stderr, format , ##args)
191−#define AUBIO_WRN(format, args...) aubio_log(stderr, "AUBIO WARNING: " format, ##args)
236+#define AUBIO_ERR(format, args...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " format , ##args)
237+#define AUBIO_INF(format, args...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " format , ##args)
238+#define AUBIO_MSG(format, args...) aubio_log(AUBIO_LOG_MSG, format , ##args)
239+#define AUBIO_DBG(format, args...) aubio_log(AUBIO_LOG_DBG, format , ##args)
240+#define AUBIO_WRN(format, args...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " format, ##args)
192241 #endif
193242
194243 #define AUBIO_ERROR AUBIO_ERR
@@ -196,6 +245,9 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 1 unmodified line
196245 #define AUBIO_QUIT(_s) exit(_s)
197246 #define AUBIO_SPRINTF sprintf
198247
248+#define AUBIO_MAX_SAMPLERATE (192000*8)
249+#define AUBIO_MAX_CHANNELS 1024
250+
199251 /* pi and 2*pi */
200252 #ifndef M_PI
201253 #define PI (3.14159265358979323846)
@@ -220,6 +272,7 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 18 unmodified lines
220272 #define LOG logf
221273 #define FLOOR floorf
222274 #define CEIL ceilf
275+#define ATAN atanf
223276 #define ATAN2 atan2f
224277 #else
225278 #define EXP exp
@@ -232,6 +285,7 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 6 unmodified lines
232285 #define LOG log
233286 #define FLOOR floor
234287 #define CEIL ceil
288+#define ATAN atan
235289 #define ATAN2 atan2
236290 #endif
237291 #define ROUND(x) FLOOR(x+.5)
src/cvec.c+36−8
@@ -85,31 +85,40 @@ void cvec_copy(const cvec_t *s, cvec_t *t) { · 84 unmodified lines
8585 s->length, t->length);
8686 return;
8787 }
88−#ifdef HAVE_MEMCPY_HACKS
88+#if defined(HAVE_INTEL_IPP)
89+ aubio_ippsCopy(s->phas, t->phas, (int)s->length);
90+ aubio_ippsCopy(s->norm, t->norm, (int)s->length);
91+#elif defined(HAVE_MEMCPY_HACKS)
8992 memcpy(t->norm, s->norm, t->length * sizeof(smpl_t));
9093 memcpy(t->phas, s->phas, t->length * sizeof(smpl_t));
91−#else /* HAVE_MEMCPY_HACKS */
94+#else
9295 uint_t j;
9396 for (j=0; j< t->length; j++) {
9497 t->norm[j] = s->norm[j];
9598 t->phas[j] = s->phas[j];
9699 }
97−#endif /* HAVE_MEMCPY_HACKS */
100+#endif
98101 }
99102
100−void cvec_norm_set_all (cvec_t *s, smpl_t val) {
103+void cvec_norm_set_all(cvec_t *s, smpl_t val) {
104+#if defined(HAVE_INTEL_IPP)
105+ aubio_ippsSet(val, s->norm, (int)s->length);
106+#else
101107 uint_t j;
102108 for (j=0; j< s->length; j++) {
103109 s->norm[j] = val;
104110 }
111+#endif
105112 }
106113
107114 void cvec_norm_zeros(cvec_t *s) {
108−#ifdef HAVE_MEMCPY_HACKS
115+#if defined(HAVE_INTEL_IPP)
116+ aubio_ippsZero(s->norm, (int)s->length);
117+#elif defined(HAVE_MEMCPY_HACKS)
109118 memset(s->norm, 0, s->length * sizeof(smpl_t));
110−#else /* HAVE_MEMCPY_HACKS */
119+#else
111120 cvec_norm_set_all (s, 0.);
112−#endif /* HAVE_MEMCPY_HACKS */
121+#endif
113122 }
114123
115124 void cvec_norm_ones(cvec_t *s) {
@@ -117,14 +126,20 @@ void cvec_norm_ones(cvec_t *s) { · 1 unmodified line
117126 }
118127
119128 void cvec_phas_set_all (cvec_t *s, smpl_t val) {
129+#if defined(HAVE_INTEL_IPP)
130+ aubio_ippsSet(val, s->phas, (int)s->length);
131+#else
120132 uint_t j;
121133 for (j=0; j< s->length; j++) {
122134 s->phas[j] = val;
123135 }
136+#endif
124137 }
125138
126139 void cvec_phas_zeros(cvec_t *s) {
127−#ifdef HAVE_MEMCPY_HACKS
140+#if defined(HAVE_INTEL_IPP)
141+ aubio_ippsZero(s->phas, (int)s->length);
142+#elif defined(HAVE_MEMCPY_HACKS)
128143 memset(s->phas, 0, s->length * sizeof(smpl_t));
129144 #else
130145 cvec_phas_set_all (s, 0.);
@@ -139,3 +154,16 @@ void cvec_zeros(cvec_t *s) { · 8 unmodified lines
139154 cvec_norm_zeros(s);
140155 cvec_phas_zeros(s);
141156 }
157+
158+void cvec_logmag(cvec_t *s, smpl_t lambda) {
159+#if defined(HAVE_INTEL_IPP)
160+ aubio_ippsMulC(s->norm, lambda, s->norm, (int)s->length);
161+ aubio_ippsAddC(s->norm, 1.0, s->norm, (int)s->length);
162+ aubio_ippsLn(s->norm, s->norm, (int)s->length);
163+#else
164+ uint_t j;
165+ for (j=0; j< s->length; j++) {
166+ s->norm[j] = LOG(lambda * s->norm[j] + 1);
167+ }
168+#endif
169+}
src/cvec.h+10−0
@@ -230,6 +230,16 @@ void cvec_phas_ones(cvec_t *s); · 229 unmodified lines
230230 */
231231 void cvec_zeros(cvec_t *s);
232232
233+/** take logarithmic magnitude
234+
235+ \param s input cvec to compress
236+ \param lambda value to use for normalisation
237+
238+ \f$ S_k = log( \lambda * S_k + 1 ) \f$
239+
240+*/
241+void cvec_logmag(cvec_t *s, smpl_t lambda);
242+
233243 #ifdef __cplusplus
234244 }
235245 #endif
src/fmat.c+3−3
@@ -110,7 +110,7 @@ void fmat_ones(fmat_t *s) { · 109 unmodified lines
110110 void fmat_rev(fmat_t *s) {
111111 uint_t i,j;
112112 for (i=0; i< s->height; i++) {
113− for (j=0; j< FLOOR(s->length/2); j++) {
113+ for (j=0; j< FLOOR((smpl_t)s->length/2); j++) {
114114 ELEM_SWAP(s->data[i][j], s->data[i][s->length-1-j]);
115115 }
116116 }
@@ -160,7 +160,7 @@ void fmat_vecmul(const fmat_t *s, const fvec_t *scale, fvec_t *output) { · 43 unmodified lines
160160 assert(s->height == output->length);
161161 assert(s->length == scale->length);
162162 #endif
163−#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
163+#if !defined(HAVE_ACCELERATE) && !defined(HAVE_BLAS)
164164 uint_t j;
165165 fvec_zeros(output);
166166 for (j = 0; j < s->length; j++) {
@@ -169,7 +169,7 @@ void fmat_vecmul(const fmat_t *s, const fvec_t *scale, fvec_t *output) { · 2 unmodified lines
169169 * s->data[k][j];
170170 }
171171 }
172−#elif defined(HAVE_ATLAS)
172+#elif defined(HAVE_BLAS)
173173 for (k = 0; k < s->height; k++) {
174174 output->data[k] = aubio_cblas_dot( s->length, scale->data, 1, s->data[k], 1);
175175 }
src/fvec.c+40−31
@@ -60,27 +60,30 @@ void fvec_print(const fvec_t *s) { · 59 unmodified lines
6060 }
6161
6262 void fvec_set_all (fvec_t *s, smpl_t val) {
63−#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)
64− uint_t j;
65− for (j=0; j< s->length; j++) {
66− s->data[j] = val;
67− }
63+#if defined(HAVE_INTEL_IPP)
64+ aubio_ippsSet(val, s->data, (int)s->length);
6865 #elif defined(HAVE_ATLAS)
6966 aubio_catlas_set(s->length, val, s->data, 1);
7067 #elif defined(HAVE_ACCELERATE)
7168 aubio_vDSP_vfill(&val, s->data, 1, s->length);
69+#else
70+ uint_t j;
71+ for ( j = 0; j< s->length; j++ )
72+ {
73+ s->data[j] = val;
74+ }
7275 #endif
7376 }
7477
7578 void fvec_zeros(fvec_t *s) {
76−#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE)
77− fvec_set_all (s, 0.);
78−#else
79−#if defined(HAVE_MEMCPY_HACKS)
79+#if defined(HAVE_INTEL_IPP)
80+ aubio_ippsZero(s->data, (int)s->length);
81+#elif defined(HAVE_ACCELERATE)
82+ aubio_vDSP_vclr(s->data, 1, s->length);
83+#elif defined(HAVE_MEMCPY_HACKS)
8084 memset(s->data, 0, s->length * sizeof(smpl_t));
8185 #else
82− aubio_vDSP_vclr(s->data, 1, s->length);
83−#endif
86+ fvec_set_all(s, 0.);
8487 #endif
8588 }
8689
@@ -90,33 +93,37 @@ void fvec_ones(fvec_t *s) { · 3 unmodified lines
9093
9194 void fvec_rev(fvec_t *s) {
9295 uint_t j;
93− for (j=0; j< FLOOR(s->length/2); j++) {
96+ for (j=0; j< FLOOR((smpl_t)s->length/2); j++) {
9497 ELEM_SWAP(s->data[j], s->data[s->length-1-j]);
9598 }
9699 }
97100
98101 void fvec_weight(fvec_t *s, const fvec_t *weight) {
99−#ifndef HAVE_ACCELERATE
100− uint_t j;
101102 uint_t length = MIN(s->length, weight->length);
102− for (j=0; j< length; j++) {
103+#if defined(HAVE_INTEL_IPP)
104+ aubio_ippsMul(s->data, weight->data, s->data, (int)length);
105+#elif defined(HAVE_ACCELERATE)
106+ aubio_vDSP_vmul( s->data, 1, weight->data, 1, s->data, 1, length );
107+#else
108+ uint_t j;
109+ for (j = 0; j < length; j++) {
103110 s->data[j] *= weight->data[j];
104111 }
105−#else
106− aubio_vDSP_vmul(s->data, 1, weight->data, 1, s->data, 1, s->length);
107112 #endif /* HAVE_ACCELERATE */
108113 }
109114
110115 void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) {
111−#ifndef HAVE_ACCELERATE
116+ uint_t length = MIN(in->length, MIN(out->length, weight->length));
117+#if defined(HAVE_INTEL_IPP)
118+ aubio_ippsMul(in->data, weight->data, out->data, (int)length);
119+#elif defined(HAVE_ACCELERATE)
120+ aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, length);
121+#else
112122 uint_t j;
113− uint_t length = MIN(out->length, weight->length);
114− for (j=0; j< length; j++) {
123+ for (j = 0; j < length; j++) {
115124 out->data[j] = in->data[j] * weight->data[j];
116125 }
117−#else
118− aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, out->length);
119−#endif /* HAVE_ACCELERATE */
126+#endif
120127 }
121128
122129 void fvec_copy(const fvec_t *s, fvec_t *t) {
@@ -125,16 +132,18 @@ void fvec_copy(const fvec_t *s, fvec_t *t) { · 2 unmodified lines
125132 s->length, t->length);
126133 return;
127134 }
128−#ifdef HAVE_NOOPT
129− uint_t j;
130− for (j=0; j< t->length; j++) {
131− t->data[j] = s->data[j];
132− }
133−#elif defined(HAVE_MEMCPY_HACKS)
134− memcpy(t->data, s->data, t->length * sizeof(smpl_t));
135−#elif defined(HAVE_ATLAS)
135+#if defined(HAVE_INTEL_IPP)
136+ aubio_ippsCopy(s->data, t->data, (int)s->length);
137+#elif defined(HAVE_BLAS)
136138 aubio_cblas_copy(s->length, s->data, 1, t->data, 1);
137139 #elif defined(HAVE_ACCELERATE)
138140 aubio_vDSP_mmov(s->data, t->data, 1, s->length, 1, 1);
141+#elif defined(HAVE_MEMCPY_HACKS)
142+ memcpy(t->data, s->data, t->length * sizeof(smpl_t));
143+#else
144+ uint_t j;
145+ for (j = 0; j < t->length; j++) {
146+ t->data[j] = s->data[j];
147+ }
139148 #endif
140149 }
src/io/audio_unit.c+1−2
@@ -18,9 +18,8 @@ · 17 unmodified lines
1818
1919 */
2020
21−#include "config.h"
22−#ifdef HAVE_AUDIO_UNIT
2321 #include "aubio_priv.h"
22+#ifdef HAVE_AUDIO_UNIT
2423
2524 #include "fvec.h"
2625 #include "fmat.h"
src/io/ioutils.c+53−0
@@ -0,0 +1,53 @@
1+/*
2+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+
23+uint_t
24+aubio_io_validate_samplerate(const char_t *kind, const char_t *path, uint_t samplerate)
25+{
26+ if ((sint_t)(samplerate) <= 0) {
27+ AUBIO_ERR("%s: failed creating %s, samplerate should be positive, not %d\n",
28+ kind, path, samplerate);
29+ return AUBIO_FAIL;
30+ }
31+ if ((sint_t)samplerate > AUBIO_MAX_SAMPLERATE) {
32+ AUBIO_ERR("%s: failed creating %s, samplerate %dHz is too large\n",
33+ kind, path, samplerate);
34+ return AUBIO_FAIL;
35+ }
36+ return AUBIO_OK;
37+}
38+
39+uint_t
40+aubio_io_validate_channels(const char_t *kind, const char_t *path, uint_t channels)
41+{
42+ if ((sint_t)(channels) <= 0) {
43+ AUBIO_ERR("sink_%s: failed creating %s, channels should be positive, not %d\n",
44+ kind, path, channels);
45+ return AUBIO_FAIL;
46+ }
47+ if (channels > AUBIO_MAX_CHANNELS) {
48+ AUBIO_ERR("sink_%s: failed creating %s, too many channels (%d but %d available)\n",
49+ kind, path, channels, AUBIO_MAX_CHANNELS);
50+ return AUBIO_FAIL;
51+ }
52+ return AUBIO_OK;
53+}
src/io/ioutils.h+60−0
@@ -0,0 +1,60 @@
1+/*
2+ Copyright (C) 2016 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#ifndef AUBIO_IOUTILS_H
22+#define AUBIO_IOUTILS_H
23+
24+/** \file
25+
26+ Simple utility functions to validate input parameters.
27+
28+*/
29+
30+#ifdef __cplusplus
31+extern "C" {
32+#endif
33+
34+/** validate samplerate
35+
36+ \param kind the object kind to report on
37+ \param path the object properties to report on
38+ \param samplerate the object properties to report on
39+ \return 0 if ok, non-zero if validation failed
40+
41+ */
42+uint_t aubio_io_validate_samplerate(const char_t *kind, const char_t *path,
43+ uint_t samplerate);
44+
45+/** validate number of channels
46+
47+ \param kind the object kind to report on
48+ \param path the object properties to report on
49+ \param channels the object properties to report on
50+ \return 0 if ok, non-zero if validation failed
51+
52+ */
53+uint_t aubio_io_validate_channels(const char_t *kind, const char_t *path,
54+ uint_t channels);
55+
56+#ifdef __cplusplus
57+}
58+#endif
59+
60+#endif /* AUBIO_IOUTILS_H */
src/io/sink.c+5−3
@@ -18,7 +18,6 @@ · 17 unmodified lines
1818
1919 */
2020
21−#include "config.h"
2221 #include "aubio_priv.h"
2322 #include "fvec.h"
2423 #include "fmat.h"
@@ -98,8 +97,11 @@ aubio_sink_t * new_aubio_sink(const char_t * uri, uint_t samplerate) { · 73 unmodified lines
9897 return s;
9998 }
10099 #endif /* HAVE_WAVWRITE */
101− AUBIO_ERROR("sink: failed creating %s with samplerate %dHz\n",
102− uri, samplerate);
100+#if !defined(HAVE_WAVWRITE) && \
101+ !defined(HAVE_SNDFILE) && \
102+ !defined(HAVE_SINK_APPLE_AUDIO)
103+ AUBIO_ERROR("sink: failed creating '%s' at %dHz (no sink built-in)\n", uri, samplerate);
104+#endif
103105 AUBIO_FREE(s);
104106 return NULL;
105107 }
src/io/sink_apple_audio.c+16−9
@@ -18,14 +18,13 @@ · 17 unmodified lines
1818
1919 */
2020
21−#include "config.h"
21+#include "aubio_priv.h"
2222
2323 #ifdef HAVE_SINK_APPLE_AUDIO
24−
25−#include "aubio_priv.h"
2624 #include "fvec.h"
2725 #include "fmat.h"
2826 #include "io/sink_apple_audio.h"
27+#include "io/ioutils.h"
2928
3029 // CFURLRef, CFURLCreateWithFileSystemPath, ...
3130 #include <CoreFoundation/CoreFoundation.h>
@@ -62,7 +61,7 @@ aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(const char_t * uri, uint_t · 30 unmodified lines
6261 s->max_frames = MAX_SIZE;
6362 s->async = false;
6463
65− if (uri == NULL) {
64+ if ( (uri == NULL) || (strlen(uri) < 1) ) {
6665 AUBIO_ERROR("sink_apple_audio: Aborted opening null path\n");
6766 goto beach;
6867 }
@@ -73,10 +72,14 @@ aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(const char_t * uri, uint_t · 4 unmodified lines
7372 s->samplerate = 0;
7473 s->channels = 0;
7574
76− // negative samplerate given, abort
77− if ((sint_t)samplerate < 0) goto beach;
7875 // zero samplerate given. do not open yet
79− if ((sint_t)samplerate == 0) return s;
76+ if ((sint_t)samplerate == 0) {
77+ return s;
78+ }
79+ // invalid samplerate given, abort
80+ if (aubio_io_validate_samplerate("sink_apple_audio", s->path, samplerate)) {
81+ goto beach;
82+ }
8083
8184 s->samplerate = samplerate;
8285 s->channels = 1;
@@ -94,7 +97,9 @@ beach: · 11 unmodified lines
9497
9598 uint_t aubio_sink_apple_audio_preset_samplerate(aubio_sink_apple_audio_t *s, uint_t samplerate)
9699 {
97− if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
100+ if (aubio_io_validate_samplerate("sink_apple_audio", s->path, samplerate)) {
101+ return AUBIO_FAIL;
102+ }
98103 s->samplerate = samplerate;
99104 // automatically open when both samplerate and channels have been set
100105 if (s->samplerate != 0 && s->channels != 0) {
@@ -105,7 +110,9 @@ uint_t aubio_sink_apple_audio_preset_samplerate(aubio_sink_apple_audio_t *s, uin · 4 unmodified lines
105110
106111 uint_t aubio_sink_apple_audio_preset_channels(aubio_sink_apple_audio_t *s, uint_t channels)
107112 {
108− if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
113+ if (aubio_io_validate_channels("sink_apple_audio", s->path, channels)) {
114+ return AUBIO_FAIL;
115+ }
109116 s->channels = channels;
110117 // automatically open when both samplerate and channels have been set
111118 if (s->samplerate != 0 && s->channels != 0) {
src/io/sink_sndfile.c+20−11
@@ -19,18 +19,17 @@ · 18 unmodified lines
1919 */
2020
2121
22−#include "config.h"
22+#include "aubio_priv.h"
2323
2424 #ifdef HAVE_SNDFILE
2525
2626 #include <sndfile.h>
2727
28−#include "aubio_priv.h"
2928 #include "fvec.h"
3029 #include "fmat.h"
3130 #include "io/sink_sndfile.h"
31+#include "io/ioutils.h"
3232
33−#define MAX_CHANNELS 6
3433 #define MAX_SIZE 4096
3534
3635 #if !HAVE_AUBIO_DOUBLE
@@ -69,10 +68,14 @@ aubio_sink_sndfile_t * new_aubio_sink_sndfile(const char_t * path, uint_t sample · 32 unmodified lines
6968 s->samplerate = 0;
7069 s->channels = 0;
7170
72− // negative samplerate given, abort
73− if ((sint_t)samplerate < 0) goto beach;
7471 // zero samplerate given. do not open yet
75− if ((sint_t)samplerate == 0) return s;
72+ if ((sint_t)samplerate == 0) {
73+ return s;
74+ }
75+ // invalid samplerate given, abort
76+ if (aubio_io_validate_samplerate("sink_sndfile", s->path, samplerate)) {
77+ goto beach;
78+ }
7679
7780 s->samplerate = samplerate;
7881 s->channels = 1;
@@ -89,7 +92,9 @@ beach: · 10 unmodified lines
8992
9093 uint_t aubio_sink_sndfile_preset_samplerate(aubio_sink_sndfile_t *s, uint_t samplerate)
9194 {
92− if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
95+ if (aubio_io_validate_samplerate("sink_sndfile", s->path, samplerate)) {
96+ return AUBIO_FAIL;
97+ }
9398 s->samplerate = samplerate;
9499 // automatically open when both samplerate and channels have been set
95100 if (s->samplerate != 0 && s->channels != 0) {
@@ -100,7 +105,9 @@ uint_t aubio_sink_sndfile_preset_samplerate(aubio_sink_sndfile_t *s, uint_t samp · 4 unmodified lines
100105
101106 uint_t aubio_sink_sndfile_preset_channels(aubio_sink_sndfile_t *s, uint_t channels)
102107 {
103− if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
108+ if (aubio_io_validate_channels("sink_sndfile", s->path, channels)) {
109+ return AUBIO_FAIL;
110+ }
104111 s->channels = channels;
105112 // automatically open when both samplerate and channels have been set
106113 if (s->samplerate != 0 && s->channels != 0) {
@@ -132,15 +139,17 @@ uint_t aubio_sink_sndfile_open(aubio_sink_sndfile_t *s) { · 25 unmodified lines
132139
133140 if (s->handle == NULL) {
134141 /* show libsndfile err msg */
135− AUBIO_ERR("sink_sndfile: Failed opening %s. %s\n", s->path, sf_strerror (NULL));
142+ AUBIO_ERR("sink_sndfile: Failed opening \"%s\" with %d channels, %dHz: %s\n",
143+ s->path, s->channels, s->samplerate, sf_strerror (NULL));
136144 return AUBIO_FAIL;
137145 }
138146
139147 s->scratch_size = s->max_size*s->channels;
140148 /* allocate data for de/interleaving reallocated when needed. */
141− if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
149+ if (s->scratch_size >= MAX_SIZE * AUBIO_MAX_CHANNELS) {
150+ abort();
142151 AUBIO_ERR("sink_sndfile: %d x %d exceeds maximum aubio_sink_sndfile buffer size %d\n",
143− s->max_size, s->channels, MAX_CHANNELS * MAX_CHANNELS);
152+ s->max_size, s->channels, MAX_SIZE * AUBIO_MAX_CHANNELS);
144153 return AUBIO_FAIL;
145154 }
146155 s->scratch_data = AUBIO_ARRAY(smpl_t,s->scratch_size);
src/io/sink_wavwrite.c+17−12
@@ -19,18 +19,17 @@ · 18 unmodified lines
1919 */
2020
2121
22−#include "config.h"
22+#include "aubio_priv.h"
2323
2424 #ifdef HAVE_WAVWRITE
2525
26−#include "aubio_priv.h"
2726 #include "fvec.h"
2827 #include "fmat.h"
2928 #include "io/sink_wavwrite.h"
29+#include "io/ioutils.h"
3030
3131 #include <errno.h>
3232
33−#define MAX_CHANNELS 6
3433 #define MAX_SIZE 4096
3534
3635 #define FLOAT_TO_SHORT(x) (short)(x * 32768)
@@ -104,12 +103,14 @@ aubio_sink_wavwrite_t * new_aubio_sink_wavwrite(const char_t * path, uint_t samp · 67 unmodified lines
104103 s->samplerate = 0;
105104 s->channels = 0;
106105
107− // negative samplerate given, abort
108− if ((sint_t)samplerate < 0) goto beach;
109106 // zero samplerate given. do not open yet
110− if ((sint_t)samplerate == 0) return s;
111− // samplerate way too large, fail
112− if ((sint_t)samplerate > 192000 * 4) goto beach;
107+ if ((sint_t)samplerate == 0) {
108+ return s;
109+ }
110+ // invalid samplerate given, abort
111+ if (aubio_io_validate_samplerate("sink_wavwrite", s->path, samplerate)) {
112+ goto beach;
113+ }
113114
114115 s->samplerate = samplerate;
115116 s->channels = 1;
@@ -129,7 +130,9 @@ beach: · 13 unmodified lines
129130
130131 uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t samplerate)
131132 {
132− if ((sint_t)(samplerate) <= 0) return AUBIO_FAIL;
133+ if (aubio_io_validate_samplerate("sink_wavwrite", s->path, samplerate)) {
134+ return AUBIO_FAIL;
135+ }
133136 s->samplerate = samplerate;
134137 // automatically open when both samplerate and channels have been set
135138 if (s->samplerate != 0 && s->channels != 0) {
@@ -140,7 +143,9 @@ uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t sa · 4 unmodified lines
140143
141144 uint_t aubio_sink_wavwrite_preset_channels(aubio_sink_wavwrite_t *s, uint_t channels)
142145 {
143− if ((sint_t)(channels) <= 0) return AUBIO_FAIL;
146+ if (aubio_io_validate_channels("sink_wavwrite", s->path, channels)) {
147+ return AUBIO_FAIL;
148+ }
144149 s->channels = channels;
145150 // automatically open when both samplerate and channels have been set
146151 if (s->samplerate != 0 && s->channels != 0) {
@@ -213,9 +218,9 @@ uint_t aubio_sink_wavwrite_open(aubio_sink_wavwrite_t *s) { · 66 unmodified lines
213218
214219 s->scratch_size = s->max_size * s->channels;
215220 /* allocate data for de/interleaving reallocated when needed. */
216− if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
221+ if (s->scratch_size >= MAX_SIZE * AUBIO_MAX_CHANNELS) {
217222 AUBIO_ERR("sink_wavwrite: %d x %d exceeds SIZE maximum buffer size %d\n",
218− s->max_size, s->channels, MAX_SIZE * MAX_CHANNELS);
223+ s->max_size, s->channels, MAX_SIZE * AUBIO_MAX_CHANNELS);
219224 goto beach;
220225 }
221226 s->scratch_data = AUBIO_ARRAY(unsigned short,s->scratch_size);
src/io/source.c+7−3
@@ -18,7 +18,6 @@ · 17 unmodified lines
1818
1919 */
2020
21−#include "config.h"
2221 #include "aubio_priv.h"
2322 #include "fvec.h"
2423 #include "fmat.h"
@@ -115,8 +114,13 @@ aubio_source_t * new_aubio_source(const char_t * uri, uint_t samplerate, uint_t · 90 unmodified lines
115114 return s;
116115 }
117116 #endif /* HAVE_WAVREAD */
118− AUBIO_ERROR("source: failed creating aubio source with %s"
119− " at samplerate %d with hop_size %d\n", uri, samplerate, hop_size);
117+#if !defined(HAVE_WAVREAD) && \
118+ !defined(HAVE_LIBAV) && \
119+ !defined(HAVE_SOURCE_APPLE_AUDIO) && \
120+ !defined(HAVE_SNDFILE)
121+ AUBIO_ERROR("source: failed creating with %s at %dHz with hop size %d"
122+ " (no source built-in)\n", uri, samplerate, hop_size);
123+#endif
120124 AUBIO_FREE(s);
121125 return NULL;
122126 }
src/io/source_apple_audio.c+2−3
@@ -18,11 +18,10 @@ · 17 unmodified lines
1818
1919 */
2020
21−#include "config.h"
21+#include "aubio_priv.h"
2222
2323 #ifdef HAVE_SOURCE_APPLE_AUDIO
2424
25−#include "aubio_priv.h"
2625 #include "fvec.h"
2726 #include "fmat.h"
2827 #include "io/source_apple_audio.h"
@@ -280,7 +279,7 @@ beach: · 251 unmodified lines
280279 uint_t aubio_source_apple_audio_close (aubio_source_apple_audio_t *s)
281280 {
282281 OSStatus err = noErr;
283− if (!s->audioFile) { return AUBIO_FAIL; }
282+ if (!s->audioFile) { return AUBIO_OK; }
284283 err = ExtAudioFileDispose(s->audioFile);
285284 s->audioFile = NULL;
286285 if (err) {
src/io/source_avcodec.c+266−81
@@ -18,32 +18,51 @@ · 17 unmodified lines
1818
1919 */
2020
21−
22−#include "config.h"
21+#include "aubio_priv.h"
2322
2423 #ifdef HAVE_LIBAV
2524
25+#include <libavcodec/avcodec.h>
26+#include <libavformat/avformat.h>
27+#if defined(HAVE_SWRESAMPLE)
28+#include <libswresample/swresample.h>
29+#elif defined(HAVE_AVRESAMPLE)
30+#include <libavresample/avresample.h>
31+#endif
32+#include <libavutil/opt.h>
33+#include <stdlib.h>
34+
2635 // determine whether we use libavformat from ffmpeg or from libav
2736 #define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99 )
28−// max_analyze_duration2 was used from ffmpeg libavformat 55.43.100 through 57.2.100
37+// max_analyze_duration2 was used from ffmpeg libavformat 55.43.100 -> 57.2.100
2938 #define FFMPEG_LIBAVFORMAT_MAX_DUR2 FFMPEG_LIBAVFORMAT && ( \
3039 (LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR >= 43) \
3140 || (LIBAVFORMAT_VERSION_MAJOR == 56) \
3241 || (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR < 2) \
3342 )
3443
35−#include <libavcodec/avcodec.h>
36−#include <libavformat/avformat.h>
37−#include <libavresample/avresample.h>
38−#include <libavutil/opt.h>
39−#include <stdlib.h>
44+// backward compatibility with libavcodec55
45+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,0,0)
46+#define HAVE_AUBIO_LIBAVCODEC_DEPRECATED 1
47+#endif
48+
49+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
50+#warning "libavcodec < 56 is deprecated"
51+#define av_frame_alloc avcodec_alloc_frame
52+#define av_frame_free avcodec_free_frame
53+#define av_packet_unref av_free_packet
54+#endif
4055
4156 #include "aubio_priv.h"
4257 #include "fvec.h"
4358 #include "fmat.h"
4459 #include "source_avcodec.h"
4560
61+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 0)
4662 #define AUBIO_AVCODEC_MAX_BUFFER_SIZE FF_MIN_BUFFER_SIZE
63+#else
64+#define AUBIO_AVCODEC_MAX_BUFFER_SIZE AV_INPUT_BUFFER_MIN_SIZE
65+#endif
4766
4867 struct _aubio_source_avcodec_t {
4968 uint_t hop_size;
@@ -59,18 +78,24 @@ struct _aubio_source_avcodec_t { · 9 unmodified lines
5978 AVFormatContext *avFormatCtx;
6079 AVCodecContext *avCodecCtx;
6180 AVFrame *avFrame;
81+ AVPacket avPacket;
82+#ifdef HAVE_AVRESAMPLE
6283 AVAudioResampleContext *avr;
63− float *output;
84+#elif defined(HAVE_SWRESAMPLE)
85+ SwrContext *avr;
86+#endif
87+ smpl_t *output;
6488 uint_t read_samples;
6589 uint_t read_index;
6690 sint_t selected_stream;
6791 uint_t eof;
68− uint_t multi;
6992 };
7093
71−// hack to create or re-create the context the first time _do or _do_multi is called
72−void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s, uint_t multi);
73−void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_samples);
94+// create or re-create the context when _do or _do_multi is called
95+void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s);
96+// actually read a frame
97+void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s,
98+ uint_t * read_samples);
7499
75100 uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s);
76101
@@ -87,19 +112,31 @@ uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s) { · 10 unmodified lines
87112 }
88113
89114
90−aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t samplerate, uint_t hop_size) {
115+aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path,
116+ uint_t samplerate, uint_t hop_size) {
91117 aubio_source_avcodec_t * s = AUBIO_NEW(aubio_source_avcodec_t);
118+ AVFormatContext *avFormatCtx = s->avFormatCtx;
119+ AVCodecContext *avCodecCtx = s->avCodecCtx;
120+ AVFrame *avFrame = s->avFrame;
121+ sint_t selected_stream = -1;
122+#if FF_API_LAVF_AVCTX
123+ AVCodecParameters *codecpar;
124+#endif
125+ AVCodec *codec;
126+ uint_t i;
92127 int err;
93128 if (path == NULL) {
94129 AUBIO_ERR("source_avcodec: Aborted opening null path\n");
95130 goto beach;
96131 }
97132 if ((sint_t)samplerate < 0) {
98− AUBIO_ERR("source_avcodec: Can not open %s with samplerate %d\n", path, samplerate);
133+ AUBIO_ERR("source_avcodec: Can not open %s with samplerate %d\n",
134+ path, samplerate);
99135 goto beach;
100136 }
101137 if ((sint_t)hop_size <= 0) {
102− AUBIO_ERR("source_avcodec: Can not open %s with hop_size %d\n", path, hop_size);
138+ AUBIO_ERR("source_avcodec: Can not open %s with hop_size %d\n",
139+ path, hop_size);
103140 goto beach;
104141 }
105142
@@ -110,15 +147,16 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 4 unmodified lines
110147 s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
111148 strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
112149
150+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,0,0)
113151 // register all formats and codecs
114152 av_register_all();
153+#endif
115154
116155 if (aubio_source_avcodec_has_network_url(s)) {
117156 avformat_network_init();
118157 }
119158
120159 // try opening the file and get some info about it
121− AVFormatContext *avFormatCtx = s->avFormatCtx;
122160 avFormatCtx = NULL;
123161 if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, NULL) ) < 0 ) {
124162 char errorstr[256];
@@ -138,8 +176,8 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 13 unmodified lines
138176 if ( (err = avformat_find_stream_info(avFormatCtx, NULL)) < 0 ) {
139177 char errorstr[256];
140178 av_strerror (err, errorstr, sizeof(errorstr));
141− AUBIO_ERR("source_avcodec: Could not find stream information " "for %s (%s)\n", s->path,
142− errorstr);
179+ AUBIO_ERR("source_avcodec: Could not find stream information "
180+ "for %s (%s)\n", s->path, errorstr);
143181 goto beach;
144182 }
145183
@@ -147,10 +185,12 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 1 unmodified line
147185 //av_dump_format(avFormatCtx, 0, s->path, 0);
148186
149187 // look for the first audio stream
150− uint_t i;
151− sint_t selected_stream = -1;
152188 for (i = 0; i < avFormatCtx->nb_streams; i++) {
189+#if FF_API_LAVF_AVCTX
190+ if (avFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
191+#else
153192 if (avFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
193+#endif
154194 if (selected_stream == -1) {
155195 selected_stream = i;
156196 } else {
@@ -166,18 +206,46 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 9 unmodified lines
166206 //AUBIO_DBG("Taking stream %d in file %s\n", selected_stream, s->path);
167207 s->selected_stream = selected_stream;
168208
169− AVCodecContext *avCodecCtx = s->avCodecCtx;
209+#if FF_API_LAVF_AVCTX
210+ codecpar = avFormatCtx->streams[selected_stream]->codecpar;
211+ if (codecpar == NULL) {
212+ AUBIO_ERR("source_avcodec: Could not find decoder for %s", s->path);
213+ goto beach;
214+ }
215+ codec = avcodec_find_decoder(codecpar->codec_id);
216+
217+ /* Allocate a codec context for the decoder */
218+ avCodecCtx = avcodec_alloc_context3(codec);
219+ if (!avCodecCtx) {
220+ AUBIO_ERR("source_avcodec: Failed to allocate the %s codec context "
221+ "for path %s\n", av_get_media_type_string(AVMEDIA_TYPE_AUDIO),
222+ s->path);
223+ goto beach;
224+ }
225+#else
170226 avCodecCtx = avFormatCtx->streams[selected_stream]->codec;
171− AVCodec *codec = avcodec_find_decoder(avCodecCtx->codec_id);
227+ codec = avcodec_find_decoder(avCodecCtx->codec_id);
228+#endif
172229 if (codec == NULL) {
173230 AUBIO_ERR("source_avcodec: Could not find decoder for %s", s->path);
174231 goto beach;
175232 }
176233
234+#if FF_API_LAVF_AVCTX
235+ /* Copy codec parameters from input stream to output codec context */
236+ if ((err = avcodec_parameters_to_context(avCodecCtx, codecpar)) < 0) {
237+ AUBIO_ERR("source_avcodec: Failed to copy %s codec parameters to "
238+ "decoder context for %s\n",
239+ av_get_media_type_string(AVMEDIA_TYPE_AUDIO), s->path);
240+ goto beach;
241+ }
242+#endif
243+
177244 if ( ( err = avcodec_open2(avCodecCtx, codec, NULL) ) < 0) {
178245 char errorstr[256];
179246 av_strerror (err, errorstr, sizeof(errorstr));
180− AUBIO_ERR("source_avcodec: Could not load codec for %s (%s)\n", s->path, errorstr);
247+ AUBIO_ERR("source_avcodec: Could not load codec for %s (%s)\n", s->path,
248+ errorstr);
181249 goto beach;
182250 }
183251
@@ -198,14 +266,14 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 14 unmodified lines
198266 s->input_samplerate, s->samplerate);
199267 }
200268
201− AVFrame *avFrame = s->avFrame;
202269 avFrame = av_frame_alloc();
203270 if (!avFrame) {
204271 AUBIO_ERR("source_avcodec: Could not allocate frame for (%s)\n", s->path);
205272 }
206273
207274 /* allocate output for avr */
208− s->output = (float *)av_malloc(AUBIO_AVCODEC_MAX_BUFFER_SIZE * sizeof(float));
275+ s->output = (smpl_t *)av_malloc(AUBIO_AVCODEC_MAX_BUFFER_SIZE
276+ * sizeof(smpl_t));
209277
210278 s->read_samples = 0;
211279 s->read_index = 0;
@@ -214,11 +282,11 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 2 unmodified lines
214282 s->avCodecCtx = avCodecCtx;
215283 s->avFrame = avFrame;
216284
217− // default to mono output
218− aubio_source_avcodec_reset_resampler(s, 0);
285+ aubio_source_avcodec_reset_resampler(s);
286+
287+ if (s->avr == NULL) goto beach;
219288
220289 s->eof = 0;
221− s->multi = 0;
222290
223291 //av_log_set_level(AV_LOG_QUIET);
224292
@@ -231,47 +299,78 @@ beach: · 6 unmodified lines
231299 return NULL;
232300 }
233301
234−void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s, uint_t multi) {
235− if ( (multi != s->multi) || (s->avr == NULL) ) {
302+void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s)
303+{
304+ // create or reset resampler to/from mono/multi-channel
305+ if ( s->avr == NULL ) {
306+ int err;
236307 int64_t input_layout = av_get_default_channel_layout(s->input_channels);
237− uint_t output_channels = multi ? s->input_channels : 1;
238− int64_t output_layout = av_get_default_channel_layout(output_channels);
239− if (s->avr != NULL) {
240− avresample_close( s->avr );
241− av_free ( s->avr );
242− s->avr = NULL;
243− }
244− AVAudioResampleContext *avr = s->avr;
245− avr = avresample_alloc_context();
246−
247− av_opt_set_int(avr, "in_channel_layout", input_layout, 0);
248− av_opt_set_int(avr, "out_channel_layout", output_layout, 0);
249− av_opt_set_int(avr, "in_sample_rate", s->input_samplerate, 0);
250− av_opt_set_int(avr, "out_sample_rate", s->samplerate, 0);
308+ int64_t output_layout = av_get_default_channel_layout(s->input_channels);
309+#ifdef HAVE_AVRESAMPLE
310+ AVAudioResampleContext *avr = avresample_alloc_context();
311+#elif defined(HAVE_SWRESAMPLE)
312+ SwrContext *avr = swr_alloc();
313+#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
314+
315+ av_opt_set_int(avr, "in_channel_layout", input_layout, 0);
316+ av_opt_set_int(avr, "out_channel_layout", output_layout, 0);
317+ av_opt_set_int(avr, "in_sample_rate", s->input_samplerate, 0);
318+ av_opt_set_int(avr, "out_sample_rate", s->samplerate, 0);
251319 av_opt_set_int(avr, "in_sample_fmt", s->avCodecCtx->sample_fmt, 0);
252− av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
253− int err;
254− if ( ( err = avresample_open(avr) ) < 0) {
320+#if HAVE_AUBIO_DOUBLE
321+ av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_DBL, 0);
322+#else
323+ av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
324+#endif
325+ // TODO: use planar?
326+ //av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
327+#ifdef HAVE_AVRESAMPLE
328+ if ( ( err = avresample_open(avr) ) < 0)
329+#elif defined(HAVE_SWRESAMPLE)
330+ if ( ( err = swr_init(avr) ) < 0)
331+#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
332+ {
255333 char errorstr[256];
256334 av_strerror (err, errorstr, sizeof(errorstr));
257− AUBIO_ERR("source_avcodec: Could not open AVAudioResampleContext for %s (%s)\n",
258− s->path, errorstr);
259− //goto beach;
335+ AUBIO_ERR("source_avcodec: Could not open resampling context"
336+ " for %s (%s)\n", s->path, errorstr);
260337 return;
261338 }
262339 s->avr = avr;
263− s->multi = multi;
264340 }
265341 }
266342
267−void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_samples) {
343+void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s,
344+ uint_t * read_samples)
345+{
268346 AVFormatContext *avFormatCtx = s->avFormatCtx;
269347 AVCodecContext *avCodecCtx = s->avCodecCtx;
270348 AVFrame *avFrame = s->avFrame;
271− AVPacket avPacket;
272− av_init_packet (&avPacket);
349+ AVPacket avPacket = s->avPacket;
350+#ifdef HAVE_AVRESAMPLE
273351 AVAudioResampleContext *avr = s->avr;
274− float *output = s->output;
352+#elif defined(HAVE_SWRESAMPLE)
353+ SwrContext *avr = s->avr;
354+#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
355+ int got_frame = 0;
356+#ifdef HAVE_AVRESAMPLE
357+ int in_linesize = 0;
358+ int in_samples = avFrame->nb_samples;
359+ int out_linesize = 0;
360+ int max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE;
361+ int out_samples = 0;
362+#elif defined(HAVE_SWRESAMPLE)
363+ int in_samples = avFrame->nb_samples;
364+ int max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE / avCodecCtx->channels;
365+ int out_samples = 0;
366+#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
367+ smpl_t *output = s->output;
368+#ifndef FF_API_LAVF_AVCTX
369+ int len = 0;
370+#else
371+ int ret = 0;
372+#endif
373+ av_init_packet (&avPacket);
275374 *read_samples = 0;
276375
277376 do
@@ -284,34 +383,81 @@ void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_sam · 6 unmodified lines
284383 if (err != 0) {
285384 char errorstr[256];
286385 av_strerror (err, errorstr, sizeof(errorstr));
287− AUBIO_ERR("Could not read frame in %s (%s)\n", s->path, errorstr);
386+ AUBIO_ERR("source_avcodec: could not read frame in %s (%s)\n",
387+ s->path, errorstr);
388+ s->eof = 1;
288389 goto beach;
289390 }
290391 } while (avPacket.stream_index != s->selected_stream);
291392
292− int got_frame = 0;
293− int len = avcodec_decode_audio4(avCodecCtx, avFrame, &got_frame, &avPacket);
393+#if FF_API_LAVF_AVCTX
394+ ret = avcodec_send_packet(avCodecCtx, &avPacket);
395+ if (ret < 0 && ret != AVERROR_EOF) {
396+ AUBIO_ERR("source_avcodec: error when sending packet for %s\n", s->path);
397+ goto beach;
398+ }
399+ ret = avcodec_receive_frame(avCodecCtx, avFrame);
400+ if (ret >= 0) {
401+ got_frame = 1;
402+ }
403+ if (ret < 0) {
404+ if (ret == AVERROR(EAGAIN)) {
405+ //AUBIO_WRN("source_avcodec: output is not available right now - "
406+ // "user must try to send new input\n");
407+ goto beach;
408+ } else if (ret == AVERROR_EOF) {
409+ AUBIO_WRN("source_avcodec: the decoder has been fully flushed, "
410+ "and there will be no more output frames\n");
411+ } else {
412+ AUBIO_ERR("source_avcodec: decoding errors on %s\n", s->path);
413+ goto beach;
414+ }
415+ }
416+#else
417+ len = avcodec_decode_audio4(avCodecCtx, avFrame, &got_frame, &avPacket);
294418
295419 if (len < 0) {
296− AUBIO_ERR("Error while decoding %s\n", s->path);
420+ AUBIO_ERR("source_avcodec: error while decoding %s\n", s->path);
297421 goto beach;
298422 }
423+#endif
299424 if (got_frame == 0) {
300− //AUBIO_ERR("Could not get frame for (%s)\n", s->path);
425+ AUBIO_WRN("source_avcodec: did not get a frame when reading %s\n",
426+ s->path);
301427 goto beach;
302428 }
303429
304− int in_linesize = 0;
430+#if LIBAVUTIL_VERSION_MAJOR > 52
431+ if (avFrame->channels != (sint_t)s->input_channels) {
432+ AUBIO_WRN ("source_avcodec: trying to read from %d channel(s),"
433+ "but configured for %d; is '%s' corrupt?\n",
434+ avFrame->channels, s->input_channels, s->path);
435+ goto beach;
436+ }
437+#else
438+#warning "avutil < 53 is deprecated, crashes might occur on corrupt files"
439+#endif
440+
441+#ifdef HAVE_AVRESAMPLE
442+ in_linesize = 0;
305443 av_samples_get_buffer_size(&in_linesize, avCodecCtx->channels,
306444 avFrame->nb_samples, avCodecCtx->sample_fmt, 1);
307− int in_samples = avFrame->nb_samples;
308− int out_linesize = 0;
309− int max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE;
310− int out_samples = avresample_convert ( avr,
445+ in_samples = avFrame->nb_samples;
446+ out_linesize = 0;
447+ max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE;
448+ out_samples = avresample_convert ( avr,
311449 (uint8_t **)&output, out_linesize, max_out_samples,
312450 (uint8_t **)avFrame->data, in_linesize, in_samples);
451+#elif defined(HAVE_SWRESAMPLE)
452+ in_samples = avFrame->nb_samples;
453+ max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE / avCodecCtx->channels;
454+ out_samples = swr_convert( avr,
455+ (uint8_t **)&output, max_out_samples,
456+ (const uint8_t **)avFrame->data, in_samples);
457+#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
313458 if (out_samples <= 0) {
314− //AUBIO_ERR("No sample found while converting frame (%s)\n", s->path);
459+ AUBIO_WRN("source_avcodec: no sample found while converting frame (%s)\n",
460+ s->path);
315461 goto beach;
316462 }
317463
@@ -321,21 +467,28 @@ beach: · 3 unmodified lines
321467 s->avFormatCtx = avFormatCtx;
322468 s->avCodecCtx = avCodecCtx;
323469 s->avFrame = avFrame;
470+#if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
324471 s->avr = avr;
472+#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
325473 s->output = output;
326474
327475 av_packet_unref(&avPacket);
328476 }
329477
330−void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data, uint_t * read){
331− if (s->multi == 1) aubio_source_avcodec_reset_resampler(s, 0);
332− uint_t i;
478+void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data,
479+ uint_t * read) {
480+ uint_t i, j;
333481 uint_t end = 0;
334482 uint_t total_wrote = 0;
335483 while (total_wrote < s->hop_size) {
336484 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
337485 for (i = 0; i < end; i++) {
338− read_data->data[i + total_wrote] = s->output[i + s->read_index];
486+ read_data->data[i + total_wrote] = 0.;
487+ for (j = 0; j < s->input_channels; j++) {
488+ read_data->data[i + total_wrote] +=
489+ s->output[(i + s->read_index) * s->input_channels + j];
490+ }
491+ read_data->data[i + total_wrote] *= 1./s->input_channels;
339492 }
340493 total_wrote += end;
341494 if (total_wrote < s->hop_size) {
@@ -351,15 +504,15 @@ void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data, uin · 9 unmodified lines
351504 }
352505 }
353506 if (total_wrote < s->hop_size) {
354− for (i = end; i < s->hop_size; i++) {
507+ for (i = total_wrote; i < s->hop_size; i++) {
355508 read_data->data[i] = 0.;
356509 }
357510 }
358511 *read = total_wrote;
359512 }
360513
361−void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s, fmat_t * read_data, uint_t * read){
362− if (s->multi == 0) aubio_source_avcodec_reset_resampler(s, 1);
514+void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s,
515+ fmat_t * read_data, uint_t * read) {
363516 uint_t i,j;
364517 uint_t end = 0;
365518 uint_t total_wrote = 0;
@@ -386,7 +539,7 @@ void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s, fmat_t * read_dat · 20 unmodified lines
386539 }
387540 if (total_wrote < s->hop_size) {
388541 for (j = 0; j < read_data->height; j++) {
389− for (i = end; i < s->hop_size; i++) {
542+ for (i = total_wrote; i < s->hop_size; i++) {
390543 read_data->data[j][i] = 0.;
391544 }
392545 }
@@ -403,22 +556,42 @@ uint_t aubio_source_avcodec_get_channels(const aubio_source_avcodec_t * s) { · 10 unmodified lines
403556 }
404557
405558 uint_t aubio_source_avcodec_seek (aubio_source_avcodec_t * s, uint_t pos) {
406− int64_t resampled_pos = (uint_t)ROUND(pos * (s->input_samplerate * 1. / s->samplerate));
559+ int64_t resampled_pos =
560+ (uint_t)ROUND(pos * (s->input_samplerate * 1. / s->samplerate));
407561 int64_t min_ts = MAX(resampled_pos - 2000, 0);
408562 int64_t max_ts = MIN(resampled_pos + 2000, INT64_MAX);
409563 int seek_flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY;
410− int ret = avformat_seek_file(s->avFormatCtx, s->selected_stream,
564+ int ret = AUBIO_FAIL;
565+ if (s->avFormatCtx != NULL && s->avr != NULL) {
566+ ret = AUBIO_OK;
567+ } else {
568+ AUBIO_ERR("source_avcodec: failed seeking in %s (file not opened?)",
569+ s->path);
570+ return ret;
571+ }
572+ if ((sint_t)pos < 0) {
573+ AUBIO_ERR("source_avcodec: could not seek %s at %d (seeking position"
574+ " should be >= 0)\n", s->path, pos);
575+ return AUBIO_FAIL;
576+ }
577+ ret = avformat_seek_file(s->avFormatCtx, s->selected_stream,
411578 min_ts, resampled_pos, max_ts, seek_flags);
412579 if (ret < 0) {
413− AUBIO_ERR("Failed seeking to %d in file %s", pos, s->path);
580+ AUBIO_ERR("source_avcodec: failed seeking to %d in file %s",
581+ pos, s->path);
414582 }
415583 // reset read status
416584 s->eof = 0;
417585 s->read_index = 0;
418586 s->read_samples = 0;
587+#ifdef HAVE_AVRESAMPLE
419588 // reset the AVAudioResampleContext
420589 avresample_close(s->avr);
421590 avresample_open(s->avr);
591+#elif defined(HAVE_SWRESAMPLE)
592+ swr_close(s->avr);
593+ swr_init(s->avr);
594+#endif
422595 return ret;
423596 }
424597
@@ -432,18 +605,27 @@ uint_t aubio_source_avcodec_get_duration (aubio_source_avcodec_t * s) { · 7 unmodified lines
432605
433606 uint_t aubio_source_avcodec_close(aubio_source_avcodec_t * s) {
434607 if (s->avr != NULL) {
608+#ifdef HAVE_AVRESAMPLE
435609 avresample_close( s->avr );
610+#elif defined(HAVE_SWRESAMPLE)
611+ swr_close ( s->avr );
612+#endif
436613 av_free ( s->avr );
437614 }
438615 s->avr = NULL;
439616 if (s->avCodecCtx != NULL) {
617+#ifndef HAVE_AUBIO_LIBAVCODEC_DEPRECATED
618+ avcodec_free_context( &s->avCodecCtx );
619+#else
440620 avcodec_close ( s->avCodecCtx );
621+#endif
441622 }
442623 s->avCodecCtx = NULL;
443624 if (s->avFormatCtx != NULL) {
444− avformat_close_input ( &(s->avFormatCtx) );
625+ avformat_close_input(&s->avFormatCtx);
626+ s->avFormatCtx = NULL;
445627 }
446− s->avFormatCtx = NULL;
628+ av_packet_unref(&s->avPacket);
447629 return AUBIO_OK;
448630 }
449631
@@ -457,8 +639,11 @@ void del_aubio_source_avcodec(aubio_source_avcodec_t * s){ · 7 unmodified lines
457639 if (s->avFrame != NULL) {
458640 av_frame_free( &(s->avFrame) );
459641 }
460− if (s->path) AUBIO_FREE(s->path);
461642 s->avFrame = NULL;
643+ if (s->path) {
644+ AUBIO_FREE(s->path);
645+ }
646+ s->path = NULL;
462647 AUBIO_FREE(s);
463648 }
464649
src/io/source_sndfile.c+17−8
@@ -18,23 +18,20 @@ · 17 unmodified lines
1818
1919 */
2020
21−
22−#include "config.h"
21+#include "aubio_priv.h"
2322
2423 #ifdef HAVE_SNDFILE
2524
2625 #include <sndfile.h>
2726
28−#include "aubio_priv.h"
2927 #include "fvec.h"
3028 #include "fmat.h"
3129 #include "source_sndfile.h"
3230
3331 #include "temporal/resampler.h"
3432
35−#define MAX_CHANNELS 6
3633 #define MAX_SIZE 4096
37−#define MAX_SAMPLES MAX_CHANNELS * MAX_SIZE
34+#define MAX_SAMPLES AUBIO_MAX_CHANNELS * MAX_SIZE
3835
3936 #if !HAVE_AUBIO_DOUBLE
4037 #define aubio_sf_read_smpl sf_read_float
@@ -140,7 +137,7 @@ aubio_source_sndfile_t * new_aubio_source_sndfile(const char_t * path, uint_t sa · 99 unmodified lines
140137 }
141138 if (s->ratio > 1) {
142139 // we would need to add a ring buffer for these
143− if ( (uint_t)(s->input_hop_size * s->ratio + .5) != s->hop_size ) {
140+ if ( (uint_t)FLOOR(s->input_hop_size * s->ratio + .5) != s->hop_size ) {
144141 AUBIO_ERR("source_sndfile: can not upsample %s from %d to %d\n", s->path,
145142 s->input_samplerate, s->samplerate);
146143 goto beach;
@@ -297,7 +294,18 @@ uint_t aubio_source_sndfile_get_duration (const aubio_source_sndfile_t * s) { · 150 unmodified lines
297294
298295 uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) {
299296 uint_t resampled_pos = (uint_t)ROUND(pos / s->ratio);
300− sf_count_t sf_ret = sf_seek (s->handle, resampled_pos, SEEK_SET);
297+ sf_count_t sf_ret;
298+ if (s->handle == NULL) {
299+ AUBIO_ERR("source_sndfile: failed seeking in %s (file not opened?)\n",
300+ s->path);
301+ return AUBIO_FAIL;
302+ }
303+ if ((sint_t)pos < 0) {
304+ AUBIO_ERR("source_sndfile: could not seek %s at %d (seeking position"
305+ " should be >= 0)\n", s->path, pos);
306+ return AUBIO_FAIL;
307+ }
308+ sf_ret = sf_seek (s->handle, resampled_pos, SEEK_SET);
301309 if (sf_ret == -1) {
302310 AUBIO_ERR("source_sndfile: Failed seeking %s at %d: %s\n", s->path, pos, sf_strerror (NULL));
303311 return AUBIO_FAIL;
@@ -312,12 +320,13 @@ uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) { · 8 unmodified lines
312320
313321 uint_t aubio_source_sndfile_close (aubio_source_sndfile_t *s) {
314322 if (!s->handle) {
315− return AUBIO_FAIL;
323+ return AUBIO_OK;
316324 }
317325 if(sf_close(s->handle)) {
318326 AUBIO_ERR("source_sndfile: Error closing file %s: %s\n", s->path, sf_strerror (NULL));
319327 return AUBIO_FAIL;
320328 }
329+ s->handle = NULL;
321330 return AUBIO_OK;
322331 }
323332
src/io/source_wavread.c+48−14
@@ -18,11 +18,10 @@ · 17 unmodified lines
1818
1919 */
2020
21−#include "config.h"
21+#include "aubio_priv.h"
2222
2323 #ifdef HAVE_WAVREAD
2424
25−#include "aubio_priv.h"
2625 #include "fvec.h"
2726 #include "fmat.h"
2827 #include "source_wavread.h"
@@ -76,7 +75,7 @@ static unsigned int read_little_endian (unsigned char *buf, · 47 unmodified lines
7675 aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t samplerate, uint_t hop_size) {
7776 aubio_source_wavread_t * s = AUBIO_NEW(aubio_source_wavread_t);
7877 size_t bytes_read = 0, bytes_junk = 0, bytes_expected = 44;
79− unsigned char buf[5];
78+ unsigned char buf[5] = "\0";
8079 unsigned int format, channels, sr, byterate, blockalign, duration, bitspersample;//, data_size;
8180
8281 if (path == NULL) {
@@ -109,7 +108,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 26 unmodified lines
109108 bytes_read += fread(buf, 1, 4, s->fid);
110109 buf[4] = '\0';
111110 if ( strcmp((const char *)buf, "RIFF") != 0 ) {
112− AUBIO_ERR("source_wavread: could not find RIFF header in %s\n", s->path);
111+ AUBIO_ERR("source_wavread: Failed opening %s (could not find RIFF header)\n", s->path);
113112 goto beach;
114113 }
115114
@@ -120,7 +119,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 4 unmodified lines
120119 bytes_read += fread(buf, 1, 4, s->fid);
121120 buf[4] = '\0';
122121 if ( strcmp((const char *)buf, "WAVE") != 0 ) {
123− AUBIO_ERR("source_wavread: wrong format in RIFF header in %s\n", s->path);
122+ AUBIO_ERR("source_wavread: Failed opening %s (wrong format in RIFF header)\n", s->path);
124123 goto beach;
125124 }
126125
@@ -134,7 +133,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 7 unmodified lines
134133 buf[4] = '\0';
135134 bytes_junk += read_little_endian(buf, 4);
136135 if (fseek(s->fid, bytes_read + bytes_junk, SEEK_SET) != 0) {
137− AUBIO_ERR("source_wavread: could not seek past JUNK Chunk in %s (%s)\n",
136+ AUBIO_ERR("source_wavread: Failed opening %s (could not seek past JUNK Chunk: %s)\n",
138137 s->path, strerror(errno));
139138 goto beach;
140139 }
@@ -147,7 +146,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 6 unmodified lines
147146
148147 // get the fmt chunk
149148 if ( strcmp((const char *)buf, "fmt ") != 0 ) {
150− AUBIO_ERR("source_wavread: failed finding fmt RIFF header in %s\n", s->path);
149+ AUBIO_ERR("source_wavread: Failed opening %s (could not find 'fmt ' in RIFF header)\n", s->path);
151150 goto beach;
152151 }
153152
@@ -156,18 +155,18 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 2 unmodified lines
156155 format = read_little_endian(buf, 4);
157156 if ( format != 16 ) {
158157 // TODO accept format 18
159− AUBIO_ERR("source_wavread: file %s is not encoded with PCM\n", s->path);
158+ AUBIO_ERR("source_wavread: Failed opening %s (not encoded with PCM)\n", s->path);
160159 goto beach;
161160 }
162161 if ( buf[1] || buf[2] | buf[3] ) {
163− AUBIO_ERR("source_wavread: Subchunk1Size should be 0, in %s\n", s->path);
162+ AUBIO_ERR("source_wavread: Failed opening %s (Subchunk1Size should be 0)\n", s->path);
164163 goto beach;
165164 }
166165
167166 // AudioFormat
168167 bytes_read += fread(buf, 1, 2, s->fid);
169168 if ( buf[0] != 1 || buf[1] != 0) {
170− AUBIO_ERR("source_wavread: AudioFormat should be PCM, in %s\n", s->path);
169+ AUBIO_ERR("source_wavread: Failed opening %s (AudioFormat should be PCM)\n", s->path);
171170 goto beach;
172171 }
173172
@@ -190,6 +189,26 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 16 unmodified lines
190189 // BitsPerSample
191190 bytes_read += fread(buf, 1, 2, s->fid);
192191 bitspersample = read_little_endian(buf, 2);
192+
193+ if ( channels == 0 ) {
194+ AUBIO_ERR("source_wavread: Failed opening %s (number of channels can not be 0)\n", s->path);
195+ goto beach;
196+ }
197+
198+ if ( (sint_t)sr <= 0 ) {
199+ AUBIO_ERR("source_wavread: Failed opening %s (samplerate can not be <= 0)\n", s->path);
200+ goto beach;
201+ }
202+
203+ if ( byterate == 0 ) {
204+ AUBIO_ERR("source_wavread: Failed opening %s (byterate can not be 0)\n", s->path);
205+ goto beach;
206+ }
207+
208+ if ( bitspersample == 0 ) {
209+ AUBIO_ERR("source_wavread: Failed opening %s (bitspersample can not be 0)\n", s->path);
210+ goto beach;
211+ }
193212 #if 0
194213 if ( bitspersample != 16 ) {
195214 AUBIO_ERR("source_wavread: can not process %dbit file %s\n",
@@ -199,12 +218,12 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 3 unmodified lines
199218 #endif
200219
201220 if ( byterate * 8 != sr * channels * bitspersample ) {
202− AUBIO_ERR("source_wavread: wrong byterate in %s\n", s->path);
221+ AUBIO_ERR("source_wavread: Failed opening %s (wrong byterate)\n", s->path);
203222 goto beach;
204223 }
205224
206225 if ( blockalign * 8 != channels * bitspersample ) {
207− AUBIO_ERR("source_wavread: wrong blockalign in %s\n", s->path);
226+ AUBIO_ERR("source_wavread: Failed opening %s (wrong blockalign)\n", s->path);
208227 goto beach;
209228 }
210229
@@ -329,6 +348,11 @@ void aubio_source_wavread_do(aubio_source_wavread_t * s, fvec_t * read_data, uin · 118 unmodified lines
329348 uint_t i, j;
330349 uint_t end = 0;
331350 uint_t total_wrote = 0;
351+ if (s->fid == NULL) {
352+ AUBIO_ERR("source_wavread: could not read from %s (file not opened)\n",
353+ s->path);
354+ return;
355+ }
332356 while (total_wrote < s->hop_size) {
333357 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
334358 for (i = 0; i < end; i++) {
@@ -363,6 +387,11 @@ void aubio_source_wavread_do_multi(aubio_source_wavread_t * s, fmat_t * read_dat · 28 unmodified lines
363387 uint_t i,j;
364388 uint_t end = 0;
365389 uint_t total_wrote = 0;
390+ if (s->fid == NULL) {
391+ AUBIO_ERR("source_wavread: could not read from %s (file not opened)\n",
392+ s->path);
393+ return;
394+ }
366395 while (total_wrote < s->hop_size) {
367396 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
368397 for (j = 0; j < read_data->height; j++) {
@@ -403,7 +432,12 @@ uint_t aubio_source_wavread_get_channels(aubio_source_wavread_t * s) { · 34 unmodified lines
403432
404433 uint_t aubio_source_wavread_seek (aubio_source_wavread_t * s, uint_t pos) {
405434 uint_t ret = 0;
435+ if (s->fid == NULL) {
436+ AUBIO_ERR("source_wavread: could not seek %s (file not opened?)\n", s->path, pos);
437+ return AUBIO_FAIL;
438+ }
406439 if ((sint_t)pos < 0) {
440+ AUBIO_ERR("source_wavread: could not seek %s at %d (seeking position should be >= 0)\n", s->path, pos);
407441 return AUBIO_FAIL;
408442 }
409443 ret = fseek(s->fid, s->seek_start + pos * s->blockalign, SEEK_SET);
@@ -425,8 +459,8 @@ uint_t aubio_source_wavread_get_duration (const aubio_source_wavread_t * s) { · 15 unmodified lines
425459 }
426460
427461 uint_t aubio_source_wavread_close (aubio_source_wavread_t * s) {
428− if (!s->fid) {
429− return AUBIO_FAIL;
462+ if (s->fid == NULL) {
463+ return AUBIO_OK;
430464 }
431465 if (fclose(s->fid)) {
432466 AUBIO_ERR("source_wavread: could not close %s (%s)\n", s->path, strerror(errno));
src/io/utils_apple_audio.c+1−2
@@ -1,4 +1,4 @@
1−#include "config.h"
1+#include "aubio_priv.h"
22
33 #if defined(HAVE_SOURCE_APPLE_AUDIO) || defined(HAVE_SINK_APPLE_AUDIO)
44
@@ -6,7 +6,6 @@ · 1 unmodified line
66 #include <CoreFoundation/CoreFoundation.h>
77 // ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
88 #include <AudioToolbox/AudioToolbox.h>
9−#include "aubio_priv.h"
109
1110 int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
1211 void freeAudioBufferList(AudioBufferList *bufferList);
src/mathutils.c+90−36
@@ -24,11 +24,11 @@ · 23 unmodified lines
2424 #include "fvec.h"
2525 #include "mathutils.h"
2626 #include "musicutils.h"
27−#include "config.h"
2827
2928 /** Window types */
3029 typedef enum
3130 {
31+ aubio_win_ones,
3232 aubio_win_rectangle,
3333 aubio_win_hamming,
3434 aubio_win_hanning,
@@ -64,7 +64,9 @@ uint_t fvec_set_window (fvec_t *win, char_t *window_type) { · 29 unmodified lines
6464 if (window_type == NULL) {
6565 AUBIO_ERR ("window type can not be null.\n");
6666 return 1;
67− } else if (strcmp (window_type, "rectangle") == 0)
67+ } else if (strcmp (window_type, "ones") == 0)
68+ wintype = aubio_win_ones;
69+ else if (strcmp (window_type, "rectangle") == 0)
6870 wintype = aubio_win_rectangle;
6971 else if (strcmp (window_type, "hamming") == 0)
7072 wintype = aubio_win_hamming;
@@ -89,9 +91,11 @@ uint_t fvec_set_window (fvec_t *win, char_t *window_type) { · 18 unmodified lines
8991 return 1;
9092 }
9193 switch(wintype) {
94+ case aubio_win_ones:
95+ fvec_ones(win);
96+ break;
9297 case aubio_win_rectangle:
93− for (i=0;i<size;i++)
94− w[i] = 0.5;
98+ fvec_set_all(win, .5);
9599 break;
96100 case aubio_win_hamming:
97101 for (i=0;i<size;i++)
@@ -155,45 +159,53 @@ smpl_t · 57 unmodified lines
155159 fvec_mean (fvec_t * s)
156160 {
157161 smpl_t tmp = 0.0;
158−#ifndef HAVE_ACCELERATE
162+#if defined(HAVE_INTEL_IPP)
163+ aubio_ippsMean(s->data, (int)s->length, &tmp);
164+ return tmp;
165+#elif defined(HAVE_ACCELERATE)
166+ aubio_vDSP_meanv(s->data, 1, &tmp, s->length);
167+ return tmp;
168+#else
159169 uint_t j;
160170 for (j = 0; j < s->length; j++) {
161171 tmp += s->data[j];
162172 }
163− return tmp / (smpl_t) (s->length);
164−#else
165− aubio_vDSP_meanv(s->data, 1, &tmp, s->length);
166− return tmp;
167−#endif /* HAVE_ACCELERATE */
173+ return tmp / (smpl_t)(s->length);
174+#endif
168175 }
169176
170177 smpl_t
171178 fvec_sum (fvec_t * s)
172179 {
173180 smpl_t tmp = 0.0;
174−#ifndef HAVE_ACCELERATE
181+#if defined(HAVE_INTEL_IPP)
182+ aubio_ippsSum(s->data, (int)s->length, &tmp);
183+#elif defined(HAVE_ACCELERATE)
184+ aubio_vDSP_sve(s->data, 1, &tmp, s->length);
185+#else
175186 uint_t j;
176187 for (j = 0; j < s->length; j++) {
177188 tmp += s->data[j];
178189 }
179−#else
180− aubio_vDSP_sve(s->data, 1, &tmp, s->length);
181−#endif /* HAVE_ACCELERATE */
190+#endif
182191 return tmp;
183192 }
184193
185194 smpl_t
186195 fvec_max (fvec_t * s)
187196 {
188−#ifndef HAVE_ACCELERATE
197+#if defined(HAVE_INTEL_IPP)
198+ smpl_t tmp = 0.;
199+ aubio_ippsMax( s->data, (int)s->length, &tmp);
200+#elif defined(HAVE_ACCELERATE)
201+ smpl_t tmp = 0.;
202+ aubio_vDSP_maxv( s->data, 1, &tmp, s->length );
203+#else
189204 uint_t j;
190− smpl_t tmp = 0.0;
191− for (j = 0; j < s->length; j++) {
205+ smpl_t tmp = s->data[0];
206+ for (j = 1; j < s->length; j++) {
192207 tmp = (tmp > s->data[j]) ? tmp : s->data[j];
193208 }
194−#else
195− smpl_t tmp = 0.;
196− aubio_vDSP_maxv(s->data, 1, &tmp, s->length);
197209 #endif
198210 return tmp;
199211 }
@@ -201,15 +213,18 @@ fvec_max (fvec_t * s) · 1 unmodified line
201213 smpl_t
202214 fvec_min (fvec_t * s)
203215 {
204−#ifndef HAVE_ACCELERATE
216+#if defined(HAVE_INTEL_IPP)
217+ smpl_t tmp = 0.;
218+ aubio_ippsMin(s->data, (int)s->length, &tmp);
219+#elif defined(HAVE_ACCELERATE)
220+ smpl_t tmp = 0.;
221+ aubio_vDSP_minv(s->data, 1, &tmp, s->length);
222+#else
205223 uint_t j;
206224 smpl_t tmp = s->data[0];
207− for (j = 0; j < s->length; j++) {
225+ for (j = 1; j < s->length; j++) {
208226 tmp = (tmp < s->data[j]) ? tmp : s->data[j];
209227 }
210−#else
211− smpl_t tmp = 0.;
212− aubio_vDSP_minv(s->data, 1, &tmp, s->length);
213228 #endif
214229 return tmp;
215230 }
@@ -226,10 +241,10 @@ fvec_min_elem (fvec_t * s) · 10 unmodified lines
226241 }
227242 #else
228243 smpl_t tmp = 0.;
229− uint_t pos = 0.;
230− aubio_vDSP_minvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
244+ vDSP_Length pos = 0;
245+ aubio_vDSP_minvi(s->data, 1, &tmp, &pos, s->length);
231246 #endif
232− return pos;
247+ return (uint_t)pos;
233248 }
234249
235250 uint_t
@@ -244,10 +259,10 @@ fvec_max_elem (fvec_t * s) · 8 unmodified lines
244259 }
245260 #else
246261 smpl_t tmp = 0.;
247− uint_t pos = 0.;
248− aubio_vDSP_maxvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);
262+ vDSP_Length pos = 0;
263+ aubio_vDSP_maxvi(s->data, 1, &tmp, &pos, s->length);
249264 #endif
250− return pos;
265+ return (uint_t)pos;
251266 }
252267
253268 void
@@ -256,7 +271,7 @@ fvec_shift (fvec_t * s) · 2 unmodified lines
256271 uint_t half = s->length / 2, start = half, j;
257272 // if length is odd, middle element is moved to the end
258273 if (2 * half < s->length) start ++;
259−#ifndef HAVE_ATLAS
274+#ifndef HAVE_BLAS
260275 for (j = 0; j < half; j++) {
261276 ELEM_SWAP (s->data[j], s->data[j + start]);
262277 }
@@ -276,7 +291,7 @@ fvec_ishift (fvec_t * s) · 13 unmodified lines
276291 uint_t half = s->length / 2, start = half, j;
277292 // if length is odd, middle element is moved to the beginning
278293 if (2 * half < s->length) start ++;
279−#ifndef HAVE_ATLAS
294+#ifndef HAVE_BLAS
280295 for (j = 0; j < half; j++) {
281296 ELEM_SWAP (s->data[j], s->data[j + start]);
282297 }
@@ -290,11 +305,30 @@ fvec_ishift (fvec_t * s) · 7 unmodified lines
290305 }
291306 }
292307
308+void fvec_push(fvec_t *in, smpl_t new_elem) {
309+ uint_t i;
310+ for (i = 0; i < in->length - 1; i++) {
311+ in->data[i] = in->data[i + 1];
312+ }
313+ in->data[in->length - 1] = new_elem;
314+}
315+
316+void fvec_clamp(fvec_t *in, smpl_t absmax) {
317+ uint_t i;
318+ for (i = 0; i < in->length; i++) {
319+ if (in->data[i] > 0 && in->data[i] > ABS(absmax)) {
320+ in->data[i] = absmax;
321+ } else if (in->data[i] < 0 && in->data[i] < -ABS(absmax)) {
322+ in->data[i] = -absmax;
323+ }
324+ }
325+}
326+
293327 smpl_t
294328 aubio_level_lin (const fvec_t * f)
295329 {
296330 smpl_t energy = 0.;
297−#ifndef HAVE_ATLAS
331+#ifndef HAVE_BLAS
298332 uint_t j;
299333 for (j = 0; j < f->length; j++) {
300334 energy += SQR (f->data[j]);
@@ -353,6 +387,15 @@ fvec_add (fvec_t * o, smpl_t val) · 52 unmodified lines
353387 }
354388 }
355389
390+void
391+fvec_mul (fvec_t *o, smpl_t val)
392+{
393+ uint_t j;
394+ for (j = 0; j < o->length; j++) {
395+ o->data[j] *= val;
396+ }
397+}
398+
356399 void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp,
357400 uint_t post, uint_t pre) {
358401 uint_t length = vec->length, j;
@@ -488,7 +531,7 @@ aubio_freqtomidi (smpl_t freq) · 129 unmodified lines
488531 if (freq < 2. || freq > 100000.) return 0.; // avoid nans and infs
489532 /* log(freq/A-2)/log(2) */
490533 midi = freq / 6.875;
491− midi = LOG (midi) / 0.69314718055995;
534+ midi = LOG (midi) / 0.6931471805599453;
492535 midi *= 12;
493536 midi -= 3;
494537 return midi;
@@ -500,7 +543,7 @@ aubio_miditofreq (smpl_t midi) · 5 unmodified lines
500543 smpl_t freq;
501544 if (midi > 140.) return 0.; // avoid infs
502545 freq = (midi + 3.) / 12.;
503− freq = EXP (freq * 0.69314718055995);
546+ freq = EXP (freq * 0.6931471805599453);
504547 freq *= 6.875;
505548 return freq;
506549 }
@@ -551,6 +594,17 @@ aubio_next_power_of_two (uint_t a) · 44 unmodified lines
551594 return i;
552595 }
553596
597+uint_t
598+aubio_power_of_two_order (uint_t a)
599+{
600+ int order = 0;
601+ int temp = aubio_next_power_of_two(a);
602+ while (temp >>= 1) {
603+ ++order;
604+ }
605+ return order;
606+}
607+
554608 smpl_t
555609 aubio_db_spl (const fvec_t * o)
556610 {
src/mathutils.h+22−0
@@ -117,6 +117,17 @@ of the resulting spectrum. See Amalia de Götzen's paper referred to above. · 116 unmodified lines
117117 */
118118 void fvec_ishift (fvec_t * v);
119119
120+/** push a new element to the end of a vector, erasing the first element and
121+ * sliding all others
122+
123+ \param in vector to push to
124+ \param new_elem new_element to add at the end of the vector
125+
126+ In numpy words, this is equivalent to: in = np.concatenate([in, [new_elem]])[1:]
127+
128+*/
129+void fvec_push(fvec_t *in, smpl_t new_elem);
130+
120131 /** compute the sum of all elements of a vector
121132
122133 \param v vector to compute the sum of
@@ -182,6 +193,14 @@ void fvec_alpha_normalise (fvec_t * v, smpl_t p); · 59 unmodified lines
182193 */
183194 void fvec_add (fvec_t * v, smpl_t c);
184195
196+/** multiply each elements of a vector by a scalar
197+
198+ \param v vector to add constant to
199+ \param s constant to scale v with
200+
201+*/
202+void fvec_mul (fvec_t * v, smpl_t s);
203+
185204 /** remove the minimum value of the vector to each elements
186205
187206 \param v vector to remove minimum from
@@ -301,6 +320,9 @@ uint_t aubio_is_power_of_two(uint_t a); · 113 unmodified lines
301320 /** return the next power of power of 2 greater than a */
302321 uint_t aubio_next_power_of_two(uint_t a);
303322
323+/** return the log2 factor of the given power of 2 value a */
324+uint_t aubio_power_of_two_order(uint_t a);
325+
304326 /** compute normalised autocorrelation function
305327
306328 \param input vector to compute autocorrelation from
src/musicutils.c+85−0
@@ -0,0 +1,85 @@
1+/*
2+ Copyright (C) 2018 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+#include "musicutils.h"
23+
24+smpl_t
25+aubio_hztomel (smpl_t freq)
26+{
27+ const smpl_t lin_space = 3./200.;
28+ const smpl_t split_hz = 1000.;
29+ const smpl_t split_mel = split_hz * lin_space;
30+ const smpl_t log_space = 27./LOG(6400/1000.);
31+ if (freq < 0) {
32+ AUBIO_WRN("hztomel: input frequency should be >= 0\n");
33+ return 0;
34+ }
35+ if (freq < split_hz)
36+ {
37+ return freq * lin_space;
38+ } else {
39+ return split_mel + log_space * LOG (freq / split_hz);
40+ }
41+
42+}
43+
44+smpl_t
45+aubio_meltohz (smpl_t mel)
46+{
47+ const smpl_t lin_space = 200./3.;
48+ const smpl_t split_hz = 1000.;
49+ const smpl_t split_mel = split_hz / lin_space;
50+ const smpl_t logSpacing = POW(6400/1000., 1/27.);
51+ if (mel < 0) {
52+ AUBIO_WRN("meltohz: input mel should be >= 0\n");
53+ return 0;
54+ }
55+ if (mel < split_mel) {
56+ return lin_space * mel;
57+ } else {
58+ return split_hz * POW(logSpacing, mel - split_mel);
59+ }
60+}
61+
62+smpl_t
63+aubio_hztomel_htk (smpl_t freq)
64+{
65+ const smpl_t split_hz = 700.;
66+ const smpl_t log_space = 1127.;
67+ if (freq < 0) {
68+ AUBIO_WRN("hztomel_htk: input frequency should be >= 0\n");
69+ return 0;
70+ }
71+ return log_space * LOG (1 + freq / split_hz);
72+}
73+
74+smpl_t
75+aubio_meltohz_htk (smpl_t mel)
76+{
77+ const smpl_t split_hz = 700.;
78+ const smpl_t log_space = 1./1127.;
79+ if (mel < 0) {
80+ AUBIO_WRN("meltohz_htk: input frequency should be >= 0\n");
81+ return 0;
82+ }
83+ return split_hz * ( EXP ( mel * log_space) - 1.);
84+}
85+
src/musicutils.h+107−0
@@ -86,6 +86,105 @@ smpl_t aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize); · 85 unmodified lines
8686 /** convert frequency (Hz) to frequency bin */
8787 smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize);
8888
89+/** convert frequency (Hz) to mel
90+
91+ \param freq input frequency, in Hz
92+
93+ \return output mel
94+
95+ Converts a scalar from the frequency domain to the mel scale using Slaney
96+ Auditory Toolbox's implementation:
97+
98+ If \f$ f < 1000 \f$, \f$ m = 3 f / 200 \f$.
99+
100+ If \f$ f >= 1000 \f$, \f$ m = 1000 + 27 \frac{{ln}(f) - ln(1000))}
101+ {{ln}(6400) - ln(1000)}
102+ \f$
103+
104+ See also
105+ --------
106+
107+ aubio_meltohz(), aubio_hztomel_htk().
108+
109+*/
110+smpl_t aubio_hztomel (smpl_t freq);
111+
112+/** convert mel to frequency (Hz)
113+
114+ \param mel input mel
115+
116+ \return output frequency, in Hz
117+
118+ Converts a scalar from the mel scale to the frequency domain using Slaney
119+ Auditory Toolbox's implementation:
120+
121+ If \f$ f < 1000 \f$, \f$ f = 200 m/3 \f$.
122+
123+ If \f$ f \geq 1000 \f$, \f$ f = 1000 + \left(\frac{6400}{1000}\right)
124+ ^{\frac{m - 1000}{27}} \f$
125+
126+ See also
127+ --------
128+
129+ aubio_hztomel(), aubio_meltohz_htk().
130+
131+ References
132+ ----------
133+
134+ Malcolm Slaney, *Auditory Toolbox Version 2, Technical Report #1998-010*
135+ https://engineering.purdue.edu/~malcolm/interval/1998-010/
136+
137+*/
138+smpl_t aubio_meltohz (smpl_t mel);
139+
140+/** convert frequency (Hz) to mel
141+
142+ \param freq input frequency, in Hz
143+
144+ \return output mel
145+
146+ Converts a scalar from the frequency domain to the mel scale, using the
147+ equation defined by O'Shaughnessy, as implemented in the HTK speech
148+ recognition toolkit:
149+
150+ \f$ m = 1127 + ln(1 + \frac{f}{700}) \f$
151+
152+ See also
153+ --------
154+
155+ aubio_meltohz_htk(), aubio_hztomel().
156+
157+ References
158+ ----------
159+
160+ Douglas O'Shaughnessy (1987). *Speech communication: human and machine*.
161+ Addison-Wesley. p. 150. ISBN 978-0-201-16520-3.
162+
163+ HTK Speech Recognition Toolkit: http://htk.eng.cam.ac.uk/
164+
165+ */
166+smpl_t aubio_hztomel_htk (smpl_t freq);
167+
168+/** convert mel to frequency (Hz)
169+
170+ \param mel input mel
171+
172+ \return output frequency, in Hz
173+
174+ Converts a scalar from the mel scale to the frequency domain, using the
175+ equation defined by O'Shaughnessy, as implemented in the HTK speech
176+ recognition toolkit:
177+
178+ \f$ f = 700 * {e}^\left(\frac{f}{1127} - 1\right) \f$
179+
180+ See also
181+ --------
182+
183+ aubio_hztomel_htk(), aubio_meltohz().
184+
185+*/
186+smpl_t aubio_meltohz_htk (smpl_t mel);
187+
89188 /** convert frequency (Hz) to midi value (0-128) */
90189 smpl_t aubio_freqtomidi (smpl_t freq);
91190
@@ -156,6 +255,14 @@ uint_t aubio_silence_detection (const fvec_t * v, smpl_t threshold); · 64 unmodified lines
156255 */
157256 smpl_t aubio_level_detection (const fvec_t * v, smpl_t threshold);
158257
258+/** clamp the values of a vector within the range [-abs(max), abs(max)]
259+
260+ \param in vector to clamp
261+ \param absmax maximum value over which input vector elements should be clamped
262+
263+*/
264+void fvec_clamp(fvec_t *in, smpl_t absmax);
265+
159266 #ifdef __cplusplus
160267 }
161268 #endif
src/notes/notes.c+97−11
@@ -1,5 +1,5 @@
11 /*
2− Copyright (C) 2014 Paul Brossier <piem@aubio.org>
2+ Copyright (C) 2014-2018 Paul Brossier <piem@aubio.org>
33
44 This file is part of aubio.
55
@@ -24,6 +24,13 @@ · 18 unmodified lines
2424 #include "onset/onset.h"
2525 #include "notes/notes.h"
2626
27+#define AUBIO_DEFAULT_NOTES_SILENCE -70.
28+#define AUBIO_DEFAULT_NOTES_RELEASE_DROP 10.
29+// increase to 10. for .1 cent precision
30+// or to 100. for .01 cent precision
31+#define AUBIO_DEFAULT_CENT_PRECISION 1.
32+#define AUBIO_DEFAULT_NOTES_MINIOI_MS 30.
33+
2734 struct _aubio_notes_t {
2835
2936 uint_t onset_buf_size;
@@ -50,6 +57,9 @@ struct _aubio_notes_t { · 20 unmodified lines
5057 smpl_t silence_threshold;
5158
5259 uint_t isready;
60+
61+ smpl_t last_onset_level;
62+ smpl_t release_drop_level;
5363 };
5464
5565 aubio_notes_t * new_aubio_notes (const char_t * method,
@@ -73,11 +83,14 @@ aubio_notes_t * new_aubio_notes (const char_t * method, · 17 unmodified lines
7383 o->isready = 0;
7484
7585 o->onset = new_aubio_onset (onset_method, o->onset_buf_size, o->hop_size, o->samplerate);
86+ if (o->onset == NULL) goto fail;
7687 if (o->onset_threshold != 0.) aubio_onset_set_threshold (o->onset, o->onset_threshold);
7788 o->onset_output = new_fvec (1);
7889
7990 o->pitch = new_aubio_pitch (pitch_method, o->pitch_buf_size, o->hop_size, o->samplerate);
91+ if (o->pitch == NULL) goto fail;
8092 if (o->pitch_tolerance != 0.) aubio_pitch_set_tolerance (o->pitch, o->pitch_tolerance);
93+ aubio_pitch_set_unit (o->pitch, "midi");
8194 o->pitch_output = new_fvec (1);
8295
8396 if (strcmp(method, "default") != 0) {
@@ -87,10 +100,17 @@ aubio_notes_t * new_aubio_notes (const char_t * method, · 3 unmodified lines
87100 o->note_buffer = new_fvec(o->median);
88101 o->note_buffer2 = new_fvec(o->median);
89102
103+ if (!o->onset_output || !o->pitch_output ||
104+ !o->note_buffer || !o->note_buffer2) goto fail;
105+
90106 o->curnote = -1.;
91107 o->newnote = 0.;
92108
93− o->silence_threshold = -90.;
109+ aubio_notes_set_silence(o, AUBIO_DEFAULT_NOTES_SILENCE);
110+ aubio_notes_set_minioi_ms (o, AUBIO_DEFAULT_NOTES_MINIOI_MS);
111+
112+ o->last_onset_level = AUBIO_DEFAULT_NOTES_SILENCE;
113+ o->release_drop_level = AUBIO_DEFAULT_NOTES_RELEASE_DROP;
94114
95115 return o;
96116
@@ -99,6 +119,55 @@ fail: · 2 unmodified lines
99119 return NULL;
100120 }
101121
122+uint_t aubio_notes_set_silence(aubio_notes_t *o, smpl_t silence)
123+{
124+ uint_t err = AUBIO_OK;
125+ if (aubio_pitch_set_silence(o->pitch, silence) != AUBIO_OK) {
126+ err = AUBIO_FAIL;
127+ }
128+ if (aubio_onset_set_silence(o->onset, silence) != AUBIO_OK) {
129+ err = AUBIO_FAIL;
130+ }
131+ o->silence_threshold = silence;
132+ return err;
133+}
134+
135+smpl_t aubio_notes_get_silence(const aubio_notes_t *o)
136+{
137+ return aubio_pitch_get_silence(o->pitch);
138+}
139+
140+uint_t aubio_notes_set_minioi_ms (aubio_notes_t *o, smpl_t minioi_ms)
141+{
142+ uint_t err = AUBIO_OK;
143+ if (!o->onset || (aubio_onset_set_minioi_ms(o->onset, minioi_ms) != 0)) {
144+ err = AUBIO_FAIL;
145+ }
146+ return err;
147+}
148+
149+smpl_t aubio_notes_get_minioi_ms(const aubio_notes_t *o)
150+{
151+ return aubio_onset_get_minioi_ms(o->onset);
152+}
153+
154+uint_t aubio_notes_set_release_drop(aubio_notes_t *o, smpl_t release_drop_level)
155+{
156+ uint_t err = AUBIO_OK;
157+ if (release_drop_level <= 0.) {
158+ AUBIO_ERR("notes: release_drop should be >= 0, got %f\n", release_drop_level);
159+ err = AUBIO_FAIL;
160+ } else {
161+ o->release_drop_level = release_drop_level;
162+ }
163+ return err;
164+}
165+
166+smpl_t aubio_notes_get_release_drop(const aubio_notes_t *o)
167+{
168+ return o->release_drop_level;
169+}
170+
102171 /** append new note candidate to the note_buffer and return filtered value. we
103172 * need to copy the input array as fvec_median destroy its input data.*/
104173 static void
@@ -108,18 +177,16 @@ note_append (fvec_t * note_buffer, smpl_t curnote) · 3 unmodified lines
108177 for (i = 0; i < note_buffer->length - 1; i++) {
109178 note_buffer->data[i] = note_buffer->data[i + 1];
110179 }
111− note_buffer->data[note_buffer->length - 1] = curnote;
180+ //note_buffer->data[note_buffer->length - 1] = ROUND(10.*curnote)/10.;
181+ note_buffer->data[note_buffer->length - 1] = ROUND(AUBIO_DEFAULT_CENT_PRECISION*curnote);
112182 return;
113183 }
114184
115−static uint_t
185+static smpl_t
116186 aubio_notes_get_latest_note (aubio_notes_t *o)
117187 {
118− uint_t i;
119− for (i = 0; i < o->note_buffer->length; i++) {
120− o->note_buffer2->data[i] = o->note_buffer->data[i];
121− }
122− return fvec_median (o->note_buffer2);
188+ fvec_copy(o->note_buffer, o->note_buffer2);
189+ return fvec_median (o->note_buffer2) / AUBIO_DEFAULT_CENT_PRECISION;
123190 }
124191
125192
@@ -145,6 +212,7 @@ void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * notes) · 19 unmodified lines
145212 //send_noteon(o->curnote,0);
146213 //notes->data[0] = o->curnote;
147214 //notes->data[1] = 0.;
215+ //AUBIO_WRN("notes: sending note-off at onset, not enough level\n");
148216 notes->data[2] = o->curnote;
149217 } else {
150218 if (o->median) {
@@ -152,6 +220,7 @@ void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * notes) · 1 unmodified line
152220 } else {
153221 /* kill old note */
154222 //send_noteon(o->curnote,0, o->samplerate);
223+ //AUBIO_WRN("notes: sending note-off at onset, new onset detected\n");
155224 notes->data[2] = o->curnote;
156225 /* get and send new one */
157226 //send_noteon(new_pitch,127+(int)floor(curlevel), o->samplerate);
@@ -159,16 +228,33 @@ void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * notes) · 1 unmodified line
159228 notes->data[1] = 127 + (int)floor(curlevel);
160229 o->curnote = new_pitch;
161230 }
231+ o->last_onset_level = curlevel;
162232 }
163233 } else {
164− if (o->median) {
234+ if (curlevel < o->last_onset_level - o->release_drop_level)
235+ {
236+ // send note off
237+ //AUBIO_WRN("notes: sending note-off, release detected\n");
238+ notes->data[0] = 0;
239+ notes->data[1] = 0;
240+ notes->data[2] = o->curnote;
241+ // reset last_onset_level to silence_threshold
242+ o->last_onset_level = o->silence_threshold;
243+ o->curnote = 0;
244+ }
245+ else if (o->median)
246+ {
165247 if (o->isready > 0)
166248 o->isready++;
167249 if (o->isready == o->median)
168250 {
169251 /* kill old note */
170252 //send_noteon(curnote,0);
171− notes->data[2] = o->curnote;
253+ if (o->curnote != 0)
254+ {
255+ //AUBIO_WRN("notes: sending note-off, new note detected\n");
256+ notes->data[2] = o->curnote;
257+ }
172258 o->newnote = aubio_notes_get_latest_note(o);
173259 o->curnote = o->newnote;
174260 /* get and send new one */
src/notes/notes.h+81−2
@@ -18,6 +18,12 @@ · 17 unmodified lines
1818
1919 */
2020
21+/** \file
22+
23+ Note detection object
24+
25+*/
26+
2127 #ifndef _AUBIO_NOTES_H
2228 #define _AUBIO_NOTES_H
2329
@@ -51,12 +57,85 @@ void del_aubio_notes(aubio_notes_t * o); · 27 unmodified lines
5157 /** execute note detection on an input signal frame
5258
5359 \param o note detection object as returned by new_aubio_notes()
54− \param in input signal of size [hop_size]
55− \param out output notes of size [3] ? FIXME
60+ \param input input signal of size [hop_size]
61+ \param output output notes, fvec of length 3
62+
63+ The notes output is a vector of length 3 containing:
64+ - 0. the midi note value, or 0 if no note was found
65+ - 1. the note velocity
66+ - 2. the midi note to turn off
5667
5768 */
5869 void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * output);
5970
71+/** set notes detection silence threshold
72+
73+ \param o notes detection object as returned by new_aubio_notes()
74+ \param silence new silence detection threshold
75+
76+ \return 0 on success, non-zero otherwise
77+
78+*/
79+uint_t aubio_notes_set_silence(aubio_notes_t * o, smpl_t silence);
80+
81+/** get notes detection silence threshold
82+
83+ \param o notes detection object as returned by new_aubio_notes()
84+
85+ \return current silence threshold
86+
87+*/
88+smpl_t aubio_notes_get_silence(const aubio_notes_t * o);
89+
90+/** get notes detection minimum inter-onset interval, in millisecond
91+
92+ \param o notes detection object as returned by new_aubio_notes()
93+
94+ \return current minimum inter onset interval
95+
96+ */
97+smpl_t aubio_notes_get_minioi_ms(const aubio_notes_t *o);
98+
99+/** set notes detection minimum inter-onset interval, in millisecond
100+
101+ \param o notes detection object as returned by new_aubio_notes()
102+ \param minioi_ms new inter-onset interval
103+
104+ \return 0 on success, non-zero otherwise
105+
106+*/
107+uint_t aubio_notes_set_minioi_ms (aubio_notes_t *o, smpl_t minioi_ms);
108+
109+/** get notes object release drop level, in dB
110+
111+ \param o notes detection object as returned by new_aubio_notes()
112+
113+ \return current release drop level, in dB
114+
115+ */
116+smpl_t aubio_notes_get_release_drop (const aubio_notes_t *o);
117+
118+/** set note release drop level, in dB
119+
120+ This function sets the release_drop_level parameter, in dB. When a new note
121+ is found, the current level in dB is measured. If the measured level drops
122+ under that initial level - release_drop_level, then a note-off will be
123+ emitted.
124+
125+ Defaults to `10`, in dB.
126+
127+ \note This parameter was added in version `0.4.8`. Results obtained with
128+ earlier versions can be reproduced by setting this value to `100`, so that
129+ note-off will not be played until the next note.
130+
131+ \param o notes detection object as returned by new_aubio_notes()
132+ \param release_drop new release drop level, in dB
133+
134+ \return 0 on success, non-zero otherwise
135+
136+*/
137+uint_t aubio_notes_set_release_drop (aubio_notes_t *o, smpl_t release_drop);
138+
60139 #ifdef __cplusplus
61140 }
62141 #endif
src/onset/onset.c+135−19
@@ -23,10 +23,13 @@ · 22 unmodified lines
2323 #include "cvec.h"
2424 #include "spectral/specdesc.h"
2525 #include "spectral/phasevoc.h"
26+#include "spectral/awhitening.h"
2627 #include "onset/peakpicker.h"
2728 #include "mathutils.h"
2829 #include "onset/onset.h"
2930
31+void aubio_onset_default_parameters (aubio_onset_t *o, const char_t * method);
32+
3033 /** structure to store object state */
3134 struct _aubio_onset_t {
3235 aubio_pvoc_t * pv; /**< phase vocoder */
@@ -42,6 +45,11 @@ struct _aubio_onset_t { · 9 unmodified lines
4245
4346 uint_t total_frames; /**< total number of frames processed since the beginning */
4447 uint_t last_onset; /**< last detected onset location, in frames */
48+
49+ uint_t apply_compression;
50+ smpl_t lambda_compression;
51+ uint_t apply_awhitening; /**< apply adaptive spectral whitening */
52+ aubio_spectral_whitening_t *spectral_whitening;
4553 };
4654
4755 /* execute onset detection function on iput buffer */
@@ -49,6 +57,16 @@ void aubio_onset_do (aubio_onset_t *o, const fvec_t * input, fvec_t * onset) · 1 unmodified line
4957 {
5058 smpl_t isonset = 0;
5159 aubio_pvoc_do (o->pv,input, o->fftgrain);
60+ /*
61+ if (apply_filtering) {
62+ }
63+ */
64+ if (o->apply_awhitening) {
65+ aubio_spectral_whitening_do(o->spectral_whitening, o->fftgrain);
66+ }
67+ if (o->apply_compression) {
68+ cvec_logmag(o->fftgrain, o->lambda_compression);
69+ }
5270 aubio_specdesc_do (o->od, o->fftgrain, o->desc);
5371 aubio_peakpicker_do(o->pp, o->desc, onset);
5472 isonset = onset->data[0];
@@ -57,10 +75,17 @@ void aubio_onset_do (aubio_onset_t *o, const fvec_t * input, fvec_t * onset) · 2 unmodified lines
5775 //AUBIO_DBG ("silent onset, not marking as onset\n");
5876 isonset = 0;
5977 } else {
78+ // we have an onset
6079 uint_t new_onset = o->total_frames + (uint_t)ROUND(isonset * o->hop_size);
80+ // check if last onset time was more than minioi ago
6181 if (o->last_onset + o->minioi < new_onset) {
62− //AUBIO_DBG ("accepted detection, marking as onset\n");
63− o->last_onset = new_onset;
82+ // start of file: make sure (new_onset - delay) >= 0
83+ if (o->last_onset > 0 && o->delay > new_onset) {
84+ isonset = 0;
85+ } else {
86+ //AUBIO_DBG ("accepted detection, marking as onset\n");
87+ o->last_onset = MAX(o->delay, new_onset);
88+ }
6489 } else {
6590 //AUBIO_DBG ("doubled onset, not marking as onset\n");
6691 isonset = 0;
@@ -99,6 +124,32 @@ smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o) · 32 unmodified lines
99124 return aubio_onset_get_last_s (o) * 1000.;
100125 }
101126
127+uint_t aubio_onset_set_awhitening (aubio_onset_t *o, uint_t enable)
128+{
129+ o->apply_awhitening = enable == 1 ? 1 : 0;
130+ return AUBIO_OK;
131+}
132+
133+smpl_t aubio_onset_get_awhitening (aubio_onset_t *o)
134+{
135+ return o->apply_awhitening;
136+}
137+
138+uint_t aubio_onset_set_compression (aubio_onset_t *o, smpl_t lambda)
139+{
140+ if (lambda < 0.) {
141+ return AUBIO_FAIL;
142+ }
143+ o->lambda_compression = lambda;
144+ o->apply_compression = (o->lambda_compression > 0.) ? 1 : 0;
145+ return AUBIO_OK;
146+}
147+
148+smpl_t aubio_onset_get_compression (aubio_onset_t *o)
149+{
150+ return o->apply_compression ? o->lambda_compression : 0;
151+}
152+
102153 uint_t aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence) {
103154 o->silence = silence;
104155 return AUBIO_OK;
@@ -205,35 +256,100 @@ aubio_onset_t * new_aubio_onset (const char_t * onset_mode, · 100 unmodified lines
205256 o->pv = new_aubio_pvoc(buf_size, o->hop_size);
206257 o->pp = new_aubio_peakpicker();
207258 o->od = new_aubio_specdesc(onset_mode,buf_size);
208− if (o->od == NULL) goto beach_specdesc;
209259 o->fftgrain = new_cvec(buf_size);
210260 o->desc = new_fvec(1);
261+ o->spectral_whitening = new_aubio_spectral_whitening(buf_size, hop_size, samplerate);
211262
212− /* set some default parameter */
213− aubio_onset_set_threshold (o, 0.3);
214− aubio_onset_set_delay(o, 4.3 * hop_size);
215− aubio_onset_set_minioi_ms(o, 20.);
216− aubio_onset_set_silence(o, -70.);
263+ if (!o->pv || !o->pp || !o->od || !o->fftgrain
264+ || !o->desc || !o->spectral_whitening)
265+ goto beach;
217266
218267 /* initialize internal variables */
219− o->last_onset = 0;
220− o->total_frames = 0;
268+ aubio_onset_set_default_parameters (o, onset_mode);
269+
270+ aubio_onset_reset(o);
221271 return o;
222272
223−beach_specdesc:
224− del_aubio_peakpicker(o->pp);
225− del_aubio_pvoc(o->pv);
226273 beach:
227− AUBIO_FREE(o);
274+ del_aubio_onset(o);
228275 return NULL;
229276 }
230277
278+void aubio_onset_reset (aubio_onset_t *o) {
279+ o->last_onset = 0;
280+ o->total_frames = 0;
281+}
282+
283+uint_t aubio_onset_set_default_parameters (aubio_onset_t * o, const char_t * onset_mode)
284+{
285+ uint_t ret = AUBIO_OK;
286+ /* set some default parameter */
287+ aubio_onset_set_threshold (o, 0.3);
288+ aubio_onset_set_delay (o, 4.3 * o->hop_size);
289+ aubio_onset_set_minioi_ms (o, 50.);
290+ aubio_onset_set_silence (o, -70.);
291+ // disable spectral whitening
292+ aubio_onset_set_awhitening (o, 0);
293+ // disable logarithmic magnitude
294+ aubio_onset_set_compression (o, 0.);
295+
296+ /* method specific optimisations */
297+ if (strcmp (onset_mode, "energy") == 0) {
298+ } else if (strcmp (onset_mode, "hfc") == 0 || strcmp (onset_mode, "default") == 0) {
299+ aubio_onset_set_threshold (o, 0.058);
300+ aubio_onset_set_compression (o, 1.);
301+ } else if (strcmp (onset_mode, "complexdomain") == 0
302+ || strcmp (onset_mode, "complex") == 0) {
303+ aubio_onset_set_delay (o, 4.6 * o->hop_size);
304+ aubio_onset_set_threshold (o, 0.15);
305+ aubio_onset_set_awhitening(o, 1);
306+ aubio_onset_set_compression (o, 1.);
307+ } else if (strcmp (onset_mode, "phase") == 0) {
308+ o->apply_compression = 0;
309+ aubio_onset_set_awhitening (o, 0);
310+ } else if (strcmp (onset_mode, "wphase") == 0) {
311+ // use defaults for now
312+ } else if (strcmp (onset_mode, "mkl") == 0) {
313+ aubio_onset_set_threshold (o, 0.05);
314+ aubio_onset_set_awhitening(o, 1);
315+ aubio_onset_set_compression (o, 0.02);
316+ } else if (strcmp (onset_mode, "kl") == 0) {
317+ aubio_onset_set_threshold (o, 0.35);
318+ aubio_onset_set_awhitening(o, 1);
319+ aubio_onset_set_compression (o, 0.02);
320+ } else if (strcmp (onset_mode, "specflux") == 0) {
321+ aubio_onset_set_threshold (o, 0.18);
322+ aubio_onset_set_awhitening(o, 1);
323+ aubio_spectral_whitening_set_relax_time(o->spectral_whitening, 100);
324+ aubio_spectral_whitening_set_floor(o->spectral_whitening, 1.);
325+ aubio_onset_set_compression (o, 10.);
326+ } else if (strcmp (onset_mode, "specdiff") == 0) {
327+ } else if (strcmp (onset_mode, "old_default") == 0) {
328+ // used to reproduce results obtained with the previous version
329+ aubio_onset_set_threshold (o, 0.3);
330+ aubio_onset_set_minioi_ms (o, 20.);
331+ aubio_onset_set_compression (o, 0.);
332+ } else {
333+ AUBIO_WRN("onset: unknown spectral descriptor type %s, "
334+ "using default parameters.\n", onset_mode);
335+ ret = AUBIO_FAIL;
336+ }
337+ return ret;
338+}
339+
231340 void del_aubio_onset (aubio_onset_t *o)
232341 {
233− del_aubio_specdesc(o->od);
234− del_aubio_peakpicker(o->pp);
235− del_aubio_pvoc(o->pv);
236− del_fvec(o->desc);
237− del_cvec(o->fftgrain);
342+ if (o->spectral_whitening)
343+ del_aubio_spectral_whitening(o->spectral_whitening);
344+ if (o->od)
345+ del_aubio_specdesc(o->od);
346+ if (o->pp)
347+ del_aubio_peakpicker(o->pp);
348+ if (o->pv)
349+ del_aubio_pvoc(o->pv);
350+ if (o->desc)
351+ del_fvec(o->desc);
352+ if (o->fftgrain)
353+ del_cvec(o->fftgrain);
238354 AUBIO_FREE(o);
239355 }
src/onset/onset.h+59−0
@@ -117,6 +117,44 @@ smpl_t aubio_onset_get_last_s (const aubio_onset_t *o); · 116 unmodified lines
117117 */
118118 smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o);
119119
120+/** set onset detection adaptive whitening
121+
122+ \param o onset detection object as returned by new_aubio_onset()
123+ \param enable 1 to enable, 0 to disable
124+
125+ \return 0 if successful, 1 otherwise
126+
127+*/
128+uint_t aubio_onset_set_awhitening(aubio_onset_t * o, uint_t enable);
129+
130+/** get onset detection adaptive whitening
131+
132+ \param o onset detection object as returned by new_aubio_onset()
133+
134+ \return 1 if enabled, 0 otherwise
135+
136+*/
137+smpl_t aubio_onset_get_awhitening(aubio_onset_t * o);
138+
139+/** set or disable log compression
140+
141+ \param o onset detection object as returned by new_aubio_onset()
142+ \param lambda logarithmic compression factor, 0 to disable
143+
144+ \return 0 if successful, 1 otherwise
145+
146+ */
147+uint_t aubio_onset_set_compression(aubio_onset_t *o, smpl_t lambda);
148+
149+/** get onset detection log compression
150+
151+ \param o onset detection object as returned by new_aubio_onset()
152+
153+ \returns 0 if disabled, compression factor otherwise
154+
155+ */
156+smpl_t aubio_onset_get_compression(aubio_onset_t *o);
157+
120158 /** set onset detection silence threshold
121159
122160 \param o onset detection object as returned by new_aubio_onset()
@@ -274,6 +312,27 @@ smpl_t aubio_onset_get_delay_ms(const aubio_onset_t * o); · 151 unmodified lines
274312 */
275313 smpl_t aubio_onset_get_threshold(const aubio_onset_t * o);
276314
315+/** set default parameters
316+
317+ \param o onset detection object as returned by new_aubio_onset()
318+ \param onset_mode detection mode to adjust
319+
320+ This function is called at the end of new_aubio_onset().
321+
322+ */
323+uint_t aubio_onset_set_default_parameters (aubio_onset_t * o, const char_t * onset_mode);
324+
325+/** reset onset detection
326+
327+ \param o onset detection object as returned by new_aubio_onset()
328+
329+ Reset current time and last onset to 0.
330+
331+ This function is called at the end of new_aubio_onset().
332+
333+ */
334+void aubio_onset_reset(aubio_onset_t * o);
335+
277336 /** delete onset detection object
278337
279338 \param o onset detection object to delete
src/onset/peakpicker.c+11−15
@@ -92,27 +92,21 @@ aubio_peakpicker_do (aubio_peakpicker_t * p, fvec_t * onset, fvec_t * out) · 91 unmodified lines
9292 fvec_t *thresholded = p->thresholded;
9393 fvec_t *scratch = p->scratch;
9494 smpl_t mean = 0., median = 0.;
95− uint_t length = p->win_post + p->win_pre + 1;
9695 uint_t j = 0;
9796
98− /* store onset in onset_keep */
99− /* shift all elements but last, then write last */
100− for (j = 0; j < length - 1; j++) {
101− onset_keep->data[j] = onset_keep->data[j + 1];
102− onset_proc->data[j] = onset_keep->data[j];
103− }
104− onset_keep->data[length - 1] = onset->data[0];
105− onset_proc->data[length - 1] = onset->data[0];
97+ /* push new novelty to the end */
98+ fvec_push(onset_keep, onset->data[0]);
99+ /* store a copy */
100+ fvec_copy(onset_keep, onset_proc);
106101
107− /* filter onset_proc */
108− /** \bug filtfilt calculated post+pre times, should be only once !? */
102+ /* filter this copy */
109103 aubio_filter_do_filtfilt (p->biquad, onset_proc, scratch);
110104
111105 /* calculate mean and median for onset_proc */
112106 mean = fvec_mean (onset_proc);
113− /* copy to scratch */
114− for (j = 0; j < length; j++)
115− scratch->data[j] = onset_proc->data[j];
107+
108+ /* copy to scratch and compute its median */
109+ fvec_copy(onset_proc, scratch);
116110 median = p->thresholdfn (scratch);
117111
118112 /* shift peek array */
@@ -185,7 +179,9 @@ new_aubio_peakpicker (void) · 66 unmodified lines
185179 generated with octave butter function: [b,a] = butter(2, 0.34);
186180 */
187181 t->biquad = new_aubio_filter_biquad (0.15998789, 0.31997577, 0.15998789,
188− -0.59488894, 0.23484048);
182+ // FIXME: broken since c9e20ca, revert for now
183+ //-0.59488894, 0.23484048);
184+ 0.23484048, 0);
189185
190186 return t;
191187 }
src/pitch/pitch.c+50−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
3232 #include "pitch/pitchfcomb.h"
3333 #include "pitch/pitchschmitt.h"
3434 #include "pitch/pitchyinfft.h"
35+#include "pitch/pitchyinfast.h"
3536 #include "pitch/pitchspecacf.h"
3637 #include "pitch/pitch.h"
3738
@@ -45,6 +46,7 @@ typedef enum · 7 unmodified lines
4546 aubio_pitcht_schmitt, /**< `schmitt`, Schmitt trigger */
4647 aubio_pitcht_fcomb, /**< `fcomb`, Fast comb filter */
4748 aubio_pitcht_yinfft, /**< `yinfft`, Spectral YIN */
49+ aubio_pitcht_yinfast, /**< `yinfast`, YIN fast */
4850 aubio_pitcht_specacf, /**< `specacf`, Spectral autocorrelation */
4951 aubio_pitcht_default
5052 = aubio_pitcht_yinfft, /**< `default` */
@@ -94,6 +96,7 @@ static void aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * · 43 unmodified lines
9496 static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
9597 static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
9698 static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
99+static void aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
97100 static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
98101
99102 /* internal functions for frequency conversion */
@@ -111,8 +114,14 @@ new_aubio_pitch (const char_t * pitch_mode, · 11 unmodified lines
111114 {
112115 aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t);
113116 aubio_pitch_type pitch_type;
117+ if (pitch_mode == NULL) {
118+ AUBIO_ERR ("pitch: can not use ‘NULL‘ for pitch detection method\n");
119+ goto beach;
120+ }
114121 if (strcmp (pitch_mode, "mcomb") == 0)
115122 pitch_type = aubio_pitcht_mcomb;
123+ else if (strcmp (pitch_mode, "yinfast") == 0)
124+ pitch_type = aubio_pitcht_yinfast;
116125 else if (strcmp (pitch_mode, "yinfft") == 0)
117126 pitch_type = aubio_pitcht_yinfft;
118127 else if (strcmp (pitch_mode, "yin") == 0)
@@ -138,7 +147,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 19 unmodified lines
138147 AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize);
139148 goto beach;
140149 } else if (bufsize < hopsize) {
141− AUBIO_ERR("pitch: hop size (%d) is larger than win size (%d)\n", bufsize, hopsize);
150+ AUBIO_ERR("pitch: hop size (%d) is larger than win size (%d)\n", hopsize, bufsize);
142151 goto beach;
143152 } else if ((sint_t)samplerate < 1) {
144153 AUBIO_ERR("pitch: samplerate (%d) can not be < 1\n", samplerate);
@@ -155,6 +164,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 10 unmodified lines
155164 case aubio_pitcht_yin:
156165 p->buf = new_fvec (bufsize);
157166 p->p_object = new_aubio_pitchyin (bufsize);
167+ if (!p->p_object) goto beach;
158168 p->detect_cb = aubio_pitch_do_yin;
159169 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence;
160170 aubio_pitchyin_set_tolerance (p->p_object, 0.15);
@@ -162,6 +172,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 1 unmodified line
162172 case aubio_pitcht_mcomb:
163173 p->filtered = new_fvec (hopsize);
164174 p->pv = new_aubio_pvoc (bufsize, hopsize);
175+ if (!p->pv) goto beach;
165176 p->fftgrain = new_cvec (bufsize);
166177 p->p_object = new_aubio_pitchmcomb (bufsize, hopsize);
167178 p->filter = new_aubio_filter_c_weighting (samplerate);
@@ -170,6 +181,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 2 unmodified lines
170181 case aubio_pitcht_fcomb:
171182 p->buf = new_fvec (bufsize);
172183 p->p_object = new_aubio_pitchfcomb (bufsize, hopsize);
184+ if (!p->p_object) goto beach;
173185 p->detect_cb = aubio_pitch_do_fcomb;
174186 break;
175187 case aubio_pitcht_schmitt:
@@ -180,13 +192,23 @@ new_aubio_pitch (const char_t * pitch_mode, · 4 unmodified lines
180192 case aubio_pitcht_yinfft:
181193 p->buf = new_fvec (bufsize);
182194 p->p_object = new_aubio_pitchyinfft (samplerate, bufsize);
195+ if (!p->p_object) goto beach;
183196 p->detect_cb = aubio_pitch_do_yinfft;
184197 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence;
185198 aubio_pitchyinfft_set_tolerance (p->p_object, 0.85);
186199 break;
200+ case aubio_pitcht_yinfast:
201+ p->buf = new_fvec (bufsize);
202+ p->p_object = new_aubio_pitchyinfast (bufsize);
203+ if (!p->p_object) goto beach;
204+ p->detect_cb = aubio_pitch_do_yinfast;
205+ p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfast_get_confidence;
206+ aubio_pitchyinfast_set_tolerance (p->p_object, 0.15);
207+ break;
187208 case aubio_pitcht_specacf:
188209 p->buf = new_fvec (bufsize);
189210 p->p_object = new_aubio_pitchspecacf (bufsize);
211+ if (!p->p_object) goto beach;
190212 p->detect_cb = aubio_pitch_do_specacf;
191213 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance;
192214 aubio_pitchspecacf_set_tolerance (p->p_object, 0.85);
@@ -197,6 +219,8 @@ new_aubio_pitch (const char_t * pitch_mode, · 4 unmodified lines
197219 return p;
198220
199221 beach:
222+ if (p->filtered) del_fvec(p->filtered);
223+ if (p->buf) del_fvec(p->buf);
200224 AUBIO_FREE(p);
201225 return NULL;
202226 }
@@ -228,6 +252,10 @@ del_aubio_pitch (aubio_pitch_t * p) · 25 unmodified lines
228252 del_fvec (p->buf);
229253 del_aubio_pitchyinfft (p->p_object);
230254 break;
255+ case aubio_pitcht_yinfast:
256+ del_fvec (p->buf);
257+ del_aubio_pitchyinfast (p->p_object);
258+ break;
231259 case aubio_pitcht_specacf:
232260 del_fvec (p->buf);
233261 del_aubio_pitchspecacf (p->p_object);
@@ -318,6 +346,9 @@ aubio_pitch_set_tolerance (aubio_pitch_t * p, smpl_t tol) · 84 unmodified lines
318346 case aubio_pitcht_yinfft:
319347 aubio_pitchyinfft_set_tolerance (p->p_object, tol);
320348 break;
349+ case aubio_pitcht_yinfast:
350+ aubio_pitchyinfast_set_tolerance (p->p_object, tol);
351+ break;
321352 default:
322353 break;
323354 }
@@ -335,6 +366,9 @@ aubio_pitch_get_tolerance (aubio_pitch_t * p) · 11 unmodified lines
335366 case aubio_pitcht_yinfft:
336367 tolerance = aubio_pitchyinfft_get_tolerance (p->p_object);
337368 break;
369+ case aubio_pitcht_yinfast:
370+ tolerance = aubio_pitchyinfast_get_tolerance (p->p_object);
371+ break;
338372 default:
339373 break;
340374 }
@@ -412,6 +446,21 @@ aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) · 71 unmodified lines
412446 obuf->data[0] = pitch;
413447 }
414448
449+void
450+aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
451+{
452+ smpl_t pitch = 0.;
453+ aubio_pitch_slideblock (p, ibuf);
454+ aubio_pitchyinfast_do (p->p_object, p->buf, obuf);
455+ pitch = obuf->data[0];
456+ if (pitch > 0) {
457+ pitch = p->samplerate / (pitch + 0.);
458+ } else {
459+ pitch = 0.;
460+ }
461+ obuf->data[0] = pitch;
462+}
463+
415464 void
416465 aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
417466 {
src/pitch/pitch.h+7−0
@@ -81,6 +81,11 @@ extern "C" { · 80 unmodified lines
8181
8282 see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
8383
84+ \b \p yinfast : Yinfast algorithm
85+
86+ This algorithm is equivalent to the YIN algorithm, but computed in the
87+ spectral domain for efficiency. See also `python/demos/demo_yin_compare.py`.
88+
8489 \b \p yinfft : Yinfft algorithm
8590
8691 This algorithm was derived from the YIN algorithm. In this implementation, a
@@ -150,6 +155,8 @@ aubio_pitch_t *new_aubio_pitch (const char_t * method, · 63 unmodified lines
150155 \param o pitch detection object as returned by new_aubio_pitch()
151156 \param mode set pitch units for output
152157
158+ mode can be one of "Hz", "midi", "cent", or "bin". Defaults to "Hz".
159+
153160 \return 0 if successfull, non-zero otherwise
154161
155162 */
src/pitch/pitchfcomb.c+6−1
@@ -53,12 +53,17 @@ new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize) · 52 unmodified lines
5353 aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t);
5454 p->fftSize = bufsize;
5555 p->stepSize = hopsize;
56+ p->fft = new_aubio_fft (bufsize);
57+ if (!p->fft) goto beach;
5658 p->winput = new_fvec (bufsize);
5759 p->fftOut = new_cvec (bufsize);
5860 p->fftLastPhase = new_fvec (bufsize);
59− p->fft = new_aubio_fft (bufsize);
6061 p->win = new_aubio_window ("hanning", bufsize);
6162 return p;
63+
64+beach:
65+ AUBIO_FREE(p);
66+ return NULL;
6267 }
6368
6469 /* input must be stepsize long */
src/pitch/pitchmcomb.c+8−1
@@ -37,6 +37,7 @@ void aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag); · 36 unmodified lines
3737 /* not used but useful : sort by amplitudes (or anything else)
3838 * sort_pitchpeak(peaks, length);
3939 */
40+#if 0
4041 /** spectral_peak comparison function (must return signed int) */
4142 static sint_t aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y);
4243 /** sort spectral_peak against their mag */
@@ -44,13 +45,16 @@ void aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins); · 1 unmodified line
4445 /** select the best candidates */
4546 uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain,
4647 smpl_t * cands);
48+#endif
4749
4850 /** sort spectral_candidate against their comb ene */
4951 void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates,
5052 uint_t nbins);
53+#if 0
5154 /** sort spectral_candidate against their frequency */
5255 void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
5356 uint_t nbins);
57+#endif
5458
5559 struct _aubio_pitchmcomb_t
5660 {
@@ -133,6 +137,7 @@ aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, fvec_t * o · 76 unmodified lines
133137 } */
134138 }
135139
140+#if 0
136141 uint_t
137142 aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands)
138143 {
@@ -163,6 +168,7 @@ aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * can · 24 unmodified lines
163168 return 0;
164169 }
165170 }
171+#endif
166172
167173 void
168174 aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag)
@@ -313,6 +319,7 @@ aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks, uint_t length) · 144 unmodified lines
313319 return pos;
314320 }
315321
322+#if 0
316323 void
317324 aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins)
318325 {
@@ -342,7 +349,6 @@ aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates, · 23 unmodified lines
342349 }
343350 }
344351
345−
346352 void
347353 aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
348354 uint_t nbins)
@@ -356,6 +362,7 @@ aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates, · 7 unmodified lines
356362 }
357363 }
358364 }
365+#endif
359366
360367 aubio_pitchmcomb_t *
361368 new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize)
src/pitch/pitchspecacf.c+6−1
@@ -42,15 +42,20 @@ aubio_pitchspecacf_t * · 41 unmodified lines
4242 new_aubio_pitchspecacf (uint_t bufsize)
4343 {
4444 aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t);
45+ p->fft = new_aubio_fft (bufsize);
46+ if (!p->fft) goto beach;
4547 p->win = new_aubio_window ("hanningz", bufsize);
4648 p->winput = new_fvec (bufsize);
47− p->fft = new_aubio_fft (bufsize);
4849 p->fftout = new_fvec (bufsize);
4950 p->sqrmag = new_fvec (bufsize);
5051 p->acf = new_fvec (bufsize / 2 + 1);
5152 p->tol = 1.;
5253 p->confidence = 0.;
5354 return p;
55+
56+beach:
57+ AUBIO_FREE(p);
58+ return NULL;
5459 }
5560
5661 void
src/pitch/pitchyin.c+29−22
@@ -36,9 +36,10 @@ struct _aubio_pitchyin_t · 35 unmodified lines
3636 {
3737 fvec_t *yin;
3838 smpl_t tol;
39− smpl_t confidence;
39+ uint_t peak_pos;
4040 };
4141
42+#if 0
4243 /** compute difference function
4344
4445 \param input input signal
@@ -60,6 +61,7 @@ void aubio_pitchyin_getcum (fvec_t * yinbuf); · 15 unmodified lines
6061
6162 */
6263 uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf);
64+#endif
6365
6466 aubio_pitchyin_t *
6567 new_aubio_pitchyin (uint_t bufsize)
@@ -67,6 +69,7 @@ new_aubio_pitchyin (uint_t bufsize) · 1 unmodified line
6769 aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t);
6870 o->yin = new_fvec (bufsize / 2);
6971 o->tol = 0.15;
72+ o->peak_pos = 0;
7073 return o;
7174 }
7275
@@ -77,6 +80,7 @@ del_aubio_pitchyin (aubio_pitchyin_t * o) · 4 unmodified lines
7780 AUBIO_FREE (o);
7881 }
7982
83+#if 0
8084 /* outputs the difference function */
8185 void
8286 aubio_pitchyin_diff (fvec_t * input, fvec_t * yin)
@@ -126,46 +130,49 @@ aubio_pitchyin_getpitch (const fvec_t * yin) · 43 unmodified lines
126130 //AUBIO_DBG("No pitch found");
127131 return 0;
128132 }
129−
133+#endif
130134
131135 /* all the above in one */
132136 void
133137 aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out)
134138 {
135− smpl_t tol = o->tol;
136− fvec_t *yin = o->yin;
137− uint_t j, tau = 0;
139+ const smpl_t tol = o->tol;
140+ fvec_t* yin = o->yin;
141+ const smpl_t *input_data = input->data;
142+ const uint_t length = yin->length;
143+ smpl_t *yin_data = yin->data;
144+ uint_t j, tau;
138145 sint_t period;
139− smpl_t tmp = 0., tmp2 = 0.;
140− yin->data[0] = 1.;
141− for (tau = 1; tau < yin->length; tau++) {
142− yin->data[tau] = 0.;
143− for (j = 0; j < yin->length; j++) {
144− tmp = input->data[j] - input->data[j + tau];
145− yin->data[tau] += SQR (tmp);
146+ smpl_t tmp, tmp2 = 0.;
147+
148+ yin_data[0] = 1.;
149+ for (tau = 1; tau < length; tau++) {
150+ yin_data[tau] = 0.;
151+ for (j = 0; j < length; j++) {
152+ tmp = input_data[j] - input_data[j + tau];
153+ yin_data[tau] += SQR (tmp);
146154 }
147− tmp2 += yin->data[tau];
155+ tmp2 += yin_data[tau];
148156 if (tmp2 != 0) {
149157 yin->data[tau] *= tau / tmp2;
150158 } else {
151159 yin->data[tau] = 1.;
152160 }
153161 period = tau - 3;
154− if (tau > 4 && (yin->data[period] < tol) &&
155− (yin->data[period] < yin->data[period + 1])) {
156− out->data[0] = fvec_quadratic_peak_pos (yin, period);
157− goto beach;
162+ if (tau > 4 && (yin_data[period] < tol) &&
163+ (yin_data[period] < yin_data[period + 1])) {
164+ o->peak_pos = (uint_t)period;
165+ out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
166+ return;
158167 }
159168 }
160− out->data[0] = fvec_quadratic_peak_pos (yin, fvec_min_elem (yin));
161−beach:
162− return;
169+ o->peak_pos = (uint_t)fvec_min_elem (yin);
170+ out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
163171 }
164172
165173 smpl_t
166174 aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) {
167− o->confidence = 1. - fvec_min (o->yin);
168− return o->confidence;
175+ return 1. - o->yin->data[o->peak_pos];
169176 }
170177
171178 uint_t
src/pitch/pitchyinfast.c+201−0
@@ -0,0 +1,201 @@
1+/*
2+ Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+/* This algorithm was developed by A. de Cheveigné and H. Kawahara and
22+ * published in:
23+ *
24+ * de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency
25+ * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930.
26+ *
27+ * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
28+ */
29+
30+#include "aubio_priv.h"
31+#include "fvec.h"
32+#include "mathutils.h"
33+#include "cvec.h"
34+#include "spectral/fft.h"
35+#include "pitch/pitchyinfast.h"
36+
37+struct _aubio_pitchyinfast_t
38+{
39+ fvec_t *yin;
40+ smpl_t tol;
41+ uint_t peak_pos;
42+ fvec_t *tmpdata;
43+ fvec_t *sqdiff;
44+ fvec_t *kernel;
45+ fvec_t *samples_fft;
46+ fvec_t *kernel_fft;
47+ aubio_fft_t *fft;
48+};
49+
50+aubio_pitchyinfast_t *
51+new_aubio_pitchyinfast (uint_t bufsize)
52+{
53+ aubio_pitchyinfast_t *o = AUBIO_NEW (aubio_pitchyinfast_t);
54+ o->yin = new_fvec (bufsize / 2);
55+ o->tmpdata = new_fvec (bufsize);
56+ o->sqdiff = new_fvec (bufsize / 2);
57+ o->kernel = new_fvec (bufsize);
58+ o->samples_fft = new_fvec (bufsize);
59+ o->kernel_fft = new_fvec (bufsize);
60+ o->fft = new_aubio_fft (bufsize);
61+ if (!o->yin || !o->tmpdata || !o->tmpdata || !o->sqdiff
62+ || !o->kernel || !o->samples_fft || !o->kernel || !o->fft)
63+ {
64+ del_aubio_pitchyinfast(o);
65+ return NULL;
66+ }
67+ o->tol = 0.15;
68+ o->peak_pos = 0;
69+ return o;
70+}
71+
72+void
73+del_aubio_pitchyinfast (aubio_pitchyinfast_t * o)
74+{
75+ if (o->yin)
76+ del_fvec (o->yin);
77+ if (o->tmpdata)
78+ del_fvec (o->tmpdata);
79+ if (o->sqdiff)
80+ del_fvec (o->sqdiff);
81+ if (o->kernel)
82+ del_fvec (o->kernel);
83+ if (o->samples_fft)
84+ del_fvec (o->samples_fft);
85+ if (o->kernel_fft)
86+ del_fvec (o->kernel_fft);
87+ if (o->fft)
88+ del_aubio_fft (o->fft);
89+ AUBIO_FREE (o);
90+}
91+
92+/* all the above in one */
93+void
94+aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * input, fvec_t * out)
95+{
96+ const smpl_t tol = o->tol;
97+ fvec_t* yin = o->yin;
98+ const uint_t length = yin->length;
99+ uint_t B = o->tmpdata->length;
100+ uint_t W = o->yin->length; // B / 2
101+ fvec_t tmp_slice, kernel_ptr;
102+ uint_t tau;
103+ sint_t period;
104+ smpl_t tmp2 = 0.;
105+
106+ // compute r_t(0) + r_t+tau(0)
107+ {
108+ fvec_t *squares = o->tmpdata;
109+ fvec_weighted_copy(input, input, squares);
110+#if 0
111+ for (tau = 0; tau < W; tau++) {
112+ tmp_slice.data = squares->data + tau;
113+ tmp_slice.length = W;
114+ o->sqdiff->data[tau] = fvec_sum(&tmp_slice);
115+ }
116+#else
117+ tmp_slice.data = squares->data;
118+ tmp_slice.length = W;
119+ o->sqdiff->data[0] = fvec_sum(&tmp_slice);
120+ for (tau = 1; tau < W; tau++) {
121+ o->sqdiff->data[tau] = o->sqdiff->data[tau-1];
122+ o->sqdiff->data[tau] -= squares->data[tau-1];
123+ o->sqdiff->data[tau] += squares->data[W+tau-1];
124+ }
125+#endif
126+ fvec_add(o->sqdiff, o->sqdiff->data[0]);
127+ }
128+ // compute r_t(tau) = -2.*ifft(fft(samples)*fft(samples[W-1::-1]))
129+ {
130+ fvec_t *compmul = o->tmpdata;
131+ fvec_t *rt_of_tau = o->samples_fft;
132+ aubio_fft_do_complex(o->fft, input, o->samples_fft);
133+ // build kernel, take a copy of first half of samples
134+ tmp_slice.data = input->data;
135+ tmp_slice.length = W;
136+ kernel_ptr.data = o->kernel->data + 1;
137+ kernel_ptr.length = W;
138+ fvec_copy(&tmp_slice, &kernel_ptr);
139+ // reverse them
140+ fvec_rev(&kernel_ptr);
141+ // compute fft(kernel)
142+ aubio_fft_do_complex(o->fft, o->kernel, o->kernel_fft);
143+ // compute complex product
144+ compmul->data[0] = o->kernel_fft->data[0] * o->samples_fft->data[0];
145+ for (tau = 1; tau < W; tau++) {
146+ compmul->data[tau] = o->kernel_fft->data[tau] * o->samples_fft->data[tau];
147+ compmul->data[tau] -= o->kernel_fft->data[B-tau] * o->samples_fft->data[B-tau];
148+ }
149+ compmul->data[W] = o->kernel_fft->data[W] * o->samples_fft->data[W];
150+ for (tau = 1; tau < W; tau++) {
151+ compmul->data[B-tau] = o->kernel_fft->data[B-tau] * o->samples_fft->data[tau];
152+ compmul->data[B-tau] += o->kernel_fft->data[tau] * o->samples_fft->data[B-tau];
153+ }
154+ // compute inverse fft
155+ aubio_fft_rdo_complex(o->fft, compmul, rt_of_tau);
156+ // compute square difference r_t(tau) = sqdiff - 2 * r_t_tau[W-1:-1]
157+ for (tau = 0; tau < W; tau++) {
158+ yin->data[tau] = o->sqdiff->data[tau] - 2. * rt_of_tau->data[tau+W];
159+ }
160+ }
161+
162+ // now build yin and look for first minimum
163+ fvec_zeros(out);
164+ yin->data[0] = 1.;
165+ for (tau = 1; tau < length; tau++) {
166+ tmp2 += yin->data[tau];
167+ if (tmp2 != 0) {
168+ yin->data[tau] *= tau / tmp2;
169+ } else {
170+ yin->data[tau] = 1.;
171+ }
172+ period = tau - 3;
173+ if (tau > 4 && (yin->data[period] < tol) &&
174+ (yin->data[period] < yin->data[period + 1])) {
175+ o->peak_pos = (uint_t)period;
176+ out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
177+ return;
178+ }
179+ }
180+ // use global minimum
181+ o->peak_pos = (uint_t)fvec_min_elem (yin);
182+ out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
183+}
184+
185+smpl_t
186+aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o) {
187+ return 1. - o->yin->data[o->peak_pos];
188+}
189+
190+uint_t
191+aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol)
192+{
193+ o->tol = tol;
194+ return 0;
195+}
196+
197+smpl_t
198+aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o)
199+{
200+ return o->tol;
201+}
src/pitch/pitchyinfast.h+102−0
@@ -0,0 +1,102 @@
1+/*
2+ Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+/** \file
22+
23+ Pitch detection using YIN algorithm (fast implementation)
24+
25+ This algorithm was developed by A. de Cheveigne and H. Kawahara and
26+ published in:
27+
28+ De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency
29+ estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930.
30+
31+ This implementation compute the autocorrelation function using time domain
32+ convolution computed in the spectral domain.
33+
34+ see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
35+ http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf
36+
37+*/
38+
39+#ifndef AUBIO_PITCHYINFAST_H
40+#define AUBIO_PITCHYINFAST_H
41+
42+#ifdef __cplusplus
43+extern "C" {
44+#endif
45+
46+/** pitch detection object */
47+typedef struct _aubio_pitchyinfast_t aubio_pitchyinfast_t;
48+
49+/** creation of the pitch detection object
50+
51+ \param buf_size size of the input buffer to analyse
52+
53+*/
54+aubio_pitchyinfast_t *new_aubio_pitchyinfast (uint_t buf_size);
55+
56+/** deletion of the pitch detection object
57+
58+ \param o pitch detection object as returned by new_aubio_pitchyin()
59+
60+*/
61+void del_aubio_pitchyinfast (aubio_pitchyinfast_t * o);
62+
63+/** execute pitch detection an input buffer
64+
65+ \param o pitch detection object as returned by new_aubio_pitchyin()
66+ \param samples_in input signal vector (length as specified at creation time)
67+ \param cands_out pitch period candidates, in samples
68+
69+*/
70+void aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * samples_in, fvec_t * cands_out);
71+
72+
73+/** set tolerance parameter for YIN algorithm
74+
75+ \param o YIN pitch detection object
76+ \param tol tolerance parameter for minima selection [default 0.15]
77+
78+*/
79+uint_t aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol);
80+
81+/** get tolerance parameter for YIN algorithm
82+
83+ \param o YIN pitch detection object
84+ \return tolerance parameter for minima selection [default 0.15]
85+
86+*/
87+smpl_t aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o);
88+
89+/** get current confidence of YIN algorithm
90+
91+ \param o YIN pitch detection object
92+ \return confidence parameter
93+
94+*/
95+smpl_t aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o);
96+
97+#ifdef __cplusplus
98+}
99+#endif
100+
101+#endif /* AUBIO_PITCHYINFAST_H */
102+
src/pitch/pitchyinfft.c+18−7
@@ -36,7 +36,7 @@ struct _aubio_pitchyinfft_t · 35 unmodified lines
3636 aubio_fft_t *fft; /**< fft object to compute square difference function */
3737 fvec_t *yinfft; /**< Yin function */
3838 smpl_t tol; /**< Yin tolerance */
39− smpl_t confidence; /**< confidence */
39+ uint_t peak_pos; /**< currently selected peak pos*/
4040 uint_t short_period; /** shortest period under which to check for octave error */
4141 };
4242
@@ -44,7 +44,7 @@ static const smpl_t freqs[] = { · 1 unmodified line
4444 0., 20., 25., 31.5, 40., 50., 63., 80., 100., 125.,
4545 160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250.,
4646 1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000.,
47− 12500., 15000., 20000., 25100
47+ 12500., 15000., 20000., 25100., -1.
4848 };
4949
5050 static const smpl_t weight[] = {
@@ -62,15 +62,20 @@ new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize) · 11 unmodified lines
6262 aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t);
6363 p->winput = new_fvec (bufsize);
6464 p->fft = new_aubio_fft (bufsize);
65+ if (!p->fft) goto beach;
6566 p->fftout = new_fvec (bufsize);
6667 p->sqrmag = new_fvec (bufsize);
6768 p->yinfft = new_fvec (bufsize / 2 + 1);
6869 p->tol = 0.85;
70+ p->peak_pos = 0;
6971 p->win = new_aubio_window ("hanningz", bufsize);
7072 p->weight = new_fvec (bufsize / 2 + 1);
7173 for (i = 0; i < p->weight->length; i++) {
7274 freq = (smpl_t) i / (smpl_t) bufsize *(smpl_t) samplerate;
73− while (freq > freqs[j]) {
75+ while (freq > freqs[j] && freqs[j] > 0) {
76+ //AUBIO_DBG("freq %3.5f > %3.5f \tsamplerate %d (Hz) \t"
77+ // "(weight length %d, bufsize %d) %d %d\n", freq, freqs[j],
78+ // samplerate, p->weight->length, bufsize, i, j);
7479 j += 1;
7580 }
7681 a0 = weight[j - 1];
@@ -95,6 +100,11 @@ new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize) · 18 unmodified lines
95100 // check for octave errors above 1300 Hz
96101 p->short_period = (uint_t)ROUND(samplerate / 1300.);
97102 return p;
103+
104+beach:
105+ if (p->winput) del_fvec(p->winput);
106+ AUBIO_FREE(p);
107+ return NULL;
98108 }
99109
100110 void
@@ -155,11 +165,13 @@ aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, const fvec_t * input, fvec_t * ou · 54 unmodified lines
155165 /* should compare the minimum value of each interpolated peaks */
156166 halfperiod = FLOOR (tau / 2 + .5);
157167 if (yin->data[halfperiod] < p->tol)
158− output->data[0] = fvec_quadratic_peak_pos (yin, halfperiod);
168+ p->peak_pos = halfperiod;
159169 else
160− output->data[0] = fvec_quadratic_peak_pos (yin, tau);
170+ p->peak_pos = tau;
171+ output->data[0] = fvec_quadratic_peak_pos (yin, p->peak_pos);
161172 }
162173 } else {
174+ p->peak_pos = 0;
163175 output->data[0] = 0.;
164176 }
165177 }
@@ -179,8 +191,7 @@ del_aubio_pitchyinfft (aubio_pitchyinfft_t * p) · 13 unmodified lines
179191
180192 smpl_t
181193 aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) {
182− o->confidence = 1. - fvec_min (o->yinfft);
183− return o->confidence;
194+ return 1. - o->yinfft->data[o->peak_pos];
184195 }
185196
186197 uint_t
src/spectral/awhitening.c+120−0
@@ -0,0 +1,120 @@
1+/*
2+ * Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org>
3+ *
4+ * This file is part of aubio.
5+ *
6+ * aubio is free software: you can redistribute it and/or modify it under the
7+ * terms of the GNU General Public License as published by the Free Software
8+ * Foundation, either version 3 of the License, or (at your option) any later
9+ * version.
10+ *
11+ * aubio is distributed in the hope that it will be useful, but WITHOUT ANY
12+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14+ * details.
15+ *
16+ * You should have received a copy of the GNU General Public License along with
17+ * aubio. If not, see <http://www.gnu.org/licenses/>.
18+ *
19+ */
20+
21+#include "aubio_priv.h"
22+#include "fvec.h"
23+#include "cvec.h"
24+#include "mathutils.h"
25+#include "spectral/awhitening.h"
26+
27+#define aubio_spectral_whitening_default_relax_time 250 // in seconds, between 22 and 446
28+#define aubio_spectral_whitening_default_decay 0.001 // -60dB attenuation
29+#define aubio_spectral_whitening_default_floor 1.e-4 // from 1.e-6 to .2
30+
31+/** structure to store object state */
32+struct _aubio_spectral_whitening_t {
33+ uint_t buf_size;
34+ uint_t hop_size;
35+ uint_t samplerate;
36+ smpl_t relax_time;
37+ smpl_t r_decay;
38+ smpl_t floor;
39+ fvec_t *peak_values;
40+};
41+
42+void
43+aubio_spectral_whitening_do (aubio_spectral_whitening_t * o, cvec_t * fftgrain)
44+{
45+ uint_t i = 0;
46+ for (i = 0; i < o->peak_values->length; i++) {
47+ smpl_t tmp = MAX(o->r_decay * o->peak_values->data[i], o->floor);
48+ o->peak_values->data[i] = MAX(fftgrain->norm[i], tmp);
49+ fftgrain->norm[i] /= o->peak_values->data[i];
50+ }
51+}
52+
53+aubio_spectral_whitening_t *
54+new_aubio_spectral_whitening (uint_t buf_size, uint_t hop_size, uint_t samplerate)
55+{
56+ aubio_spectral_whitening_t *o = AUBIO_NEW (aubio_spectral_whitening_t);
57+ if ((sint_t)buf_size < 1) {
58+ AUBIO_ERR("spectral_whitening: got buffer_size %d, but can not be < 1\n", buf_size);
59+ goto beach;
60+ } else if ((sint_t)hop_size < 1) {
61+ AUBIO_ERR("spectral_whitening: got hop_size %d, but can not be < 1\n", hop_size);
62+ goto beach;
63+ } else if ((sint_t)samplerate < 1) {
64+ AUBIO_ERR("spectral_whitening: got samplerate %d, but can not be < 1\n", samplerate);
65+ goto beach;
66+ }
67+ o->peak_values = new_fvec (buf_size / 2 + 1);
68+ o->buf_size = buf_size;
69+ o->hop_size = hop_size;
70+ o->samplerate = samplerate;
71+ o->floor = aubio_spectral_whitening_default_floor;
72+ aubio_spectral_whitening_set_relax_time (o, aubio_spectral_whitening_default_relax_time);
73+ aubio_spectral_whitening_reset (o);
74+ return o;
75+
76+beach:
77+ AUBIO_FREE(o);
78+ return NULL;
79+}
80+
81+uint_t
82+aubio_spectral_whitening_set_relax_time (aubio_spectral_whitening_t * o, smpl_t relax_time)
83+{
84+ o->relax_time = relax_time;
85+ o->r_decay = POW (aubio_spectral_whitening_default_decay,
86+ (o->hop_size / (float) o->samplerate) / o->relax_time);
87+ return AUBIO_OK;
88+}
89+
90+smpl_t
91+aubio_spectral_whitening_get_relax_time (aubio_spectral_whitening_t * o)
92+{
93+ return o->relax_time;
94+}
95+
96+uint_t
97+aubio_spectral_whitening_set_floor (aubio_spectral_whitening_t *o, smpl_t floor)
98+{
99+ o->floor = floor;
100+ return AUBIO_OK;
101+}
102+
103+smpl_t aubio_spectral_whitening_get_floor (aubio_spectral_whitening_t *o)
104+{
105+ return o->floor;
106+}
107+
108+void
109+aubio_spectral_whitening_reset (aubio_spectral_whitening_t * o)
110+{
111+ /* cover the case n == 0. */
112+ fvec_set_all (o->peak_values, o->floor);
113+}
114+
115+void
116+del_aubio_spectral_whitening (aubio_spectral_whitening_t * o)
117+{
118+ del_fvec (o->peak_values);
119+ AUBIO_FREE (o);
120+}
src/spectral/awhitening.h+125−0
@@ -0,0 +1,125 @@
1+/*
2+ Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+/** \file
22+
23+ Spectral adaptive whitening
24+
25+ References:
26+
27+ D. Stowell and M. D. Plumbley. Adaptive whitening for improved real-time
28+ audio onset detection. In Proceedings of the International Computer Music
29+ Conference (ICMC), 2007, Copenhagen, Denmark.
30+
31+ http://www.eecs.qmul.ac.uk/~markp/2007/StowellPlumbley07-icmc.pdf
32+
33+ S. Böck,, F. Krebs, and M. Schedl. Evaluating the Online Capabilities of
34+ Onset Detection Methods. In Proceedings of the 13th International Society for
35+ Music Information Retrieval Conference (ISMIR), 2012, Porto, Portugal.
36+
37+ http://ismir2012.ismir.net/event/papers/049_ISMIR_2012.pdf
38+ http://www.cp.jku.at/research/papers/Boeck_etal_ISMIR_2012.pdf
39+
40+*/
41+
42+
43+#ifndef _AUBIO_SPECTRAL_WHITENING_H
44+#define _AUBIO_SPECTRAL_WHITENING_H
45+
46+#ifdef __cplusplus
47+extern "C" {
48+#endif
49+
50+/** spectral whitening structure */
51+typedef struct _aubio_spectral_whitening_t aubio_spectral_whitening_t;
52+
53+/** execute spectral adaptive whitening, in-place
54+
55+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
56+ \param fftgrain input signal spectrum as computed by aubio_pvoc_do() or aubio_fft_do()
57+
58+*/
59+void aubio_spectral_whitening_do (aubio_spectral_whitening_t * o,
60+ cvec_t * fftgrain);
61+
62+/** creation of a spectral whitening object
63+
64+ \param buf_size window size of input grains
65+ \param hop_size number of samples between two consecutive input grains
66+ \param samplerate sampling rate of the input signal
67+
68+*/
69+aubio_spectral_whitening_t *new_aubio_spectral_whitening (uint_t buf_size,
70+ uint_t hop_size,
71+ uint_t samplerate);
72+
73+/** reset spectral whitening object
74+
75+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
76+
77+ */
78+void aubio_spectral_whitening_reset (aubio_spectral_whitening_t * o);
79+
80+/** set relaxation time for spectral whitening
81+
82+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
83+ \param relax_time relaxation time in seconds between 20 and 500, defaults 250
84+
85+ */
86+uint_t aubio_spectral_whitening_set_relax_time (aubio_spectral_whitening_t * o,
87+ smpl_t relax_time);
88+
89+/** get relaxation time of spectral whitening
90+
91+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
92+ \return relaxation time in seconds
93+
94+*/
95+smpl_t aubio_spectral_whitening_get_relax_time (aubio_spectral_whitening_t * o);
96+
97+/** set floor for spectral whitening
98+
99+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
100+ \param floor value (typically between 1.e-6 and .2, defaults to 1.e-4)
101+
102+ */
103+uint_t aubio_spectral_whitening_set_floor (aubio_spectral_whitening_t * o,
104+ smpl_t floor);
105+
106+/** get floor of spectral whitening
107+
108+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
109+ \return floor value
110+
111+*/
112+smpl_t aubio_spectral_whitening_get_floor (aubio_spectral_whitening_t * o);
113+
114+/** deletion of a spectral whitening
115+
116+ \param o spectral whitening object as returned by new_aubio_spectral_whitening()
117+
118+*/
119+void del_aubio_spectral_whitening (aubio_spectral_whitening_t * o);
120+
121+#ifdef __cplusplus
122+}
123+#endif
124+
125+#endif /* _AUBIO_SPECTRAL_WHITENING_H */
src/spectral/dct.c+174−0
@@ -0,0 +1,174 @@
1+/*
2+ Copyright (C) 2018 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+/** \file
22+
23+ Discrete Cosine Transform
24+
25+ Functions aubio_dct_do() and aubio_dct_rdo() are equivalent to MATLAB/Octave
26+ dct() and idct() functions, as well as scipy.fftpack.dct(x, norm='ortho') and
27+ scipy.fftpack.idct(x, norm='ortho')
28+
29+ \example spectral/test-dct.c
30+
31+*/
32+
33+#include "aubio_priv.h"
34+#include "fvec.h"
35+#include "spectral/dct.h"
36+
37+// function pointers prototypes
38+typedef void (*aubio_dct_do_t)(aubio_dct_t * s, const fvec_t * input, fvec_t * output);
39+typedef void (*aubio_dct_rdo_t)(aubio_dct_t * s, const fvec_t * input, fvec_t * output);
40+typedef void (*del_aubio_dct_t)(aubio_dct_t * s);
41+
42+#if defined(HAVE_ACCELERATE)
43+typedef struct _aubio_dct_accelerate_t aubio_dct_accelerate_t;
44+extern aubio_dct_accelerate_t * new_aubio_dct_accelerate (uint_t size);
45+extern void aubio_dct_accelerate_do(aubio_dct_accelerate_t *s, const fvec_t *input, fvec_t *output);
46+extern void aubio_dct_accelerate_rdo(aubio_dct_accelerate_t *s, const fvec_t *input, fvec_t *output);
47+extern void del_aubio_dct_accelerate (aubio_dct_accelerate_t *s);
48+#elif defined(HAVE_FFTW3)
49+typedef struct _aubio_dct_fftw_t aubio_dct_fftw_t;
50+extern aubio_dct_fftw_t * new_aubio_dct_fftw (uint_t size);
51+extern void aubio_dct_fftw_do(aubio_dct_fftw_t *s, const fvec_t *input, fvec_t *output);
52+extern void aubio_dct_fftw_rdo(aubio_dct_fftw_t *s, const fvec_t *input, fvec_t *output);
53+extern void del_aubio_dct_fftw (aubio_dct_fftw_t *s);
54+#elif defined(HAVE_INTEL_IPP)
55+typedef struct _aubio_dct_ipp_t aubio_dct_ipp_t;
56+extern aubio_dct_ipp_t * new_aubio_dct_ipp (uint_t size);
57+extern void aubio_dct_ipp_do(aubio_dct_ipp_t *s, const fvec_t *input, fvec_t *output);
58+extern void aubio_dct_ipp_rdo(aubio_dct_ipp_t *s, const fvec_t *input, fvec_t *output);
59+extern void del_aubio_dct_ipp (aubio_dct_ipp_t *s);
60+#else
61+typedef struct _aubio_dct_ooura_t aubio_dct_ooura_t;
62+extern aubio_dct_ooura_t * new_aubio_dct_ooura (uint_t size);
63+extern void aubio_dct_ooura_do(aubio_dct_ooura_t *s, const fvec_t *input, fvec_t *output);
64+extern void aubio_dct_ooura_rdo(aubio_dct_ooura_t *s, const fvec_t *input, fvec_t *output);
65+extern void del_aubio_dct_ooura (aubio_dct_ooura_t *s);
66+#endif
67+
68+// plain mode
69+typedef struct _aubio_dct_plain_t aubio_dct_plain_t;
70+extern aubio_dct_plain_t * new_aubio_dct_plain (uint_t size);
71+extern void aubio_dct_plain_do(aubio_dct_plain_t *s, const fvec_t *input, fvec_t *output);
72+extern void aubio_dct_plain_rdo(aubio_dct_plain_t *s, const fvec_t *input, fvec_t *output);
73+extern void del_aubio_dct_plain (aubio_dct_plain_t *s);
74+
75+struct _aubio_dct_t {
76+ void *dct;
77+ aubio_dct_do_t dct_do;
78+ aubio_dct_rdo_t dct_rdo;
79+ del_aubio_dct_t del_dct;
80+};
81+
82+aubio_dct_t* new_aubio_dct (uint_t size) {
83+ aubio_dct_t * s = AUBIO_NEW(aubio_dct_t);
84+#if defined(HAVE_ACCELERATE)
85+ // vDSP supports sizes = f * 2 ** n, where n >= 4 and f in [1, 3, 5, 15]
86+ // see https://developer.apple.com/documentation/accelerate/1449930-vdsp_dct_createsetup
87+ {
88+ uint_t radix = size;
89+ uint_t order = 0;
90+ while ((radix >= 1) && ((radix / 2) * 2 == radix)) {
91+ radix /= 2;
92+ order++;
93+ }
94+ if (order < 4 || (radix != 1 && radix != 3 && radix != 5 && radix != 15)) {
95+ goto plain;
96+ }
97+ }
98+ s->dct = (void *)new_aubio_dct_accelerate (size);
99+ if (s->dct) {
100+ s->dct_do = (aubio_dct_do_t)aubio_dct_accelerate_do;
101+ s->dct_rdo = (aubio_dct_rdo_t)aubio_dct_accelerate_rdo;
102+ s->del_dct = (del_aubio_dct_t)del_aubio_dct_accelerate;
103+ return s;
104+ }
105+#elif defined(HAVE_FFTW3)
106+ // fftw supports any positive integer size
107+ s->dct = (void *)new_aubio_dct_fftw (size);
108+ if (s->dct) {
109+ s->dct_do = (aubio_dct_do_t)aubio_dct_fftw_do;
110+ s->dct_rdo = (aubio_dct_rdo_t)aubio_dct_fftw_rdo;
111+ s->del_dct = (del_aubio_dct_t)del_aubio_dct_fftw;
112+ return s;
113+ } else {
114+ AUBIO_WRN("dct: unexpected error while creating dct_fftw with size %d\n",
115+ size);
116+ goto plain;
117+ }
118+#elif defined(HAVE_INTEL_IPP)
119+ // unclear from the docs, but intel ipp seems to support any size
120+ s->dct = (void *)new_aubio_dct_ipp (size);
121+ if (s->dct) {
122+ s->dct_do = (aubio_dct_do_t)aubio_dct_ipp_do;
123+ s->dct_rdo = (aubio_dct_rdo_t)aubio_dct_ipp_rdo;
124+ s->del_dct = (del_aubio_dct_t)del_aubio_dct_ipp;
125+ return s;
126+ } else {
127+ AUBIO_WRN("dct: unexpected error while creating dct_ipp with size %d\n",
128+ size);
129+ goto plain;
130+ }
131+#else
132+ // ooura support sizes that are power of 2
133+ if (aubio_is_power_of_two(size) != 1 || size == 1) {
134+ goto plain;
135+ }
136+ s->dct = (void *)new_aubio_dct_ooura (size);
137+ if (s->dct) {
138+ s->dct_do = (aubio_dct_do_t)aubio_dct_ooura_do;
139+ s->dct_rdo = (aubio_dct_rdo_t)aubio_dct_ooura_rdo;
140+ s->del_dct = (del_aubio_dct_t)del_aubio_dct_ooura;
141+ return s;
142+ }
143+#endif
144+ // falling back to plain mode
145+ AUBIO_WRN("dct: no optimised implementation could be created for size %d\n",
146+ size);
147+plain:
148+ s->dct = (void *)new_aubio_dct_plain (size);
149+ if (s->dct) {
150+ s->dct_do = (aubio_dct_do_t)aubio_dct_plain_do;
151+ s->dct_rdo = (aubio_dct_rdo_t)aubio_dct_plain_rdo;
152+ s->del_dct = (del_aubio_dct_t)del_aubio_dct_plain;
153+ return s;
154+ } else {
155+ goto beach;
156+ }
157+beach:
158+ AUBIO_ERROR("dct: failed creating with size %d, should be > 0\n", size);
159+ del_aubio_dct(s);
160+ return NULL;
161+}
162+
163+void del_aubio_dct(aubio_dct_t *s) {
164+ if (s->dct && s->del_dct) s->del_dct (s->dct);
165+ AUBIO_FREE (s);
166+}
167+
168+void aubio_dct_do(aubio_dct_t *s, const fvec_t *input, fvec_t *output) {
169+ s->dct_do ((void *)s->dct, input, output);
170+}
171+
172+void aubio_dct_rdo(aubio_dct_t *s, const fvec_t *input, fvec_t *output) {
173+ s->dct_rdo ((void *)s->dct, input, output);
174+}
src/spectral/dct.h+85−0
@@ -0,0 +1,85 @@
1+/*
2+ Copyright (C) 2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+/** \file
22+
23+ Discrete Cosine Transform
24+
25+ Functions aubio_dct_do() and aubio_dct_rdo() are equivalent to MATLAB/Octave
26+ dct() and idct() functions, as well as scipy.fftpack.dct(x, norm='ortho') and
27+ scipy.fftpack.idct(x, norm='ortho')
28+
29+ \example spectral/test-dct.c
30+
31+*/
32+
33+#ifndef AUBIO_DCT_H
34+#define AUBIO_DCT_H
35+
36+#ifdef __cplusplus
37+extern "C" {
38+#endif
39+
40+/** DCT object
41+
42+ This object computes forward and backward DCT type 2 with orthonormal
43+ scaling.
44+
45+*/
46+typedef struct _aubio_dct_t aubio_dct_t;
47+
48+/** create new DCT computation object
49+
50+ \param size length of the DCT
51+
52+*/
53+aubio_dct_t * new_aubio_dct(uint_t size);
54+
55+/** compute forward DCT
56+
57+ \param s dct object as returned by new_aubio_dct
58+ \param input input signal
59+ \param dct_output transformed input array
60+
61+*/
62+void aubio_dct_do (aubio_dct_t *s, const fvec_t * input, fvec_t * dct_output);
63+
64+/** compute backward DCT
65+
66+ \param s dct object as returned by new_aubio_dct
67+ \param input input signal
68+ \param idct_output transformed input array
69+
70+*/
71+void aubio_dct_rdo (aubio_dct_t *s, const fvec_t * input, fvec_t * idct_output);
72+
73+
74+/** delete DCT object
75+
76+ \param s dct object as returned by new_aubio_dct
77+
78+*/
79+void del_aubio_dct (aubio_dct_t *s);
80+
81+#ifdef __cplusplus
82+}
83+#endif
84+
85+#endif /* AUBIO_DCT_H */
src/spectral/dct_accelerate.c+102−0
@@ -0,0 +1,102 @@
1+/*
2+ Copyright (C) 2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+#include "fvec.h"
23+#include "spectral/dct.h"
24+
25+#if defined(HAVE_ACCELERATE)
26+
27+#if HAVE_AUBIO_DOUBLE
28+#warning "no double-precision dct with accelerate"
29+#endif
30+
31+struct _aubio_dct_accelerate_t {
32+ uint_t size;
33+ fvec_t *tmp;
34+ vDSP_DFT_Setup setup;
35+ vDSP_DFT_Setup setupInv;
36+};
37+
38+typedef struct _aubio_dct_accelerate_t aubio_dct_accelerate_t;
39+
40+void del_aubio_dct_accelerate (aubio_dct_accelerate_t *s);
41+
42+aubio_dct_accelerate_t * new_aubio_dct_accelerate (uint_t size) {
43+ aubio_dct_accelerate_t * s = AUBIO_NEW(aubio_dct_accelerate_t);
44+
45+ if ((sint_t)size < 16 || !aubio_is_power_of_two(size)) {
46+ AUBIO_ERR("dct: can only create with sizes greater than 16 and"
47+ " that are powers of two, requested %d\n", size);
48+ goto beach;
49+ }
50+
51+ s->setup = vDSP_DCT_CreateSetup(NULL, (vDSP_Length)size, vDSP_DCT_II);
52+ s->setupInv = vDSP_DCT_CreateSetup(NULL, (vDSP_Length)size, vDSP_DCT_III);
53+ if (s->setup == NULL || s->setupInv == NULL) {
54+ goto beach;
55+ }
56+
57+ s->size = size;
58+
59+ return s;
60+
61+beach:
62+ del_aubio_dct_accelerate(s);
63+ return NULL;
64+}
65+
66+void del_aubio_dct_accelerate(aubio_dct_accelerate_t *s) {
67+ if (s->setup) vDSP_DFT_DestroySetup(s->setup);
68+ if (s->setupInv) vDSP_DFT_DestroySetup(s->setupInv);
69+ AUBIO_FREE(s);
70+}
71+
72+void aubio_dct_accelerate_do(aubio_dct_accelerate_t *s, const fvec_t *input, fvec_t *output) {
73+
74+ vDSP_DCT_Execute(s->setup, (const float *)input->data, (float *)output->data);
75+
76+ // apply orthonormal scaling
77+ output->data[0] *= SQRT(1./s->size);
78+ smpl_t scaler = SQRT(2./s->size);
79+
80+ aubio_vDSP_vsmul(output->data + 1, 1, &scaler, output->data + 1, 1,
81+ output->length - 1);
82+
83+}
84+
85+void aubio_dct_accelerate_rdo(aubio_dct_accelerate_t *s, const fvec_t *input, fvec_t *output) {
86+
87+ output->data[0] = input->data[0] / SQRT(1./s->size);
88+ smpl_t scaler = 1./SQRT(2./s->size);
89+
90+ aubio_vDSP_vsmul(input->data + 1, 1, &scaler, output->data + 1, 1,
91+ output->length - 1);
92+
93+ vDSP_DCT_Execute(s->setupInv, (const float *)output->data,
94+ (float *)output->data);
95+
96+ scaler = 2./s->size;
97+
98+ aubio_vDSP_vsmul(output->data, 1, &scaler, output->data, 1, output->length);
99+
100+}
101+
102+#endif //defined(HAVE_ACCELERATE)
src/spectral/dct_fftw.c+130−0
@@ -0,0 +1,130 @@
1+/*
2+ Copyright (C) 2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+#include "fvec.h"
23+#include "spectral/dct.h"
24+
25+#ifdef HAVE_FFTW3
26+
27+#include <fftw3.h>
28+#include <pthread.h>
29+
30+#ifdef HAVE_FFTW3F
31+#if HAVE_AUBIO_DOUBLE
32+#error "Using aubio in double precision with fftw3 in single precision"
33+#endif /* HAVE_AUBIO_DOUBLE */
34+#else /* HAVE_FFTW3F */
35+#if !HAVE_AUBIO_DOUBLE
36+#error "Using aubio in single precision with fftw3 in double precision"
37+#endif /* HAVE_AUBIO_DOUBLE */
38+#endif /* HAVE_FFTW3F */
39+
40+#ifdef HAVE_FFTW3F
41+#define fftw_malloc fftwf_malloc
42+#define fftw_free fftwf_free
43+#define fftw_execute fftwf_execute
44+#define fftw_plan_dft_r2c_1d fftwf_plan_dft_r2c_1d
45+#define fftw_plan_dft_c2r_1d fftwf_plan_dft_c2r_1d
46+#define fftw_plan_r2r_1d fftwf_plan_r2r_1d
47+#define fftw_plan fftwf_plan
48+#define fftw_destroy_plan fftwf_destroy_plan
49+#endif
50+
51+// defined in src/spectral/fft.c
52+extern pthread_mutex_t aubio_fftw_mutex;
53+
54+typedef struct _aubio_dct_fftw_t aubio_dct_fftw_t;
55+
56+struct _aubio_dct_fftw_t {
57+ uint_t size;
58+ fvec_t *in, *out;
59+ smpl_t *data;
60+ fftw_plan pfw, pbw;
61+ smpl_t scalers[5];
62+};
63+
64+aubio_dct_fftw_t * new_aubio_dct_fftw (uint_t size) {
65+ aubio_dct_fftw_t * s = AUBIO_NEW(aubio_dct_fftw_t);
66+ if ((sint_t)size <= 0) {
67+ AUBIO_ERR("dct_fftw: can only create with size > 0, requested %d\n",
68+ size);
69+ goto beach;
70+ }
71+ s->size = size;
72+ s->in = new_fvec(size);
73+ s->out = new_fvec(size);
74+ pthread_mutex_lock(&aubio_fftw_mutex);
75+ s->data = (smpl_t *)fftw_malloc(sizeof(smpl_t) * size);
76+ s->pfw = fftw_plan_r2r_1d(size, s->in->data, s->data, FFTW_REDFT10,
77+ FFTW_ESTIMATE);
78+ s->pbw = fftw_plan_r2r_1d(size, s->data, s->out->data, FFTW_REDFT01,
79+ FFTW_ESTIMATE);
80+ pthread_mutex_unlock(&aubio_fftw_mutex);
81+ s->scalers[0] = SQRT(1./(4.*s->size));
82+ s->scalers[1] = SQRT(1./(2.*s->size));
83+ s->scalers[2] = 1. / s->scalers[0];
84+ s->scalers[3] = 1. / s->scalers[1];
85+ s->scalers[4] = .5 / s->size;
86+ return s;
87+beach:
88+ AUBIO_FREE(s);
89+ return NULL;
90+}
91+
92+void del_aubio_dct_fftw(aubio_dct_fftw_t *s) {
93+ pthread_mutex_lock(&aubio_fftw_mutex);
94+ fftw_destroy_plan(s->pfw);
95+ fftw_destroy_plan(s->pbw);
96+ fftw_free(s->data);
97+ pthread_mutex_unlock(&aubio_fftw_mutex);
98+ del_fvec(s->in);
99+ del_fvec(s->out);
100+ AUBIO_FREE(s);
101+}
102+
103+void aubio_dct_fftw_do(aubio_dct_fftw_t *s, const fvec_t *input, fvec_t *output) {
104+ uint_t i;
105+ fvec_copy(input, s->in);
106+ fftw_execute(s->pfw);
107+ //fvec_copy(s->out, output);
108+ s->data[0] *= s->scalers[0];
109+ for (i = 1; i < s->size; i++) {
110+ s->data[i] *= s->scalers[1];
111+ }
112+ memcpy(output->data, s->data, output->length * sizeof(smpl_t));
113+}
114+
115+void aubio_dct_fftw_rdo(aubio_dct_fftw_t *s, const fvec_t *input, fvec_t *output) {
116+ uint_t i;
117+ memcpy(s->data, input->data, input->length * sizeof(smpl_t));
118+ //s->data[0] *= .5;
119+ s->data[0] *= s->scalers[2];
120+ for (i = 1; i < s->size; i++) {
121+ s->data[i] *= s->scalers[3];
122+ }
123+ fftw_execute(s->pbw);
124+ for (i = 0; i < s->size; i++) {
125+ s->out->data[i] *= s->scalers[4];
126+ }
127+ fvec_copy(s->out, output);
128+}
129+
130+#endif //HAVE_FFTW3
src/spectral/dct_ipp.c+150−0
@@ -0,0 +1,150 @@
1+/*
2+ Copyright (C) 2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+#include "fvec.h"
23+#include "spectral/dct.h"
24+
25+#if defined(HAVE_INTEL_IPP)
26+
27+#if !HAVE_AUBIO_DOUBLE
28+#define aubio_IppFloat Ipp32f
29+#define aubio_ippsDCTFwdSpec IppsDCTFwdSpec_32f
30+#define aubio_ippsDCTInvSpec IppsDCTInvSpec_32f
31+#define aubio_ippsDCTFwdGetSize ippsDCTFwdGetSize_32f
32+#define aubio_ippsDCTInvGetSize ippsDCTInvGetSize_32f
33+#define aubio_ippsDCTFwdInit ippsDCTFwdInit_32f
34+#define aubio_ippsDCTInvInit ippsDCTInvInit_32f
35+#define aubio_ippsDCTFwd ippsDCTFwd_32f
36+#define aubio_ippsDCTInv ippsDCTInv_32f
37+#else /* HAVE_AUBIO_DOUBLE */
38+#define aubio_IppFloat Ipp64f
39+#define aubio_ippsDCTFwdSpec IppsDCTFwdSpec_64f
40+#define aubio_ippsDCTInvSpec IppsDCTInvSpec_64f
41+#define aubio_ippsDCTFwdGetSize ippsDCTFwdGetSize_64f
42+#define aubio_ippsDCTInvGetSize ippsDCTInvGetSize_64f
43+#define aubio_ippsDCTFwdInit ippsDCTFwdInit_64f
44+#define aubio_ippsDCTInvInit ippsDCTInvInit_64f
45+#define aubio_ippsDCTFwd ippsDCTFwd_64f
46+#define aubio_ippsDCTInv ippsDCTInv_64f
47+#endif
48+
49+typedef struct _aubio_dct_ipp_t aubio_dct_ipp_t;
50+
51+struct _aubio_dct_ipp_t {
52+ uint_t size;
53+ Ipp8u* pSpecFwd;
54+ Ipp8u* pSpecInv;
55+ Ipp8u* pSpecBuffer;
56+ Ipp8u* pBuffer;
57+ aubio_ippsDCTFwdSpec* pFwdDCTSpec;
58+ aubio_ippsDCTInvSpec* pInvDCTSpec;
59+};
60+
61+void del_aubio_dct_ipp (aubio_dct_ipp_t *s);
62+
63+aubio_dct_ipp_t * new_aubio_dct_ipp (uint_t size) {
64+ aubio_dct_ipp_t * s = AUBIO_NEW(aubio_dct_ipp_t);
65+
66+ const IppHintAlgorithm qualityHint = ippAlgHintAccurate; // ippAlgHintFast;
67+ int pSpecSize, pSpecBufferSize, pBufferSize;
68+ IppStatus status;
69+
70+ if ((sint_t)size <= 0) {
71+ AUBIO_ERR("dct: can only create with sizes greater than 0, requested %d\n",
72+ size);
73+ goto beach;
74+ }
75+
76+ status = aubio_ippsDCTFwdGetSize(size, qualityHint, &pSpecSize,
77+ &pSpecBufferSize, &pBufferSize);
78+ if (status != ippStsNoErr) {
79+ AUBIO_ERR("dct: failed to initialize dct. IPP error: %d\n", status);
80+ goto beach;
81+ }
82+
83+ //AUBIO_INF("dct: fwd initialized with %d %d %d\n", pSpecSize, pSpecBufferSize,
84+ // pBufferSize);
85+
86+ s->pSpecFwd = ippsMalloc_8u(pSpecSize);
87+ s->pSpecInv = ippsMalloc_8u(pSpecSize);
88+ if (pSpecSize > 0) {
89+ s->pSpecBuffer = ippsMalloc_8u(pSpecBufferSize);
90+ } else {
91+ s->pSpecBuffer = NULL;
92+ }
93+ s->pBuffer = ippsMalloc_8u(pBufferSize);
94+
95+ status = aubio_ippsDCTInvGetSize(size, qualityHint, &pSpecSize,
96+ &pSpecBufferSize, &pBufferSize);
97+ if (status != ippStsNoErr) {
98+ AUBIO_ERR("dct: failed to initialize dct. IPP error: %d\n", status);
99+ goto beach;
100+ }
101+
102+ //AUBIO_INF("dct: inv initialized with %d %d %d\n", pSpecSize, pSpecBufferSize,
103+ // pBufferSize);
104+
105+ status = aubio_ippsDCTFwdInit(&(s->pFwdDCTSpec), size, qualityHint, s->pSpecFwd,
106+ s->pSpecBuffer);
107+ if (status != ippStsNoErr) {
108+ AUBIO_ERR("dct: failed to initialize fwd dct. IPP error: %d\n", status);
109+ goto beach;
110+ }
111+
112+ status = aubio_ippsDCTInvInit(&(s->pInvDCTSpec), size, qualityHint, s->pSpecInv,
113+ s->pSpecBuffer);
114+ if (status != ippStsNoErr) {
115+ AUBIO_ERR("dct: failed to initialize inv dct. IPP error: %d\n", status);
116+ goto beach;
117+ }
118+
119+ s->size = size;
120+
121+ return s;
122+
123+beach:
124+ del_aubio_dct_ipp(s);
125+ return NULL;
126+}
127+
128+void del_aubio_dct_ipp(aubio_dct_ipp_t *s) {
129+ ippFree(s->pSpecFwd);
130+ ippFree(s->pSpecInv);
131+ ippFree(s->pSpecBuffer);
132+ ippFree(s->pBuffer);
133+ AUBIO_FREE(s);
134+}
135+
136+void aubio_dct_ipp_do(aubio_dct_ipp_t *s, const fvec_t *input, fvec_t *output) {
137+
138+ aubio_ippsDCTFwd((const aubio_IppFloat*)input->data,
139+ (aubio_IppFloat*)output->data, s->pFwdDCTSpec, s->pBuffer);
140+
141+}
142+
143+void aubio_dct_ipp_rdo(aubio_dct_ipp_t *s, const fvec_t *input, fvec_t *output) {
144+
145+ aubio_ippsDCTInv((const aubio_IppFloat*)input->data,
146+ (aubio_IppFloat*)output->data, s->pInvDCTSpec, s->pBuffer);
147+
148+}
149+
150+#endif //defined(HAVE_INTEL_IPP)
src/spectral/dct_ooura.c+96−0
@@ -0,0 +1,96 @@
1+/*
2+ Copyright (C) 2017 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+#include "fvec.h"
23+#include "spectral/dct.h"
24+
25+#if !defined(HAVE_ACCELERATE) && !defined(HAVE_FFTW3) && !defined(HAVE_INTEL_IPP)
26+
27+typedef struct _aubio_dct_ooura_t aubio_dct_ooura_t;
28+
29+extern void aubio_ooura_ddct(int, int, smpl_t *, int *, smpl_t *);
30+
31+struct _aubio_dct_ooura_t {
32+ uint_t size;
33+ fvec_t *input;
34+ smpl_t *w;
35+ int *ip;
36+ smpl_t scalers[5];
37+};
38+
39+aubio_dct_ooura_t * new_aubio_dct_ooura (uint_t size) {
40+ aubio_dct_ooura_t * s = AUBIO_NEW(aubio_dct_ooura_t);
41+ if (aubio_is_power_of_two(size) != 1 || (sint_t)size <= 0) {
42+ AUBIO_ERR("dct_ooura: can only create with sizes power of two, requested %d\n",
43+ size);
44+ goto beach;
45+ }
46+ s->size = size;
47+ s->input = new_fvec(s->size);
48+ s->w = AUBIO_ARRAY(smpl_t, s->size * 5 / 4);
49+ s->ip = AUBIO_ARRAY(int, 3 + (1 << (int)FLOOR(LOG(s->size/2) / LOG(2))) / 2);
50+ s->ip[0] = 0;
51+ s->scalers[0] = 2. * SQRT(1./(4.*s->size));
52+ s->scalers[1] = 2. * SQRT(1./(2.*s->size));
53+ s->scalers[2] = 1. / s->scalers[0];
54+ s->scalers[3] = 1. / s->scalers[1];
55+ s->scalers[4] = 2. / s->size;
56+ return s;
57+beach:
58+ AUBIO_FREE(s);
59+ return NULL;
60+}
61+
62+void del_aubio_dct_ooura(aubio_dct_ooura_t *s) {
63+ del_fvec(s->input);
64+ AUBIO_FREE(s->ip);
65+ AUBIO_FREE(s->w);
66+ AUBIO_FREE(s);
67+}
68+
69+void aubio_dct_ooura_do(aubio_dct_ooura_t *s, const fvec_t *input, fvec_t *output) {
70+ uint_t i = 0;
71+ fvec_copy(input, s->input);
72+ aubio_ooura_ddct(s->size, -1, s->input->data, s->ip, s->w);
73+ // apply orthonormal scaling
74+ s->input->data[0] *= s->scalers[0];
75+ for (i = 1; i < s->input->length; i++) {
76+ s->input->data[i] *= s->scalers[1];
77+ }
78+ fvec_copy(s->input, output);
79+}
80+
81+void aubio_dct_ooura_rdo(aubio_dct_ooura_t *s, const fvec_t *input, fvec_t *output) {
82+ uint_t i = 0;
83+ fvec_copy(input, s->input);
84+ s->input->data[0] *= s->scalers[2];
85+ for (i = 1; i < s->input->length; i++) {
86+ s->input->data[i] *= s->scalers[3];
87+ }
88+ s->input->data[0] *= .5;
89+ aubio_ooura_ddct(s->size, 1, s->input->data, s->ip, s->w);
90+ for (i = 0; i < s->input->length; i++) {
91+ s->input->data[i] *= s->scalers[4];
92+ }
93+ fvec_copy(s->input, output);
94+}
95+
96+#endif //!defined(HAVE_ACCELERATE) && !defined(HAVE_FFTW3)
src/spectral/dct_plain.c+105−0
@@ -0,0 +1,105 @@
1+/*
2+ Copyright (C) 2018 Paul Brossier <piem@aubio.org>
3+
4+ This file is part of aubio.
5+
6+ aubio is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ aubio is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with aubio. If not, see <http://www.gnu.org/licenses/>.
18+
19+*/
20+
21+#include "aubio_priv.h"
22+#include "fvec.h"
23+#include "fmat.h"
24+#include "spectral/dct.h"
25+
26+typedef struct _aubio_dct_plain_t aubio_dct_plain_t;
27+
28+struct _aubio_dct_plain_t {
29+ uint_t size;
30+ fmat_t *dct_coeffs; /** DCT type II orthonormal transform, size * size */
31+ fmat_t *idct_coeffs; /** DCT type III orthonormal transform, size * size */
32+};
33+
34+void del_aubio_dct_plain (aubio_dct_plain_t *s);
35+
36+aubio_dct_plain_t * new_aubio_dct_plain (uint_t size) {
37+ aubio_dct_plain_t * s = AUBIO_NEW(aubio_dct_plain_t);
38+ uint_t i, j;
39+ smpl_t scaling;
40+ if (aubio_is_power_of_two (size) == 1 && size > 16) {
41+ AUBIO_WRN("dct_plain: using plain dct but size %d is a power of two\n", size);
42+ }
43+ if ((sint_t)size <= 0) {
44+ AUBIO_ERR("dct_plain: can only create with size > 0, requested %d\n",
45+ size);
46+ goto failure;
47+ }
48+
49+ s->size = size;
50+
51+ s->dct_coeffs = new_fmat (size, size);
52+ s->idct_coeffs = new_fmat (size, size);
53+
54+ /* compute DCT type-II transformation matrix
55+ dct_coeffs[j][i] = cos ( j * (i+.5) * PI / n_filters )
56+ */
57+ scaling = SQRT (2. / size);
58+ for (i = 0; i < size; i++) {
59+ for (j = 1; j < size; j++) {
60+ s->dct_coeffs->data[j][i] =
61+ scaling * COS (j * (i + 0.5) * PI / size );
62+ }
63+ s->dct_coeffs->data[0][i] = 1. / SQRT (size);
64+ }
65+
66+ /* compute DCT type-III transformation matrix
67+ idct_coeffs[j][i] = cos ( i * (j+.5) * PI / n_filters )
68+ */
69+ scaling = SQRT (2. / size);
70+ for (j = 0; j < size; j++) {
71+ for (i = 1; i < size; i++) {
72+ s->idct_coeffs->data[j][i] =
73+ scaling * COS (i * (j + 0.5) * PI / size );
74+ }
75+ s->idct_coeffs->data[j][0] = 1. / SQRT (size);
76+ }
77+ return s;
78+failure:
79+ del_aubio_dct_plain(s);
80+ return NULL;
81+}
82+
83+void del_aubio_dct_plain (aubio_dct_plain_t *s) {
84+ if (s->dct_coeffs)
85+ del_fmat(s->dct_coeffs);
86+ if (s->idct_coeffs)
87+ del_fmat(s->idct_coeffs);
88+ AUBIO_FREE(s);
89+}
90+
91+void aubio_dct_plain_do(aubio_dct_plain_t *s, const fvec_t *input, fvec_t *output) {
92+ if (input->length != output->length || input->length != s->size) {
93+ AUBIO_WRN("dct_plain: using input length %d, but output length = %d and size = %d\n",
94+ input->length, output->length, s->size);
95+ }
96+ fmat_vecmul(s->dct_coeffs, input, output);
97+}
98+
99+void aubio_dct_plain_rdo(aubio_dct_plain_t *s, const fvec_t *input, fvec_t *output) {
100+ if (input->length != output->length || input->length != s->size) {
101+ AUBIO_WRN("dct_plain: using input length %d, but output length = %d and size = %d\n",
102+ input->length, output->length, s->size);
103+ }
104+ fmat_vecmul(s->idct_coeffs, input, output);
105+}
src/spectral/fft.c+214−46
@@ -77,8 +77,7 @@ typedef FFTW_TYPE fft_data_t; · 76 unmodified lines
7777 // a global mutex for FFTW thread safety
7878 pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER;
7979
80−#else
81−#ifdef HAVE_ACCELERATE // using ACCELERATE
80+#elif defined HAVE_ACCELERATE // using ACCELERATE
8281 // https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html
8382 #include <Accelerate/Accelerate.h>
8483
@@ -90,11 +89,12 @@ pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER; · 5 unmodified lines
9089 #define aubio_vDSP_zvphas vDSP_zvphas
9190 #define aubio_vDSP_vsadd vDSP_vsadd
9291 #define aubio_vDSP_vsmul vDSP_vsmul
93−#define aubio_vDSP_create_fftsetup vDSP_create_fftsetup
94−#define aubio_vDSP_destroy_fftsetup vDSP_destroy_fftsetup
9592 #define aubio_DSPComplex DSPComplex
9693 #define aubio_DSPSplitComplex DSPSplitComplex
97−#define aubio_FFTSetup FFTSetup
94+#define aubio_vDSP_DFT_Setup vDSP_DFT_Setup
95+#define aubio_vDSP_DFT_zrop_CreateSetup vDSP_DFT_zrop_CreateSetup
96+#define aubio_vDSP_DFT_Execute vDSP_DFT_Execute
97+#define aubio_vDSP_DFT_DestroySetup vDSP_DFT_DestroySetup
9898 #define aubio_vvsqrt vvsqrtf
9999 #else
100100 #define aubio_vDSP_ctoz vDSP_ctozD
@@ -104,40 +104,74 @@ pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER; · 3 unmodified lines
104104 #define aubio_vDSP_zvphas vDSP_zvphasD
105105 #define aubio_vDSP_vsadd vDSP_vsaddD
106106 #define aubio_vDSP_vsmul vDSP_vsmulD
107−#define aubio_vDSP_create_fftsetup vDSP_create_fftsetupD
108−#define aubio_vDSP_destroy_fftsetup vDSP_destroy_fftsetupD
109107 #define aubio_DSPComplex DSPDoubleComplex
110108 #define aubio_DSPSplitComplex DSPDoubleSplitComplex
111−#define aubio_FFTSetup FFTSetupD
109+#define aubio_vDSP_DFT_Setup vDSP_DFT_SetupD
110+#define aubio_vDSP_DFT_zrop_CreateSetup vDSP_DFT_zrop_CreateSetupD
111+#define aubio_vDSP_DFT_Execute vDSP_DFT_ExecuteD
112+#define aubio_vDSP_DFT_DestroySetup vDSP_DFT_DestroySetupD
112113 #define aubio_vvsqrt vvsqrt
113114 #endif /* HAVE_AUBIO_DOUBLE */
114115
115−#else // using OOURA
116+#elif defined HAVE_INTEL_IPP // using INTEL IPP
117+
118+#if !HAVE_AUBIO_DOUBLE
119+#define aubio_IppFloat Ipp32f
120+#define aubio_IppComplex Ipp32fc
121+#define aubio_FFTSpec FFTSpec_R_32f
122+#define aubio_ippsMalloc_complex ippsMalloc_32fc
123+#define aubio_ippsFFTInit_R ippsFFTInit_R_32f
124+#define aubio_ippsFFTGetSize_R ippsFFTGetSize_R_32f
125+#define aubio_ippsFFTInv_CCSToR ippsFFTInv_CCSToR_32f
126+#define aubio_ippsFFTFwd_RToCCS ippsFFTFwd_RToCCS_32f
127+#define aubio_ippsAtan2 ippsAtan2_32f_A21
128+#else /* HAVE_AUBIO_DOUBLE */
129+#define aubio_IppFloat Ipp64f
130+#define aubio_IppComplex Ipp64fc
131+#define aubio_FFTSpec FFTSpec_R_64f
132+#define aubio_ippsMalloc_complex ippsMalloc_64fc
133+#define aubio_ippsFFTInit_R ippsFFTInit_R_64f
134+#define aubio_ippsFFTGetSize_R ippsFFTGetSize_R_64f
135+#define aubio_ippsFFTInv_CCSToR ippsFFTInv_CCSToR_64f
136+#define aubio_ippsFFTFwd_RToCCS ippsFFTFwd_RToCCS_64f
137+#define aubio_ippsAtan2 ippsAtan2_64f_A50
138+#endif
139+
140+
141+#else // using OOURA
116142 // let's use ooura instead
117143 extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *);
118144
119−#endif /* HAVE_ACCELERATE */
120−#endif /* HAVE_FFTW3 */
145+#endif
121146
122147 struct _aubio_fft_t {
123148 uint_t winsize;
124149 uint_t fft_size;
150+
125151 #ifdef HAVE_FFTW3 // using FFTW3
126152 real_t *in, *out;
127153 fftw_plan pfw, pbw;
128− fft_data_t * specdata; /* complex spectral data */
129−#else
130−#ifdef HAVE_ACCELERATE // using ACCELERATE
131− int log2fftsize;
132− aubio_FFTSetup fftSetup;
154+ fft_data_t * specdata; /* complex spectral data */
155+
156+#elif defined HAVE_ACCELERATE // using ACCELERATE
157+ aubio_vDSP_DFT_Setup fftSetupFwd;
158+ aubio_vDSP_DFT_Setup fftSetupBwd;
133159 aubio_DSPSplitComplex spec;
134160 smpl_t *in, *out;
161+
162+#elif defined HAVE_INTEL_IPP // using Intel IPP
163+ smpl_t *in, *out;
164+ Ipp8u* memSpec;
165+ Ipp8u* memInit;
166+ Ipp8u* memBuffer;
167+ struct aubio_FFTSpec* fftSpec;
168+ aubio_IppComplex* complexOut;
135169 #else // using OOURA
136170 smpl_t *in, *out;
137171 smpl_t *w;
138172 int *ip;
139−#endif /* HAVE_ACCELERATE */
140−#endif /* HAVE_FFTW3 */
173+#endif /* using OOURA */
174+
141175 fvec_t * compspec;
142176 };
143177
@@ -147,6 +181,7 @@ aubio_fft_t * new_aubio_fft (uint_t winsize) { · 3 unmodified lines
147181 AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize);
148182 goto beach;
149183 }
184+
150185 #ifdef HAVE_FFTW3
151186 uint_t i;
152187 s->winsize = winsize;
@@ -175,17 +210,72 @@ aubio_fft_t * new_aubio_fft (uint_t winsize) { · 22 unmodified lines
175210 for (i = 0; i < s->fft_size; i++) {
176211 s->specdata[i] = 0.;
177212 }
178−#else
179−#ifdef HAVE_ACCELERATE // using ACCELERATE
213+
214+#elif defined HAVE_ACCELERATE // using ACCELERATE
215+ {
216+ uint_t radix = winsize;
217+ uint_t order = 0;
218+ while ((radix / 2) * 2 == radix) {
219+ radix /= 2;
220+ order++;
221+ }
222+ if (order < 4 || (radix != 1 && radix != 3 && radix != 5 && radix != 15)) {
223+ AUBIO_ERR("fft: vDSP/Accelerate supports FFT with sizes = "
224+ "f * 2 ** n, where n > 4 and f in [1, 3, 5, 15], but requested %d. "
225+ "Use the closest power of two, or try recompiling aubio with "
226+ "--enable-fftw3.\n", winsize);
227+ goto beach;
228+ }
229+ }
180230 s->winsize = winsize;
181231 s->fft_size = winsize;
182232 s->compspec = new_fvec(winsize);
183− s->log2fftsize = (uint_t)log2f(s->fft_size);
184233 s->in = AUBIO_ARRAY(smpl_t, s->fft_size);
185234 s->out = AUBIO_ARRAY(smpl_t, s->fft_size);
186235 s->spec.realp = AUBIO_ARRAY(smpl_t, s->fft_size/2);
187236 s->spec.imagp = AUBIO_ARRAY(smpl_t, s->fft_size/2);
188− s->fftSetup = aubio_vDSP_create_fftsetup(s->log2fftsize, FFT_RADIX2);
237+ s->fftSetupFwd = aubio_vDSP_DFT_zrop_CreateSetup(NULL,
238+ s->fft_size, vDSP_DFT_FORWARD);
239+ s->fftSetupBwd = aubio_vDSP_DFT_zrop_CreateSetup(s->fftSetupFwd,
240+ s->fft_size, vDSP_DFT_INVERSE);
241+
242+#elif defined HAVE_INTEL_IPP // using Intel IPP
243+ const IppHintAlgorithm qualityHint = ippAlgHintAccurate; // OR ippAlgHintFast;
244+ const int flags = IPP_FFT_NODIV_BY_ANY; // we're scaling manually afterwards
245+ int order = aubio_power_of_two_order(winsize);
246+ int sizeSpec, sizeInit, sizeBuffer;
247+ IppStatus status;
248+
249+ if (winsize <= 4 || aubio_is_power_of_two(winsize) != 1)
250+ {
251+ AUBIO_ERR("intel IPP fft: can only create with sizes > 4 and power of two, requested %d,"
252+ " try recompiling aubio with --enable-fftw3\n", winsize);
253+ goto beach;
254+ }
255+
256+ status = aubio_ippsFFTGetSize_R(order, flags, qualityHint,
257+ &sizeSpec, &sizeInit, &sizeBuffer);
258+ if (status != ippStsNoErr) {
259+ AUBIO_ERR("fft: failed to initialize fft. IPP error: %d\n", status);
260+ goto beach;
261+ }
262+ s->fft_size = s->winsize = winsize;
263+ s->compspec = new_fvec(winsize);
264+ s->in = AUBIO_ARRAY(smpl_t, s->winsize);
265+ s->out = AUBIO_ARRAY(smpl_t, s->winsize);
266+ s->memSpec = ippsMalloc_8u(sizeSpec);
267+ s->memBuffer = ippsMalloc_8u(sizeBuffer);
268+ if (sizeInit > 0 ) {
269+ s->memInit = ippsMalloc_8u(sizeInit);
270+ }
271+ s->complexOut = aubio_ippsMalloc_complex(s->fft_size / 2 + 1);
272+ status = aubio_ippsFFTInit_R(
273+ &s->fftSpec, order, flags, qualityHint, s->memSpec, s->memInit);
274+ if (status != ippStsNoErr) {
275+ AUBIO_ERR("fft: failed to initialize. IPP error: %d\n", status);
276+ goto beach;
277+ }
278+
189279 #else // using OOURA
190280 if (aubio_is_power_of_two(winsize) != 1) {
191281 AUBIO_ERR("fft: can only create with sizes power of two, requested %d,"
@@ -200,9 +290,10 @@ aubio_fft_t * new_aubio_fft (uint_t winsize) { · 8 unmodified lines
200290 s->ip = AUBIO_ARRAY(int , s->fft_size);
201291 s->w = AUBIO_ARRAY(smpl_t, s->fft_size);
202292 s->ip[0] = 0;
203−#endif /* HAVE_ACCELERATE */
204−#endif /* HAVE_FFTW3 */
293+#endif /* using OOURA */
294+
205295 return s;
296+
206297 beach:
207298 AUBIO_FREE(s);
208299 return NULL;
@@ -210,25 +301,33 @@ beach: · 1 unmodified line
210301
211302 void del_aubio_fft(aubio_fft_t * s) {
212303 /* destroy data */
213− del_fvec(s->compspec);
214304 #ifdef HAVE_FFTW3 // using FFTW3
215305 pthread_mutex_lock(&aubio_fftw_mutex);
216306 fftw_destroy_plan(s->pfw);
217307 fftw_destroy_plan(s->pbw);
218308 fftw_free(s->specdata);
219309 pthread_mutex_unlock(&aubio_fftw_mutex);
220−#else /* HAVE_FFTW3 */
221−#ifdef HAVE_ACCELERATE // using ACCELERATE
310+
311+#elif defined HAVE_ACCELERATE // using ACCELERATE
222312 AUBIO_FREE(s->spec.realp);
223313 AUBIO_FREE(s->spec.imagp);
224− aubio_vDSP_destroy_fftsetup(s->fftSetup);
314+ aubio_vDSP_DFT_DestroySetup(s->fftSetupBwd);
315+ aubio_vDSP_DFT_DestroySetup(s->fftSetupFwd);
316+
317+#elif defined HAVE_INTEL_IPP // using Intel IPP
318+ ippFree(s->memSpec);
319+ ippFree(s->memInit);
320+ ippFree(s->memBuffer);
321+ ippFree(s->complexOut);
322+
225323 #else // using OOURA
226324 AUBIO_FREE(s->w);
227325 AUBIO_FREE(s->ip);
228−#endif /* HAVE_ACCELERATE */
229−#endif /* HAVE_FFTW3 */
230− AUBIO_FREE(s->out);
326+#endif
327+
328+ del_fvec(s->compspec);
231329 AUBIO_FREE(s->in);
330+ AUBIO_FREE(s->out);
232331 AUBIO_FREE(s);
233332 }
234333
@@ -251,6 +350,7 @@ void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compsp · 16 unmodified lines
251350 #else
252351 memcpy(s->in, input->data, s->winsize * sizeof(smpl_t));
253352 #endif /* HAVE_MEMCPY_HACKS */
353+
254354 #ifdef HAVE_FFTW3 // using FFTW3
255355 fftw_execute(s->pfw);
256356 #ifdef HAVE_COMPLEX_H
@@ -265,12 +365,13 @@ void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compsp · 8 unmodified lines
265365 compspec->data[i] = s->specdata[i];
266366 }
267367 #endif /* HAVE_COMPLEX_H */
268−#else /* HAVE_FFTW3 */
269−#ifdef HAVE_ACCELERATE // using ACCELERATE
368+
369+#elif defined HAVE_ACCELERATE // using ACCELERATE
270370 // convert real data to even/odd format used in vDSP
271371 aubio_vDSP_ctoz((aubio_DSPComplex*)s->in, 2, &s->spec, 1, s->fft_size/2);
272372 // compute the FFT
273− aubio_vDSP_fft_zrip(s->fftSetup, &s->spec, 1, s->log2fftsize, FFT_FORWARD);
373+ aubio_vDSP_DFT_Execute(s->fftSetupFwd, s->spec.realp, s->spec.imagp,
374+ s->spec.realp, s->spec.imagp);
274375 // convert from vDSP complex split to [ r0, r1, ..., rN, iN-1, .., i2, i1]
275376 compspec->data[0] = s->spec.realp[0];
276377 compspec->data[s->fft_size / 2] = s->spec.imagp[0];
@@ -281,6 +382,19 @@ void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compsp · 4 unmodified lines
281382 // apply scaling
282383 smpl_t scale = 1./2.;
283384 aubio_vDSP_vsmul(compspec->data, 1, &scale, compspec->data, 1, s->fft_size);
385+
386+#elif defined HAVE_INTEL_IPP // using Intel IPP
387+
388+ // apply fft
389+ aubio_ippsFFTFwd_RToCCS(s->in, (aubio_IppFloat*)s->complexOut, s->fftSpec, s->memBuffer);
390+ // convert complex buffer to [ r0, r1, ..., rN, iN-1, .., i2, i1]
391+ compspec->data[0] = s->complexOut[0].re;
392+ compspec->data[s->fft_size / 2] = s->complexOut[s->fft_size / 2].re;
393+ for (i = 1; i < s->fft_size / 2; i++) {
394+ compspec->data[i] = s->complexOut[i].re;
395+ compspec->data[s->fft_size - i] = s->complexOut[i].im;
396+ }
397+
284398 #else // using OOURA
285399 aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w);
286400 compspec->data[0] = s->in[0];
@@ -289,8 +403,7 @@ void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compsp · 2 unmodified lines
289403 compspec->data[i] = s->in[2 * i];
290404 compspec->data[s->winsize - i] = - s->in[2 * i + 1];
291405 }
292−#endif /* HAVE_ACCELERATE */
293−#endif /* HAVE_FFTW3 */
406+#endif /* using OOURA */
294407 }
295408
296409 void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * output) {
@@ -313,8 +426,8 @@ void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * ou · 16 unmodified lines
313426 for (i = 0; i < output->length; i++) {
314427 output->data[i] = s->out[i]*renorm;
315428 }
316−#else /* HAVE_FFTW3 */
317−#ifdef HAVE_ACCELERATE // using ACCELERATE
429+
430+#elif defined HAVE_ACCELERATE // using ACCELERATE
318431 // convert from real imag [ r0, r1, ..., rN, iN-1, .., i2, i1]
319432 // to vDSP packed format [ r0, rN, r1, i1, ..., rN-1, iN-1 ]
320433 s->out[0] = compspec->data[0];
@@ -326,12 +439,30 @@ void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * ou · 5 unmodified lines
326439 // convert to split complex format used in vDSP
327440 aubio_vDSP_ctoz((aubio_DSPComplex*)s->out, 2, &s->spec, 1, s->fft_size/2);
328441 // compute the FFT
329− aubio_vDSP_fft_zrip(s->fftSetup, &s->spec, 1, s->log2fftsize, FFT_INVERSE);
442+ aubio_vDSP_DFT_Execute(s->fftSetupBwd, s->spec.realp, s->spec.imagp,
443+ s->spec.realp, s->spec.imagp);
330444 // convert result to real output
331445 aubio_vDSP_ztoc(&s->spec, 1, (aubio_DSPComplex*)output->data, 2, s->fft_size/2);
332446 // apply scaling
333447 smpl_t scale = 1.0 / s->winsize;
334448 aubio_vDSP_vsmul(output->data, 1, &scale, output->data, 1, s->fft_size);
449+
450+#elif defined HAVE_INTEL_IPP // using Intel IPP
451+
452+ // convert from real imag [ r0, 0, ..., rN, iN-1, .., i2, i1, iN-1] to complex format
453+ s->complexOut[0].re = compspec->data[0];
454+ s->complexOut[0].im = 0;
455+ s->complexOut[s->fft_size / 2].re = compspec->data[s->fft_size / 2];
456+ s->complexOut[s->fft_size / 2].im = 0.0;
457+ for (i = 1; i < s->fft_size / 2; i++) {
458+ s->complexOut[i].re = compspec->data[i];
459+ s->complexOut[i].im = compspec->data[s->fft_size - i];
460+ }
461+ // apply fft
462+ aubio_ippsFFTInv_CCSToR((const aubio_IppFloat *)s->complexOut, output->data, s->fftSpec, s->memBuffer);
463+ // apply scaling
464+ aubio_ippsMulC(output->data, 1.0 / s->winsize, output->data, s->fft_size);
465+
335466 #else // using OOURA
336467 smpl_t scale = 2.0 / s->winsize;
337468 s->out[0] = compspec->data[0];
@@ -344,8 +475,7 @@ void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * ou · 6 unmodified lines
344475 for (i=0; i < s->winsize; i++) {
345476 output->data[i] = s->out[i] * scale;
346477 }
347−#endif /* HAVE_ACCELERATE */
348−#endif /* HAVE_FFTW3 */
478+#endif
349479 }
350480
351481 void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum) {
@@ -365,15 +495,42 @@ void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum) { · 13 unmodified lines
365495 } else {
366496 spectrum->phas[0] = 0.;
367497 }
498+#if defined(HAVE_INTEL_IPP)
499+ // convert from real imag [ r0, r1, ..., rN, iN-1, ..., i2, i1, i0]
500+ // to [ r0, r1, ..., rN, i0, i1, i2, ..., iN-1]
501+ for (i = 1; i < spectrum->length / 2; i++) {
502+ ELEM_SWAP(compspec->data[compspec->length - i],
503+ compspec->data[spectrum->length + i - 1]);
504+ }
505+ aubio_ippsAtan2(compspec->data + spectrum->length,
506+ compspec->data + 1, spectrum->phas + 1, spectrum->length - 1);
507+ // revert the imaginary part back again
508+ for (i = 1; i < spectrum->length / 2; i++) {
509+ ELEM_SWAP(compspec->data[spectrum->length + i - 1],
510+ compspec->data[compspec->length - i]);
511+ }
512+#else
368513 for (i=1; i < spectrum->length - 1; i++) {
369514 spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i],
370515 compspec->data[i]);
371516 }
372− if (compspec->data[compspec->length/2] < 0) {
373− spectrum->phas[spectrum->length - 1] = PI;
517+#endif
518+#ifdef HAVE_FFTW3
519+ // for even length only, make sure last element is 0 or PI
520+ if (2 * (compspec->length / 2) == compspec->length) {
521+#endif
522+ if (compspec->data[compspec->length/2] < 0) {
523+ spectrum->phas[spectrum->length - 1] = PI;
524+ } else {
525+ spectrum->phas[spectrum->length - 1] = 0.;
526+ }
527+#ifdef HAVE_FFTW3
374528 } else {
375− spectrum->phas[spectrum->length - 1] = 0.;
529+ i = spectrum->length - 1;
530+ spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i],
531+ compspec->data[i]);
376532 }
533+#endif
377534 }
378535
379536 void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum) {
@@ -383,8 +540,19 @@ void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum) { · 3 unmodified lines
383540 spectrum->norm[i] = SQRT(SQR(compspec->data[i])
384541 + SQR(compspec->data[compspec->length - i]) );
385542 }
386− spectrum->norm[spectrum->length-1] =
387− ABS(compspec->data[compspec->length/2]);
543+#ifdef HAVE_FFTW3
544+ // for even length, make sure last element is > 0
545+ if (2 * (compspec->length / 2) == compspec->length) {
546+#endif
547+ spectrum->norm[spectrum->length-1] =
548+ ABS(compspec->data[compspec->length/2]);
549+#ifdef HAVE_FFTW3
550+ } else {
551+ i = spectrum->length - 1;
552+ spectrum->norm[i] = SQRT(SQR(compspec->data[i])
553+ + SQR(compspec->data[compspec->length - i]) );
554+ }
555+#endif
388556 }
389557
390558 void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec) {
src/spectral/filterbank.c+48−0
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 #include "fvec.h"
2424 #include "fmat.h"
2525 #include "cvec.h"
26+#include "vecutils.h"
2627 #include "spectral/filterbank.h"
2728 #include "mathutils.h"
2829
@@ -32,6 +33,8 @@ struct _aubio_filterbank_t · 3 unmodified lines
3233 uint_t win_s;
3334 uint_t n_filters;
3435 fmat_t *filters;
36+ smpl_t norm;
37+ smpl_t power;
3538 };
3639
3740 aubio_filterbank_t *
@@ -39,13 +42,29 @@ new_aubio_filterbank (uint_t n_filters, uint_t win_s) · 1 unmodified line
3942 {
4043 /* allocate space for filterbank object */
4144 aubio_filterbank_t *fb = AUBIO_NEW (aubio_filterbank_t);
45+
46+ if ((sint_t)n_filters <= 0) {
47+ AUBIO_ERR("filterbank: n_filters should be > 0, got %d\n", n_filters);
48+ goto fail;
49+ }
50+ if ((sint_t)win_s <= 0) {
51+ AUBIO_ERR("filterbank: win_s should be > 0, got %d\n", win_s);
52+ goto fail;
53+ }
4254 fb->win_s = win_s;
4355 fb->n_filters = n_filters;
4456
4557 /* allocate filter tables, a matrix of length win_s and of height n_filters */
4658 fb->filters = new_fmat (n_filters, win_s / 2 + 1);
4759
60+ fb->norm = 1;
61+
62+ fb->power = 1;
63+
4864 return fb;
65+fail:
66+ AUBIO_FREE (fb);
67+ return NULL;
4968 }
5069
5170 void
@@ -67,6 +86,8 @@ aubio_filterbank_do (aubio_filterbank_t * f, const cvec_t * in, fvec_t * out) · 15 unmodified lines
6786 tmp.length = in->length;
6887 tmp.data = in->norm;
6988
89+ if (f->power != 1.) fvec_pow(&tmp, f->power);
90+
7091 fmat_vecmul(f->filters, &tmp, out);
7192
7293 return;
@@ -84,3 +105,30 @@ aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filter_coeff · 11 unmodified lines
84105 fmat_copy(filter_coeffs, f->filters);
85106 return 0;
86107 }
108+
109+uint_t
110+aubio_filterbank_set_norm (aubio_filterbank_t *f, smpl_t norm)
111+{
112+ if (norm != 0 && norm != 1) return AUBIO_FAIL;
113+ f->norm = norm;
114+ return AUBIO_OK;
115+}
116+
117+smpl_t
118+aubio_filterbank_get_norm (aubio_filterbank_t *f)
119+{
120+ return f->norm;
121+}
122+
123+uint_t
124+aubio_filterbank_set_power (aubio_filterbank_t *f, smpl_t power)
125+{
126+ f->power = power;
127+ return AUBIO_OK;
128+}
129+
130+smpl_t
131+aubio_filterbank_get_power (aubio_filterbank_t *f)
132+{
133+ return f->power;
134+}
src/spectral/filterbank.h+41−0
@@ -83,6 +83,47 @@ fmat_t *aubio_filterbank_get_coeffs (const aubio_filterbank_t * f); · 82 unmodified lines
8383 */
8484 uint_t aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filters);
8585
86+/** set norm parameter
87+
88+ \param f filterbank object, as returned by new_aubio_filterbank()
89+ \param norm `1` to norm the filters, `0` otherwise.
90+
91+ If set to `0`, the filters will not be normalized. If set to `1`,
92+ each filter will be normalized to one. Defaults to `1`.
93+
94+ This function should be called *before* setting the filters with one of
95+ aubio_filterbank_set_triangle_bands(), aubio_filterbank_set_mel_coeffs(),
96+ aubio_filterbank_set_mel_coeffs_htk(), or
97+ aubio_filterbank_set_mel_coeffs_slaney().
98+
99+ */
100+uint_t aubio_filterbank_set_norm (aubio_filterbank_t *f, smpl_t norm);
101+
102+/** get norm parameter
103+
104+ \param f filterbank object, as returned by new_aubio_filterbank()
105+ \returns `1` if norm is set, `0` otherwise. Defaults to `1`.
106+
107+ */
108+smpl_t aubio_filterbank_get_norm (aubio_filterbank_t *f);
109+
110+/** set power parameter
111+
112+ \param f filterbank object, as returned by new_aubio_filterbank()
113+ \param power Raise norm of the input spectrum norm to this power before
114+ computing filterbank. Defaults to `1`.
115+
116+ */
117+uint_t aubio_filterbank_set_power (aubio_filterbank_t *f, smpl_t power);
118+
119+/** get power parameter
120+
121+ \param f filterbank object, as returned by new_aubio_filterbank()
122+ \return current power parameter. Defaults to `1`.
123+
124+ */
125+smpl_t aubio_filterbank_get_power (aubio_filterbank_t *f);
126+
86127 #ifdef __cplusplus
87128 }
88129 #endif
src/spectral/filterbank_mel.c+126−35
@@ -54,9 +54,21 @@ aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb, · 53 unmodified lines
5454 n_filters, freqs->length - 2);
5555 }
5656
57− if (freqs->data[freqs->length - 1] > samplerate / 2) {
58− AUBIO_WRN ("Nyquist frequency is %fHz, but highest frequency band ends at \
59−%fHz\n", samplerate / 2, freqs->data[freqs->length - 1]);
57+ for (fn = 0; fn < freqs->length; fn++) {
58+ if (freqs->data[fn] < 0) {
59+ AUBIO_ERR("filterbank_mel: freqs must contain only positive values.\n");
60+ return AUBIO_FAIL;
61+ } else if (freqs->data[fn] > samplerate / 2) {
62+ AUBIO_WRN("filterbank_mel: freqs should contain only "
63+ "values < samplerate / 2.\n");
64+ } else if (fn > 0 && freqs->data[fn] < freqs->data[fn-1]) {
65+ AUBIO_ERR("filterbank_mel: freqs should be a list of frequencies "
66+ "sorted from low to high, but freq[%d] < freq[%d-1]\n", fn, fn);
67+ return AUBIO_FAIL;
68+ } else if (fn > 0 && freqs->data[fn] == freqs->data[fn-1]) {
69+ AUBIO_WRN("filterbank_mel: set_triangle_bands received a list "
70+ "with twice the frequency %f\n", freqs->data[fn]);
71+ }
6072 }
6173
6274 /* convenience reference to lower/center/upper frequency for each triangle */

194 more lines aren’t shown here.

src/spectral/filterbank_mel.h+51−4

This diff is large: its 68 lines aren’t shown here.

src/spectral/mfcc.c+90−29

This diff is large: its 177 lines aren’t shown here.

src/spectral/mfcc.h+96−2

This diff is large: its 113 lines aren’t shown here.

src/spectral/ooura_fft8g.c+11−10

This diff is large: its 64 lines aren’t shown here.

src/spectral/phasevoc.c+15−1

This diff is large: its 34 lines aren’t shown here.

src/spectral/phasevoc.h+11−0

This diff is large: its 25 lines aren’t shown here.

src/spectral/specdesc.c+30−1

This diff is large: its 90 lines aren’t shown here.

src/spectral/specdesc.h+12−2

This diff is large: its 28 lines aren’t shown here.

src/synth/sampler.c+0−1

This diff is large: its 8 lines aren’t shown here.

src/synth/wavetable.c+9−2

This diff is large: its 32 lines aren’t shown here.

src/synth/wavetable.h+2−0

This diff is large: its 9 lines aren’t shown here.

src/tempo/beattracking.h+1−1

This diff is large: its 9 lines aren’t shown here.

src/tempo/tempo.c+30−17

This diff is large: its 94 lines aren’t shown here.

src/tempo/tempo.h+2−2

This diff is large: its 11 lines aren’t shown here.

src/temporal/biquad.c+1−1

This diff is large: its 9 lines aren’t shown here.

src/temporal/resampler.c+4−2

This diff is large: its 19 lines aren’t shown here.

src/utils/hist.c+3−0

This diff is large: its 10 lines aren’t shown here.

src/utils/log.c+1−2

This diff is large: its 17 lines aren’t shown here.

src/utils/log.h+2−1

This diff is large: its 12 lines aren’t shown here.

src/utils/parameter.c+0−1

This diff is large: its 8 lines aren’t shown here.

src/utils/windll.c+3−3

This diff is large: its 21 lines aren’t shown here.

src/vecutils.c+0−1

This diff is large: its 5 lines aren’t shown here.

src/wscript_build+14−3

This diff is large: its 46 lines aren’t shown here.

tests/create_tests_source.py+42−0

This diff is large: its 43 lines aren’t shown here.

tests/src/io/test-sink-multi.c+4−5

This diff is large: its 22 lines aren’t shown here.

tests/src/io/test-sink.c+2−2

This diff is large: its 11 lines aren’t shown here.

tests/src/io/test-sink_apple_audio-multi.c+5−5

This diff is large: its 30 lines aren’t shown here.

tests/src/io/test-sink_apple_audio.c+3−3

This diff is large: its 20 lines aren’t shown here.

tests/src/io/test-sink_sndfile-multi.c+5−6

This diff is large: its 32 lines aren’t shown here.

tests/src/io/test-sink_sndfile.c+3−4

This diff is large: its 27 lines aren’t shown here.

tests/src/io/test-sink_wavwrite-multi.c+5−5

This diff is large: its 30 lines aren’t shown here.

tests/src/io/test-sink_wavwrite.c+3−3

This diff is large: its 20 lines aren’t shown here.

tests/src/io/test-source.c+4−4

This diff is large: its 22 lines aren’t shown here.

tests/src/io/test-source_apple_audio.c+5−5

This diff is large: its 31 lines aren’t shown here.

tests/src/io/test-source_avcodec.c+5−5

This diff is large: its 31 lines aren’t shown here.

tests/src/io/test-source_multi.c+2−2

This diff is large: its 11 lines aren’t shown here.

tests/src/io/test-source_seek.c+4−4

This diff is large: its 22 lines aren’t shown here.

tests/src/io/test-source_sndfile.c+5−5

This diff is large: its 31 lines aren’t shown here.

tests/src/io/test-source_wavread.c+5−6

This diff is large: its 38 lines aren’t shown here.

tests/src/notes/test-notes.c+24−0

This diff is large: its 25 lines aren’t shown here.

tests/src/onset/test-onset.c+42−4

This diff is large: its 69 lines aren’t shown here.

tests/src/pitch/test-pitch.c+37−0

This diff is large: its 43 lines aren’t shown here.

tests/src/spectral/test-awhitening.c+102−0

This diff is large: its 103 lines aren’t shown here.

tests/src/spectral/test-dct.c+49−0

This diff is large: its 50 lines aren’t shown here.

tests/src/spectral/test-filterbank.c+12−0

This diff is large: its 22 lines aren’t shown here.

tests/src/spectral/test-mfcc.c+8−3

This diff is large: its 22 lines aren’t shown here.

tests/src/spectral/test-phasevoc.c+8−1

This diff is large: its 23 lines aren’t shown here.

tests/src/spectral/test-tss.c+4−0

This diff is large: its 11 lines aren’t shown here.

tests/src/synth/test-sampler.c+14−5

This diff is large: its 37 lines aren’t shown here.

tests/src/synth/test-wavetable.c+4−4

This diff is large: its 22 lines aren’t shown here.

tests/src/tempo/test-tempo.c+78−8

This diff is large: its 130 lines aren’t shown here.

tests/src/temporal/test-filter.c+19−0

This diff is large: its 33 lines aren’t shown here.

tests/src/test-mathutils.c+2−1

This diff is large: its 16 lines aren’t shown here.

tests/src/utils/test-hist.c+1−0

This diff is large: its 8 lines aren’t shown here.

tests/src/utils/test-log.c+17−13

This diff is large: its 58 lines aren’t shown here.

tests/utils_tests.h+138−2

This diff is large: its 153 lines aren’t shown here.

tests/wscript_build+19−2

This diff is large: its 33 lines aren’t shown here.

this_version.py+107−0

This diff is large: its 108 lines aren’t shown here.

waf_gensyms.py+40−0

This diff is large: its 41 lines aren’t shown here.

wscript+297−77

This diff is large: its 560 lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t