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
7 7
8 # pre-installed python version, see:8 # pre-installed python version, see:
9 # http://www.appveyor.com/docs/installed-software#python9 # http://www.appveyor.com/docs/installed-software#python
10 - PYTHON: "C:\\Python27"10 - PYTHONDIR: C:\Python27
11 PYTHON_VERSION: "2.7.x"11 PYTHON_VERSION: 2.7.x
12 PYTHON_ARCH: "32"12 PYTHON_ARCH: 32
13 13
14 - PYTHON: "C:\\Python27-x64"14 - PYTHONDIR: C:\Python27-x64
15 PYTHON_VERSION: "2.7.x"15 PYTHON_VERSION: 2.7.x
16 PYTHON_ARCH: "64"16 PYTHON_ARCH: 64
17 17
18 - PYTHON: "C:\\Python34"18 - PYTHONDIR: C:\Python35
19 PYTHON_VERSION: "3.4.x"19 PYTHON_VERSION: 3.5.x
20 PYTHON_ARCH: "32"20 PYTHON_ARCH: 32
21 21
22 - PYTHON: "C:\\Python34-x64"22 - PYTHONDIR: C:\Python35-x64
23 PYTHON_VERSION: "3.4.x"23 PYTHON_VERSION: 3.5.x
24 PYTHON_ARCH: "64"24 PYTHON_ARCH: 64
25 25
26 - PYTHON: "C:\\Python35"26 - PYTHONDIR: C:\Python36
27 PYTHON_VERSION: "3.5.x"27 PYTHON_VERSION: 3.6.x
28 PYTHON_ARCH: "32"28 PYTHON_ARCH: 32
29 29
30 - PYTHON: "C:\\Python35-x64"30 - PYTHONDIR: C:\Python36-x64
31 PYTHON_VERSION: "3.5.x"31 PYTHON_VERSION: 3.6.x
32 PYTHON_ARCH: "64"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"
35 33
36install: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
37 41
42install:
38 - ECHO "Installed SDKs:"43 - ECHO "Installed SDKs:"
39 - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""44 - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
40 45
46 - "SET PATH=%PYTHONDIR%;%PYTHONDIR%\\Scripts;%PATH%"
47
41 # Check that we have the expected version and architecture for Python48 # Check that we have the expected version and architecture for Python
42 - "%PYTHON%\\python.exe --version"49 - "python --version"
43 - "%PYTHON%\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\""50 - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
44 51
45 # We need wheel installed to build wheels52 - "python -m pip install --disable-pip-version-check --user --upgrade pip"
46 - "%PYTHON%\\python.exe -m pip install wheel"53 - "python -m pip install --upgrade setuptools"
47 54
48 - "SET PATH=%PATH_EXTRAS%;%PYTHON%;%PYTHON%\\Scripts;%PATH%"55 # We need wheel installed to build wheels
56 - "python -m pip install wheel"
49 57
50 - "pip install --disable-pip-version-check --user --upgrade pip"58 - "pip install -r requirements.txt"
51 - "pip install --upgrade setuptools"
52 59
53before_build:60before_build:
54 - curl -fsS -o waf https://waf.io/waf-1.8.2261 - "bash scripts/get_waf.sh"
55 - curl -fsS -o waf.bat https://raw.githubusercontent.com/waf-project/waf/master/utils/waf.bat
56 62
57build_script:63build_script:
58 # build python module without using libaubio64 # also build libaubio with waf
59 - "pip install -r requirements.txt"65 - python waf configure build install --verbose --msvc_version="msvc 14.0"
60 - "python setup.py build"66 # clean before building python package
61 - "pip install ."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
76test_script:
62 - "python python\\demos\\demo_create_test_sounds.py"77 - "python python\\demos\\demo_create_test_sounds.py"
63 - "nose2 --verbose"78 - "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 @@
1apt-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
7pip-install: &pip-install
8 name: Install pip dependencies
9 command: |
10 pip install --user -r requirements.txt
11
12build-wheel: &build-wheel
13 name: Build python wheel
14 command: |
15 pip wheel -v -v -v --wheel-dir=dist .
16
17install-wheel: &install-wheel
18 name: Install python wheel
19 command: |
20 pip install --user dist/aubio*.whl
21
22test-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
28test-nose2-nosounds: &test-nose2-nosounds
29 name: Test python wheel
30 command: |
31 PATH=/home/circleci/.local/bin:$PATH nose2 -v
32
33uninstall-wheel: &uninstall-wheel
34 name: Uninstall python wheel
35 command: |
36 pip show -f aubio
37 pip uninstall --verbose --yes aubio
38
39version: 2
40jobs:
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
96workflows:
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]
2branch = True
3source = aubio
.gitignore+7−0
@@ -30,6 +30,7 @@ build/ · 29 unmodified lines
30# doxygen30# doxygen
31doc/web/31doc/web/
32doc/full/32doc/full/
33doc/_build/
33 34
34python/gen35python/gen
35python/dist36python/dist
@@ -37,9 +38,15 @@ python/MANIFEST · 1 unmodified line
37python/*.db38python/*.db
38python/*.wav39python/*.wav
39 40
41pip-delete-this-directory.txt
42
40aubio-*.tar.bz243aubio-*.tar.bz2
41aubio-*.zip44aubio-*.zip
45dist/*.tar.gz
46dist/*.whl
42 47
43# test sounds48# test sounds
44python/tests/sounds49python/tests/sounds
45aubio.egg-info50aubio.egg-info
51.eggs
52.cache
.travis.yml+59−42
@@ -2,67 +2,59 @@ language: python · 1 unmodified line
2 2
3matrix:3matrix:
4 include:4 include:
5 - python: 2.75 - python: 3.5
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
14 os: linux6 os: linux
15 compiler: gcc7 compiler: gcc
16 env: ARCH=x86_64
17 - python: 3.48 - python: 3.4
18 os: linux9 os: linux
19 compiler: gcc10 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
29 - python: 2.711 - python: 2.7
30 os: linux12 os: linux
31 compiler: gcc13 compiler: gcc
32 env: ARCH=x86_64 HAVE_DOUBLE=1 WAFOPTS=--enable-fftw314 - python: 3.5
33 - python: 2.7
34 os: linux15 os: linux
35 compiler: gcc16 compiler: gcc
36 env: ARCH=i386 HAVE_DOUBLE=117 env: CFLAGS="-Os" WAFOPTS="--disable-samplerate --disable-sndfile"
37 - python: 3.418 - python: 3.4
38 os: linux19 os: linux
39 compiler: gcc20 compiler: gcc
40 env: ARCH=x86_64 HAVE_DOUBLE=121 env: HAVE_AUBIO_DOUBLE=1 CFLAGS="-O3" WAFOPTS="--enable-fftw3"
41 - python: 3.422 - python: 2.7
42 os: linux23 os: linux
43 compiler: gcc24 compiler: gcc
44 env: ARCH=i386 HAVE_DOUBLE=125 env: CFLAGS="`dpkg-buildflags --get CFLAGS`" LDFLAGS="`dpkg-buildflags --get LDFLAGS`"
26 - language: C
27 os: osx
28 compiler: clang
45 - language: C29 - language: C
46 os: osx30 os: osx
47 compiler: clang31 compiler: clang
48 env: ARCH=x86_64 HAVE_DOUBLE=132 env: CFLAGS="-Os" HAVE_AUBIO_DOUBLE=1 WAFOPTS="--disable-accelerate"
49 - language: C33 - language: C
50 os: osx34 os: osx
51 compiler: clang35 compiler: clang
52 env: ARCH=i386 HAVE_DOUBLE=136 env: WAFOPTS="--enable-fat --disable-avcodec --disable-sndfile --disable-samplerate --disable-rubberband"
53 - language: C37 - language: C
54 os: osx38 os: osx
55 compiler: clang39 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
57 - language: C41 - language: C
58 os: osx42 os: osx
59 compiler: clang43 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
47dist: trusty
48sudo: required
61 49
62addons:50addons:
63 apt:51 apt:
64 packages:52 packages:
65 - bzip253 - bzip2
54 - libavcodec-dev
55 - libavformat-dev
56 - libavresample-dev
57 - libavutil-dev
66 - libsndfile1-dev58 - libsndfile1-dev
67 - libsamplerate-dev59 - libsamplerate-dev
68 - libjack-dev60 - libjack-dev
@@ -70,33 +62,58 @@ addons: · 1 unmodified line
70 - libfftw3-dev62 - libfftw3-dev
71 - librubberband-dev63 - librubberband-dev
72 - sox64 - sox
65 - lcov
66 homebrew:
67 packages:
68 - sox
69 - ffmpeg
70 - libsndfile
71 - libsamplerate
72 - rubberband
73 - lcov
74 #update: true
73 75
74before_install:76before_install:
75 - |77 - |
76 if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then78 if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
77 brew update
78 brew install sox libsamplerate libsndfile rubberband
79 export PATH="$HOME/Library/Python/2.7/bin/:$PATH"79 export PATH="$HOME/Library/Python/2.7/bin/:$PATH"
80 fi;80 fi;
81 81
82
83install:82install:
84 - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry pip install nose2; fi83 - |
85 - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_retry pip install --user nose2; fi84 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
86 91
87script:92script:
88 - make create_test_sounds93 - make create_test_sounds
89 - make build94 - |
90 - make build_python95 if [[ -z "$AUBIO_NOTESTS" ]]; then
91 - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make test_python; fi96 make test_lib_python_clean
92 - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make test_python_osx; fi97 make coverage
93 - make clean_python98 else
94 - make clean99 make test_lib_only_clean
95 - make distcheck100 fi;
96 - make test_pure_python101
102after_success:
103 - |
104 if [[ -z "$AUBIO_NOTESTS" ]]; then
105 # upload to codecov
106 bash <(curl -s https://codecov.io/bash)
107 fi
97 108
98notifications:109notifications:
99 irc:110 irc:
100 channels:111 channels:
101 - "irc.freenode.org#aubio"112 - "irc.freenode.org#aubio"
102 use_notice: true113 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 @@
12018-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
772018-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
1642017-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
2312017-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
2902017-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
12016-08-16 Paul Brossier <piem@aubio.org>5092016-08-16 Paul Brossier <piem@aubio.org>
2 510
3 [ Interface ]511 [ Interface ]
MANIFEST.in+8−9
@@ -1,7 +1,10 @@
1include AUTHORS COPYING README.md VERSION ChangeLog1include AUTHORS COPYING README.md VERSION ChangeLog
2include python/README.md2include python/README.md
3include Makefile wscript */wscript_build3include this_version.py
4include waf_gensyms.py
4include waf5include waf
6recursive-include waflib *.py
7include Makefile wscript */wscript_build
5include aubio.pc.in8include aubio.pc.in
6include nose2.cfg9include nose2.cfg
7include requirements.txt10include requirements.txt
@@ -10,16 +13,12 @@ include src/*/*.c src/*/*.h · 2 unmodified lines
10include examples/*.c examples/*.h13include examples/*.c examples/*.h
11include tests/*.h tests/*/*.c tests/*/*/*.c14include tests/*.h tests/*/*.c tests/*/*/*.c
12include python/ext/*.h15include python/ext/*.h
13include python/__init__.py16recursive-include python *.py
14include python/lib/__init__.py17include python/README.md
15include python/lib/moresetuptools.py
16include python/lib/gen_external.py
17include python/lib/gen_code.py
18include python/tests/run_all_tests18include python/tests/run_all_tests
19include python/tests/*.py19include python/tests/eval_pitch
20include python/demos/*.py
21include python/tests/*.expected20include python/tests/*.expected
22include doc/*.txt doc/*.rst doc/*.cfg doc/Makefile doc/make.bat doc/conf.py21include doc/*.txt doc/*.rst doc/*.cfg doc/Makefile doc/make.bat doc/conf.py
22exclude doc/full.cfg
23include scripts/* scripts/apple/Info.plist scripts/apple/Modules/module.modulemap23include scripts/* scripts/apple/Info.plist scripts/apple/Modules/module.modulemap
24exclude python/gen/*24exclude python/gen/*
25exclude 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
1WAFCMD=python waf12WAFCMD=python waf
2WAFURL=https://waf.io/waf-1.8.2213
14#WAFOPTS:=
15# turn on verbose mode
16WAFOPTS += --verbose
17# build wafopts
18WAFOPTS += --destdir $(DESTDIR)
19# multiple jobs
20WAFOPTS += --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
23WAFOPTS += $(shell [ -z $(HAVE_AUBIO_DOUBLE) ] || echo --enable-double )
24
25PIPOPTS += --verbose
26
27DESTDIR:=$(PWD)/build/dist
28PYDESTDIR:=$(PWD)/build/pydist
29
30# default install locations
31PREFIX?=/usr/local
32EXEC_PREFIX?=$(PREFIX)
33LIBDIR?=$(PREFIX)/lib
34INCLUDEDIR?=$(PREFIX)/include
35DATAROOTDIR?=$(PREFIX)/share
36MANDIR?=$(DATAROOTDIR)/man
37
38# default nose2 command
39NOSE2?=nose2 -N 4 --verbose
3 40
4SOX=sox41SOX=sox
5 42
6ENABLE_DOUBLE := $(shell [ -z $(HAVE_DOUBLE) ] || echo --enable-double )
7TESTSOUNDS := python/tests/sounds43TESTSOUNDS := python/tests/sounds
8 44
45LCOVOPTS += --rc lcov_branch_coverage=1
46
9all: build47all: build
10 48
11checkwaf:49checkwaf:
12 @[ -f waf ] || make getwaf50 @[ -f waf ] || make getwaf
13 51
14getwaf:52getwaf:
15 @./scripts/get_waf.sh53 ./scripts/get_waf.sh
54
55expandwaf: 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
16 61
17expandwaf:62cleanwaf:
18 @[ -d wafilb ] || rm -fr waflib63 rm -rf waf waflib .waf*
19 @$(WAFCMD) --help > /dev/null
20 @mv .waf*/waflib . && rm -fr .waf*
21 @sed '/^#==>$$/,$$d' waf > waf2 && mv waf2 waf
22 @chmod +x waf
23 64
24configure: checkwaf65configure: checkwaf
25 $(WAFCMD) configure $(WAFOPTS) $(ENABLE_DOUBLE)66 $(WAFCMD) configure $(WAFOPTS)
26 67
27build: configure68build: configure
28 $(WAFCMD) build $(WAFOPTS)69 $(WAFCMD) build $(WAFOPTS)
29 70
71install:
72 # install
73 $(WAFCMD) install $(WAFOPTS)
74
75list_installed:
76 find $(DESTDIR) -ls | sed 's|$(DESTDIR)|/«destdir»|'
77
78list_installed_python:
79 pip show -f aubio
80
81list_all_installed: list_installed list_installed_python
82
83uninstall:
84 # uninstall
85 $(WAFCMD) uninstall $(WAFOPTS)
86
87delete_install:
88 rm -rf $(PWD)/dist/test
89
30build_python:90build_python:
31 python ./setup.py generate $(ENABLE_DOUBLE) build91 # build python-aubio, using locally built libaubio if found
92 python ./setup.py build
93
94build_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
104deps_python:
105 # install or upgrade python requirements
106 pip install $(PIPOPTS) --requirement requirements.txt
107
108# use pip or distutils?
109install_python: install_python_with_pip
110uninstall_python: uninstall_python_with_pip
111#install_python: install_python_with_distutils
112#uninstall_python: uninstall_python_with_distutils
32 113
33test_python: export LD_LIBRARY_PATH=$(PWD)/build/src114install_python_with_pip:
34test_python:115 # install package
35 pip install -v -r requirements.txt116 pip install $(PIPOPTS) .
36 pip install -v .
37 nose2 --verbose
38 pip uninstall -y -v aubio
39 117
40test_python_osx:118uninstall_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
123install_python_with_distutils:
124 ./setup.py install $(PIPOPTS) $(DISTUTILSOPTS)
125
126uninstall_python_with_distutils:
127 #./setup.py uninstall
128 [ -d $(PYDESTDIR)/$(LIBDIR) ] && echo Warning: did not clean $(PYDESTDIR)/$(LIBDIR) || true
129
130force_uninstall_python:
131 # ignore failure if not installed
132 -make uninstall_python
133
134local_dylib:
135 # DYLD_LIBRARY_PATH is no more on mac os
41 # create links from ~/lib/lib* to build/src/lib*136 # 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 ) || true137 [ -f $(PWD)/build/src/libaubio.[0-9].dylib ] && ( mkdir -p ~/lib && cp -prv build/src/libaubio.[0-9].dylib ~/lib ) || true
43 # then run the tests138
44 pip install --user -v -r requirements.txt139test_python: export LD_LIBRARY_PATH=$(DESTDIR)/$(LIBDIR)
45 pip install --user -v .140test_python: export PYTHONPATH=$(PYDESTDIR)/$(LIBDIR)
46 nose2 --verbose141test_python: local_dylib
47 pip uninstall -y -v aubio142 # run test with installed package
143 # ./python/tests/run_all_tests --verbose
144 # run with nose2, multiple processes
145 $(NOSE2)
48 146
49clean_python:147clean_python:
50 ./setup.py clean148 ./setup.py clean
51 149
52test_pure_python:150check_clean_python:
53 -pip uninstall -v -y aubio151 # check cleaning a second time works
54 -rm -rf build/ python/gen/152 make clean_python
55 -rm -f dist/*.egg153 make clean_python
56 -pip install -v -r requirements.txt154
57 CFLAGS=-Os python setup.py bdist_egg155clean: checkwaf
58 [ "$(TRAVIS_OS_NAME)" == "osx" ] && easy_install --user dist/*.egg || \156 # optionnaly clean before build
59 easy_install dist/*.egg157 -$(WAFCMD) clean
60 nose2 -N 4158 # remove possible left overs
61 pip uninstall -v -y aubio159 -rm -rf doc/_build
62 160
63test_pure_python_wheel:161check_clean:
64 -pip uninstall -v -y aubio162 # check cleaning after build works
65 -rm -rf build/ python/gen/163 $(WAFCMD) clean
66 -rm -f dist/*.whl164 # check cleaning a second time works
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
74build_python3:
75 python3 ./setup.py generate $(ENABLE_DOUBLE) build
76
77clean_python3:
78 python3 ./setup.py clean
79
80clean:
81 $(WAFCMD) clean165 $(WAFCMD) clean
82 166
167distclean:
168 $(WAFCMD) distclean
169 -rm -rf doc/_build/
170 -rm -rf doc/web/
171
172check_distclean:
173 make distclean
174
83distcheck: checkwaf175distcheck: checkwaf
84 $(WAFCMD) distcheck $(WAFOPTS) $(ENABLE_DOUBLE)176 $(WAFCMD) distcheck $(WAFOPTS)
85 177
86help:178help:
87 $(WAFCMD) --help179 $(WAFCMD) --help
@@ -89,8 +181,113 @@ help: · 1 unmodified line
89create_test_sounds:181create_test_sounds:
90 -[ -z `which $(SOX)` ] && ( echo $(SOX) could not be found) || true182 -[ -z `which $(SOX)` ] && ( echo $(SOX) could not be found) || true
91 -mkdir -p $(TESTSOUNDS)183 -mkdir -p $(TESTSOUNDS)
92 -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_1f_silence.wav" synth 1s silence 0184 -$(SOX) -r 44100 -b 16 -n "$(TESTSOUNDS)/44100Hz_1f_silence.wav" trim 0 1s
93 -$(SOX) -r 22050 -b 16 -n "$(TESTSOUNDS)/22050Hz_5s_brownnoise.wav" synth 5 brownnoise vol 0.9185 -$(SOX) -r 22050 -b 16 -n "$(TESTSOUNDS)/22050Hz_5s_brownnoise.wav" synth 5 brownnoise vol 0.9
94 -$(SOX) -r 32000 -b 16 -n "$(TESTSOUNDS)/32000Hz_127f_sine440.wav" synth 127s sine 440 vol 0.9186 -$(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.9187 -$(SOX) -r 8000 -b 16 -n "$(TESTSOUNDS)/8000Hz_30s_silence.wav" trim 0 30
96 -$(SOX) -r 48000 -b 32 -n "$(TESTSOUNDS)/48000Hz_60s_sweep.wav" synth 60 sine 100-20000 vol 0.9188 -$(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
193test_lib_only: clean distclean configure build install list_installed
194# additionally, clean after a fresh build
195test_lib_only_clean: test_lib_only uninstall check_clean check_distclean
196
197# build libaubio, build and test python-aubio against it
198test_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
205test_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
212test_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
221test_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
228test_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
235test_python_only_clean: test_python_only \
236 uninstall_python \
237 check_clean_python
238
239coverage_cycle: coverage_zero_counters coverage_report
240
241coverage_zero_counters:
242 lcov --zerocounters --directory .
243
244coverage: export CFLAGS=--coverage
245coverage: export LDFLAGS=--coverage
246coverage: export PYTHONPATH=$(PWD)/python/lib
247coverage: export LD_LIBRARY_PATH=$(PWD)/build/src
248coverage: 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
268coverage_report: export WAFOPTS += --disable-docs
269coverage_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
279sphinx: configure
280 $(WAFCMD) sphinx $(WAFOPTS)
281
282doxygen: configure
283 $(WAFCMD) doxygen $(WAFOPTS)
284
285manpages: configure
286 $(WAFCMD) manpages $(WAFOPTS)
287
288html: doxygen sphinx
289
290docs: html manpages
291
292dist: distclean expandwaf
293 $(WAFCMD) dist
README.md+49−114
@@ -1,5 +1,13 @@
1aubio library1aubio
2=============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)
3 11
4aubio is a library to label music and sounds. It listens to audio signals and12aubio is a library to label music and sounds. It listens to audio signals and
5attempts to detect events. For instance, when a drum is hit, at which frequency13attempts 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
20 - digital filters (low pass, high pass, and more)28 - digital filters (low pass, high pass, and more)
21 - spectral filtering29 - spectral filtering
22 - transient/steady-state separation30 - transient/steady-state separation
23 - sound file and audio devices read and write access31 - sound file read and write access
24 - various mathematics utilities for music applications32 - various mathematics utilities for music applications
25 33
26The name aubio comes from _audio_ with a typo: some errors are likely to be34The 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
29Python module37Python module
30-------------38-------------
31 39
32A python module to access the library functions is also provided. Please see40A python module for aubio is provided. For more information on how to use it,
33the file [`python/README.md`](python/README.md) for more information on how to41please see the file [`python/README.md`](python/README.md) and the
34use it.42[manual](https://aubio.org/manual/latest/) .
43
44Tools
45-----
35 46
36Examples tools47The python module comes with the following command line tools:
37--------------48
49 - `aubio` extracts informations from sound files
50 - `aubiocut` slices sound files at onset or beat timestamps
38 51
39A few simple command line tools are included along with the library:52Additional command line tools are included along with the library:
40 53
41 - `aubioonset` outputs the time stamp of detected note onsets54 - `aubioonset` outputs the time stamp of detected note onsets
42 - `aubiopitch` attempts to identify a fundamental frequency, or pitch, for55 - `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
46 - `aubionotes` emits midi-like notes, with an onset, a pitch, and a duration59 - `aubionotes` emits midi-like notes, with an onset, a pitch, and a duration
47 - `aubioquiet` extracts quiet and loud regions60 - `aubioquiet` extracts quiet and loud regions
48 61
49Additionally, the python module comes with the following script:62Documentation
50 63-------------
51 - `aubiocut` slices sound files at onset or beat timestamps
52
53Implementation and Design Basics
54--------------------------------
55
56The library is written in C and is optimised for speed and portability.
57
58The 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);
65 64
66For performance and real-time operation, no memory allocation or freeing take65 - [manual](https://aubio.org/manual/latest/), generated with sphinx
67place in the `_do` methods. Instead, memory allocation should always take place66 - [developer documentation](https://aubio.org/doc/latest/), generated with Doxygen
68in the `new_` methods, whereas free operations are done in the `del_` methods.
69 67
70The latest version of the documentation can be found at:68The latest version of the documentation can be found at:
71 69
@@ -74,105 +72,42 @@ The latest version of the documentation can be found at: · 2 unmodified lines
74Build Instructions72Build Instructions
75------------------73------------------
76 74
77A number of distributions already include aubio. Check your favorite package75aubio compiles on Linux, Mac OS X, Windows, Cygwin, and iOS.
78management system, or have a look at the [download
79page](https://aubio.org/download).
80
81aubio uses [waf](https://waf.io/) to configure, compile, and test the source:
82
83 ./waf configure
84 ./waf build
85
86If waf is not found in the directory, you can download and install it with:
87
88 make getwaf
89
90aubio compiles on Linux, Mac OS X, Cygwin, and iOS.
91
92Installation
93------------
94
95To install aubio library and headers on your system, use:
96 76
97 sudo ./waf install77To compile aubio, you should be able to simply run:
98 78
99To uninstall:79 make
100 80
101 sudo ./waf uninstall81To compile the python module:
102 82
103If you don't have root access to install libaubio on your system, you can use83 ./setup.py build
104libaubio without installing libaubio either by setting `LD_LIBRARY_PATH`, or by
105copying it to `~/lib`.
106 84
107On Linux, you should be able to set `LD_LIBRARY_PATH` with:85See the [manual](https://aubio.org/manual/latest/) for more information about
86[installing aubio](https://aubio.org/manual/latest/installing.html).
108 87
109 $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/src88Citation
89--------
110 90
111On Mac OS X, a copy or a symlink can be made in `~/lib`:91Please use the DOI link above to cite this release in your publications. For
92more information, see also the [about
93page](https://aubio.org/manual/latest/about.html) in [aubio
94manual](https://aubio.org/manual/latest/).
112 95
113 $ mkdir -p ~/lib96Homepage
114 $ ln -sf $PWD/build/src/libaubio*.dylib ~/lib/97--------
115
116Note on Mac OS X systems older than El Capitan (10.11), the `DYLD_LIBRARY_PATH`
117variable can be set as follows:
118
119 $ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$PWD/build/src
120
121Credits and Publications
122------------------------
123
124This library gathers music signal processing algorithms designed at the Centre
125for Digital Music and elsewhere. This software project was developed along the
126research I did at the Centre for Digital Music, Queen Mary, University of
127London. Most of this C code was written by myself, starting from published
128papers and existing code. The header files of each algorithm contains brief
129descriptions and references to the corresponding papers.
130
131Special thanks go Juan Pablo Bello, Chris Duxbury, Samer Abdallah, Alain de
132Cheveigne for their help and publications. Also many thanks to Miguel Ramirez
133and Nicolas Wack for their bug fixing.
134
135Substantial informations about the algorithms and their evaluation are gathered
136in:
137
138 - Paul Brossier, _[Automatic annotation of musical audio for interactive
139 systems](https://aubio.org/phd)_, PhD thesis, Centre for Digital music,
140Queen Mary University of London, London, UK, 2006.
141
142Additional results obtained with this software were discussed in the following
143papers:
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),
147in _Proceedings of the International Computer Music Conference_, 2004, Miami,
148Florida, 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),
152in _Proceedings of the International Symposium on Music Information Retrieval_,
1532004, Barcelona, Spain
154
155
156Contact Info and Mailing List
157-----------------------------
158 98
159The home page of this project can be found at: https://aubio.org/99The home page of this project can be found at: https://aubio.org/
160 100
161Questions, comments, suggestions, and contributions are welcome. Use the101License
162mailing list: <aubio-user@aubio.org>.102-------
163
164To subscribe to the list, use the mailman form:
165http://lists.aubio.org/listinfo/aubio-user/
166
167Alternatively, feel free to contact directly the author.
168
169
170Copyright and License Information
171---------------------------------
172
173Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
174 103
175aubio is free software: you can redistribute it and/or modify it under the104aubio is free software: you can redistribute it and/or modify it under the
176terms of the GNU General Public License as published by the Free Software105terms of the GNU General Public License as published by the Free Software
177Foundation, either version 3 of the License, or (at your option) any later106Foundation, either version 3 of the License, or (at your option) any later
178version.107version.
108
109Contributing
110------------
111
112Patches are welcome: please fork the latest git repository and create a feature
113branch. Submitted requests should pass all continuous integration tests.
VERSION+3−3
@@ -1,7 +1,7 @@
1AUBIO_MAJOR_VERSION=01AUBIO_MAJOR_VERSION=0
2AUBIO_MINOR_VERSION=42AUBIO_MINOR_VERSION=4
3AUBIO_PATCH_VERSION=43AUBIO_PATCH_VERSION=9
4AUBIO_VERSION_STATUS='~alpha'4AUBIO_VERSION_STATUS='~alpha'
5LIBAUBIO_LT_CUR=55LIBAUBIO_LT_CUR=5
6LIBAUBIO_LT_REV=06LIBAUBIO_LT_REV=4
7LIBAUBIO_LT_AGE=47LIBAUBIO_LT_AGE=8
aubio.pc.in+1−1
@@ -7,4 +7,4 @@ Name: aubio · 6 unmodified lines
7Description: a library for audio labelling7Description: a library for audio labelling
8Version: @VERSION@8Version: @VERSION@
9Libs: -L${libdir} -laubio9Libs: -L${libdir} -laubio
10Cflags: -I${includedir} 10Cflags: -I${includedir}
azure-pipelines.yml+38−0
@@ -0,0 +1,38 @@
1# configuration file for azure continuous integration
2jobs:
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
39 @echo " doctest to run all doctests embedded in the documentation (if enabled)"39 @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 40
41clean:41clean:
42 -rm -rf _static
42 -rm -rf $(BUILDDIR)/*43 -rm -rf $(BUILDDIR)/*
43 44
44html:45html:
46 mkdir -p _static
45 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html47 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 @echo48 @echo
47 @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."49 @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
doc/about.rst+73−0
@@ -0,0 +1,73 @@
1About
2=====
3
4This library gathers a collection of music signal processing algorithms written
5by several people. The documentation of each algorithms contains a brief
6description and references to the corresponding papers.
7
8Credits
9-------
10
11Many 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
21Special thanks to Juan Pablo Bello, Chris Duxbury, Samer Abdallah, Alain de
22Cheveigne for their help. Also many thanks to Miguel Ramirez and Nicolas Wack
23for their advices and help fixing bugs.
24
25Publications
26------------
27
28Substantial informations about several of the algorithms and their evaluation
29are 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
35Additional results obtained with this software were discussed in the following
36papers:
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
49Citation
50--------
51
52Please refer to the Zenodo link in the file README.md to cite this release.
53
54Copyright
55---------
56
57Copyright © 2003-2017 Paul Brossier <piem@aubio.org>
58
59License
60-------
61
62aubio is a `free <https://www.debian.org/intro/free>`_ and `open source
63<http://www.opensource.org/docs/definition.php>`_ software; **you** can
64redistribute 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
67Foundation <https://fsf.org>`_, either version 3 of the License, or (at your
68option) 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
3Android build
4-------------
5
6To compile aubio for android, you will need to get the `Android Native
7Development Toolkit (NDK) <https://developer.android.com/ndk/>`_, prepare a
8standalone toolchain, and tell waf to use the NDK toolchain. An example script
9to complete these tasks is available in ``scripts/build_android``.
doc/aubio.txt+141−0
@@ -0,0 +1,141 @@
1NAME
2 aubio - a command line tool to extract information from sound files
3
4SYNOPSIS
5
6 aubio [-h] [-V] <command> ...
7
8COMMANDS
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
24GENERAL 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
32COMMON 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
57ONSET
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
71PITCH
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
85BEAT
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
92TEMPO
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
99NOTES
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
109MFCC
110
111 The "mfcc" command accepts all common options and no additional options.
112
113MELBANDS
114
115 The "melbands" command accepts all common options and no additional options.
116
117EXAMPLES
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
132SEE ALSO
133
134 aubiocut(1)
135
136AUTHOR
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
34 -b, --beat Use beat locations instead of onset locations.34 -b, --beat Use beat locations instead of onset locations.
35 35
36 -t, --onset-threshold thres Set the threshold value for the onset peak36 -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 to37 picking. Values are typically in the range [0.001, 0.900]. Lower threshold
38 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of38 values imply more onsets detected. Increasing this threshold should reduce
39 over-detections. Defaults to 0.3.39 the number of incorrect detections. Defaults to 0.3.
40 40
41 -c, --cut Cut input sound file at detected labels. A new sound files for41 -c, --cut Cut input sound file at detected labels. A new sound files for
42 each slice will be created in the current directory.42 each slice will be created in the current directory.
@@ -50,6 +50,8 @@ OPTIONS · 7 unmodified lines
50 --cut-until-nslices n How many extra slices should be added at the end of50 --cut-until-nslices n How many extra slices should be added at the end of
51 each slice (default 0).51 each slice (default 0).
52 52
53 --create-first Alway create first slice.
54
53 -h, --help Print a short help message and exit.55 -h, --help Print a short help message and exit.
54 56
55 -v, --verbose Be verbose.57 -v, --verbose Be verbose.
doc/aubiomfcc.txt+2−2
@@ -15,7 +15,7 @@ DESCRIPTION · 14 unmodified lines
15 15
16 MFCCs are coefficients that make up for the mel-frequency spectrum, a16 MFCCs are coefficients that make up for the mel-frequency spectrum, a
17 representation of the short-term power spectrum of a sound. By default, 1317 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.
19 19
20 When started with an input source (-i/--input), the coefficients are given on20 When started with an input source (-i/--input), the coefficients are given on
21 the console, prefixed by their timestamps in seconds.21 the console, prefixed by their timestamps in seconds.
@@ -51,7 +51,7 @@ REFERENCES · 29 unmodified lines
51 according to Malcolm Slaney's Auditory Toolbox, available at the following51 according to Malcolm Slaney's Auditory Toolbox, available at the following
52 url:52 url:
53 53
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)
55 55
56SEE ALSO56SEE ALSO
57 57
doc/aubionotes.txt+10−2
@@ -6,7 +6,7 @@ SYNOPSIS · 5 unmodified lines
6 aubionotes source6 aubionotes source
7 aubionotes [[-i] source]7 aubionotes [[-i] source]
8 [-r rate] [-B win] [-H hop]8 [-r rate] [-B win] [-H hop]
9 [-O method] [-t thres]9 [-O method] [-t thres] [-d drop]
10 [-p method] [-u unit] [-l thres]10 [-p method] [-u unit] [-l thres]
11 [-T time-format]11 [-T time-format]
12 [-s sil]12 [-s sil]
@@ -50,6 +50,9 @@ OPTIONS · 37 unmodified lines
50 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of50 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of
51 over-detections. Defaults to 0.3.51 over-detections. Defaults to 0.3.
52 52
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
53 -p, --pitch method The pitch detection method to use. See PITCH METHODS56 -p, --pitch method The pitch detection method to use. See PITCH METHODS
54 below. Defaults to 'default'.57 below. Defaults to 'default'.
55 58
@@ -65,6 +68,10 @@ OPTIONS · 9 unmodified lines
65 will not be detected. A value of -20.0 would eliminate most onsets but the68 will not be detected. A value of -20.0 would eliminate most onsets but the
66 loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.69 loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
67 70
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
68 -T, --timeformat format Set time format (samples, ms, seconds). Defaults to75 -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
69 seconds.76 seconds.
70 77
@@ -84,7 +91,8 @@ ONSET METHODS · 13 unmodified lines
84 91
85PITCH METHODS92PITCH METHODS
86 93
87 Available methods: default, schmitt, fcomb, mcomb, specacf, yin, yinfft.94 Available methods: default, schmitt, fcomb, mcomb, specacf, yin, yinfft,
95 yinfast.
88 96
89 See aubiopitch(1) for details about these methods.97 See aubiopitch(1) for details about these methods.
90 98
doc/aubioonset.txt+13−5
@@ -9,7 +9,8 @@ SYNOPSIS · 8 unmodified lines
9 [-O method] [-t thres]9 [-O method] [-t thres]
10 [-T time-format]10 [-T time-format]
11 [-s sil] [-m] [-f]11 [-s sil] [-m] [-f]
12 [-j] [-v] [-h]12 [-j] [-N miditap-note] [-V miditap-velo]
13 [-v] [-h]
13 14
14DESCRIPTION15DESCRIPTION
15 16
@@ -48,11 +49,14 @@ OPTIONS · 32 unmodified lines
48 below. Defaults to 'default'.49 below. Defaults to 'default'.
49 50
50 -t, --onset-threshold thres Set the threshold value for the onset peak51 -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 to52 picking. Values are typically in the range [0.001, 0.900]. Lower threshold
52 0.1. Lower threshold values imply more onsets detected. Try 0.5 in case of53 values imply more onsets detected. Increasing this threshold should reduce
53 over-detections. Defaults to 0.3.54 the number of incorrect detections. Defaults to 0.3.
54 55
55 -s, --silence sil Set the silence threshold, in dB, under which the pitch56 -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
56 will not be detected. A value of -20.0 would eliminate most onsets but the60 will not be detected. A value of -20.0 would eliminate most onsets but the
57 loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.61 loudest ones. A value of -90.0 would select all onsets. Defaults to -90.0.
58 62
@@ -67,6 +71,10 @@ OPTIONS · 8 unmodified lines
67 -j, --jack Use Jack input/output. You will need a Jack connection71 -j, --jack Use Jack input/output. You will need a Jack connection
68 controller to feed aubio some signal and listen to its output.72 controller to feed aubio some signal and listen to its output.
69 73
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
70 -h, --help Print a short help message and exit.78 -h, --help Print a short help message and exit.
71 79
72 -v, --verbose Be verbose.80 -v, --verbose Be verbose.
doc/aubiopitch.txt+6−0
@@ -120,6 +120,12 @@ PITCH METHODS · 119 unmodified lines
120 Chapter 3, Pitch Analysis, PhD thesis, Centre for Digital music, Queen Mary120 Chapter 3, Pitch Analysis, PhD thesis, Centre for Digital music, Queen Mary
121 University of London, London, UK, 2006.121 University of London, London, UK, 2006.
122 122
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
123SEE ALSO129SEE ALSO
124 130
125 aubioonset(1),131 aubioonset(1),
doc/aubiotrack.txt+7−2
@@ -8,7 +8,8 @@ SYNOPSIS · 7 unmodified lines
8 [-r rate] [-B win] [-H hop]8 [-r rate] [-B win] [-H hop]
9 [-T time-format]9 [-T time-format]
10 [-s sil] [-m]10 [-s sil] [-m]
11 [-j] [-v] [-h]11 [-j] [-N miditap-note] [-V miditap-velo]
12 [-v] [-h]
12 13
13DESCRIPTION14DESCRIPTION
14 15
@@ -54,6 +55,10 @@ OPTIONS · 39 unmodified lines
54 -j, --jack Use Jack input/output. You will need a Jack connection55 -j, --jack Use Jack input/output. You will need a Jack connection
55 controller to feed aubio some signal and listen to its output.56 controller to feed aubio some signal and listen to its output.
56 57
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
57 -T, --timeformat format Set time format (samples, ms, seconds). Defaults to62 -T, --timeformat format Set time format (samples, ms, seconds). Defaults to
58 seconds.63 seconds.
59 64
@@ -72,7 +77,7 @@ BEAT TRACKING METHODS · 12 unmodified lines
72 77
73 Matthew E. P. Davies, Paul Brossier, and Mark D. Plumbley. Beat tracking78 Matthew E. P. Davies, Paul Brossier, and Mark D. Plumbley. Beat tracking
74 towards automatic musical accompaniment. In Proceedings of the Audio79 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.
76 81
77SEE ALSO82SEE ALSO
78 83
doc/binaries.rst+12−0
@@ -0,0 +1,12 @@
1Pre-compiled binaries
2---------------------
3
4`Pre-compiled binaries <https://aubio.org/download>`_
5are available for
6`macOS <https://aubio.org/download#osx>`_,
7`iOS <https://aubio.org/download#ios>`_,
8and
9`windows <https://aubio.org/download#win>`_
10
11To 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
20 20
21The **latest stable release** can be downloaded from https://aubio.org/download::21The **latest stable release** can be downloaded from https://aubio.org/download::
22 22
23 $ curl -O http://aubio.org/pub/aubio-0.4.3.tar.bz223 $ curl -O http://aubio.org/pub/aubio-<version>.tar.bz2
24 $ tar xf aubio-0.4.3.tar.bz224 $ tar xf aubio-<version>.tar.bz2
25 $ cd aubio-0.4.325 $ cd aubio-<version>/
26 26
27Git repository27Git repository
28--------------28--------------
@@ -30,7 +30,7 @@ Git repository · 1 unmodified line
30The **latest git branch** can be obtained with::30The **latest git branch** can be obtained with::
31 31
32 $ git clone git://git.aubio.org/git/aubio32 $ git clone git://git.aubio.org/git/aubio
33 $ cd aubio33 $ cd aubio/
34 34
35The following command will fetch the correct `waf`_ version (not included in35The following command will fetch the correct `waf`_ version (not included in
36aubio's git)::36aubio's git)::
@@ -73,6 +73,34 @@ command:: · 36 unmodified lines
73 73
74 $ waf configure build74 $ waf configure build
75 75
76
77Running as a user
78-----------------
79
80To use aubio without actually installing, for instance if you don't have root
81access to install libaubio on your system,
82
83On Linux or macOS, sourcing the script ``scripts/setenv_local.sh`` should help::
84
85 $ source ./scripts/setenv_local.sh
86
87This script sets ``LD_LIBRARY_PATH``, for libaubio, and ``PYTHONPATH`` for the
88python module.
89
90On Linux, you should be able to set ``LD_LIBRARY_PATH`` with::
91
92 $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/src
93
94On 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
99Note on Mac OS X systems older than El Capitan (10.11), the ``DYLD_LIBRARY_PATH``
100variable can be set as follows::
101
102 $ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$PWD/build/src
103
76Cleaning104Cleaning
77--------105--------
78 106
@@ -94,5 +122,8 @@ invocation, use the ``distclean`` command:: · 15 unmodified lines
94 122
95.. _Git Bash: https://git-for-windows.github.io/123.. _Git Bash: https://git-for-windows.github.io/
96 124
97.. toctree::125.. _xcode-frameworks-label:
98 :maxdepth: 2126
127.. include:: xcode_frameworks.rst
128
129.. include:: android.rst
doc/cli.rst+25−6
@@ -3,7 +3,12 @@ · 2 unmodified lines
3Command line tools3Command line tools
4==================4==================
5 5
6A few simple command line tools are included along with the library.6The 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
11More command line tools are included along with the library.
7 12
8 - ``aubioonset`` outputs the time stamp of detected note onsets13 - ``aubioonset`` outputs the time stamp of detected note onsets
9 - ``aubiopitch`` attempts to identify a fundamental frequency, or pitch, for14 - ``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
13 - ``aubionotes`` emits midi-like notes, with an onset, a pitch, and a duration18 - ``aubionotes`` emits midi-like notes, with an onset, a pitch, and a duration
14 - ``aubioquiet`` extracts quiet and loud regions19 - ``aubioquiet`` extracts quiet and loud regions
15 20
16Additionally, the python module comes with the following script:
17 21
18 - ``aubiocut`` slices sound files at onset or beat timestamps22``aubio``
23---------
24
25.. literalinclude:: aubio.txt
26 :language: text
27
28
29``aubiocut``
30--------------
31
32.. literalinclude:: aubiocut.txt
33 :language: text
19 34
20 35
21``aubioonset``36``aubioonset``
22--------------37--------------
23 38
24.. literalinclude:: aubioonset.txt39.. literalinclude:: aubioonset.txt
40 :language: text
25 41
26``aubiopitch``42``aubiopitch``
27--------------43--------------
28 44
29.. literalinclude:: aubiopitch.txt45.. literalinclude:: aubiopitch.txt
46 :language: text
30 47
31``aubiomfcc``48``aubiomfcc``
32--------------49--------------
33 50
34.. literalinclude:: aubiomfcc.txt51.. literalinclude:: aubiomfcc.txt
52 :language: text
35 53
36``aubiotrack``54``aubiotrack``
37--------------55--------------
38 56
39.. literalinclude:: aubiotrack.txt57.. literalinclude:: aubiotrack.txt
58 :language: text
40 59
41``aubionotes``60``aubionotes``
42--------------61--------------
43 62
44.. literalinclude:: aubionotes.txt63.. literalinclude:: aubionotes.txt
64 :language: text
45 65
46``aubioquiet``66``aubioquiet``
47--------------67--------------
48 68
49.. literalinclude:: aubioquiet.txt69.. literalinclude:: aubioquiet.txt
70 :language: text
50 71
51``aubiocut``
52--------------
53 72
54.. literalinclude:: aubiocut.txt73.. include:: cli_features.rst
doc/cli_features.rst+42−0
@@ -0,0 +1,42 @@
1Command 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
281. ``aubiocut --output`` is used to specify a directory, not a file.
29
302. Option ``--bufsize`` is useless for ``aubioquiet``
31
323. ``aubioquiet`` could have a jack output
33
344. Regression, re-add slicing at silences to ``aubiocut``
35
365. ``aubiocut`` could cut on notes
37
386. ``aubionotes`` needs onset/pitch setters.
39
407. Silence was different for pitch and onset, test.
41
428. Some ``aubiotrack`` options should be disabled (minioi, threshold).
doc/conf.py+37−9
@@ -13,10 +13,14 @@ · 12 unmodified lines
13 13
14import sys, os14import sys, os
15 15
16# get version using this_version.py
17sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
18from this_version import get_aubio_version
19
16# If extensions (or modules to document with autodoc) are in another directory,20# If extensions (or modules to document with autodoc) are in another directory,
17# add these directories to sys.path here. If the directory is relative to the21# add these directories to sys.path here. If the directory is relative to the
18# documentation root, use os.path.abspath to make it absolute, like shown here.22# documentation root, use os.path.abspath to make it absolute, like shown here.
19sys.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/...'))
20 24
21# -- General configuration -----------------------------------------------------25# -- General configuration -----------------------------------------------------
22 26
@@ -25,7 +29,14 @@ sys.path.insert(0, os.path.abspath('../../python/build/lib.macosx-10.6-intel-2.7 · 2 unmodified lines
25 29
26# Add any Sphinx extension module names here, as strings. They can be extensions30# Add any Sphinx extension module names here, as strings. They can be extensions
27# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.31# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28extensions = ['sphinx.ext.viewcode', 'sphinx.ext.autodoc']32extensions = ['sphinx.ext.viewcode', 'sphinx.ext.autodoc',
33 'sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
34
35autodoc_member_order = 'groupwise'
36
37intersphinx_mapping = {
38 'numpy': ('https://docs.scipy.org/doc/numpy/', None),
39 }
29 40
30# Add any paths that contain templates here, relative to this directory.41# Add any paths that contain templates here, relative to this directory.
31templates_path = ['_templates']42templates_path = ['_templates']
@@ -41,16 +52,17 @@ master_doc = 'index' · 9 unmodified lines
41 52
42# General information about the project.53# General information about the project.
43project = u'aubio'54project = u'aubio'
44copyright = u'2016, Paul Brossier'55copyright = u'2018, Paul Brossier'
45 56
46# The version info for the project you're documenting, acts as replacement for57# The version info for the project you're documenting, acts as replacement for
47# |version| and |release|, also used in various other places throughout the58# |version| and |release|, also used in various other places throughout the
48# built documents.59# built documents.
49#60#
50# The short X.Y version.61# The short X.Y version.
51version = '0.4'62
63version = get_aubio_version()[:3]
52# The full version, including alpha/beta/rc tags.64# The full version, including alpha/beta/rc tags.
53release = 'latest'65release = get_aubio_version()
54 66
55# The language for content autogenerated by Sphinx. Refer to documentation67# The language for content autogenerated by Sphinx. Refer to documentation
56# for a list of supported languages.68# for a list of supported languages.
@@ -64,7 +76,17 @@ release = 'latest' · 7 unmodified lines
64 76
65# List of patterns, relative to source directory, that match files and77# List of patterns, relative to source directory, that match files and
66# directories to ignore when looking for source files.78# directories to ignore when looking for source files.
67exclude_patterns = ['_build']79exclude_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 ]
68 90
69# The reST default role (used for this markup: `text`) to use for all documents.91# The reST default role (used for this markup: `text`) to use for all documents.
70#default_role = None92#default_role = None
@@ -91,7 +113,10 @@ modindex_common_prefix = ['aubio.'] · 20 unmodified lines
91 113
92# The theme to use for HTML and HTML Help pages. See the documentation for114# The theme to use for HTML and HTML Help pages. See the documentation for
93# a list of builtin themes.115# a list of builtin themes.
94html_theme = 'default'116#html_theme = 'agogo'
117#html_theme = 'default'
118#html_theme = 'haiku'
119html_theme = 'pyramid'
95 120
96# Theme options are theme-specific and customize the look and feel of a theme121# Theme options are theme-specific and customize the look and feel of a theme
97# further. For a list of options available for each theme, see the122# further. For a list of options available for each theme, see the
@@ -120,7 +145,7 @@ html_theme = 'default' · 22 unmodified lines
120# Add any paths that contain custom static files (such as style sheets) here,145# Add any paths that contain custom static files (such as style sheets) here,
121# relative to this directory. They are copied after the builtin static files,146# relative to this directory. They are copied after the builtin static files,
122# so a file named "default.css" will overwrite the builtin "default.css".147# so a file named "default.css" will overwrite the builtin "default.css".
123html_static_path = ['_static']148html_static_path = [] #['_static']
124 149
125# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,150# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126# using the given strftime format.151# using the given strftime format.
@@ -150,7 +175,7 @@ html_static_path = ['_static'] · 23 unmodified lines
150#html_show_sourcelink = True175#html_show_sourcelink = True
151 176
152# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.177# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153#html_show_sphinx = True178html_show_sphinx = False
154 179
155# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.180# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156#html_show_copyright = True181#html_show_copyright = True
@@ -240,3 +265,6 @@ texinfo_documents = [ · 83 unmodified lines
240 265
241# How to display URL addresses: 'footnote', 'no', or 'inline'.266# How to display URL addresses: 'footnote', 'no', or 'inline'.
242#texinfo_show_urls = 'footnote'267#texinfo_show_urls = 'footnote'
268
269def 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
9https://anonscm.debian.org/cgit/collab-maint/aubio.git/. Use9https://anonscm.debian.org/cgit/collab-maint/aubio.git/. Use
10``git-buildpackage`` to build from the git repository. For instance:10``git-buildpackage`` to build from the git repository. For instance:
11 11
12.. code-block:: bash12.. code-block:: console
13 13
14 $ git clone git://anonscm.debian.org/collab-maint/aubio.git14 $ git clone git://anonscm.debian.org/collab-maint/aubio.git
15 $ cd aubio15 $ cd aubio
doc/develop.rst+89−35
@@ -1,46 +1,94 @@
1Developping with aubio1.. _develop:
2======================
3 2
4Read `Contribute`_ to report issues and request new features.3Developing with aubio
4=====================
5 5
6See `Doxygen documentation`_ for the complete documentation of the C library,6Here is a brief overview of the C library.
7built using `Doxygen <http://www.doxygen.org/>`_.
8 7
9Below is a brief `Library overview`_.8For a more detailed list of available functions, see the `API documentation
9<https://aubio.org/doc/latest/>`_.
10 10
11Library overview11To report issues, ask questions, and request new features, use `Github Issues
12----------------12<https://github.com/aubio/aubio/issues>`_
13 13
14Here is a brief overview of the C library. See also the `Doxygen14Design Basics
15documentation`_ for a more detailed list of available functions.15-------------
16 16
17Vectors and matrix17The library is written in C and is optimised for speed and portability.
18``````````````````
19 18
20``fvec_t`` are used to hold vectors of float (``smpl_t``).19All memory allocations take place in the `new_` methods. Each successful call
20to `new_` should have a matching call to `del_` to deallocate the object.
21 21
22.. literalinclude:: ../tests/src/test-fvec.c22.. code-block:: C
23 :language: C
24 :lines: 7
25 23
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
29The main computations are done in the `_do` methods.
26 30
27.. code-block:: C31.. code-block:: C
28 32
29 // set some elements33 // _do to process output = foobar(input)
30 vec->data[511] = 2.;34 audio_foobar_do (aubio_foobar_t * foobar, fvec_t * input, cvec_t * output);
31 vec->data[vec->length-2] = 1.;
32 35
33Similarly, ``fmat_t`` are used to hold matrix of floats.36Most 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
45In 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
52Basic 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);
34 83
35.. literalinclude:: ../tests/src/test-fmat.c
36 :language: C
37 :lines: 9-19
38 84
39Reading a sound file85Reading a sound file
40````````````````````86--------------------
41In this example, ``aubio_source`` is used to read a media file.
42 87
43First, create the objects we need.88In this example, `aubio_source <https://aubio.org/doc/latest/source_8h.html>`_
89is used to read a media file.
90
91First, define a few variables and allocate some memory.
44 92
45.. literalinclude:: ../tests/src/io/test-source.c93.. literalinclude:: ../tests/src/io/test-source.c
46 :language: C94 :language: C
@@ -56,17 +104,17 @@ Now for the processing loop: · 9 unmodified lines
56 :language: C104 :language: C
57 :lines: 40-44105 :lines: 40-44
58 106
59At the end of the processing loop, clean-up and de-allocate memory:107At the end of the processing loop, memory is deallocated:
60 108
61.. literalinclude:: ../tests/src/io/test-source.c109.. literalinclude:: ../tests/src/io/test-source.c
62 :language: C110 :language: C
63 :lines: 50-56111 :lines: 55-56
64 112
65See the complete example: :download:`test-source.c113See the complete example: :download:`test-source.c
66<../tests/src/io/test-source.c>`.114<../tests/src/io/test-source.c>`.
67 115
68Computing the spectrum116Computing a spectrum
69``````````````````````117--------------------
70 118
71Now let's create a phase vocoder:119Now let's create a phase vocoder:
72 120
@@ -74,11 +122,17 @@ Now let's create a phase vocoder: · 1 unmodified line
74 :language: C122 :language: C
75 :lines: 6-11123 :lines: 6-11
76 124
77The processing loop could know look like:125The processing loop could now look like:
126
127.. literalinclude:: ../tests/src/spectral/test-phasevoc.c
128 :language: C
129 :lines: 20-37
130
131Time to clean up the previously allocated memory:
78 132
79.. literalinclude:: ../tests/src/spectral/test-phasevoc.c133.. literalinclude:: ../tests/src/spectral/test-phasevoc.c
80 :language: C134 :language: C
81 :lines: 21-35135 :lines: 39-44
82 136
83See the complete example: :download:`test-phasevoc.c137See the complete example: :download:`test-phasevoc.c
84<../tests/src/spectral/test-phasevoc.c>`.138<../tests/src/spectral/test-phasevoc.c>`.
@@ -88,13 +142,13 @@ See the complete example: :download:`test-phasevoc.c · 3 unmodified lines
88Doxygen documentation142Doxygen documentation
89---------------------143---------------------
90 144
91The latest version of the doxygen documentation is available at:145The latest version of the API documentation is built using `Doxygen
146<http://www.doxygen.org/>`_ and is available at:
92 147
93 https://aubio.org/doc/latest148 https://aubio.org/doc/latest/
94 149
95Contribute150Contribute
96----------151----------
97 152
98Please report any issue and feature request at the `Github issue tracker153Please report any issue and feature request at the `Github issue tracker
99<https://github.com/aubio/aubio/issues>`_. Patches and pull-requests welcome!154<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
5 5
6A number of distributions already include aubio. Check your favorite package6A number of distributions already include aubio. Check your favorite package
7management system, or have a look at the `aubio download page7management system, or have a look at the `aubio download page
8<http://aubio.org/download>`_ for more options.8<https://aubio.org/download>`_ for more options.
9
10To use aubio in a macOS or iOS application, see :ref:`xcode-frameworks-label`.
11 9
12To use aubio in an android project, see :ref:`android`.10To use aubio in an android project, see :ref:`android`.
13 11
14.. toctree::12To compile aubio from source, read :ref:`building`.
15 13
16 debian_packages14.. include:: binaries.rst
17 xcode_frameworks
18 android
19 15
20To 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.81@INCLUDE_PATH = ./doc
2 2@INCLUDE = web.cfg
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
27DOXYFILE_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
35PROJECT_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
41PROJECT_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
47PROJECT_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
54PROJECT_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.
60 3
61OUTPUT_DIRECTORY = full4OUTPUT_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
71CREATE_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
79ALLOW_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
94OUTPUT_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
101BRIEF_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
110REPEAT_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
121ABBREVIATE_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
128ALWAYS_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
136INLINE_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
143FULL_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
155STRIP_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
164STRIP_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
171SHORT_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
180JAVADOC_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
188QT_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
200MULTILINE_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
206INHERIT_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
213SEPARATE_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
219TAB_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
231ALIASES =
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
237TCL_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
245OPTIMIZE_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
253OPTIMIZE_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
259OPTIMIZE_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
265OPTIMIZE_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
284EXTENSION_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
294MARKDOWN_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
302AUTOLINK_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
312BUILTIN_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
318CPP_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
326SIP_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
336IDL_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
344DISTRIBUTE_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
353SUBGROUPING = 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
364INLINE_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
374INLINE_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
385TYPEDEF_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
398LOOKUP_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
412EXTRACT_ALL = YES5EXTRACT_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
418EXTRACT_PRIVATE = YES6EXTRACT_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
424EXTRACT_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
430EXTRACT_STATIC = YES7EXTRACT_STATIC = YES
431 8FILE_PATTERNS = *.h *.c
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
438EXTRACT_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
446EXTRACT_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
455EXTRACT_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
463HIDE_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
471HIDE_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
478HIDE_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
485HIDE_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
492INTERNAL_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
501CASE_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
508HIDE_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
514SHOW_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
521SHOW_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
527FORCE_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
533INLINE_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
540SORT_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
548SORT_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
560SORT_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
567SORT_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
577SORT_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
587STRICT_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
594GENERATE_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
601GENERATE_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
607GENERATE_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
614GENERATE_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
620ENABLED_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
631MAX_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
638SHOW_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
645SHOW_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
652SHOW_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
662FILE_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
675LAYOUT_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
685CITE_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
696QUIET = 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
705WARNINGS = 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
712WARN_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
720WARN_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
728WARN_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
738WARN_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
744WARN_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
756INPUT = ../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
765INPUT_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
776FILE_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
783RECURSIVE = 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
792EXCLUDE =9EXCLUDE =
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
799EXCLUDE_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
808EXCLUDE_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
819EXCLUDE_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
825EXAMPLE_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
833EXAMPLE_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
840EXAMPLE_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
846IMAGE_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
863INPUT_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
872FILTER_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
879FILTER_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
887FILTER_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
894USE_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
907SOURCE_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
913INLINE_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
920STRIP_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
926REFERENCED_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
932REFERENCES_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
940REFERENCES_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
950SOURCE_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
972USE_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
980VERBATIM_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
991CLANG_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
999CLANG_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
1010ALPHABETICAL_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
1017COLS_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
1025IGNORE_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
1034GENERATE_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
1042HTML_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
1049HTML_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
1069HTML_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
1079HTML_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
1091HTML_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
1104HTML_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
1114HTML_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
1125HTML_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
1133HTML_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
1144HTML_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
1152HTML_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
1160HTML_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
1173HTML_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
1187GENERATE_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
1195DOCSET_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
1203DOCSET_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
1211DOCSET_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
1217DOCSET_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
1235GENERATE_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
1242CHM_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
1250HHC_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
1257GENERATE_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
1263CHM_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
1271BINARY_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
1278TOC_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
1287GENERATE_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
1294QCH_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
1302QHP_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
1311QHP_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
1319QHP_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
1327QHP_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
1334QHP_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
1341QHG_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
1353GENERATE_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
1361ECLIPSE_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
1372DISABLE_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
1389GENERATE_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
1399ENUM_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
1406TREEVIEW_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
1413EXT_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
1422FORMULA_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
1433FORMULA_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
1444USE_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
1454MATHJAX_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
1467MATHJAX_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
1474MATHJAX_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
1482MATHJAX_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
1503SEARCHENGINE = 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
1515SERVER_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
1531EXTERNAL_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
1542SEARCHENGINE_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
1550SEARCHDATA_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
1558EXTERNAL_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
1568EXTRA_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
1577GENERATE_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
1585LATEX_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
1596LATEX_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
1603MAKEINDEX_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
1611COMPACT_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
1620PAPER_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
1629EXTRA_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
1645LATEX_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
1656LATEX_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
1664LATEX_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
1673PDF_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
1681USE_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
1690LATEX_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
1697LATEX_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
1707LATEX_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
1715LATEX_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
1726GENERATE_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
1734RTF_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
1742COMPACT_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
1754RTF_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
1764RTF_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
1771RTF_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
1781GENERATE_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
1790MAN_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
1799MAN_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
1806MAN_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
1815MAN_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
1825GENERATE_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
1833XML_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
1842XML_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
1852GENERATE_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
1860DOCBOOK_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
1869DOCBOOK_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
1881GENERATE_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
1893GENERATE_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
1901PERLMOD_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
1911PERLMOD_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
1919PERLMOD_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
1929ENABLE_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
1938MACRO_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
1946EXPAND_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
1953SEARCH_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
1960INCLUDE_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
1968INCLUDE_FILE_PATTERNS =10INCLUDE_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
1978PREDEFINED =
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
1987EXPAND_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
1997SKIP_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
2016TAGFILES =
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
2022GENERATE_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
2028ALLEXTERNALS = 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
2035EXTERNAL_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
2042EXTERNAL_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
2048PERL_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
2061CLASS_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
2070MSCGEN_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
2077DIA_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
2083HIDE_UNDOC_RELATIONS = NO11HIDE_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
2092HAVE_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
2102DOT_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
2112DOT_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
2119DOT_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
2126DOT_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
2134CLASS_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
2143COLLABORATION_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
2150GROUP_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
2158UML_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
2171UML_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
2179TEMPLATE_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
2188INCLUDE_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
2197INCLUDED_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
2208CALL_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
2219CALLER_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
2226GRAPHICAL_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
2235DIRECTORY_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
2248DOT_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
2260INTERACTIVE_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
2266DOT_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
2273DOTFILE_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
2279MSCFILE_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
2285DIAFILE_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
2294PLANTUML_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
2306DOT_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
2318MAX_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
2330DOT_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
2339DOT_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
2347GENERATE_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
2354DOT_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
10performing pitch detection, tapping the beat and producing midi streams from10performing pitch detection, tapping the beat and producing midi streams from
11live audio.11live audio.
12 12
13Quick 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
25Project 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
13Features45Features
14========46========
15 47
@@ -37,65 +69,8 @@ Content · 21 unmodified lines
37 :maxdepth: 269 :maxdepth: 2
38 70
39 installing71 installing
40 cli
41 python_module72 python_module
73 python
74 cli
42 develop75 develop
43 76 about
44Project 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
59Current 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
87Copyright and License
88=====================
89
90Copyright © 2003-2016 Paul Brossier <piem@aubio.org>
91
92aubio is a `free <http://www.debian.org/intro/free>`_ and `open source
93<http://www.opensource.org/docs/definition.php>`_ software; **you** can
94redistribute 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
97Foundation <https://fsf.org>`_, either version 3 of the License, or (at your
98option) 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.
doc/installing.rst+69−9
@@ -4,16 +4,76 @@ Installing aubio · 3 unmodified lines
4aubio runs on Linux, Windows, macOS, iOS, Android, and probably a few others4aubio runs on Linux, Windows, macOS, iOS, Android, and probably a few others
5operating systems.5operating systems.
6 6
7To download a pre-compiled version of the library, head to :ref:`download`.7Aubio is available as a C library and as a python module.
8 8
9To install the python extension, head to :ref:`python`.9Cheat sheet
10-----------
10 11
11To compile aubio form source, first check the :ref:`requirements`, then read12- :ref:`get aubio latest source code <building>`::
12:ref:`building`.
13 13
14.. toctree::14 # official repo
15 :maxdepth: 215 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
16 20
17 download21
18 requirements22- :ref:`build aubio from source <building>`::
19 building23
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
4Data-types
5----------
6
7This 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
4Examples
5--------
6
7Below is a short selection of examples using the aubio module.
8
9Read a sound file
10.................
11
12Here is a simple script, :download:`demo_source_simple.py
13<../python/demos/demo_source_simple.py>` that reads all the samples from a
14media file using :class:`source`:
15
16.. literalinclude:: ../python/demos/demo_source_simple.py
17 :language: python
18
19Filter a sound file
20...................
21
22Here is another example, :download:`demo_filter.py
23<../python/demos/demo_filter.py>`, which applies a filter to a sound file
24and 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
36More examples
37.............
38
39For more examples showing how to use other components of the module, see
40the `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
4Input/Output
5------------
6
7This section contains the documentation for two classes:
8:class:`source`, to read audio samples from files, and :class:`sink`,
9to 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
4Utilities
5---------
6
7This section documents various helper functions included in the aubio library.
8
9Note name conversion
10....................
11
12.. midiconv.py
13
14.. autofunction:: note2midi
15
16.. autofunction:: midi2note
17
18.. autofunction:: freq2note
19
20.. autofunction:: note2freq
21
22Frequency 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
44Audio file slicing
45..................
46
47.. slicing.py
48
49.. autofunction:: slice_source_at_stamps
50
51Windowing
52.........
53
54.. python/ext/py-musicutils.h
55
56.. autofunction:: window
57
58Audio 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
68Vector 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
19Python documentation
20====================
21
22This module provides a number of classes and functions for the analysis of
23music and audio signals.
24
25Contents
26--------
27
28.. toctree::
29 :maxdepth: 1
30
31 py_datatypes
32 py_io
33 py_utils
34 py_examples
35
36Introduction
37------------
38
39This document provides a reference guide. For documentation on how to
40install aubio, see :ref:`python-install`.
41
42Examples included in this guide and within the code are written assuming
43both `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
51provided with the python module. This version adds documentation for some
52classes, 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:
2 2
3Python module3Installing aubio for Python
4=============4===========================
5 5
6The aubio extension for Python is available for Python 2.7 and Python 3.6aubio is available as a package for Python 2.7 and Python 3. The aubio
7extension 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
12For general documentation on how to install Python packages, see `Installing
13Packages`_.
7 14
8Installing aubio with pip15Installing aubio with pip
9-------------------------16-------------------------
10 17
11aubio can now be installed using ``pip``:18aubio can be installed from `PyPI`_ using ``pip``:
12 19
13.. code-block:: bash20.. code-block:: console
14 21
15 $ pip install aubio22 $ pip install aubio
16 23
17Building the module24See also `Installing from PyPI`_ for general documentation.
18-------------------
19 25
20From ``aubio`` source directory, run the following:26.. note::
21 27
22.. code-block:: bash28 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.
23 31
24 $ ./setup.py clean32.. _PyPI: https://pypi.python.org/pypi/aubio
25 $ ./setup.py build33.. _Installing Packages: https://packaging.python.org/tutorials/installing-packages/
26 $ sudo ./setup.py install34.. _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
37Installing aubio with conda
38---------------------------
27 39
28Using aubio in python40`Conda packages`_ are available through the `conda-forge`_ channel for Linux,
29---------------------41macOS, and Windows:
30 42
31Once you have python-aubio installed, you should be able to run ``python -c43.. code-block:: console
32"import aubio"``.
33 44
34A simple example45 $ conda config --add channels conda-forge
35................46 $ conda install -c conda-forge aubio
36 47
37Here is a :download:`simple script <../python/demos/demo_source_simple.py>`48.. _Conda packages: https://anaconda.org/conda-forge/aubio
38that reads all the samples from a media file:49.. _conda-forge: https://conda-forge.org/
39 50
40.. literalinclude:: ../python/demos/demo_source_simple.py51.. _py-doubleprecision:
41 :language: python
42 52
43Filtering an input sound file53Double precision
44.............................54----------------
45 55
46Here is a more complete example, :download:`demo_filter.py56This module can be compiled in double-precision mode, in which case the
47<../python/demos/demo_filter.py>`. This files executes the following:57default type for floating-point samples will be 64-bit. The default is
58single precision mode (32-bit, recommended).
59
60To 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 .
48 68
49* read an input media file (``aubio.source``)69**Note**: If linking against `libaubio`, make sure the library was also
70compiled in :ref:`doubleprecision` mode.
50 71
51* filter it using an `A-weighting <https://en.wikipedia.org/wiki/A-weighting>`_
52 filter (``aubio.digital_filter``)
53 72
54* write result to a new file (``aubio.sink``)73Checking your installation
74--------------------------
55 75
56.. literalinclude:: ../python/demos/demo_filter.py76Once the python module is installed, its version can be checked with:
57 :language: python
58 77
59More demos78.. code-block:: console
60..........79
80 $ python -c "import aubio; print(aubio.version, aubio.float_type)"
81
82The command line `aubio` is also installed:
83
84.. code-block:: console
85
86 $ aubio -h
61 87
62Check out the `python demos folder`_ for more examples.
63 88
64Python tests89Python tests
65------------90------------
66 91
67A number of `python tests`_ are provided. To run them, use92A number of Python tests are provided in the `python tests`_. To run them,
68``python/tests/run_all_tests``.93install `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
69 99
70.. _python demos folder: https://github.com/aubio/aubio/blob/master/python/demos
71.. _demo_filter.py: https://github.com/aubio/aubio/blob/master/python/demos/demo_filter.py100.. _demo_filter.py: https://github.com/aubio/aubio/blob/master/python/demos/demo_filter.py
72.. _python tests: https://github.com/aubio/aubio/blob/master/python/tests101.. _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 @@
1.. _requirements:1.. _requirements:
2 2
3Requirements3Build options
4============4=============
5
6If built without any external dependencies aubio can be somewhat useful, for
7instance to read, process, and write simple wav files.
8
9To support more media input formats and add more features to aubio, you can use
10one or all of the following `external libraries`_.
11
12You may also want to know more about the `other options`_ and the `platform
13notes`_
14
15The configure script will automatically for these extra libraries. To make sure
16the library or feature is used, pass the `--enable-flag` to waf. To disable
17this feature, use `--disable-feature`.
18
19To find out more about the build commands, use the `--verbose` option.
20
21External libraries
22------------------
23
24External libraries are checked for using ``pkg-config``. Set the
25``PKG_CONFIG_PATH`` environment variable if you have them installed in an
26unusual 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
34Media libraries
35---------------
36
37libav
38.....
39
40 `libav.org <https://libav.org/>`_, open source audio and video processing
41 tools.
42
43If 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
45from all formats supported by `libav
46<https://libav.org/documentation/general.html#Audio-Codecs>`_.
47
48* libavcodec
49* libavformat
50* libavutil
51* libavresample
52
53To enable this option, configure with ``--enable-avcodec``. The build will then
54failed if the required libraries are not found. To disable this option,
55configure with ``--disable-avcodec``
56
57
58libsndfile
59..........
60
61 `libsndfile <http://www.mega-nerd.com/libsndfile/>`_, a C library for reading
62 and writing sampled sound files.
63
64With libsndfile built in, ``aubio_source_sndfile`` will be built in and used by
65``aubio_source``.
66
67To enable this option, configure with ``--enable-sndfile``. The build will then
68fail if the required library is not found. To disable this option, configure
69with ``--disable-sndfile``
70
71libsamplerate
72.............
73
74 `libsamplerate <http://www.mega-nerd.com/SRC/>`_, a sample rate converter for
75 audio.
76
77With libsamplerate built in, ``aubio_source_sndfile`` will support resampling,
78and ``aubio_resample`` will be fully functional.
79
80To enable this option, configure with ``--enable-samplerate``. The build will
81then fail if the required library is not found. To disable this option,
82configure with ``--disable-samplerate``
83
84Optimisation libraries
85----------------------
86
87libfftw3
88........
89
90 `FFTW <http://fftw.org/>`_, a C subroutine for computing the discrete Fourier
91 transform
92
93With libfftw3 built in, ``aubio_fft`` will use `FFTW`_ to
94compute Fast Fourier Transform (FFT), allowing aubio to compute FFT on length
95that are not a power of 2.
96
97To enable this option, configure with ``--enable-fftw3``. The build will
98then fail if the required library is not found. To disable this option,
99configure with ``--disable-fftw3``
100
101blas
102....
103
104On macOs/iOS, `blas
105<https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms>`_ are made
106available through the Accelerate framework.
107
108On Linux, they can be enabled with ``--enable-blas``. On Debian (etch),
109`atlas`_, `openblas`_, and `libblas`_ have been successfully tested.
110
111When 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
134atlas
135.....
136
137`ATLAS BLAS APIs <http://math-atlas.sourceforge.net/>`_ will be used the path
138returned by ``pkg-config --libs blas`` contains ``atlas``.
139
140..
141 ``<atlas/cblas.h>`` will be included.
142
143Example:
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
154openblas
155........
156
157`OpenBlas libraries <https://www.openblas.net/>`_ will be used when the output
158of ``pkg-config --libs blas`` contains 'openblas',
159
160..
161 ``<openblas/cblas.h>`` will be included.
162
163Example:
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
174libblas
175.......
176
177`Netlib's libblas (LAPACK) <https://www.netlib.org/lapack/>`_ will be used if
178no specific library path is specified by ``pkg-config``
179
180..
181 ``<cblas.h>`` will be included.
182
183Example:
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
5 193
6While aubio can be built without any external dependencies, we **recommend** to
7use at least some of the following libraries.
8 194
9Platform notes195Platform notes
10--------------196--------------
@@ -41,6 +227,9 @@ The following system frameworks will be used on Mac OS X systems: · 30 unmodified lines
41The following `External libraries`_ will also be checked: `libav`_,227The following `External libraries`_ will also be checked: `libav`_,
42`libsamplerate`_, `libsndfile`_, `libfftw3`_.228`libsamplerate`_, `libsndfile`_, `libfftw3`_.
43 229
230To build a fat binary on a darwin like system (macOS, tvOS, appleOS, ...)
231platforms, configure with ``--enable-fat``.
232
44Windows233Windows
45.......234.......
46 235
@@ -86,7 +275,7 @@ and on iOS Simulator: · 39 unmodified lines
86Set ``CFLAGS`` and ``LINKFLAGS`` to change these default values, or edit275Set ``CFLAGS`` and ``LINKFLAGS`` to change these default values, or edit
87``wscript`` directly.276``wscript`` directly.
88 277
89Build options278Other options
90-------------279-------------
91 280
92Some additional options can be passed to the configure step. For the complete281Some additional options can be passed to the configure step. For the complete
@@ -94,105 +283,91 @@ list of options, run: · 1 unmodified line
94 283
95.. code:: bash284.. code:: bash
96 285
97 $ ./waf configure --help286 $ ./waf --help
98
99Double precision
100................
101
102To compile aubio in double precision mode, configure with ``--enable-double``.
103
104To compile aubio in single precision mode, use ``--disable-double`` (default).
105
106Fat binary
107..........
108
109To build a fat binary on Mac OS platforms, configure with ``--enable-fat``.
110
111External libraries
112------------------
113
114External libraries are checked for using ``pkg-config``. Set the
115``PKG_CONFIG_PATH`` environment variable if you have them installed in an
116unusual location.
117 287
288Here is an example of a custom command:
118 289
119.. note::290.. code:: bash
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
124libav
125.....
126
127 `libav.org <https://libav.org/>`_, open source audio and video processing
128 tools.
129
130If 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
132from all formats supported by `libav
133<https://libav.org/documentation/general.html#Audio-Codecs>`_.
134
135* libavcodec
136* libavformat
137* libavutil
138* libavresample
139
140To enable this option, configure with ``--enable-avcodec``. The build will then
141failed if the required libraries are not found. To disable this option,
142configure with ``--disable-avcodec``
143 291
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
144 299
145libsndfile300.. _doubleprecision:
146..........
147 301
148 `libsndfile <http://www.mega-nerd.com/libsndfile/>`_, a C library for reading302Double precision
149 and writing sampled sound files.303................
150 304
151With libsndfile built in, ``aubio_source_sndfile`` will be built in and used by305The datatype used to store real numbers in aubio is named `smpl_t`. By default,
152``aubio_source``.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
309higher precision, for instance to prevent arithmetic underflow in recursive
310filters. In aubio, these special samples are named `lsmp_t` and defined as
311`double` by default (64-bit).
312
313Sometimes it may be useful to compile aubio in `double-precision`, for instance
314to reproduce numerical results obtained with 64-bit routines. In this case,
315`smpl_t` will be defined as `double`.
316
317The following table shows how `smpl_t` and `lsmp_t` are defined in single- and
318double-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``
153 332
154To enable this option, configure with ``--enable-sndfile``. The build will then333To compile aubio in double precision mode, configure with ``--enable-double``.
155fail if the required library is not found. To disable this option, configure
156with ``--disable-sndfile``
157 334
158libsamplerate335To compile in single-precision mode (default), use ``--disable-double`` (or
159.............336simply none of these two options).
160 337
161 `libsamplerate <http://www.mega-nerd.com/SRC/>`_, a sample rate converter for338Disabling the tests
162 audio.339...................
163 340
164With libsamplerate built in, ``aubio_source_sndfile`` will support resampling,341In some case, for instance when cross-compiling, unit tests should not be run.
165and ``aubio_resample`` will be fully functional.342Option ``--notests`` can be used for this purpose. The tests will not be
343executed, but the binaries will be compiled, ensuring that linking against
344libaubio works as expected.
166 345
167To enable this option, configure with ``--enable-samplerate``. The build will346.. note::
168then fail if the required library is not found. To disable this option,
169configure with ``--disable-samplerate``
170 347
171libfftw3348 The ``--notests`` option should be passed to both ``build`` and ``install``
172........349 targets, otherwise waf will try to run them.
173 350
174 `FFTW <http://fftw.org/>`_, a C subroutine for computing the discrete Fourier351Edit wscript
175 transform352............
176 353
177With libfftw3 built in, ``aubio_fft`` will use `FFTW`_ to354Many of the options are gathered in the file `wscript`. a good starting point
178compute Fast Fourier Transform (FFT), allowing aubio to compute FFT on length355when looking for additional options.
179that are not a power of 2.
180 356
181To enable this option, configure with ``--enable-fftw3``. The build will357.. _build_docs:
182then fail if the required library is not found. To disable this option,
183configure with ``--disable-fftw3``
184 358
185External tools359Building the docs
186--------------360-----------------
187 361
188If the following tools are found, additional documentations are built:362If the following command line tools are found, the documentation will be built
363built:
189 364
190 - `doxygen <http://doxygen.org>`_ to build the :ref:`doxygen-documentation`.365 - `doxygen <http://doxygen.org>`_ to build the :ref:`doxygen-documentation`.
191 - `txt2man <https://github.com/mvertes/txt2man>`_ to build the :ref:`manpages`366 - `txt2man <https://github.com/mvertes/txt2man>`_ to build the :ref:`manpages`
367 - `sphinx <http://sphinx-doc.org>`_ to build this document
192 368
193These tools are searched for in the current ``PATH`` environment variable.369These tools are searched for in the current ``PATH`` environment variable.
194By default, the documentation is built only if the tools are found.370By default, the documentation is built only if the tools are found.
195 371
196To disable the documentation, configure with ``--disable-docs``. To build with372To disable the documentation, configure with ``--disable-docs``. To build with
197the documentation, configure with ``--enable-docs``.373the documentation, configure with ``--enable-docs``.
198
doc/statuslinks.rst+24−0
@@ -0,0 +1,24 @@
1Current 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.81# Doxyfile 1.8.13
2 2
3# This file describes the settings to be used by the documentation system3# This file describes the settings to be used by the documentation system
4# doxygen (www.doxygen.org) for a project.4# doxygen (www.doxygen.org) for a project.
@@ -38,7 +38,7 @@ PROJECT_NAME = aubio · 33 unmodified lines
38# could be handy for archiving the generated documentation or if some version38# could be handy for archiving the generated documentation or if some version
39# control system is used.39# control system is used.
40 40
41PROJECT_NUMBER = "0.4.2~alpha"41PROJECT_NUMBER = "latest"
42 42
43# Using the PROJECT_BRIEF tag one can provide an optional one line description43# 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 a44# 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
46 46
47PROJECT_BRIEF =47PROJECT_BRIEF =
48 48
49# With the PROJECT_LOGO tag one can specify an logo or icon that is included in49# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
50# the documentation. The maximum height of the logo should not exceed 55 pixels50# in the documentation. The maximum height of the logo should not exceed 55
51# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo51# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
52# to the output directory.52# the logo to the output directory.
53 53
54PROJECT_LOGO =54PROJECT_LOGO =
55 55
@@ -60,7 +60,7 @@ PROJECT_LOGO = · 4 unmodified lines
60 60
61OUTPUT_DIRECTORY = web61OUTPUT_DIRECTORY = web
62 62
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-
64# directories (in 2 levels) under the output directory of each output format and64# directories (in 2 levels) under the output directory of each output format and
65# will distribute the generated files over these directories. Enabling this65# will distribute the generated files over these directories. Enabling this
66# option can be useful when feeding doxygen a huge amount of source files, where66# 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
93 93
94OUTPUT_LANGUAGE = English94OUTPUT_LANGUAGE = English
95 95
96# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member96# 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 class97# descriptions after the members that are listed in the file and class
98# documentation (similar to Javadoc). Set to NO to disable this.98# documentation (similar to Javadoc). Set to NO to disable this.
99# The default value is: YES.99# The default value is: YES.
100 100
101BRIEF_MEMBER_DESC = YES101BRIEF_MEMBER_DESC = YES
102 102
103# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief103# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
104# description of a member or function before the detailed description104# description of a member or function before the detailed description
105#105#
106# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the106# 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
135 135
136INLINE_INHERITED_MEMB = NO136INLINE_INHERITED_MEMB = NO
137 137
138# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path138# 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 the139# 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 used140# shortest path that makes the file name unique will be used
141# The default value is: YES.141# The default value is: YES.
@@ -205,9 +205,9 @@ MULTILINE_CPP_IS_BRIEF = NO · 63 unmodified lines
205 205
206INHERIT_DOCS = YES206INHERIT_DOCS = YES
207 207
208# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a208# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
209# new page for each member. If set to NO, the documentation of a member will be209# page for each member. If set to NO, the documentation of a member will be part
210# part of the file/class/namespace that contains it.210# of the file/class/namespace that contains it.
211# The default value is: NO.211# The default value is: NO.
212 212
213SEPARATE_MEMBER_PAGES = NO213SEPARATE_MEMBER_PAGES = NO
@@ -276,7 +276,7 @@ OPTIMIZE_OUTPUT_VHDL = NO · 62 unmodified lines
276# instance to make doxygen treat .inc files as Fortran files (default is PHP),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.277# and .f files as C (default is Fortran), use: inc=Fortran f=C.
278#278#
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.
280#280#
281# Note that for custom extensions you also need to set FILE_PATTERNS otherwise281# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
282# the files are not read by doxygen.282# the files are not read by doxygen.
@@ -293,10 +293,19 @@ EXTENSION_MAPPING = · 10 unmodified lines
293 293
294MARKDOWN_SUPPORT = YES294MARKDOWN_SUPPORT = YES
295 295
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
303TOC_INCLUDE_HEADINGS = 0
304
296# When enabled doxygen tries to link words that correspond to documented305# When enabled doxygen tries to link words that correspond to documented
297# classes, or namespaces to their corresponding documentation. Such a link can306# 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 word307# be prevented in individual cases by putting a % sign in front of the word or
299# or globally by setting AUTOLINK_SUPPORT to NO.308# globally by setting AUTOLINK_SUPPORT to NO.
300# The default value is: YES.309# The default value is: YES.
301 310
302AUTOLINK_SUPPORT = YES311AUTOLINK_SUPPORT = YES
@@ -336,13 +345,20 @@ SIP_SUPPORT = NO · 33 unmodified lines
336IDL_PROPERTY_SUPPORT = YES345IDL_PROPERTY_SUPPORT = YES
337 346
338# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC347# 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 first348# 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 default349# 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.350# all members of a group must be documented explicitly.
342# The default value is: NO.351# The default value is: NO.
343 352
344DISTRIBUTE_GROUP_DOC = NO353DISTRIBUTE_GROUP_DOC = NO
345 354
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
360GROUP_NESTED_COMPOUNDS = NO
361
346# Set the SUBGROUPING tag to YES to allow class member groups of the same type362# 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 that363# (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 prevent364# 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
401# Build related configuration options417# Build related configuration options
402#---------------------------------------------------------------------------418#---------------------------------------------------------------------------
403 419
404# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in420# 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. Private421# documentation are documented, even if no documentation was available. Private
406# class members and static file members will be hidden unless the422# class members and static file members will be hidden unless the
407# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.423# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -411,35 +427,35 @@ LOOKUP_CACHE_SIZE = 0 · 3 unmodified lines
411 427
412EXTRACT_ALL = NO428EXTRACT_ALL = NO
413 429
414# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will430# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
415# be included in the documentation.431# be included in the documentation.
416# The default value is: NO.432# The default value is: NO.
417 433
418EXTRACT_PRIVATE = NO434EXTRACT_PRIVATE = NO
419 435
420# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal436# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
421# scope will be included in the documentation.437# scope will be included in the documentation.
422# The default value is: NO.438# The default value is: NO.
423 439
424EXTRACT_PACKAGE = NO440EXTRACT_PACKAGE = NO
425 441
426# If the EXTRACT_STATIC tag is set to YES all static members of a file will be442# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
427# included in the documentation.443# included in the documentation.
428# The default value is: NO.444# The default value is: NO.
429 445
430EXTRACT_STATIC = NO446EXTRACT_STATIC = NO
431 447
432# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined448# 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 NO449# 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 effect450# only classes defined in header files are included. Does not have any effect
435# for Java sources.451# for Java sources.
436# The default value is: YES.452# The default value is: YES.
437 453
438EXTRACT_LOCAL_CLASSES = YES454EXTRACT_LOCAL_CLASSES = YES
439 455
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,
441# which are defined in the implementation section but not in the interface are457# 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 are458# included in the documentation. If set to NO, only methods in the interface are
443# included.459# included.
444# The default value is: NO.460# The default value is: NO.
445 461
@@ -464,21 +480,21 @@ HIDE_UNDOC_MEMBERS = NO · 18 unmodified lines
464 480
465# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all481# 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 set482# 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 has483# to NO, these classes will be included in the various overviews. This option
468# no effect if EXTRACT_ALL is enabled.484# has no effect if EXTRACT_ALL is enabled.
469# The default value is: NO.485# The default value is: NO.
470 486
471HIDE_UNDOC_CLASSES = NO487HIDE_UNDOC_CLASSES = NO
472 488
473# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend489# 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 be490# (class|struct|union) declarations. If set to NO, these declarations will be
475# included in the documentation.491# included in the documentation.
476# The default value is: NO.492# The default value is: NO.
477 493
478HIDE_FRIEND_COMPOUNDS = NO494HIDE_FRIEND_COMPOUNDS = NO
479 495
480# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any496# 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 these497# 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.498# blocks will be appended to the function's detailed documentation block.
483# The default value is: NO.499# The default value is: NO.
484 500
@@ -492,7 +508,7 @@ HIDE_IN_BODY_DOCS = NO · 7 unmodified lines
492INTERNAL_DOCS = NO508INTERNAL_DOCS = NO
493 509
494# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file510# 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 also511# 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 differ512# 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. Windows513# 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.514# and Mac users are advised to set this option to NO.
@@ -501,12 +517,19 @@ INTERNAL_DOCS = NO · 2 unmodified lines
501CASE_SENSE_NAMES = NO517CASE_SENSE_NAMES = NO
502 518
503# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with519# 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 the520# their full class and namespace scopes in the documentation. If set to YES, the
505# scope will be hidden.521# scope will be hidden.
506# The default value is: NO.522# The default value is: NO.
507 523
508HIDE_SCOPE_NAMES = NO524HIDE_SCOPE_NAMES = NO
509 525
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
531HIDE_COMPOUND_REFERENCE= NO
532
510# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of533# 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.534# the files that are included by a file in the documentation of that file.
512# The default value is: YES.535# The default value is: YES.
@@ -534,14 +557,14 @@ INLINE_INFO = YES · 21 unmodified lines
534 557
535# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the558# 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 member559# (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.
538# The default value is: YES.561# The default value is: YES.
539 562
540SORT_MEMBER_DOCS = YES563SORT_MEMBER_DOCS = YES
541 564
542# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief565# 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 member566# descriptions of file, namespace and class members alphabetically by member
544# name. If set to NO the members will appear in declaration order. Note that567# 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.568# this will also influence the order of the classes in the class list.
546# The default value is: NO.569# The default value is: NO.
547 570
@@ -586,27 +609,25 @@ SORT_BY_SCOPE_NAME = NO · 38 unmodified lines
586 609
587STRICT_PROTO_MATCHING = NO610STRICT_PROTO_MATCHING = NO
588 611
589# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the612# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
590# todo list. This list is created by putting \todo commands in the613# list. This list is created by putting \todo commands in the documentation.
591# documentation.
592# The default value is: YES.614# The default value is: YES.
593 615
594GENERATE_TODOLIST = YES616GENERATE_TODOLIST = YES
595 617
596# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the618# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
597# test list. This list is created by putting \test commands in the619# list. This list is created by putting \test commands in the documentation.
598# documentation.
599# The default value is: YES.620# The default value is: YES.
600 621
601GENERATE_TESTLIST = YES622GENERATE_TESTLIST = YES
602 623
603# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug624# 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.625# list. This list is created by putting \bug commands in the documentation.
605# The default value is: YES.626# The default value is: YES.
606 627
607GENERATE_BUGLIST = YES628GENERATE_BUGLIST = YES
608 629
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)
610# the deprecated list. This list is created by putting \deprecated commands in631# the deprecated list. This list is created by putting \deprecated commands in
611# the documentation.632# the documentation.
612# The default value is: YES.633# The default value is: YES.
@@ -631,8 +652,8 @@ ENABLED_SECTIONS = · 18 unmodified lines
631MAX_INITIALIZER_LINES = 30652MAX_INITIALIZER_LINES = 30
632 653
633# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at654# 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 list655# the bottom of the documentation of classes and structs. If set to YES, the
635# will mention the files that were used to generate the documentation.656# list will mention the files that were used to generate the documentation.
636# The default value is: YES.657# The default value is: YES.
637 658
638SHOW_USED_FILES = YES659SHOW_USED_FILES = YES
@@ -696,7 +717,7 @@ CITE_BIB_FILES = · 57 unmodified lines
696QUIET = NO717QUIET = NO
697 718
698# The WARNINGS tag can be used to turn on/off the warning messages that are719# 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 YES720# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
700# this implies that the warnings are on.721# this implies that the warnings are on.
701#722#
702# Tip: Turn warnings on while writing the documentation.723# Tip: Turn warnings on while writing the documentation.
@@ -704,7 +725,7 @@ QUIET = NO · 1 unmodified line
704 725
705WARNINGS = YES726WARNINGS = YES
706 727
707# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate728# 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 flag729# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
709# will automatically be disabled.730# will automatically be disabled.
710# The default value is: YES.731# The default value is: YES.
@@ -721,12 +742,18 @@ WARN_IF_DOC_ERROR = YES · 10 unmodified lines
721 742
722# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that743# 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 return744# 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 parameter745# value. If set to NO, doxygen will only warn about wrong or incomplete
725# documentation, but not about the absence of documentation.746# parameter documentation, but not about the absence of documentation.
726# The default value is: NO.747# The default value is: NO.
727 748
728WARN_NO_PARAMDOC = NO749WARN_NO_PARAMDOC = NO
729 750
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
755WARN_AS_ERROR = NO
756
730# The WARN_FORMAT tag determines the format of the warning messages that doxygen757# 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, which758# 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 originated759# will be replaced by the file and line number from which the warning originated
@@ -750,7 +777,7 @@ WARN_LOGFILE = · 17 unmodified lines
750# The INPUT tag is used to specify the files and/or directories that contain777# 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 or778# documented source files. You may enter file names like myfile.cpp or
752# directories like /usr/src/myproject. Separate the files or directories with779# directories like /usr/src/myproject. Separate the files or directories with
753# spaces.780# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
754# Note: If this tag is empty the current directory is searched.781# Note: If this tag is empty the current directory is searched.
755 782
756INPUT = ../src783INPUT = ../src
@@ -766,12 +793,17 @@ INPUT_ENCODING = UTF-8 · 9 unmodified lines
766 793
767# If the value of the INPUT tag contains directories, you can use the794# 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 and795# 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 the796# *.h) to filter out the source-files in the directories.
770# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,797#
771# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,798# Note that for custom extensions or not directly supported extensions you also
772# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,799# need to set EXTENSION_MAPPING for the extension otherwise the files are not
773# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,800# read by doxygen.
774# *.qsf, *.as and *.js.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.
775 807
776FILE_PATTERNS = *.h808FILE_PATTERNS = *.h
777 809
@@ -790,6 +822,7 @@ RECURSIVE = YES · 12 unmodified lines
790 822
791EXCLUDE = ../src/aubio_priv.h \823EXCLUDE = ../src/aubio_priv.h \
792 ../src/mathutils.h \824 ../src/mathutils.h \
825 ../src/io/ioutils.h \
793 ../src/io/audio_unit.h \826 ../src/io/audio_unit.h \
794 ../src/io/source_sndfile.h \827 ../src/io/source_sndfile.h \
795 ../src/io/source_apple_audio.h \828 ../src/io/source_apple_audio.h \
@@ -802,6 +835,7 @@ EXCLUDE = ../src/aubio_priv.h \ · 6 unmodified lines
802 ../src/pitch/pitchmcomb.h \835 ../src/pitch/pitchmcomb.h \
803 ../src/pitch/pitchyin.h \836 ../src/pitch/pitchyin.h \
804 ../src/pitch/pitchyinfft.h \837 ../src/pitch/pitchyinfft.h \
838 ../src/pitch/pitchyinfast.h \
805 ../src/pitch/pitchschmitt.h \839 ../src/pitch/pitchschmitt.h \
806 ../src/pitch/pitchfcomb.h \840 ../src/pitch/pitchfcomb.h \
807 ../src/pitch/pitchspecacf.h \841 ../src/pitch/pitchspecacf.h \
@@ -878,6 +912,10 @@ IMAGE_PATH = · 70 unmodified lines
878# Note that the filter must not add or remove lines; it is applied before the912# Note that the filter must not add or remove lines; it is applied before the
879# code is scanned, but not when the output code is generated. If lines are added913# code is scanned, but not when the output code is generated. If lines are added
880# or removed, the anchors will not be placed correctly.914# 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.
881 919
882INPUT_FILTER =920INPUT_FILTER =
883 921
@@ -887,11 +925,15 @@ INPUT_FILTER = · 3 unmodified lines
887# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how925# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
888# filters are used. If the FILTER_PATTERNS tag is empty or if none of the926# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
889# patterns match the file name, INPUT_FILTER is applied.927# 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.
890 932
891FILTER_PATTERNS =933FILTER_PATTERNS =
892 934
893# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using935# 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 for936# INPUT_FILTER) will also be used to filter the input files that are used for
895# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).937# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
896# The default value is: NO.938# The default value is: NO.
897 939
@@ -951,7 +993,7 @@ REFERENCED_BY_RELATION = YES · 53 unmodified lines
951REFERENCES_RELATION = YES993REFERENCES_RELATION = YES
952 994
953# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set995# 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 and996# to YES then the hyperlinks from functions in REFERENCES_RELATION and
955# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will997# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
956# link to the documentation.998# link to the documentation.
957# The default value is: YES.999# The default value is: YES.
@@ -998,13 +1040,13 @@ USE_HTAGS = NO · 40 unmodified lines
998 1040
999VERBATIM_HEADERS = YES1041VERBATIM_HEADERS = YES
1000 1042
1001# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the1043# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
1002# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the1044# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
1003# cost of reduced performance. This can be particularly helpful with template1045# cost of reduced performance. This can be particularly helpful with template
1004# rich C++ code for which doxygen's built-in parser lacks the necessary type1046# rich C++ code for which doxygen's built-in parser lacks the necessary type
1005# information.1047# information.
1006# Note: The availability of this option depends on whether or not doxygen was1048# 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.
1008# The default value is: NO.1050# The default value is: NO.
1009 1051
1010CLANG_ASSISTED_PARSING = NO1052CLANG_ASSISTED_PARSING = NO
@@ -1047,7 +1089,7 @@ IGNORE_PREFIX = · 36 unmodified lines
1047# Configuration options related to the HTML output1089# Configuration options related to the HTML output
1048#---------------------------------------------------------------------------1090#---------------------------------------------------------------------------
1049 1091
1050# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output1092# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
1051# The default value is: YES.1093# The default value is: YES.
1052 1094
1053GENERATE_HTML = YES1095GENERATE_HTML = YES
@@ -1113,10 +1155,10 @@ HTML_STYLESHEET = · 59 unmodified lines
1113# cascading style sheets that are included after the standard style sheets1155# cascading style sheets that are included after the standard style sheets
1114# created by doxygen. Using this option one can overrule certain style aspects.1156# created by doxygen. Using this option one can overrule certain style aspects.
1115# This is preferred over using HTML_STYLESHEET since it does not replace the1157# 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.
1117# Doxygen will copy the style sheet files to the output directory.1159# 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 last1160# Note: The order of the extra style sheet files is of importance (e.g. the last
1119# stylesheet in the list overrules the setting of the previous ones in the1161# style sheet in the list overrules the setting of the previous ones in the
1120# list). For an example see the documentation.1162# list). For an example see the documentation.
1121# This tag requires that the tag GENERATE_HTML is set to YES.1163# This tag requires that the tag GENERATE_HTML is set to YES.
1122 1164
@@ -1133,7 +1175,7 @@ HTML_EXTRA_STYLESHEET = · 10 unmodified lines
1133HTML_EXTRA_FILES =1175HTML_EXTRA_FILES =
1134 1176
1135# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen1177# 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 to1178# will adjust the colors in the style sheet and background images according to
1137# this color. Hue is specified as an angle on a colorwheel, see1179# this color. Hue is specified as an angle on a colorwheel, see
1138# http://en.wikipedia.org/wiki/Hue for more information. For instance the value1180# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
1139# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 3001181# 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
1164 1206
1165# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML1207# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1166# page will contain the date and time when the page was generated. Setting this1208# 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.1209# to YES can help to show when doxygen was last run and thus if the
1168# The default value is: YES.1210# documentation is up to date.
1211# The default value is: NO.
1169# This tag requires that the tag GENERATE_HTML is set to YES.1212# This tag requires that the tag GENERATE_HTML is set to YES.
1170 1213
1171HTML_TIMESTAMP = NO1214HTML_TIMESTAMP = NO
@@ -1261,28 +1304,28 @@ GENERATE_HTMLHELP = NO · 89 unmodified lines
1261CHM_FILE =1304CHM_FILE =
1262 1305
1263# The HHC_LOCATION tag can be used to specify the location (absolute path1306# 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-empty1307# including file name) of the HTML help compiler (hhc.exe). If non-empty,
1265# doxygen will try to run the HTML help compiler on the generated index.hhp.1308# doxygen will try to run the HTML help compiler on the generated index.hhp.
1266# The file has to be specified with full path.1309# The file has to be specified with full path.
1267# This tag requires that the tag GENERATE_HTMLHELP is set to YES.1310# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1268 1311
1269HHC_LOCATION =1312HHC_LOCATION =
1270 1313
1271# The GENERATE_CHI flag controls if a separate .chi index file is generated (1314# 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).1315# (YES) or that it should be included in the master .chm file (NO).
1273# The default value is: NO.1316# The default value is: NO.
1274# This tag requires that the tag GENERATE_HTMLHELP is set to YES.1317# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1275 1318
1276GENERATE_CHI = NO1319GENERATE_CHI = NO
1277 1320
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)
1279# and project file content.1322# and project file content.
1280# This tag requires that the tag GENERATE_HTMLHELP is set to YES.1323# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1281 1324
1282CHM_INDEX_ENCODING =1325CHM_INDEX_ENCODING =
1283 1326
1284# The BINARY_TOC flag controls whether a binary table of contents is generated (1327# 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 it1328# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
1286# enables the Previous and Next buttons.1329# enables the Previous and Next buttons.
1287# The default value is: NO.1330# The default value is: NO.
1288# This tag requires that the tag GENERATE_HTMLHELP is set to YES.1331# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1396,7 +1439,7 @@ DISABLE_INDEX = NO · 107 unmodified lines
1396# index structure (just like the one that is generated for HTML Help). For this1439# index structure (just like the one that is generated for HTML Help). For this
1397# to work a browser that supports JavaScript, DHTML, CSS and frames is required1440# to work a browser that supports JavaScript, DHTML, CSS and frames is required
1398# (i.e. any modern browser). Windows users are probably better off using the1441# (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 can1442# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
1400# further fine-tune the look of the index. As an example, the default style1443# further fine-tune the look of the index. As an example, the default style
1401# sheet generated by doxygen has an example that shows how to put an image at1444# sheet generated by doxygen has an example that shows how to put an image at
1402# the root of the tree instead of the PROJECT_NAME. Since the tree basically has1445# 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
1424 1467
1425TREEVIEW_WIDTH = 2501468TREEVIEW_WIDTH = 250
1426 1469
1427# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to1470# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
1428# external symbols imported via tag files in a separate window.1471# external symbols imported via tag files in a separate window.
1429# The default value is: NO.1472# The default value is: NO.
1430# This tag requires that the tag GENERATE_HTML is set to YES.1473# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1453,7 +1496,7 @@ FORMULA_TRANSPARENT = YES · 22 unmodified lines
1453 1496
1454# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see1497# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1455# http://www.mathjax.org) which uses client side Javascript for the rendering1498# 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 LaTeX1499# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
1457# installed or if you want to formulas look prettier in the HTML output. When1500# installed or if you want to formulas look prettier in the HTML output. When
1458# enabled you may also need to install MathJax separately and configure the path1501# enabled you may also need to install MathJax separately and configure the path
1459# to it using the MATHJAX_RELPATH option.1502# to it using the MATHJAX_RELPATH option.
@@ -1483,7 +1526,7 @@ MATHJAX_FORMAT = HTML-CSS · 23 unmodified lines
1483# The default value is: http://cdn.mathjax.org/mathjax/latest.1526# The default value is: http://cdn.mathjax.org/mathjax/latest.
1484# This tag requires that the tag USE_MATHJAX is set to YES.1527# This tag requires that the tag USE_MATHJAX is set to YES.
1485 1528
1486MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest1529MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
1487 1530
1488# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax1531# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1489# extension names that should be enabled during MathJax rendering. For example1532# extension names that should be enabled during MathJax rendering. For example
@@ -1539,7 +1582,7 @@ SERVER_BASED_SEARCH = NO · 49 unmodified lines
1539# external search engine pointed to by the SEARCHENGINE_URL option to obtain the1582# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1540# search results.1583# search results.
1541#1584#
1542# Doxygen ships with an example indexer ( doxyindexer) and search engine1585# Doxygen ships with an example indexer (doxyindexer) and search engine
1543# (doxysearch.cgi) which are based on the open source search engine library1586# (doxysearch.cgi) which are based on the open source search engine library
1544# Xapian (see: http://xapian.org/).1587# Xapian (see: http://xapian.org/).
1545#1588#
@@ -1552,7 +1595,7 @@ EXTERNAL_SEARCH = NO · 6 unmodified lines
1552# The SEARCHENGINE_URL should point to a search engine hosted by a web server1595# The SEARCHENGINE_URL should point to a search engine hosted by a web server
1553# which will return the search results when EXTERNAL_SEARCH is enabled.1596# which will return the search results when EXTERNAL_SEARCH is enabled.
1554#1597#
1555# Doxygen ships with an example indexer ( doxyindexer) and search engine1598# Doxygen ships with an example indexer (doxyindexer) and search engine
1556# (doxysearch.cgi) which are based on the open source search engine library1599# (doxysearch.cgi) which are based on the open source search engine library
1557# Xapian (see: http://xapian.org/). See the section "External Indexing and1600# Xapian (see: http://xapian.org/). See the section "External Indexing and
1558# Searching" for details.1601# Searching" for details.
@@ -1590,7 +1633,7 @@ EXTRA_SEARCH_MAPPINGS = · 31 unmodified lines
1590# Configuration options related to the LaTeX output1633# Configuration options related to the LaTeX output
1591#---------------------------------------------------------------------------1634#---------------------------------------------------------------------------
1592 1635
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.
1594# The default value is: YES.1637# The default value is: YES.
1595 1638
1596GENERATE_LATEX = NO1639GENERATE_LATEX = NO
@@ -1621,7 +1664,7 @@ LATEX_CMD_NAME = latex · 24 unmodified lines
1621 1664
1622MAKEINDEX_CMD_NAME = makeindex1665MAKEINDEX_CMD_NAME = makeindex
1623 1666
1624# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX1667# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
1625# documents. This may be useful for small projects and may help to save some1668# documents. This may be useful for small projects and may help to save some
1626# trees in general.1669# trees in general.
1627# The default value is: NO.1670# The default value is: NO.
@@ -1639,9 +1682,12 @@ COMPACT_LATEX = NO · 11 unmodified lines
1639PAPER_TYPE = a41682PAPER_TYPE = a4
1640 1683
1641# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names1684# 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 for1685# that should be included in the LaTeX output. The package can be specified just
1643# instance you can specify1686# by its name or with the correct syntax as to be used with the LaTeX
1644# EXTRA_PACKAGES=times1687# \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}
1645# If left blank no extra packages will be included.1691# If left blank no extra packages will be included.
1646# This tag requires that the tag GENERATE_LATEX is set to YES.1692# This tag requires that the tag GENERATE_LATEX is set to YES.
1647 1693
@@ -1656,9 +1702,9 @@ EXTRA_PACKAGES = · 8 unmodified lines
1656# Note: Only use a user-defined header if you know what you are doing! The1702# Note: Only use a user-defined header if you know what you are doing! The
1657# following commands have a special meaning inside the header: $title,1703# following commands have a special meaning inside the header: $title,
1658# $datetime, $date, $doxygenversion, $projectname, $projectnumber,1704# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1659# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,1705# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
1660# for the replacement values of the other commands the user is refered to1706# string, for the replacement values of the other commands the user is referred
1661# HTML_HEADER.1707# to HTML_HEADER.
1662# This tag requires that the tag GENERATE_LATEX is set to YES.1708# This tag requires that the tag GENERATE_LATEX is set to YES.
1663 1709
1664LATEX_HEADER =1710LATEX_HEADER =
@@ -1674,6 +1720,17 @@ LATEX_HEADER = · 9 unmodified lines
1674 1720
1675LATEX_FOOTER =1721LATEX_FOOTER =
1676 1722
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
1732LATEX_EXTRA_STYLESHEET =
1733
1677# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or1734# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1678# other source files which should be copied to the LATEX_OUTPUT output1735# other source files which should be copied to the LATEX_OUTPUT output
1679# directory. Note that the files will be copied as-is; there are no commands or1736# 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
1692PDF_HYPERLINKS = YES1749PDF_HYPERLINKS = YES
1693 1750
1694# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate1751# 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 a1752# the PDF file directly from the LaTeX files. Set this option to YES, to get a
1696# higher quality PDF documentation.1753# higher quality PDF documentation.
1697# The default value is: YES.1754# The default value is: YES.
1698# This tag requires that the tag GENERATE_LATEX is set to YES.1755# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1733,11 +1790,19 @@ LATEX_SOURCE_CODE = NO · 34 unmodified lines
1733 1790
1734LATEX_BIB_STYLE = plain1791LATEX_BIB_STYLE = plain
1735 1792
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
1799LATEX_TIMESTAMP = NO
1800
1736#---------------------------------------------------------------------------1801#---------------------------------------------------------------------------
1737# Configuration options related to the RTF output1802# Configuration options related to the RTF output
1738#---------------------------------------------------------------------------1803#---------------------------------------------------------------------------
1739 1804
1740# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The1805# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
1741# RTF output is optimized for Word 97 and may not look too pretty with other RTF1806# RTF output is optimized for Word 97 and may not look too pretty with other RTF
1742# readers/editors.1807# readers/editors.
1743# The default value is: NO.1808# The default value is: NO.
@@ -1752,7 +1817,7 @@ GENERATE_RTF = NO · 8 unmodified lines
1752 1817
1753RTF_OUTPUT = rtf1818RTF_OUTPUT = rtf
1754 1819
1755# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF1820# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
1756# documents. This may be useful for small projects and may help to save some1821# documents. This may be useful for small projects and may help to save some
1757# trees in general.1822# trees in general.
1758# The default value is: NO.1823# The default value is: NO.
@@ -1789,11 +1854,21 @@ RTF_STYLESHEET_FILE = · 30 unmodified lines
1789 1854
1790RTF_EXTENSIONS_FILE =1855RTF_EXTENSIONS_FILE =
1791 1856
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
1865RTF_SOURCE_CODE = NO
1866
1792#---------------------------------------------------------------------------1867#---------------------------------------------------------------------------
1793# Configuration options related to the man page output1868# Configuration options related to the man page output
1794#---------------------------------------------------------------------------1869#---------------------------------------------------------------------------
1795 1870
1796# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for1871# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
1797# classes and files.1872# classes and files.
1798# The default value is: NO.1873# The default value is: NO.
1799 1874
@@ -1837,7 +1912,7 @@ MAN_LINKS = NO · 37 unmodified lines
1837# Configuration options related to the XML output1912# Configuration options related to the XML output
1838#---------------------------------------------------------------------------1913#---------------------------------------------------------------------------
1839 1914
1840# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that1915# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
1841# captures the structure of the code including all documentation.1916# captures the structure of the code including all documentation.
1842# The default value is: NO.1917# The default value is: NO.
1843 1918
@@ -1851,7 +1926,7 @@ GENERATE_XML = NO · 7 unmodified lines
1851 1926
1852XML_OUTPUT = xml1927XML_OUTPUT = xml
1853 1928
1854# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program1929# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
1855# listings (including syntax highlighting and cross-referencing information) to1930# listings (including syntax highlighting and cross-referencing information) to
1856# the XML output. Note that enabling this will significantly increase the size1931# the XML output. Note that enabling this will significantly increase the size
1857# of the XML output.1932# of the XML output.
@@ -1864,7 +1939,7 @@ XML_PROGRAMLISTING = YES · 6 unmodified lines
1864# Configuration options related to the DOCBOOK output1939# Configuration options related to the DOCBOOK output
1865#---------------------------------------------------------------------------1940#---------------------------------------------------------------------------
1866 1941
1867# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files1942# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
1868# that can be used to generate PDF.1943# that can be used to generate PDF.
1869# The default value is: NO.1944# The default value is: NO.
1870 1945
@@ -1878,7 +1953,7 @@ GENERATE_DOCBOOK = NO · 7 unmodified lines
1878 1953
1879DOCBOOK_OUTPUT = docbook1954DOCBOOK_OUTPUT = docbook
1880 1955
1881# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the1956# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
1882# program listings (including syntax highlighting and cross-referencing1957# program listings (including syntax highlighting and cross-referencing
1883# information) to the DOCBOOK output. Note that enabling this will significantly1958# information) to the DOCBOOK output. Note that enabling this will significantly
1884# increase the size of the DOCBOOK output.1959# increase the size of the DOCBOOK output.
@@ -1891,10 +1966,10 @@ DOCBOOK_PROGRAMLISTING = NO · 6 unmodified lines
1891# Configuration options for the AutoGen Definitions output1966# Configuration options for the AutoGen Definitions output
1892#---------------------------------------------------------------------------1967#---------------------------------------------------------------------------
1893 1968
1894# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen1969# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
1895# Definitions (see http://autogen.sf.net) file that captures the structure of1970# AutoGen Definitions (see http://autogen.sf.net) file that captures the
1896# the code including all documentation. Note that this feature is still1971# structure of the code including all documentation. Note that this feature is
1897# experimental and incomplete at the moment.1972# still experimental and incomplete at the moment.
1898# The default value is: NO.1973# The default value is: NO.
1899 1974
1900GENERATE_AUTOGEN_DEF = NO1975GENERATE_AUTOGEN_DEF = NO
@@ -1903,7 +1978,7 @@ GENERATE_AUTOGEN_DEF = NO · 2 unmodified lines
1903# Configuration options related to the Perl module output1978# Configuration options related to the Perl module output
1904#---------------------------------------------------------------------------1979#---------------------------------------------------------------------------
1905 1980
1906# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module1981# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
1907# file that captures the structure of the code including all documentation.1982# file that captures the structure of the code including all documentation.
1908#1983#
1909# Note that this feature is still experimental and incomplete at the moment.1984# Note that this feature is still experimental and incomplete at the moment.
@@ -1911,7 +1986,7 @@ GENERATE_AUTOGEN_DEF = NO · 1 unmodified line
1911 1986
1912GENERATE_PERLMOD = NO1987GENERATE_PERLMOD = NO
1913 1988
1914# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary1989# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
1915# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI1990# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
1916# output from the Perl module output.1991# output from the Perl module output.
1917# The default value is: NO.1992# The default value is: NO.
@@ -1919,9 +1994,9 @@ GENERATE_PERLMOD = NO · 1 unmodified line
1919 1994
1920PERLMOD_LATEX = NO1995PERLMOD_LATEX = NO
1921 1996
1922# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely1997# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
1923# formatted so it can be parsed by a human reader. This is useful if you want to1998# 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 the1999# understand what is going on. On the other hand, if this tag is set to NO, the
1925# size of the Perl module output will be much smaller and Perl will parse it2000# size of the Perl module output will be much smaller and Perl will parse it
1926# just the same.2001# just the same.
1927# The default value is: YES.2002# The default value is: YES.
@@ -1941,14 +2016,14 @@ PERLMOD_MAKEVAR_PREFIX = · 13 unmodified lines
1941# Configuration options related to the preprocessor2016# Configuration options related to the preprocessor
1942#---------------------------------------------------------------------------2017#---------------------------------------------------------------------------
1943 2018
1944# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all2019# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
1945# C-preprocessor directives found in the sources and include files.2020# C-preprocessor directives found in the sources and include files.
1946# The default value is: YES.2021# The default value is: YES.
1947 2022
1948ENABLE_PREPROCESSING = YES2023ENABLE_PREPROCESSING = YES
1949 2024
1950# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names2025# 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 be2026# in the source code. If set to NO, only conditional compilation will be
1952# performed. Macro expansion can be done in a controlled way by setting2027# performed. Macro expansion can be done in a controlled way by setting
1953# EXPAND_ONLY_PREDEF to YES.2028# EXPAND_ONLY_PREDEF to YES.
1954# The default value is: NO.2029# The default value is: NO.
@@ -1964,7 +2039,7 @@ MACRO_EXPANSION = NO · 9 unmodified lines
1964 2039
1965EXPAND_ONLY_PREDEF = NO2040EXPAND_ONLY_PREDEF = NO
1966 2041
1967# If the SEARCH_INCLUDES tag is set to YES the includes files in the2042# If the SEARCH_INCLUDES tag is set to YES, the include files in the
1968# INCLUDE_PATH will be searched if a #include is found.2043# INCLUDE_PATH will be searched if a #include is found.
1969# The default value is: YES.2044# The default value is: YES.
1970# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.2045# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2040,20 +2115,21 @@ TAGFILES = · 69 unmodified lines
2040 2115
2041GENERATE_TAGFILE =2116GENERATE_TAGFILE =
2042 2117
2043# If the ALLEXTERNALS tag is set to YES all external class will be listed in the2118# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
2044# class index. If set to NO only the inherited external classes will be listed.2119# the class index. If set to NO, only the inherited external classes will be
2120# listed.
2045# The default value is: NO.2121# The default value is: NO.
2046 2122
2047ALLEXTERNALS = NO2123ALLEXTERNALS = NO
2048 2124
2049# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in2125# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
2050# the modules index. If set to NO, only the current project's groups will be2126# in the modules index. If set to NO, only the current project's groups will be
2051# listed.2127# listed.
2052# The default value is: YES.2128# The default value is: YES.
2053 2129
2054EXTERNAL_GROUPS = YES2130EXTERNAL_GROUPS = YES
2055 2131
2056# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in2132# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
2057# the related pages index. If set to NO, only the current project's pages will2133# the related pages index. If set to NO, only the current project's pages will
2058# be listed.2134# be listed.
2059# The default value is: YES.2135# The default value is: YES.
@@ -2070,7 +2146,7 @@ PERL_PATH = /usr/bin/perl · 10 unmodified lines
2070# Configuration options related to the dot tool2146# Configuration options related to the dot tool
2071#---------------------------------------------------------------------------2147#---------------------------------------------------------------------------
2072 2148
2073# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram2149# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
2074# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to2150# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
2075# NO turns the diagrams off. Note that this option also works with HAVE_DOT2151# NO turns the diagrams off. Note that this option also works with HAVE_DOT
2076# disabled, but it is recommended to install and use dot, since it yields more2152# disabled, but it is recommended to install and use dot, since it yields more
@@ -2095,7 +2171,7 @@ MSCGEN_PATH = · 18 unmodified lines
2095 2171
2096DIA_PATH =2172DIA_PATH =
2097 2173
2098# If set to YES, the inheritance and collaboration graphs will hide inheritance2174# If set to YES the inheritance and collaboration graphs will hide inheritance
2099# and usage relations if the target is undocumented or is not a class.2175# and usage relations if the target is undocumented or is not a class.
2100# The default value is: YES.2176# The default value is: YES.
2101 2177
@@ -2168,7 +2244,7 @@ COLLABORATION_GRAPH = YES · 66 unmodified lines
2168 2244
2169GROUP_GRAPHS = YES2245GROUP_GRAPHS = YES
2170 2246
2171# If the UML_LOOK tag is set to YES doxygen will generate inheritance and2247# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
2172# collaboration diagrams in a style similar to the OMG's Unified Modeling2248# collaboration diagrams in a style similar to the OMG's Unified Modeling
2173# Language.2249# Language.
2174# The default value is: NO.2250# The default value is: NO.
@@ -2220,7 +2296,8 @@ INCLUDED_BY_GRAPH = YES · 45 unmodified lines
2220#2296#
2221# Note that enabling this option will significantly increase the time of a run.2297# Note that enabling this option will significantly increase the time of a run.
2222# So in most cases it will be better to enable call graphs for selected2298# 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.
2224# The default value is: NO.2301# The default value is: NO.
2225# This tag requires that the tag HAVE_DOT is set to YES.2302# This tag requires that the tag HAVE_DOT is set to YES.
2226 2303
@@ -2231,7 +2308,8 @@ CALL_GRAPH = NO · 4 unmodified lines
2231#2308#
2232# Note that enabling this option will significantly increase the time of a run.2309# Note that enabling this option will significantly increase the time of a run.
2233# So in most cases it will be better to enable caller graphs for selected2310# 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.
2235# The default value is: NO.2313# The default value is: NO.
2236# This tag requires that the tag HAVE_DOT is set to YES.2314# This tag requires that the tag HAVE_DOT is set to YES.
2237 2315
@@ -2254,13 +2332,17 @@ GRAPHICAL_HIERARCHY = YES · 16 unmodified lines
2254DIRECTORY_GRAPH = YES2332DIRECTORY_GRAPH = YES
2255 2333
2256# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images2334# 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/)).
2258# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order2338# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2259# to make the SVG files visible in IE 9+ (other browsers do not have this2339# to make the SVG files visible in IE 9+ (other browsers do not have this
2260# requirement).2340# requirement).
2261# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,2341# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
2262# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,2342# 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.
2264# The default value is: png.2346# The default value is: png.
2265# This tag requires that the tag HAVE_DOT is set to YES.2347# This tag requires that the tag HAVE_DOT is set to YES.
2266 2348
@@ -2308,10 +2390,19 @@ DIAFILE_DIRS = · 41 unmodified lines
2308# PlantUML is not used or called during a preprocessing step. Doxygen will2390# PlantUML is not used or called during a preprocessing step. Doxygen will
2309# generate a warning when it encounters a \startuml command in this case and2391# generate a warning when it encounters a \startuml command in this case and
2310# will not generate output for the diagram.2392# will not generate output for the diagram.
2311# This tag requires that the tag HAVE_DOT is set to YES.
2312 2393
2313PLANTUML_JAR_PATH =2394PLANTUML_JAR_PATH =
2314 2395
2396# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
2397# configuration file for plantuml.
2398
2399PLANTUML_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
2404PLANTUML_INCLUDE_PATH =
2405
2315# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes2406# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2316# that will be shown in the graph. If the number of nodes in a graph becomes2407# that will be shown in the graph. If the number of nodes in a graph becomes
2317# larger than this value, doxygen will truncate the graph, which is visualized2408# larger than this value, doxygen will truncate the graph, which is visualized
@@ -2348,7 +2439,7 @@ MAX_DOT_GRAPH_DEPTH = 0 · 30 unmodified lines
2348 2439
2349DOT_TRANSPARENT = NO2440DOT_TRANSPARENT = NO
2350 2441
2351# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output2442# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
2352# files in one run (i.e. multiple -o and -T options on the command line). This2443# files in one run (i.e. multiple -o and -T options on the command line). This
2353# makes dot run faster, but since only newer versions of dot (>1.8.10) support2444# makes dot run faster, but since only newer versions of dot (>1.8.10) support
2354# this, this feature is disabled by default.2445# this, this feature is disabled by default.
@@ -2365,7 +2456,7 @@ DOT_MULTI_TARGETS = NO · 10 unmodified lines
2365 2456
2366GENERATE_LEGEND = YES2457GENERATE_LEGEND = YES
2367 2458
2368# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot2459# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
2369# files that are used to generate the various graphs.2460# files that are used to generate the various graphs.
2370# The default value is: YES.2461# The default value is: YES.
2371# This tag requires that the tag HAVE_DOT is set to YES.2462# 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:1Frameworks for Xcode
2 2--------------------
3Using aubio frameworks in Xcode
4-------------------------------
5 3
6`Binary frameworks`_ are available and ready to use in your XCode project, for4`Binary frameworks`_ are available and ready to use in your XCode project, for
7`iOS`_ and `macOS`_.5`iOS`_ and `macOS`_.
@@ -34,7 +32,41 @@ Using aubio frameworks in Xcode · 26 unmodified lines
34 32
35 import aubio33 import aubio
36 34
35Using aubio from swift
36----------------------
37
38Once you have downloaded and installed :ref:`aubio.framework
39<xcode-frameworks-label>`, you sould be able to use aubio from C, Obj-C, and
40Swift source files.
41
42
43Here 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
37.. _Binary frameworks: https://aubio.org/download70.. _Binary frameworks: https://aubio.org/download
38.. _iOS: https://aubio.org/download#ios71.. _iOS: https://aubio.org/download#ios
39.. _macOS: https://aubio.org/download#osx72.. _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
48}48}
49 49
50int main(int argc, char **argv) {50int main(int argc, char **argv) {
51 int ret = 0;
51 // change some default params52 // change some default params
52 buffer_size = 512;53 buffer_size = 512;
53 hop_size = 256;54 hop_size = 256;
@@ -62,6 +63,10 @@ int main(int argc, char **argv) { · 8 unmodified lines
62 fftgrain = new_cvec (buffer_size);63 fftgrain = new_cvec (buffer_size);
63 mfcc = new_aubio_mfcc(buffer_size, n_filters, n_coefs, samplerate);64 mfcc = new_aubio_mfcc(buffer_size, n_filters, n_coefs, samplerate);
64 mfcc_out = new_fvec(n_coefs);65 mfcc_out = new_fvec(n_coefs);
66 if (pv == NULL || fftgrain == NULL || mfcc == NULL || mfcc_out == NULL) {
67 ret = 1;
68 goto beach;
69 }
65 70
66 examples_common_process((aubio_process_func_t)process_block, process_print);71 examples_common_process((aubio_process_func_t)process_block, process_print);
67 72
@@ -70,7 +75,7 @@ int main(int argc, char **argv) { · 2 unmodified lines
70 del_aubio_mfcc(mfcc);75 del_aubio_mfcc(mfcc);
71 del_fvec(mfcc_out);76 del_fvec(mfcc_out);
72 77
78beach:
73 examples_common_del();79 examples_common_del();
74 return 0;80 return ret;
75}81}
76
examples/aubionotes.c+33−6
@@ -21,6 +21,8 @@ · 20 unmodified lines
21#include "utils.h"21#include "utils.h"
22#define PROG_HAS_PITCH 122#define PROG_HAS_PITCH 1
23#define PROG_HAS_ONSET 123#define PROG_HAS_ONSET 1
24#define PROG_HAS_NOTES 1
25#define PROG_HAS_SILENCE 1
24#define PROG_HAS_JACK 126#define PROG_HAS_JACK 1
25// TODO add PROG_HAS_OUTPUT27// TODO add PROG_HAS_OUTPUT
26#include "parse_args.h"28#include "parse_args.h"
@@ -33,12 +35,12 @@ void process_block (fvec_t *ibuf, fvec_t *obuf) · 6 unmodified lines
33 aubio_notes_do (notes, ibuf, obuf);35 aubio_notes_do (notes, ibuf, obuf);
34 // did we get a note off?36 // did we get a note off?
35 if (obuf->data[2] != 0) {37 if (obuf->data[2] != 0) {
36 lastmidi = aubio_freqtomidi (obuf->data[2]) + .5;38 lastmidi = obuf->data[2];
37 send_noteon(lastmidi, 0);39 send_noteon(lastmidi, 0);
38 }40 }
39 // did we get a note on?41 // did we get a note on?
40 if (obuf->data[0] != 0) {42 if (obuf->data[0] != 0) {
41 lastmidi = aubio_freqtomidi (obuf->data[0]) + .5;43 lastmidi = obuf->data[0];
42 send_noteon(lastmidi, obuf->data[1]);44 send_noteon(lastmidi, obuf->data[1]);
43 }45 }
44}46}
@@ -49,6 +51,8 @@ void process_print (void) · 4 unmodified lines
49}51}
50 52
51int main(int argc, char **argv) {53int main(int argc, char **argv) {
54 int ret = 0;
55
52 examples_common_init(argc,argv);56 examples_common_init(argc,argv);
53 57
54 verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);58 verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
@@ -64,15 +68,38 @@ int main(int argc, char **argv) { · 9 unmodified lines
64 verbmsg ("tolerance: %f\n", pitch_tolerance);68 verbmsg ("tolerance: %f\n", pitch_tolerance);
65 69
66 notes = new_aubio_notes ("default", buffer_size, hop_size, samplerate);70 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 }
67 92
68 examples_common_process((aubio_process_func_t)process_block, process_print);93 examples_common_process((aubio_process_func_t)process_block, process_print);
69 94
70 // send a last note off95 // send a last note off if required
71 send_noteon (lastmidi, 0);96 if (lastmidi) {
97 send_noteon (lastmidi, 0);
98 }
72 99
73 del_aubio_notes (notes);100 del_aubio_notes (notes);
74 101
102beach:
75 examples_common_del();103 examples_common_del();
76 return 0;104 return ret;
77}105}
78
examples/aubioonset.c+22−11
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include "utils.h"21#include "utils.h"
22#define PROG_HAS_ONSET 122#define PROG_HAS_ONSET 1
23#define PROG_HAS_OUTPUT 123#define PROG_HAS_OUTPUT 1
24#define PROG_HAS_SILENCE 1
24#define PROG_HAS_JACK 125#define PROG_HAS_JACK 1
25#include "parse_args.h"26#include "parse_args.h"
26 27
@@ -42,10 +43,11 @@ void process_block(fvec_t *ibuf, fvec_t *obuf) · 15 unmodified lines
42 } else {43 } else {
43 aubio_wavetable_stop ( wavetable );44 aubio_wavetable_stop ( wavetable );
44 }45 }
45 if (mix_input)46 if (mix_input) {
46 aubio_wavetable_do (wavetable, ibuf, obuf);47 aubio_wavetable_do (wavetable, ibuf, obuf);
47 else48 } else {
48 aubio_wavetable_do (wavetable, obuf, obuf);49 aubio_wavetable_do (wavetable, obuf, obuf);
50 }
49}51}
50 52
51void process_print (void)53void process_print (void)
@@ -57,20 +59,26 @@ void process_print (void) · 5 unmodified lines
57}59}
58 60
59int main(int argc, char **argv) {61int main(int argc, char **argv) {
62 int ret = 0;
60 examples_common_init(argc,argv);63 examples_common_init(argc,argv);
61 64
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
69 o = new_aubio_onset (onset_method, buffer_size, hop_size, samplerate);65 o = new_aubio_onset (onset_method, buffer_size, hop_size, samplerate);
66 if (o == NULL) { ret = 1; goto beach; }
70 if (onset_threshold != 0.)67 if (onset_threshold != 0.)
71 aubio_onset_set_threshold (o, onset_threshold);68 aubio_onset_set_threshold (o, onset_threshold);
72 if (silence_threshold != -90.)69 if (silence_threshold != -90.)
73 aubio_onset_set_silence (o, silence_threshold);70 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));
74 82
75 onset = new_fvec (1);83 onset = new_fvec (1);
76 84
@@ -81,12 +89,15 @@ int main(int argc, char **argv) { · 4 unmodified lines
81 examples_common_process((aubio_process_func_t)process_block, process_print);89 examples_common_process((aubio_process_func_t)process_block, process_print);
82 90
83 // send a last note off91 // send a last note off
84 send_noteon (miditap_note, 0);92 if (usejack) {
93 send_noteon (miditap_note, 0);
94 }
85 95
86 del_aubio_onset (o);96 del_aubio_onset (o);
87 del_aubio_wavetable (wavetable);97 del_aubio_wavetable (wavetable);
88 del_fvec (onset);98 del_fvec (onset);
89 99
100beach:
90 examples_common_del();101 examples_common_del();
91 return 0;102 return ret;
92}103}
examples/aubiopitch.c+5−2
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include "utils.h"21#include "utils.h"
22#define PROG_HAS_PITCH 122#define PROG_HAS_PITCH 1
23#define PROG_HAS_OUTPUT 123#define PROG_HAS_OUTPUT 1
24#define PROG_HAS_SILENCE 1
24#define PROG_HAS_JACK 125#define PROG_HAS_JACK 1
25#include "parse_args.h"26#include "parse_args.h"
26 27
@@ -51,6 +52,7 @@ void process_print (void) · 24 unmodified lines
51}52}
52 53
53int main(int argc, char **argv) {54int main(int argc, char **argv) {
55 int ret = 0;
54 56
55 buffer_size = 2048;57 buffer_size = 2048;
56 58
@@ -64,6 +66,7 @@ int main(int argc, char **argv) { · 7 unmodified lines
64 verbmsg ("tolerance: %f\n", pitch_tolerance);66 verbmsg ("tolerance: %f\n", pitch_tolerance);
65 67
66 o = new_aubio_pitch (pitch_method, buffer_size, hop_size, samplerate);68 o = new_aubio_pitch (pitch_method, buffer_size, hop_size, samplerate);
69 if (o == NULL) { ret = 1; goto beach; }
67 if (pitch_tolerance != 0.)70 if (pitch_tolerance != 0.)
68 aubio_pitch_set_tolerance (o, pitch_tolerance);71 aubio_pitch_set_tolerance (o, pitch_tolerance);
69 if (silence_threshold != -90.)72 if (silence_threshold != -90.)
@@ -82,7 +85,7 @@ int main(int argc, char **argv) { · 12 unmodified lines
82 del_aubio_wavetable (wavetable);85 del_aubio_wavetable (wavetable);
83 del_fvec (pitch);86 del_fvec (pitch);
84 87
88beach:
85 examples_common_del();89 examples_common_del();
86 return 0;90 return ret;
87}91}
88
examples/aubioquiet.c+1−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
19*/19*/
20 20
21#include "utils.h"21#include "utils.h"
22#define PROG_HAS_SILENCE 1
22#include "parse_args.h"23#include "parse_args.h"
23 24
24sint_t wassilence = 1, issilence;25sint_t wassilence = 1, issilence;
examples/aubiotrack.c+12−5
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include "utils.h"21#include "utils.h"
22#define PROG_HAS_TEMPO 122#define PROG_HAS_TEMPO 1
23#define PROG_HAS_ONSET 123#define PROG_HAS_ONSET 1
24#define PROG_HAS_SILENCE 1
24#define PROG_HAS_OUTPUT 125#define PROG_HAS_OUTPUT 1
25#define PROG_HAS_JACK 126#define PROG_HAS_JACK 1
26#include "parse_args.h"27#include "parse_args.h"
@@ -45,10 +46,11 @@ void process_block(fvec_t * ibuf, fvec_t *obuf) { · 18 unmodified lines
45 } else {46 } else {
46 aubio_wavetable_stop ( wavetable );47 aubio_wavetable_stop ( wavetable );
47 }48 }
48 if (mix_input)49 if (mix_input) {
49 aubio_wavetable_do (wavetable, ibuf, obuf);50 aubio_wavetable_do (wavetable, ibuf, obuf);
50 else51 } else {
51 aubio_wavetable_do (wavetable, obuf, obuf);52 aubio_wavetable_do (wavetable, obuf, obuf);
53 }
52}54}
53 55
54void process_print (void) {56void process_print (void) {
@@ -59,6 +61,7 @@ void process_print (void) { · 4 unmodified lines
59}61}
60 62
61int main(int argc, char **argv) {63int main(int argc, char **argv) {
64 int ret = 0;
62 // override general settings from utils.c65 // override general settings from utils.c
63 buffer_size = 1024;66 buffer_size = 1024;
64 hop_size = 512;67 hop_size = 512;
@@ -74,9 +77,11 @@ int main(int argc, char **argv) { · 9 unmodified lines
74 77
75 tempo_out = new_fvec(2);78 tempo_out = new_fvec(2);
76 tempo = new_aubio_tempo(tempo_method, buffer_size, hop_size, samplerate);79 tempo = new_aubio_tempo(tempo_method, buffer_size, hop_size, samplerate);
80 if (tempo == NULL) { ret = 1; goto beach; }
77 // set silence threshold very low to output beats even during silence81 // set silence threshold very low to output beats even during silence
78 // aubio_tempo_set_silence(tempo, -1000.);82 // aubio_tempo_set_silence(tempo, -1000.);
79 if (onset_threshold != 0.) aubio_tempo_set_threshold (tempo, onset_threshold);83 if (onset_threshold != 0.) aubio_tempo_set_threshold (tempo, onset_threshold);
84 if (onset_minioi != 0.) errmsg ("warning: minioio not supported yet\n");
80 85
81 wavetable = new_aubio_wavetable (samplerate, hop_size);86 wavetable = new_aubio_wavetable (samplerate, hop_size);
82 aubio_wavetable_set_freq ( wavetable, 2450.);87 aubio_wavetable_set_freq ( wavetable, 2450.);
@@ -85,13 +90,15 @@ int main(int argc, char **argv) { · 2 unmodified lines
85 examples_common_process((aubio_process_func_t)process_block,process_print);90 examples_common_process((aubio_process_func_t)process_block,process_print);
86 91
87 // send a last note off92 // send a last note off
88 send_noteon (miditap_note, 0);93 if (usejack) {
94 send_noteon (miditap_note, 0);
95 }
89 96
90 del_aubio_tempo(tempo);97 del_aubio_tempo(tempo);
91 del_aubio_wavetable (wavetable);98 del_aubio_wavetable (wavetable);
92 del_fvec(tempo_out);99 del_fvec(tempo_out);
93 100
101beach:
94 examples_common_del();102 examples_common_del();
95 return 0;103 return ret;
96}104}
97
examples/parse_args.h+62−11
@@ -36,6 +36,7 @@ extern uint_t hop_size; · 35 unmodified lines
36// onset stuff36// onset stuff
37extern char_t * onset_method;37extern char_t * onset_method;
38extern smpl_t onset_threshold;38extern smpl_t onset_threshold;
39extern smpl_t onset_minioi;
39// pitch stuff40// pitch stuff
40extern char_t * pitch_method;41extern char_t * pitch_method;
41extern char_t * pitch_unit;42extern char_t * pitch_unit;
@@ -46,6 +47,7 @@ extern uint_t time_format; · 4 unmodified lines
46extern char_t * tempo_method;47extern char_t * tempo_method;
47// more general stuff48// more general stuff
48extern smpl_t silence_threshold;49extern smpl_t silence_threshold;
50extern smpl_t release_drop;
49extern uint_t mix_input;51extern uint_t mix_input;
50// midi tap52// midi tap
51extern smpl_t miditap_note;53extern smpl_t miditap_note;
@@ -63,8 +65,8 @@ int parse_args (int argc, char **argv); · 11 unmodified lines
63// internal stuff65// internal stuff
64extern int blocks;66extern int blocks;
65 67
66extern fvec_t *ibuf;68extern fvec_t *input_buffer;
67extern fvec_t *obuf;69extern fvec_t *output_buffer;
68 70
69const char *prog_name;71const char *prog_name;
70 72
@@ -91,17 +93,25 @@ void usage (FILE * stream, int exit_code) · 20 unmodified lines
91 " default=hfc\n"93 " default=hfc\n"
92 " -t --onset-threshold set onset detection threshold\n"94 " -t --onset-threshold set onset detection threshold\n"
93 " a value between 0.1 (more detections) and 1 (less); default=0.3\n"95 " 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"
94#endif /* PROG_HAS_ONSET */98#endif /* PROG_HAS_ONSET */
95#ifdef PROG_HAS_PITCH99#ifdef PROG_HAS_PITCH
96 " -p --pitch select pitch detection algorithm\n"100 " -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"
98 " -u --pitch-unit select pitch output unit\n"102 " -u --pitch-unit select pitch output unit\n"
99 " <default|freq|hertz|Hz|midi|cent|bin>; default=freq\n"103 " <default|freq|hertz|Hz|midi|cent|bin>; default=freq\n"
100 " -l --pitch-tolerance select pitch tolerance\n"104 " -l --pitch-tolerance select pitch tolerance\n"
101 " (yin, yinfft only) a value between 0.1 and 0.7; default=0.3\n"105 " (yin, yinfft only) a value between 0.1 and 0.7; default=0.3\n"
102#endif /* PROG_HAS_PITCH */106#endif /* PROG_HAS_PITCH */
107#ifdef PROG_HAS_SILENCE
103 " -s --silence select silence threshold\n"108 " -s --silence select silence threshold\n"
104 " a value in dB, for instance -70, or -100; default=-90\n"109 " 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
105 " -T --time-format select time values output format\n"115 " -T --time-format select time values output format\n"
106 " (samples, ms, seconds) default=seconds\n"116 " (samples, ms, seconds) default=seconds\n"
107#ifdef PROG_HAS_OUTPUT117#ifdef PROG_HAS_OUTPUT
@@ -109,10 +119,14 @@ void usage (FILE * stream, int exit_code) · 1 unmodified line
109 " input signal will be added to output synthesis\n"119 " input signal will be added to output synthesis\n"
110 " -f --force-overwrite overwrite output file if needed\n"120 " -f --force-overwrite overwrite output file if needed\n"
111 " do not fail if output file already exists\n"121 " do not fail if output file already exists\n"
112#endif122#endif /* PROG_HAS_OUTPUT */
113#ifdef PROG_HAS_JACK123#if defined(PROG_HAS_JACK) && defined(HAVE_JACK)
114 " -j --jack use Jack\n"124 " -j --jack use Jack\n"
115#endif125#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) */
116 " -v --verbose be verbose\n"130 " -v --verbose be verbose\n"
117 " -h --help display this message\n"131 " -h --help display this message\n"
118 );132 );
@@ -131,18 +145,30 @@ parse_args (int argc, char **argv) · 12 unmodified lines
131 "i:r:B:H:"145 "i:r:B:H:"
132#ifdef PROG_HAS_JACK146#ifdef PROG_HAS_JACK
133 "j"147 "j"
148#if defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH)
149 "N:V:"
150#endif /* defined(PROG_HAS_ONSET) && !defined(PROG_HAS_PITCH) */
134#endif /* PROG_HAS_JACK */151#endif /* PROG_HAS_JACK */
135#ifdef PROG_HAS_OUTPUT152#ifdef PROG_HAS_OUTPUT
136 "o:"153 "o:"
137#endif /* PROG_HAS_OUTPUT */154#endif /* PROG_HAS_OUTPUT */
138#ifdef PROG_HAS_ONSET155#ifdef PROG_HAS_ONSET
139 "O:t:"156 "O:t:M:"
140#endif /* PROG_HAS_ONSET */157#endif /* PROG_HAS_ONSET */
141#ifdef PROG_HAS_PITCH158#ifdef PROG_HAS_PITCH
142 "p:u:l:"159 "p:u:l:"
143#endif /* PROG_HAS_PITCH */160#endif /* PROG_HAS_PITCH */
144 "T:"161 "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 ;
146 int next_option;172 int next_option;
147 struct option long_options[] = {173 struct option long_options[] = {
148 {"help", 0, NULL, 'h'},174 {"help", 0, NULL, 'h'},
@@ -153,6 +179,10 @@ parse_args (int argc, char **argv) · 4 unmodified lines
153 {"hopsize", 1, NULL, 'H'},179 {"hopsize", 1, NULL, 'H'},
154#ifdef PROG_HAS_JACK180#ifdef PROG_HAS_JACK
155 {"jack", 0, NULL, 'j'},181 {"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 */
156#endif /* PROG_HAS_JACK */186#endif /* PROG_HAS_JACK */
157#ifdef PROG_HAS_OUTPUT187#ifdef PROG_HAS_OUTPUT
158 {"output", 1, NULL, 'o'},188 {"output", 1, NULL, 'o'},
@@ -160,24 +190,32 @@ parse_args (int argc, char **argv) · 1 unmodified line
160#ifdef PROG_HAS_ONSET190#ifdef PROG_HAS_ONSET
161 {"onset", 1, NULL, 'O'},191 {"onset", 1, NULL, 'O'},
162 {"onset-threshold", 1, NULL, 't'},192 {"onset-threshold", 1, NULL, 't'},
193 {"onset-minioi", 1, NULL, 'M'},
163#endif /* PROG_HAS_ONSET */194#endif /* PROG_HAS_ONSET */
164#ifdef PROG_HAS_PITCH195#ifdef PROG_HAS_PITCH
165 {"pitch", 1, NULL, 'p'},196 {"pitch", 1, NULL, 'p'},
166 {"pitch-unit", 1, NULL, 'u'},197 {"pitch-unit", 1, NULL, 'u'},
167 {"pitch-tolerance", 1, NULL, 'l'},198 {"pitch-tolerance", 1, NULL, 'l'},
168#endif /* PROG_HAS_PITCH */199#endif /* PROG_HAS_PITCH */
200#ifdef PROG_HAS_SILENCE
169 {"silence", 1, NULL, 's'},201 {"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 */
170 {"time-format", 1, NULL, 'T'},206 {"time-format", 1, NULL, 'T'},
207#ifdef PROG_HAS_OUTPUT
171 {"mix-input", 0, NULL, 'm'},208 {"mix-input", 0, NULL, 'm'},
172 {"force-overwrite", 0, NULL, 'f'},209 {"force-overwrite", 0, NULL, 'f'},
210#endif /* PROG_HAS_OUTPUT */
173 {NULL, 0, NULL, 0}211 {NULL, 0, NULL, 0}
174 };212 };
175#endif /* HAVE_GETOPT_H */213#endif /* HAVE_GETOPT_H */
176 prog_name = argv[0];214 // better safe than sorry
177 if (argc < 1) {215 if (argc < 1) {
178 usage (stderr, 1);216 usage (stderr, 1);
179 return -1;
180 }217 }
218 prog_name = argv[0];
181#ifdef HAVE_GETOPT_H219#ifdef HAVE_GETOPT_H
182 do {220 do {
183 next_option = getopt_long (argc, argv, options, long_options, NULL);221 next_option = getopt_long (argc, argv, options, long_options, NULL);
@@ -191,6 +229,12 @@ parse_args (int argc, char **argv) · 7 unmodified lines
191 case 'j':229 case 'j':
192 usejack = 1;230 usejack = 1;
193 break;231 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;
194 case 'i':238 case 'i':
195 source_uri = optarg;239 source_uri = optarg;
196 break;240 break;
@@ -215,6 +259,9 @@ parse_args (int argc, char **argv) · 18 unmodified lines
215 case 't': /* threshold value for onset */259 case 't': /* threshold value for onset */
216 onset_threshold = (smpl_t) atof (optarg);260 onset_threshold = (smpl_t) atof (optarg);
217 break;261 break;
262 case 'M': /* minimum inter-onset-interval */
263 onset_minioi = (smpl_t) atof (optarg);
264 break;
218 case 'p':265 case 'p':
219 pitch_method = optarg;266 pitch_method = optarg;
220 break;267 break;
@@ -238,6 +285,9 @@ parse_args (int argc, char **argv) · 17 unmodified lines
238 case 's': /* silence threshold */285 case 's': /* silence threshold */
239 silence_threshold = (smpl_t) atof (optarg);286 silence_threshold = (smpl_t) atof (optarg);
240 break;287 break;
288 case 'd': /* release-drop threshold */
289 release_drop = (smpl_t) atof (optarg);
290 break;
241 case 'm': /* mix_input flag */291 case 'm': /* mix_input flag */
242 mix_input = 1;292 mix_input = 1;
243 break;293 break;
@@ -277,7 +327,8 @@ parse_args (int argc, char **argv) · 33 unmodified lines
277 usejack = 1;327 usejack = 1;
278#else328#else
279 errmsg("Error: no arguments given (and no available audio input)\n");329 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 );
281#endif /* HAVE_JACK */332#endif /* HAVE_JACK */
282#else333#else
283 errmsg("Error: no arguments given\n");334 errmsg("Error: no arguments given\n");
examples/utils.c+22−13
@@ -43,6 +43,7 @@ uint_t hop_size = 256; · 42 unmodified lines
43// onset stuff43// onset stuff
44char_t * onset_method = "default";44char_t * onset_method = "default";
45smpl_t onset_threshold = 0.0; // will be set if != 0.45smpl_t onset_threshold = 0.0; // will be set if != 0.
46smpl_t onset_minioi = 0.0; // will be set if != 0.
46// pitch stuff47// pitch stuff
47char_t * pitch_unit = "default";48char_t * pitch_unit = "default";
48char_t * pitch_method = "default";49char_t * pitch_method = "default";
@@ -53,6 +54,7 @@ uint_t time_format = 0; // for "seconds", 1 for "ms", 2 for "samples" · 4 unmodified lines
53char_t * tempo_method = "default";54char_t * tempo_method = "default";
54// more general stuff55// more general stuff
55smpl_t silence_threshold = -90.;56smpl_t silence_threshold = -90.;
57smpl_t release_drop = 10.;
56uint_t mix_input = 0;58uint_t mix_input = 0;
57 59
58uint_t force_overwrite = 0;60uint_t force_overwrite = 0;
@@ -61,8 +63,8 @@ uint_t force_overwrite = 0; · 2 unmodified lines
61// internal memory stuff63// internal memory stuff
62aubio_source_t *this_source = NULL;64aubio_source_t *this_source = NULL;
63aubio_sink_t *this_sink = NULL;65aubio_sink_t *this_sink = NULL;
64fvec_t *ibuf;66fvec_t *input_buffer;
65fvec_t *obuf;67fvec_t *output_buffer;
66 68
67smpl_t miditap_note = 69.;69smpl_t miditap_note = 69.;
68smpl_t miditap_velo = 65.;70smpl_t miditap_velo = 65.;
@@ -74,7 +76,12 @@ extern void usage (FILE * stream, int exit_code); · 5 unmodified lines
74extern int parse_args (int argc, char **argv);76extern int parse_args (int argc, char **argv);
75 77
76#if HAVE_JACK78#if HAVE_JACK
79#define MAX_MIDI_EVENTS 128
80#define MAX_MIDI_EVENT_SIZE 3
77aubio_jack_t *jack_setup;81aubio_jack_t *jack_setup;
82jack_midi_event_t ev;
83jack_midi_data_t midi_data[MAX_MIDI_EVENTS * MAX_MIDI_EVENT_SIZE];
84size_t midi_event_count = 0;
78#endif /* HAVE_JACK */85#endif /* HAVE_JACK */
79 86
80void examples_common_init (int argc, char **argv);87void examples_common_init (int argc, char **argv);
@@ -119,15 +126,15 @@ void examples_common_init (int argc, char **argv) · 38 unmodified lines
119 source_uri = "jack";126 source_uri = "jack";
120#endif /* HAVE_JACK */127#endif /* HAVE_JACK */
121 }128 }
122 ibuf = new_fvec (hop_size);129 input_buffer = new_fvec (hop_size);
123 obuf = new_fvec (hop_size);130 output_buffer = new_fvec (hop_size);
124 131
125}132}
126 133
127void examples_common_del (void)134void examples_common_del (void)
128{135{
129 del_fvec (ibuf);136 del_fvec (input_buffer);
130 del_fvec (obuf);137 del_fvec (output_buffer);
131 aubio_cleanup ();138 aubio_cleanup ();
132 fflush(stderr);139 fflush(stderr);
133 fflush(stdout);140 fflush(stdout);
@@ -141,6 +148,8 @@ void examples_common_process (aubio_process_func_t process_func, · 7 unmodified lines
141 if (usejack) {148 if (usejack) {
142 149
143#ifdef HAVE_JACK150#ifdef HAVE_JACK
151 ev.size = MAX_MIDI_EVENT_SIZE;
152 ev.time = 0; // send it now
144 debug ("Jack activation ...\n");153 debug ("Jack activation ...\n");
145 aubio_jack_activate (jack_setup, process_func);154 aubio_jack_activate (jack_setup, process_func);
146 debug ("Processing (Ctrl+C to quit) ...\n");155 debug ("Processing (Ctrl+C to quit) ...\n");
@@ -157,14 +166,14 @@ void examples_common_process (aubio_process_func_t process_func, · 10 unmodified lines
157 blocks = 0;166 blocks = 0;
158 167
159 do {168 do {
160 aubio_source_do (this_source, ibuf, &read);169 aubio_source_do (this_source, input_buffer, &read);
161 process_func (ibuf, obuf);170 process_func (input_buffer, output_buffer);
162 // print to console if verbose or no output given171 // print to console if verbose or no output given
163 if (verbose || sink_uri == NULL) {172 if (verbose || sink_uri == NULL) {
164 print();173 print();
165 }174 }
166 if (this_sink) {175 if (this_sink) {
167 aubio_sink_do (this_sink, obuf, hop_size);176 aubio_sink_do (this_sink, output_buffer, hop_size);
168 }177 }
169 blocks++;178 blocks++;
170 total_read += read;179 total_read += read;
@@ -184,11 +193,11 @@ void · 13 unmodified lines
184send_noteon (smpl_t pitch, smpl_t velo)193send_noteon (smpl_t pitch, smpl_t velo)
185{194{
186#ifdef HAVE_JACK195#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;
191 if (usejack) {196 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 }
192 ev.buffer[2] = velo;201 ev.buffer[2] = velo;
193 ev.buffer[1] = pitch;202 ev.buffer[1] = pitch;
194 if (velo == 0) {203 if (velo == 0) {
examples/utils.h+1−1
@@ -66,7 +66,7 @@ typedef void (aubio_print_func_t) (void); · 65 unmodified lines
66void send_noteon (smpl_t pitch, smpl_t velo);66void send_noteon (smpl_t pitch, smpl_t velo);
67 67
68/** common process function */68/** common process function */
69typedef int (*aubio_process_func_t) (fvec_t * input, fvec_t * output);69typedef void (*aubio_process_func_t) (fvec_t * input, fvec_t * output);
70 70
71void process_block (fvec_t *ibuf, fvec_t *obuf);71void process_block (fvec_t *ibuf, fvec_t *obuf);
72void process_print (void);72void process_print (void);
python/README.md+88−79
@@ -1,100 +1,109 @@
1Python aubio module1aubio
2===================2=====
3 3
4This module wraps the aubio library for Python using the numpy module.4aubio is a collection of tools for music and audio analysis.
5 5
6Using the Python aubio module6This package integrates the aubio library with [NumPy] to provide a set of
7-----------------------------7efficient tools to process and analyse audio signals, including:
8 8
9After 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
10 15
11 $ python16aubio works with both Python 2 and Python 3.
12 [...]
13 >>> import aubio
14 >>> help(aubio.miditofreq)
15 17
16Finding some inspiration18Links
17------------------------19-----
18 20
19Some examples are available in the `python/demos` directory. These scripts are21- [module documentation][doc_python]
20small programs written in python and using python-aubio.22- [installation instructions][doc_python_install]
23- [aubio manual][manual]
24- [aubio homepage][homepage]
25- [issue tracker][bugtracker]
21 26
22For instance, `demo_source.py` reads a media file.27Demos
28-----
23 29
24 $ ./python/demos/demo_source.py /path/to/sound/sample.wav30Some examples are available in the [`python/demos`][demos_dir] folder. Each
31script is a command line program which accepts one ore more argument.
25 32
26and `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.
27 34
28 $ ./python/demo/demo_timestretch_online.py loop.wav stretched_loop.wav 0.92`35### Analysis
29 36
30Note: you might need to install additional modules to run some of the demos.37- `demo_source.py` uses aubio to read audio samples from media files
31Some demos use [matplotlib](http://matplotlib.org/) to draw plots, others use38- `demo_onset_plot.py` detects attacks in a sound file and plots the results
32[PySoundCard](https://github.com/bastibe/PySoundCard) to play and record39 using [matplotlib]
33sounds.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.
34 44
35Testing the Python module45### Real-time
36-------------------------
37 46
38To 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]
39 50
40 $ ./python/tests/run_all_tests51### Others
41 52
42Each 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
43 57
44 $ ./python/tests/test_note2midi.py -v58### Example
45 59
46Install in a virtualenv60Use `demo_timestretch_online.py` to slow down `loop.wav`, write the results in
47-----------------------61`stretched_loop.wav`:
48 62
49You should be able to install python-aubio directly from the top source63 $ python demo_timestretch_online.py loop.wav stretched_loop.wav 0.92
50directory of aubio.
51 64
52First, create a virtualenv to hold the required python module:65Built with
53
54 $ virtualenv pyaubio
55 $ source pyaubio/bin/activate
56
57Now install and build the python extension using:
58
59 $ pip install .
60
61Install requirements
62--------------------
63
64Before compiling this module, you must have compiled libaubio.
65
66A simple way to do this is with pip:
67
68 $ pip install -r requirements.txt
69
70For more information about how this module works, please refer to the [Python/C
71API 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
74Compiling python aubio
75----------------------
76
77To build the aubio Python module, run the following command from the top source
78directory of aubio:
79
80 $ ./setup.py build
81
82Note: if libaubio was previously built using waf, the script will use it.
83Otherwise, the entire library will be built inside the python extension.
84
85To find out more about `setup.py` options:
86
87 $ ./setup.py --help
88
89Installing
90----------66----------
91 67
92To install the Python module:68The core of aubio is written in C for portability and speed. In addition to
93 69[NumPy], aubio can be optionally built to use one or more of the following
94 $ ./setup.py install70libraries:
95 71
96Alternatively, you may want to use the Python module without installing it by72- media file reading:
97setting your PYTHONPATH, for instance as follows:73
98 74 - [ffmpeg] / [avcodec] to decode and read audio from almost any format,
99 $ export PYTHONPATH=$PYTHONPATH:$PWD/`ls -rtd build/lib.* | head -1`:$PWD/tests75 - [libsndfile] to read audio from uncompressed sound files,
100 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
3import alsaaudio
4import numpy as np
5import aubio
6
7# constants
8samplerate = 44100
9win_s = 2048
10hop_s = win_s // 2
11framesize = hop_s
12
13# set up audio input
14recorder = alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE)
15recorder.setperiodsize(framesize)
16recorder.setrate(samplerate)
17recorder.setformat(alsaaudio.PCM_FORMAT_FLOAT_LE)
18recorder.setchannels(1)
19
20# create aubio pitch detection (first argument is method, "default" is
21# "yinfft", can also be "yin", "mcomb", fcomb", "schmitt").
22pitcher = aubio.pitch("default", win_s, hop_s, samplerate)
23# set output unit (can be 'midi', 'cent', 'Hz', ...)
24pitcher.set_unit("Hz")
25# ignore frames under this level (dB)
26pitcher.set_silence(-40)
27
28print("Starting to listen, press Ctrl+C to stop")
29
30# main loop
31while 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
3import numpy as np
4from aubio import pitch
5import pylab as plt
6
7buf_size = 2048 * 1
8hop_size = buf_size // 4
9
10samplerate = 44100
11minfreq = 40
12maxfreq = 6000
13
14def 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
21def 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
41if __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
3from aubio import source, tempo3from aubio import source, tempo
4from numpy import median, diff4from numpy import median, diff
5 5
6def get_file_bpm(path, params = None):6def get_file_bpm(path, params=None):
7 """ Calculate the beats per minute (bpm) of a given file.7 """ Calculate the beats per minute (bpm) of a given file.
8 path: path to the file8 path: path to the file
9 param: dictionary of parameters9 param: dictionary of parameters
10 """10 """
11 if params is None:11 if params is None:
12 params = {}12 params = {}
13 try:13 # default:
14 win_s = params['win_s']14 samplerate, win_s, hop_s = 44100, 1024, 512
15 samplerate = params['samplerate']15 if 'mode' in params:
16 hop_s = params['hop_s']16 if params.mode in ['super-fast']:
17 except KeyError:17 # super fast
18 """18 samplerate, win_s, hop_s = 4000, 128, 64
19 # super fast19 elif params.mode in ['fast']:
20 samplerate, win_s, hop_s = 4000, 128, 64 20 # fast
21 # fast21 samplerate, win_s, hop_s = 8000, 512, 128
22 samplerate, win_s, hop_s = 8000, 512, 12822 elif params.mode in ['default']:
23 """23 pass
24 # default:24 else:
25 samplerate, win_s, hop_s = 44100, 1024, 51225 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
26 33
27 s = source(path, samplerate, hop_s)34 s = source(path, samplerate, hop_s)
28 samplerate = s.samplerate35 samplerate = s.samplerate
@@ -44,19 +51,29 @@ def get_file_bpm(path, params = None): · 15 unmodified lines
44 if read < hop_s:51 if read < hop_s:
45 break52 break
46 53
47 # Convert to periods and to bpm 54 def beats_to_bpm(beats, path):
48 if len(beats) > 1:55 # if enough beats are found, convert to periods then to bpm
49 if len(beats) < 4:56 if len(beats) > 1:
50 print("few beats found in {:s}".format(path))57 if len(beats) < 4:
51 bpms = 60./diff(beats)58 print("few beats found in {:s}".format(path))
52 b = median(bpms)59 bpms = 60./diff(beats)
53 else:60 return median(bpms)
54 b = 061 else:
55 print("not enough beats found in {:s}".format(path))62 print("not enough beats found in {:s}".format(path))
56 return b63 return 0
64
65 return beats_to_bpm(beats, path)
57 66
58if __name__ == '__main__':67if __name__ == '__main__':
59 import sys68 import argparse
60 for f in sys.argv[1:]:69 parser = argparse.ArgumentParser()
61 bpm = get_file_bpm(f)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)
62 print("{:6s} {:s}".format("{:2f}".format(bpm), f))79 print("{:6s} {:s}".format("{:2f}".format(bpm), f))
python/demos/demo_filter.py+31−14
@@ -1,36 +1,53 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2 2
3import sys
4import os.path
5import aubio
3 6
4def apply_filter(path):
5 from aubio import source, sink, digital_filter
6 from os.path import basename, splitext
7 7
8def apply_filter(path, target):
8 # open input file, get its samplerate9 # open input file, get its samplerate
9 s = source(path)10 s = aubio.source(path)
10 samplerate = s.samplerate11 samplerate = s.samplerate
11 12
12 # create an A-weighting filter13 # create an A-weighting filter
13 f = digital_filter(7)14 f = aubio.digital_filter(7)
14 f.set_a_weighting(samplerate)15 f.set_a_weighting(samplerate)
15 # alternatively, apply another filter
16 16
17 # create output file17 # create output file
18 o = sink("filtered_" + splitext(basename(path))[0] + ".wav", samplerate)18 o = aubio.sink(target, samplerate)
19 19
20 total_frames = 020 total_frames = 0
21 while True:21 while True:
22 # read from source
22 samples, read = s()23 samples, read = s()
24 # filter samples
23 filtered_samples = f(samples)25 filtered_samples = f(samples)
26 # write to sink
24 o(filtered_samples, read)27 o(filtered_samples, read)
28 # count frames read
25 total_frames += read29 total_frames += read
26 if read < s.hop_size: break30 # end of file reached
31 if read < s.hop_size:
32 break
27 33
34 # print some info
28 duration = total_frames / float(samplerate)35 duration = total_frames / float(samplerate)
29 print ("read {:s}".format(s.uri))36 input_str = "input: {:s} ({:.2f} s, {:d} Hz)"
30 print ("applied A-weighting filtered ({:d} Hz)".format(samplerate))37 output_str = "output: {:s}, A-weighting filtered ({:d} frames total)"
31 print ("wrote {:s} ({:.2f} s)".format(o.uri, duration))38 print(input_str.format(s.uri, duration, samplerate))
39 print(output_str.format(o.uri, total_frames))
32 40
33if __name__ == '__main__':41if __name__ == '__main__':
34 import sys42 usage = "{:s} <input_file> [output_file]".format(sys.argv[0])
35 for f in sys.argv[1:]:43 if not 1 < len(sys.argv) < 4:
36 apply_filter(f)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 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2 2
3from aubio import filterbank, fvec3"""Create a filterbank from a list of frequencies.
4from pylab import loglog, show, xlim, ylim, xlabel, ylabel, title
5from numpy import vstack, arange
6 4
7win_s = 20485This demo uses `aubio.filterbank.set_triangle_bands` to build a set of
6triangular filters from a list of frequencies.
7
8The filterbank coefficients are then modified before being displayed."""
9
10import aubio
11import numpy as np
12import matplotlib.pyplot as plt
13
14# sampling rate and size of the fft
8samplerate = 4800015samplerate = 48000
16win_s = 2048
9 17
18# define a list of custom frequency
10freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000]19freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000]
20# number of filters to create
11n_filters = len(freq_list) - 221n_filters = len(freq_list) - 2
12 22
13f = filterbank(n_filters, win_s)23# create a new filterbank
14freqs = fvec(freq_list)24f = aubio.filterbank(n_filters, win_s)
25freqs = aubio.fvec(freq_list)
15f.set_triangle_bands(freqs, samplerate)26f.set_triangle_bands(freqs, samplerate)
16 27
28# get the coefficients from the filterbank
17coeffs = f.get_coeffs()29coeffs = f.get_coeffs()
18coeffs[4] *= 5.30# apply a gain to fifth band
19 31coeffs[4] *= 6.
32# load the modified coeffs into the filterbank
20f.set_coeffs(coeffs)33f.set_coeffs(coeffs)
21 34
22times = vstack([arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)35# display the band gains in a loglog plot
23title('Bank of filters built using a simple list of boundaries\nThe middle band has been amplified by 2.')36freqs = np.vstack([np.arange(win_s // 2 + 1) * samplerate / win_s] * n_filters)
24loglog(times.T, f.get_coeffs().T, '.-')37plt.title('filterbank built from a list of frequencies\n'
25xlim([50, samplerate/2])38 'The 5th band has been amplified by a factor 6.')
26ylim([1.0e-6, 2.0e-2])39plt.loglog(freqs.T, f.get_coeffs().T, '.-')
27xlabel('log frequency (Hz)')40plt.xlim([50, samplerate/2])
28ylabel('log amplitude')41plt.ylim([1.0e-6, 2.0e-2])
29 42plt.xlabel('log frequency (Hz)')
30show()43plt.ylabel('log amplitude')
44plt.show()
python/demos/demo_notes.py+37−0
@@ -0,0 +1,37 @@
1#! /usr/bin/env python
2
3import sys
4from aubio import source, notes
5
6if len(sys.argv) < 2:
7 print("Usage: %s <filename> [samplerate]" % sys.argv[0])
8 sys.exit(1)
9
10filename = sys.argv[1]
11
12downsample = 1
13samplerate = 44100 // downsample
14if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
15
16win_s = 512 // downsample # fft size
17hop_s = 256 // downsample # hop size
18
19s = source(filename, samplerate, hop_s)
20samplerate = s.samplerate
21
22tolerance = 0.8
23
24notes_o = notes("default", win_s, hop_s, samplerate)
25
26print("%8s" % "time","[ start","vel","last ]")
27
28# total number of frames read
29total_frames = 0
30while 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
37 37
38pointer += partition38pointer += partition
39pointer += partition39pointer += partition
40freqs[ pointer : pointer + partition ] = 400 + 5 * np.random.random(sin_length/8)40freqs[ pointer : pointer + partition ] = 400 + 5 * np.random.random(sin_length//8)
41 41
42a = build_sinusoid(sin_length, freqs, samplerate)42a = build_sinusoid(sin_length, freqs, samplerate)
43 43
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
12import pyaudio
13import sys
14import numpy as np
15import aubio
16
17# initialise pyaudio
18p = pyaudio.PyAudio()
19
20# open stream
21buffer_size = 1024
22pyaudio_format = pyaudio.paFloat32
23n_channels = 1
24samplerate = 44100
25stream = p.open(format=pyaudio_format,
26 channels=n_channels,
27 rate=samplerate,
28 input=True,
29 frames_per_buffer=buffer_size)
30
31if 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
37else:
38 # run forever
39 outputsink = None
40 record_duration = None
41
42# setup pitch
43tolerance = 0.8
44win_s = 4096 # fft size
45hop_s = buffer_size # hop size
46pitch_o = aubio.pitch("default", win_s, hop_s, samplerate)
47pitch_o.set_unit("midi")
48pitch_o.set_tolerance(tolerance)
49
50print("*** starting recording")
51while 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
72print("*** done recording")
73stream.stop_stream()
74stream.close()
75p.terminate()
python/demos/demo_source_simple.py+13−9
@@ -1,16 +1,20 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2import sys, aubio2
3"""A simple example using aubio.source."""
4
5import sys
6import aubio
3 7
4samplerate = 0 # use original source samplerate8samplerate = 0 # use original source samplerate
5hop_size = 256 # number of frames to read in one block9hop_size = 256 # number of frames to read in one block
6s = aubio.source(sys.argv[1], samplerate, hop_size)10src = aubio.source(sys.argv[1], samplerate, hop_size)
7total_frames = 011total_frames = 0
8 12
9while True: # reading loop13while True:
10 samples, read = s()14 samples, read = src() # read hop_size new samples from source
11 total_frames += read15 total_frames += read # increment total number of frames
12 if read < hop_size: break # end of file reached16 if read < hop_size: # end of file reached
17 break
13 18
14fmt_string = "read {:d} frames at {:d}Hz from {:s}"19fmt_string = "read {:d} frames at {:d}Hz from {:s}"
15print (fmt_string.format(total_frames, s.samplerate, sys.argv[1]))20print(fmt_string.format(total_frames, src.samplerate, src.uri))
16
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
5Note you will need to have pyaudio installed: `pip install pyaudio`.
6
7Examples:
8 ./demo_tapthebeat.py ~/Music/track1.ogg
9
10When compiled with ffmpeg/libav, you should be able to open remote streams. For
11instance using youtube-dl (`pip install youtube-dl`):
12
13 ./demo_tapthebeat.py `youtube-dl -xg https://youtu.be/zZbM9n9j3_g`
14
15"""
16
17import sys
18import time
19import pyaudio
20import aubio
21import numpy as np
22
23win_s = 1024 # fft size
24hop_s = win_s // 2 # hop size
25
26# parse command line arguments
27if len(sys.argv) < 2:
28 print("Usage: %s <filename> [samplerate]" % sys.argv[0])
29 sys.exit(1)
30
31filename = sys.argv[1]
32
33samplerate = 0
34if len( sys.argv ) > 2: samplerate = int(sys.argv[2])
35
36# create aubio source
37a_source = aubio.source(filename, samplerate, hop_s)
38samplerate = a_source.samplerate
39
40# create aubio tempo detection
41a_tempo = aubio.tempo("default", win_s, hop_s, samplerate)
42
43# create a simple click sound
44click = 0.7 * np.sin(2. * np.pi * np.arange(hop_s) / hop_s * samplerate / 3000.)
45
46# pyaudio callback
47def 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
59p = pyaudio.PyAudio()
60pyaudio_format = pyaudio.paFloat32
61frames_per_buffer = hop_s
62n_channels = 1
63stream = 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
68stream.start_stream()
69
70# wait for stream to finish
71while stream.is_active():
72 time.sleep(0.1)
73
74# stop pyaudio stream
75stream.stop_stream()
76stream.close()
77# close pyaudio
78p.terminate()
python/demos/demo_timestretch.py+1−1
@@ -12,7 +12,7 @@ from aubio import unwrap2pi, float_type · 11 unmodified lines
12import numpy as np12import numpy as np
13 13
14win_s = 102414win_s = 1024
15hop_s = win_s / 8 # 87.5 % overlap15hop_s = win_s // 8 # 87.5 % overlap
16 16
17warmup = win_s // hop_s - 117warmup = win_s // hop_s - 1
18 18
python/demos/demo_timestretch_online.py+5−3
@@ -11,8 +11,8 @@ from aubio import source, sink, pvoc, cvec · 10 unmodified lines
11from aubio import unwrap2pi, float_type11from aubio import unwrap2pi, float_type
12import numpy as np12import numpy as np
13 13
14win_s = 102414win_s = 512
15hop_s = win_s / 8 # 87.5 % overlap15hop_s = win_s // 8 # 87.5 % overlap
16 16
17warmup = win_s // hop_s - 117warmup = win_s // hop_s - 1
18 18
@@ -92,8 +92,10 @@ while True: · 73 unmodified lines
92 old_grain.norm = np.copy(cur_grain.norm)92 old_grain.norm = np.copy(cur_grain.norm)
93 old_grain.phas = np.copy(cur_grain.phas)93 old_grain.phas = np.copy(cur_grain.phas)
94 94
95 block_read += 195 # until end of file
96 if read < hop_s: break96 if read < hop_s: break
97 # increment block counter
98 block_read += 1
97 99
98for t in range(warmup + 2): # purge the last frames from the phase vocoder100for t in range(warmup + 2): # purge the last frames from the phase vocoder
99 new_grain.norm[:] = 0101 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
10import sys
11from aubio import source, notes
12from mido import Message, MetaMessage, MidiFile, MidiTrack, second2tick, bpm2tempo
13
14if len(sys.argv) < 3:
15 print("Usage: %s <filename> <output> [samplerate]" % sys.argv[0])
16 sys.exit(1)
17
18filename = sys.argv[1]
19midioutput = sys.argv[2]
20
21downsample = 1
22samplerate = 44100 // downsample
23if len( sys.argv ) > 3: samplerate = int(sys.argv[3])
24
25win_s = 512 // downsample # fft size
26hop_s = 256 // downsample # hop size
27
28s = source(filename, samplerate, hop_s)
29samplerate = s.samplerate
30
31tolerance = 0.8
32
33notes_o = notes("default", win_s, hop_s, samplerate)
34
35print("%8s" % "time","[ start","vel","last ]")
36
37# create a midi file
38mid = MidiFile()
39track = MidiTrack()
40mid.tracks.append(track)
41
42ticks_per_beat = mid.ticks_per_beat # default: 480
43bpm = 120 # default midi tempo
44
45tempo = bpm2tempo(bpm)
46track.append(MetaMessage('set_tempo', tempo=tempo))
47track.append(MetaMessage('time_signature', numerator=4, denominator=4))
48
49def frames2tick(frames, samplerate=samplerate):
50 sec = frames / float(samplerate)
51 return int(second2tick(sec, ticks_per_beat, tempo))
52
53last_time = 0
54
55# total number of frames read
56total_frames = 0
57while 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
77mid.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
16import sys
17import numpy as np
18import matplotlib.pyplot as plt
19
20def 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
32def 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
57def 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
69def 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
95def 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
108def 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
130def 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
151testfreqs = [441., 800., 10000., 40.]
152
153if len(sys.argv) > 1:
154 testfreqs = map(float,sys.argv[1:])
155
156for 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)
175plt.show()
python/ext/aubio-types.h+9−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
27#ifdef USE_LOCAL_AUBIO27#ifdef USE_LOCAL_AUBIO
28#include "aubio.h"28#include "aubio.h"
29#else29#else
30#include "aubio/aubio.h"30#include <aubio/aubio.h>
31#endif31#endif
32 32
33#define Py_default_vector_length 102433#define Py_default_vector_length 1024
@@ -46,6 +46,14 @@ · 12 unmodified lines
46#define AUBIO_NPY_SMPL_CHR "f"46#define AUBIO_NPY_SMPL_CHR "f"
47#endif47#endif
48 48
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
49// compat with Python < 2.657// compat with Python < 2.6
50#ifndef Py_TYPE58#ifndef Py_TYPE
51#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)59#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
python/ext/aubiomodule.c+167−27
@@ -2,77 +2,202 @@ · 1 unmodified line
2#include "aubio-types.h"2#include "aubio-types.h"
3#include "py-musicutils.h"3#include "py-musicutils.h"
4 4
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
5static char aubio_module_doc[] = "Python module for the aubio library";10static char aubio_module_doc[] = "Python module for the aubio library";
6 11
7static char Py_alpha_norm_doc[] = ""12static 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"
9"\n"16"\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"
11"\n"28"\n"
12"Example\n"29"Example\n"
13"-------\n"30"-------\n"
14"\n"31"\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"";
16 44
17static char Py_bintomidi_doc[] = ""45static 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"
19"\n"50"\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"
21"\n"64"\n"
22"Example\n"65"Example\n"
23"-------\n"66"-------\n"
24"\n"67"\n"
25">>> midi = bintomidi(float, samplerate = 44100, fftsize = 1024)";68">>> aubio.bintomidi(10, 44100, 1024)\n"
69"68.62871551513672\n"
70"";
26 71
27static char Py_miditobin_doc[] = ""72static char Py_miditobin_doc[] = ""
28"miditobin(float, samplerate = integer, fftsize = integer) -> float\n"73"miditobin(midi, samplerate, fftsize)\n"
29"\n"74"\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"
31"\n"77"\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"
33"-------\n"88"-------\n"
89"float\n"
90" Frequency converted to FFT bin.\n"
91"\n"
92"Examples\n"
93"--------\n"
34"\n"94"\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"";
36 100
37static char Py_bintofreq_doc[] = ""101static 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"
39"\n"106"\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"
41"\n"120"\n"
42"Example\n"121"Example\n"
43"-------\n"122"-------\n"
44"\n"123"\n"
45">>> freq = bintofreq(bin, samplerate = 44100, fftsize = 1024)";124">>> aubio.bintofreq(10, 44100, 1024)\n"
125"430.6640625\n"
126"";
46 127
47static char Py_freqtobin_doc[] = ""128static char Py_freqtobin_doc[] = ""
48"freqtobin(float, samplerate = integer, fftsize = integer) -> float\n"129"freqtobin(freq, samplerate, fftsize)\n"
49"\n"130"\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"
51"\n"133"\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"
53"-------\n"144"-------\n"
145"float\n"
146" Frequency converted to FFT bin.\n"
147"\n"
148"Examples\n"
149"--------\n"
54"\n"150"\n"
55">>> bin = freqtobin(freq, samplerate = 44100, fftsize = 1024)";151">>> aubio.freqtobin(440, 44100, 1024)\n"
152"10.216779708862305\n"
153"";
56 154
57static char Py_zero_crossing_rate_doc[] = ""155static 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"
59"\n"159"\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"
61"\n"169"\n"
62"Example\n"170"Example\n"
63"-------\n"171"-------\n"
64"\n"172"\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"";
66 177
67static char Py_min_removal_doc[] = ""178static 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"
69"\n"182"\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"
71"\n"194"\n"
72"Example\n"195"Example\n"
73"-------\n"196"-------\n"
74"\n"197"\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"";
76 201
77extern void add_ufuncs ( PyObject *m );202extern void add_ufuncs ( PyObject *m );
78extern int generated_types_ready(void);203extern int generated_types_ready(void);
@@ -112,7 +237,9 @@ Py_bintomidi (PyObject * self, PyObject * args) · 33 unmodified lines
112 smpl_t input, samplerate, fftsize;237 smpl_t input, samplerate, fftsize;
113 smpl_t output;238 smpl_t output;
114 239
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)) {
116 return NULL;243 return NULL;
117 }244 }
118 245
@@ -127,7 +254,9 @@ Py_miditobin (PyObject * self, PyObject * args) · 8 unmodified lines
127 smpl_t input, samplerate, fftsize;254 smpl_t input, samplerate, fftsize;
128 smpl_t output;255 smpl_t output;
129 256
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)) {
131 return NULL;260 return NULL;
132 }261 }
133 262
@@ -142,7 +271,9 @@ Py_bintofreq (PyObject * self, PyObject * args) · 8 unmodified lines
142 smpl_t input, samplerate, fftsize;271 smpl_t input, samplerate, fftsize;
143 smpl_t output;272 smpl_t output;
144 273
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)) {
146 return NULL;277 return NULL;
147 }278 }
148 279
@@ -157,7 +288,9 @@ Py_freqtobin (PyObject * self, PyObject * args) · 8 unmodified lines
157 smpl_t input, samplerate, fftsize;288 smpl_t input, samplerate, fftsize;
158 smpl_t output;289 smpl_t output;
159 290
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)) {
161 return NULL;294 return NULL;
162 }295 }
163 296
@@ -237,6 +370,12 @@ static PyMethodDef aubio_methods[] = { · 73 unmodified lines
237 {"silence_detection", Py_aubio_silence_detection, METH_VARARGS, Py_aubio_silence_detection_doc},370 {"silence_detection", Py_aubio_silence_detection, METH_VARARGS, Py_aubio_silence_detection_doc},
238 {"level_detection", Py_aubio_level_detection, METH_VARARGS, Py_aubio_level_detection_doc},371 {"level_detection", Py_aubio_level_detection, METH_VARARGS, Py_aubio_level_detection_doc},
239 {"window", Py_aubio_window, METH_VARARGS, Py_aubio_window_doc},372 {"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},
240 {NULL, NULL, 0, NULL} /* Sentinel */379 {NULL, NULL, 0, NULL} /* Sentinel */
241};380};
242 381
@@ -323,6 +462,7 @@ initaubio (void) · 80 unmodified lines
323 PyModule_AddObject (m, "sink", (PyObject *) & Py_sinkType);462 PyModule_AddObject (m, "sink", (PyObject *) & Py_sinkType);
324 463
325 PyModule_AddStringConstant(m, "float_type", AUBIO_NPY_SMPL_STR);464 PyModule_AddStringConstant(m, "float_type", AUBIO_NPY_SMPL_STR);
465 PyModule_AddStringConstant(m, "__version__", DEFINEDSTRING(AUBIO_VERSION));
326 466
327 // add generated objects467 // add generated objects
328 add_generated_objects(m);468 add_generated_objects(m);
python/ext/py-cvec.c+42−12
@@ -19,7 +19,37 @@ typedef struct · 18 unmodified lines
19 uint_t length;19 uint_t length;
20} Py_cvec;20} Py_cvec;
21 21
22static char Py_cvec_doc[] = "cvec object";22static 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"";
23 53
24 54
25PyObject *55PyObject *
@@ -142,14 +172,14 @@ Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure) · 116 unmodified lines
142{172{
143 npy_intp length;173 npy_intp length;
144 if (!PyAubio_IsValidVector(input)) {174 if (!PyAubio_IsValidVector(input)) {
145 return 1;175 return -1;
146 }176 }
147 length = PyArray_SIZE ((PyArrayObject *)input);177 length = PyArray_SIZE ((PyArrayObject *)input);
148 if (length != vec->length) {178 if (length != vec->length) {
149 PyErr_Format (PyExc_ValueError,179 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,
151 vec->length);181 vec->length);
152 return 1;182 return -1;
153 }183 }
154 184
155 Py_XDECREF(vec->norm);185 Py_XDECREF(vec->norm);
@@ -163,14 +193,14 @@ Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) · 7 unmodified lines
163{193{
164 npy_intp length;194 npy_intp length;
165 if (!PyAubio_IsValidVector(input)) {195 if (!PyAubio_IsValidVector(input)) {
166 return 1;196 return -1;
167 }197 }
168 length = PyArray_SIZE ((PyArrayObject *)input);198 length = PyArray_SIZE ((PyArrayObject *)input);
169 if (length != vec->length) {199 if (length != vec->length) {
170 PyErr_Format (PyExc_ValueError,200 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,
172 vec->length);202 vec->length);
173 return 1;203 return -1;
174 }204 }
175 205
176 Py_XDECREF(vec->phas);206 Py_XDECREF(vec->phas);
@@ -182,7 +212,7 @@ Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) · 5 unmodified lines
182static PyMemberDef Py_cvec_members[] = {212static PyMemberDef Py_cvec_members[] = {
183 // TODO remove READONLY flag and define getter/setter213 // TODO remove READONLY flag and define getter/setter
184 {"length", T_INT, offsetof (Py_cvec, length), READONLY,214 {"length", T_INT, offsetof (Py_cvec, length), READONLY,
185 "length attribute"},215 "int: Length of `norm` and `phas` vectors."},
186 {NULL} /* Sentinel */216 {NULL} /* Sentinel */
187};217};
188 218
@@ -191,11 +221,11 @@ static PyMethodDef Py_cvec_methods[] = { · 2 unmodified lines
191};221};
192 222
193static PyGetSetDef Py_cvec_getseters[] = {223static PyGetSetDef Py_cvec_getseters[] = {
194 {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, 224 {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm,
195 "Numpy vector of shape (length,) containing the magnitude",225 "numpy.ndarray: Vector of shape `(length,)` containing the magnitude.",
196 NULL},226 NULL},
197 {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, 227 {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas,
198 "Numpy vector of shape (length,) containing the phase",228 "numpy.ndarray: Vector of shape `(length,)` containing the phase.",
199 NULL},229 NULL},
200 {NULL} /* sentinel */230 {NULL} /* sentinel */
201};231};
python/ext/py-filterbank.c+133−9
@@ -94,7 +94,7 @@ Py_filterbank_do(Py_filterbank * self, PyObject * args) · 93 unmodified lines
94 94
95 if (self->vec.length != self->win_s / 2 + 1) {95 if (self->vec.length != self->win_s / 2 + 1) {
96 PyErr_Format(PyExc_ValueError,96 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",
98 self->vec.length, self->win_s / 2 + 1);98 self->vec.length, self->win_s / 2 + 1);
99 return NULL;99 return NULL;
100 }100 }
@@ -122,8 +122,8 @@ Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) · 21 unmodified lines
122 uint_t err = 0;122 uint_t err = 0;
123 123
124 PyObject *input;124 PyObject *input;
125 uint_t samplerate;125 smpl_t samplerate;
126 if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) {126 if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR, &input, &samplerate)) {
127 return NULL;127 return NULL;
128 }128 }
129 129
@@ -138,8 +138,14 @@ Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) · 8 unmodified lines
138 err = aubio_filterbank_set_triangle_bands (self->o,138 err = aubio_filterbank_set_triangle_bands (self->o,
139 &(self->freqs), samplerate);139 &(self->freqs), samplerate);
140 if (err > 0) {140 if (err > 0) {
141 PyErr_SetString (PyExc_ValueError,141 if (PyErr_Occurred() == NULL) {
142 "error when setting filter to A-weighting");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 }
143 return NULL;149 return NULL;
144 }150 }
145 Py_RETURN_NONE;151 Py_RETURN_NONE;
@@ -150,15 +156,79 @@ Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) · 4 unmodified lines
150{156{
151 uint_t err = 0;157 uint_t err = 0;
152 158
153 uint_t samplerate;159 smpl_t samplerate;
154 if (!PyArg_ParseTuple (args, "I", &samplerate)) {160 if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &samplerate)) {
155 return NULL;161 return NULL;
156 }162 }
157 163
158 err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate);164 err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate);
159 if (err > 0) {165 if (err > 0) {
160 PyErr_SetString (PyExc_ValueError,166 if (PyErr_Occurred() == NULL) {
161 "error when setting filter to A-weighting");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
179static PyObject *
180Py_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
208static PyObject *
209Py_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 }
162 return NULL;232 return NULL;
163 }233 }
164 Py_RETURN_NONE;234 Py_RETURN_NONE;
@@ -195,15 +265,69 @@ Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused) · 30 unmodified lines
195 aubio_filterbank_get_coeffs (self->o) );265 aubio_filterbank_get_coeffs (self->o) );
196}266}
197 267
268static PyObject *
269Py_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
291static PyObject *
292Py_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
198static PyMethodDef Py_filterbank_methods[] = {314static PyMethodDef Py_filterbank_methods[] = {
199 {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands,315 {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands,
200 METH_VARARGS, "set coefficients of filterbanks"},316 METH_VARARGS, "set coefficients of filterbanks"},
201 {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney,317 {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney,
202 METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"},318 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"},
203 {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs,323 {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs,
204 METH_NOARGS, "get coefficients of filterbank"},324 METH_NOARGS, "get coefficients of filterbank"},
205 {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs,325 {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs,
206 METH_VARARGS, "set coefficients of filterbank"},326 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"},
207 {NULL}331 {NULL}
208};332};
209 333
python/ext/py-musicutils.c+102−0
@@ -133,3 +133,105 @@ Py_aubio_level_detection(PyObject *self, PyObject *args) · 132 unmodified lines
133 133
134 return level_detection;134 return level_detection;
135}135}
136
137PyObject *
138Py_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
161PyObject *
162Py_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
185PyObject*
186Py_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
202PyObject*
203Py_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
219PyObject*
220Py_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
229PyObject*
230Py_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
2#define PY_AUBIO_MUSICUTILS_H2#define PY_AUBIO_MUSICUTILS_H
3 3
4static char Py_aubio_window_doc[] = ""4static char Py_aubio_window_doc[] = ""
5"window(string, integer) -> fvec\n"5"window(window_type, size)\n"
6"\n"6"\n"
7"Create a window\n"7"Create a window of length `size`. `window_type` should be one\n"
8"of the following:\n"
8"\n"9"\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"
10"-------\n"30"-------\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"
11"\n"41"\n"
12">>> window('hanningz', 1024)\n"42">>> aubio.window('hanningz', 1024)\n"
13"array([ 0.00000000e+00, 9.41753387e-06, 3.76403332e-05, ...,\n"43"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"";
15 94
16PyObject * Py_aubio_window(PyObject *self, PyObject *args);95PyObject * Py_aubio_window(PyObject *self, PyObject *args);
17 96
18static char Py_aubio_level_lin_doc[] = ""97static char Py_aubio_level_lin_doc[] = ""
19"level_lin(fvec) -> fvec\n"98"level_lin(x)\n"
20"\n"99"\n"
21"Compute sound level on a linear scale.\n"100"Compute sound pressure level of `x`, on a linear scale.\n"
22"\n"101"\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"
24"\n"111"\n"
25"Example\n"112"Example\n"
26"-------\n"113"-------\n"
27"\n"114"\n"
28">>> level_Lin(numpy.ones(1024))\n"115">>> aubio.level_lin(aubio.fvec(numpy.ones(1024)))\n"
29"1.0";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"";
30 128
31PyObject * Py_aubio_level_lin(PyObject *self, PyObject *args);129PyObject * Py_aubio_level_lin(PyObject *self, PyObject *args);
32 130
33static char Py_aubio_db_spl_doc[] = ""131static char Py_aubio_db_spl_doc[] = ""
34"Compute sound pressure level (SPL) in dB\n"132"db_spl(x)\n"
35"\n"133"\n"
36"This quantity is often wrongly called 'loudness'.\n"134"Compute Sound Pressure Level (SPL) of `x`, in dB.\n"
37"\n"135"\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"
39"\n"145"\n"
40"Example\n"146"Example\n"
41"-------\n"147"-------\n"
42"\n"148"\n"
43">>> db_spl(numpy.ones(1024))\n"149">>> aubio.db_spl(aubio.fvec(np.ones(1024)))\n"
44"1.0";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"";
45 168
46PyObject * Py_aubio_db_spl(PyObject *self, PyObject *args);169PyObject * Py_aubio_db_spl(PyObject *self, PyObject *args);
47 170
48static char Py_aubio_silence_detection_doc[] = ""171static 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"
50"\n"173"\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"
52"\n"175"\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"
54"-------\n"184"-------\n"
185"int\n"
186" `1` if level of `vec`, in dB SPL, is under `level`,\n"
187" `0` otherwise.\n"
55"\n"188"\n"
56">>> import numpy\n"""189"Examples\n"
57">>> silence_detection(numpy.ones(1024, dtype=\"float32\"), -80)\n"190"--------\n"
58"0";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"";
59 201
60PyObject * Py_aubio_silence_detection(PyObject *self, PyObject *args);202PyObject * Py_aubio_silence_detection(PyObject *self, PyObject *args);
61 203
62static char Py_aubio_level_detection_doc[] = ""204static 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"
64"\n"221"\n"
65"Example\n"222"Example\n"
66"-------\n"223"-------\n"
67"\n"224"\n"
68">>> import numpy\n"""225">>> aubio.level_detection(0.7*aubio.fvec(np.ones(1024)), -3.)\n"
69">>> level_detection(0.7*numpy.ones(1024, dtype=\"float32\"), -80)\n"226"1.0\n"
70"0";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"";
71 234
72PyObject * Py_aubio_level_detection(PyObject *self, PyObject *args);235PyObject * Py_aubio_level_detection(PyObject *self, PyObject *args);
73 236
237static 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"";
268PyObject * Py_aubio_shift(PyObject *self, PyObject *args);
269
270static 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"";
301PyObject * Py_aubio_ishift(PyObject *self, PyObject *args);
302
303static 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"";
324PyObject * Py_aubio_hztomel(PyObject *self, PyObject *args);
325
326static 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"";
347PyObject * Py_aubio_meltohz(PyObject *self, PyObject *args);
348
349static 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"";
358PyObject * Py_aubio_hztomel_htk(PyObject *self, PyObject *args);
359
360static 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"";
369PyObject * Py_aubio_meltohz_htk(PyObject *self, PyObject *args);
370
74#endif /* PY_AUBIO_MUSICUTILS_H */371#endif /* PY_AUBIO_MUSICUTILS_H */
python/ext/py-phasevoc.c+116−8
@@ -1,6 +1,58 @@
1#include "aubio-types.h"1#include "aubio-types.h"
2 2
3static char Py_pvoc_doc[] = "pvoc object";3static 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
4 56
5typedef struct57typedef struct
6{58{
@@ -38,10 +90,6 @@ Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) · 31 unmodified lines
38 self->win_s = Py_default_vector_length;90 self->win_s = Py_default_vector_length;
39 self->hop_s = Py_default_vector_length/2;91 self->hop_s = Py_default_vector_length/2;
40 92
41 if (self == NULL) {
42 return NULL;
43 }
44
45 if (win_s > 0) {93 if (win_s > 0) {
46 self->win_s = win_s;94 self->win_s = win_s;
47 } else if (win_s < 0) {95 } else if (win_s < 0) {
@@ -121,9 +169,11 @@ Py_pvoc_do(Py_pvoc * self, PyObject * args) · 73 unmodified lines
121 169
122static PyMemberDef Py_pvoc_members[] = {170static PyMemberDef Py_pvoc_members[] = {
123 {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY,171 {"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 ""},
125 {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY,174 {"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 ""},
127 { NULL } // sentinel177 { NULL } // sentinel
128};178};
129 179
@@ -155,9 +205,67 @@ Py_pvoc_rdo(Py_pvoc * self, PyObject * args) · 25 unmodified lines
155 return self->routput;205 return self->routput;
156}206}
157 207
208static PyObject *
209Pyaubio_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
158static PyMethodDef Py_pvoc_methods[] = {226static PyMethodDef Py_pvoc_methods[] = {
159 {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS,227 {"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 ""},
161 {NULL}269 {NULL}
162};270};
163 271
python/ext/py-sink.c+89−50
@@ -12,53 +12,78 @@ typedef struct · 11 unmodified lines
12} Py_sink;12} Py_sink;
13 13
14static char Py_sink_doc[] = ""14static char Py_sink_doc[] = ""
15" __new__(path, samplerate = 44100, channels = 1)\n"15"sink(path, samplerate=44100, channels=1)\n"
16"\n"16"\n"
17" Create a new sink, opening the given path for writing.\n"17"Write audio samples to file.\n"
18"\n"18"\n"
19" Examples\n"19"Parameters\n"
20" --------\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"
21"\n"27"\n"
22" Create a new sink at 44100Hz, mono:\n"28"Examples\n"
29"--------\n"
23"\n"30"\n"
24" >>> sink('/tmp/t.wav')\n"31"Create a new sink at 44100Hz, mono:\n"
25"\n"32"\n"
26" Create a new sink at 8000Hz, mono:\n"33">>> snk = aubio.sink('out.wav')\n"
27"\n"34"\n"
28" >>> sink('/tmp/t.wav', samplerate = 8000)\n"35"Create a new sink at 32000Hz, stereo, write 100 samples into it:\n"
29"\n"36"\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"
31"\n"39"\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"
33"\n"41"\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"
35"\n"46"\n"
36" >>> sink('/tmp/t.wav', channels = 5, samplerate = 32000)\n"47"See also\n"
37"\n"48"--------\n"
38" __call__(vec, write)\n"49"source: read audio samples from a file.\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"
46"\n";50"\n";
47 51
48static char Py_sink_do_doc[] = ""52static char Py_sink_do_doc[] = ""
49"x.do(vec, write) <==> x(vec, write)\n"53"do(vec, write)\n"
50"\n"54"\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"";
52 64
53static char Py_sink_do_multi_doc[] = ""65static 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"
55"\n"69"\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"";
57 77
58static char Py_sink_close_doc[] = ""78static char Py_sink_close_doc[] = ""
59"x.close()\n"79"close()\n"
60"\n"80"\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"";
62 87
63static PyObject *88static PyObject *
64Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)89Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
@@ -80,27 +105,20 @@ Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) · 15 unmodified lines
80 return NULL;105 return NULL;
81 }106 }
82 107
83 self->uri = "none";108 self->uri = NULL;
84 if (uri != NULL) {109 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);
86 }112 }
87 113
88 self->samplerate = Py_aubio_default_samplerate;114 self->samplerate = Py_aubio_default_samplerate;
89 if ((sint_t)samplerate > 0) {115 if (samplerate != 0) {
90 self->samplerate = samplerate;116 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;
95 }117 }
96 118
97 self->channels = 1;119 self->channels = 1;
98 if ((sint_t)channels > 0) {120 if (channels != 0) {
99 self->channels = channels;121 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;
104 }122 }
105 123
106 return (PyObject *) self;124 return (PyObject *) self;
@@ -109,17 +127,20 @@ Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) · 2 unmodified lines
109static int127static int
110Py_sink_init (Py_sink * self, PyObject * args, PyObject * kwds)128Py_sink_init (Py_sink * self, PyObject * args, PyObject * kwds)
111{129{
112 if (self->channels == 1) {130 self->o = new_aubio_sink ( self->uri, 0 );
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 }
119 if (self->o == NULL) {131 if (self->o == NULL) {
120 PyErr_SetString (PyExc_RuntimeError, "error creating sink with this uri");132 // error string was set in new_aubio_sink
121 return -1;133 return -1;
122 }134 }
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
123 self->samplerate = aubio_sink_get_samplerate ( self->o );144 self->samplerate = aubio_sink_get_samplerate ( self->o );
124 self->channels = aubio_sink_get_channels ( self->o );145 self->channels = aubio_sink_get_channels ( self->o );
125 146
@@ -131,6 +152,9 @@ Py_sink_del (Py_sink *self, PyObject *unused) · 5 unmodified lines
131{152{
132 del_aubio_sink(self->o);153 del_aubio_sink(self->o);
133 free(self->mwrite_data.data);154 free(self->mwrite_data.data);
155 if (self->uri) {
156 free(self->uri);
157 }
134 Py_TYPE(self)->tp_free((PyObject *) self);158 Py_TYPE(self)->tp_free((PyObject *) self);
135}159}
136 160
@@ -189,11 +213,11 @@ Py_sink_do_multi(Py_sink * self, PyObject * args) · 52 unmodified lines
189 213
190static PyMemberDef Py_sink_members[] = {214static PyMemberDef Py_sink_members[] = {
191 {"uri", T_STRING, offsetof (Py_sink, uri), READONLY,215 {"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."},
193 {"samplerate", T_INT, offsetof (Py_sink, samplerate), READONLY,217 {"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."},
195 {"channels", T_INT, offsetof (Py_sink, channels), READONLY,219 {"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."},
197 { NULL } // sentinel221 { NULL } // sentinel
198};222};
199 223
@@ -204,10 +228,25 @@ Pyaubio_sink_close (Py_sink *self, PyObject *unused) · 4 unmodified lines
204 Py_RETURN_NONE;228 Py_RETURN_NONE;
205}229}
206 230
231static char Pyaubio_sink_enter_doc[] = "";
232static PyObject* Pyaubio_sink_enter(Py_sink *self, PyObject *unused) {
233 Py_INCREF(self);
234 return (PyObject*)self;
235}
236
237static char Pyaubio_sink_exit_doc[] = "";
238static PyObject* Pyaubio_sink_exit(Py_sink *self, PyObject *unused) {
239 return Pyaubio_sink_close(self, unused);
240}
241
207static PyMethodDef Py_sink_methods[] = {242static PyMethodDef Py_sink_methods[] = {
208 {"do", (PyCFunction) Py_sink_do, METH_VARARGS, Py_sink_do_doc},243 {"do", (PyCFunction) Py_sink_do, METH_VARARGS, Py_sink_do_doc},
209 {"do_multi", (PyCFunction) Py_sink_do_multi, METH_VARARGS, Py_sink_do_multi_doc},244 {"do_multi", (PyCFunction) Py_sink_do_multi, METH_VARARGS, Py_sink_do_multi_doc},
210 {"close", (PyCFunction) Pyaubio_sink_close, METH_NOARGS, Py_sink_close_doc},245 {"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},
211 {NULL} /* sentinel */250 {NULL} /* sentinel */
212};251};
213 252
python/ext/py-source.c+370−41
@@ -16,68 +16,316 @@ typedef struct · 15 unmodified lines
16} Py_source;16} Py_source;
17 17
18static char Py_source_doc[] = ""18static 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"
20"\n"20"\n"
21" Create a new source, opening the given path for reading.\n"21"Read audio samples from a media file.\n"
22"\n"22"\n"
23" Examples\n"23"`source` open the file specified in `path` and creates a callable\n"
24" --------\n"24"returning `hop_size` new audio samples at each invocation.\n"
25"\n"25"\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"
27"\n"29"\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"
29"\n"34"\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"
31"\n"37"\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"
33"\n"40"\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"
35"\n"51"\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"
37"\n"56"\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"
39"\n"60"\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"
41"\n"63"\n"
42" __call__()\n"64">>> src = aubio.source('stereo.wav')\n"
43" vec, read = x() <==> vec, read = x.do()\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"
44"\n"73"\n"
45" Read vector from source.\n"74"In a more Pythonic way, it can also look like this:\n"
46"\n"75"\n"
47" See also\n"76">>> total_read = 0\n"
48" --------\n"77">>> with aubio.source('stereo.wav') as src:\n"
49" aubio.source.do\n"78"... for frames in src:\n"
50"\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"";
51 217
52static char Py_source_get_samplerate_doc[] = ""218static 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"
54"\n"222"\n"
55"Get samplerate of source.";223"Returns\n"
224"-------\n"
225"int\n"
226" Sampling rate, in Hz.\n"
227"";
56 228
57static char Py_source_get_channels_doc[] = ""229static char Py_source_get_channels_doc[] = ""
58"x.get_channels() -> number of channels\n"230"get_channels()\n"
59"\n"231"\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"";
61 239
62static char Py_source_do_doc[] = ""240static 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"
64"\n"256"\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"";
66 268
67static char Py_source_do_multi_doc[] = ""269static 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"
69"\n"283"\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"";
71 307
72static char Py_source_close_doc[] = ""308static char Py_source_close_doc[] = ""
73"x.close()\n"309"close()\n"
74"\n"310"\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"";
76 315
77static char Py_source_seek_doc[] = ""316static char Py_source_seek_doc[] = ""
78"x.seek(position)\n"317"seek(position)\n"
318"\n"
319"Seek to position in file.\n"
79"\n"320"\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"";
81 329
82static PyObject *330static PyObject *
83Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)331Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
@@ -100,9 +348,10 @@ Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) · 16 unmodified lines
100 return NULL;348 return NULL;
101 }349 }
102 350
103 self->uri = "none";351 self->uri = NULL;
104 if (uri != NULL) {352 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);
106 }355 }
107 356
108 self->samplerate = 0;357 self->samplerate = 0;
@@ -163,6 +412,9 @@ Py_source_del (Py_source *self, PyObject *unused) · 54 unmodified lines
163 del_aubio_source(self->o);412 del_aubio_source(self->o);
164 free(self->c_mread_to.data);413 free(self->c_mread_to.data);
165 }414 }
415 if (self->uri) {
416 free(self->uri);
417 }
166 Py_XDECREF(self->read_to);418 Py_XDECREF(self->read_to);
167 Py_XDECREF(self->mread_to);419 Py_XDECREF(self->mread_to);
168 Py_TYPE(self)->tp_free((PyObject *) self);420 Py_TYPE(self)->tp_free((PyObject *) self);
@@ -213,15 +465,29 @@ Py_source_do_multi(Py_source * self, PyObject * args) · 44 unmodified lines
213 465
214static PyMemberDef Py_source_members[] = {466static PyMemberDef Py_source_members[] = {
215 {"uri", T_STRING, offsetof (Py_source, uri), READONLY,467 {"uri", T_STRING, offsetof (Py_source, uri), READONLY,
216 "path at which the source was created"},468 "str (read-only): pathname or URL"},
217 {"samplerate", T_INT, offsetof (Py_source, samplerate), READONLY,469 {"samplerate", T_INT, offsetof (Py_source, samplerate), READONLY,
218 "samplerate at which the source is viewed"},470 "int (read-only): sampling rate"},
219 {"channels", T_INT, offsetof (Py_source, channels), READONLY,471 {"channels", T_INT, offsetof (Py_source, channels), READONLY,
220 "number of channels found in the source"},472 "int (read-only): number of channels"},
221 {"hop_size", T_INT, offsetof (Py_source, hop_size), READONLY,473 {"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"},
223 {"duration", T_INT, offsetof (Py_source, duration), READONLY,475 {"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 ""},
225 { NULL } // sentinel491 { NULL } // sentinel
226};492};
227 493
@@ -242,7 +508,7 @@ Pyaubio_source_get_channels (Py_source *self, PyObject *unused) · 14 unmodified lines
242static PyObject *508static PyObject *
243Pyaubio_source_close (Py_source *self, PyObject *unused)509Pyaubio_source_close (Py_source *self, PyObject *unused)
244{510{
245 aubio_source_close (self->o);511 if (aubio_source_close(self->o) != 0) return NULL;
246 Py_RETURN_NONE;512 Py_RETURN_NONE;
247}513}
248 514
@@ -272,6 +538,65 @@ Pyaubio_source_seek (Py_source *self, PyObject *args) · 23 unmodified lines
272 Py_RETURN_NONE;538 Py_RETURN_NONE;
273}539}
274 540
541static char Pyaubio_source_enter_doc[] = "";
542static PyObject* Pyaubio_source_enter(Py_source *self, PyObject *unused) {
543 Py_INCREF(self);
544 return (PyObject*)self;
545}
546
547static char Pyaubio_source_exit_doc[] = "";
548static PyObject* Pyaubio_source_exit(Py_source *self, PyObject *unused) {
549 return Pyaubio_source_close(self, unused);
550}
551
552static PyObject* Pyaubio_source_iter(PyObject *self) {
553 Py_INCREF(self);
554 return (PyObject*)self;
555}
556
557static 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
275static PyMethodDef Py_source_methods[] = {600static PyMethodDef Py_source_methods[] = {
276 {"get_samplerate", (PyCFunction) Pyaubio_source_get_samplerate,601 {"get_samplerate", (PyCFunction) Pyaubio_source_get_samplerate,
277 METH_NOARGS, Py_source_get_samplerate_doc},602 METH_NOARGS, Py_source_get_samplerate_doc},
@@ -285,6 +610,10 @@ static PyMethodDef Py_source_methods[] = { · 7 unmodified lines
285 METH_NOARGS, Py_source_close_doc},610 METH_NOARGS, Py_source_close_doc},
286 {"seek", (PyCFunction) Pyaubio_source_seek,611 {"seek", (PyCFunction) Pyaubio_source_seek,
287 METH_VARARGS, Py_source_seek_doc},612 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},
288 {NULL} /* sentinel */617 {NULL} /* sentinel */
289};618};
290 619
@@ -314,8 +643,8 @@ PyTypeObject Py_sourceType = { · 23 unmodified lines
314 0,643 0,
315 0,644 0,
316 0,645 0,
317 0,646 Pyaubio_source_iter,
318 0,647 (unaryfunc)Pyaubio_source_iter_next,
319 Py_source_methods,648 Py_source_methods,
320 Py_source_members,649 Py_source_members,
321 0,650 0,
python/ext/ufuncs.c+44−3
@@ -58,7 +58,22 @@ static char Py_aubio_unary_types[] = { · 57 unmodified lines
58 //NPY_OBJECT, NPY_OBJECT,58 //NPY_OBJECT, NPY_OBJECT,
59};59};
60 60
61static char Py_unwrap2pi_doc[] = "map angle to unit circle [-pi, pi[";61// Note: these docstrings should *not* include the function signatures
62
63static 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"";
62 77
63static void* Py_unwrap2pi_data[] = {78static void* Py_unwrap2pi_data[] = {
64 (void *)aubio_unwrap2pi,79 (void *)aubio_unwrap2pi,
@@ -67,14 +82,40 @@ static void* Py_unwrap2pi_data[] = { · 2 unmodified lines
67 //(void *)unwrap2pio,82 //(void *)unwrap2pio,
68};83};
69 84
70static char Py_freqtomidi_doc[] = "convert frequency to midi";85static 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"";
71 99
72static void* Py_freqtomidi_data[] = {100static void* Py_freqtomidi_data[] = {
73 (void *)aubio_freqtomidi,101 (void *)aubio_freqtomidi,
74 (void *)aubio_freqtomidi,102 (void *)aubio_freqtomidi,
75};103};
76 104
77static char Py_miditofreq_doc[] = "convert midi to frequency";105static 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"";
78 119
79static void* Py_miditofreq_data[] = {120static void* Py_miditofreq_data[] = {
80 (void *)aubio_miditofreq,121 (void *)aubio_miditofreq,
python/lib/__init__.py+0−0

Empty file deleted.

python/lib/aubio/__init__.py+72−5
@@ -1,18 +1,85 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2# -*- coding: utf8 -*-
3
4"""
5aubio
6=====
7
8Provides a number of classes and functions for music and audio signal
9analysis.
10
11How to use the documentation
12----------------------------
13
14Documentation of the python module is available as docstrings provided
15within the code, and a reference guide available online from `the
16aubio homepage <https://aubio.org/documentation>`_.
17
18The docstrings examples are written assuming `aubio` and `numpy` have been
19imported with:
20
21>>> import aubio
22>>> import numpy as np
23"""
2 24
3import numpy25import numpy
4from ._aubio import *26from ._aubio import __version__ as version
5from ._aubio import float_type27from ._aubio import float_type
28from ._aubio import *
6from .midiconv import *29from .midiconv import *
7from .slicing import *30from .slicing import *
8 31
32
9class fvec(numpy.ndarray):33class 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'))
11 58
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):
13 if isinstance(input_arg, int):75 if isinstance(input_arg, int):
14 if input_arg == 0:76 if input_arg == 0:
15 raise ValueError("vector length of 1 or more expected")77 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')
17 else:79 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
6This file was written by Paul Brossier <piem@aubio.org> and is released under
7the GNU/GPL v3.
8
9Note: this script is mostly about parsing command line arguments. For more
10readable code examples, check out the `python/demos` folder."""
11
12import sys
13import argparse
14import warnings
15import aubio
16
17def 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
41def 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
47def 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
64def 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
79def 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
89def 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
99def 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
111def 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
121def 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
131def 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
142def 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
159class 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
268def samples2seconds(n_frames, samplerate):
269 return "%f\t" % (n_frames / float(samplerate))
270
271def samples2milliseconds(n_frames, samplerate):
272 return "%f\t" % (1000. * n_frames / float(samplerate))
273
274def samples2samples(n_frames, _samplerate):
275 return "%d\t" % n_frames
276
277def 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
289class 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
318class 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
342class 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
360class 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
373class 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
393class 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
418class 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
442class 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
465class 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
498class 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
521def _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
547def 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
7import sys
8from aubio.cmd import AubioArgumentParser, _cut_slice
9
10def 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
93def _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
136def 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 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2""" utilities to convert midi note number to and from note names """2""" utilities to convert midi note number to and from note names """
3 3
4__all__ = ['note2midi', 'midi2note', 'freq2note']
5
6import sys4import sys
5from ._aubio import freqtomidi, miditofreq
6
7__all__ = ['note2midi', 'midi2note', 'freq2note', 'note2freq']
8
7py3 = sys.version_info[0] == 39py3 = sys.version_info[0] == 3
8if py3:10if py3:
9 str_instances = str11 str_instances = str
@@ -12,18 +14,65 @@ else: · 2 unmodified lines
12 str_instances = (str, unicode)14 str_instances = (str, unicode)
13 int_instances = (int, long)15 int_instances = (int, long)
14 16
17
15def note2midi(note):18def note2midi(note):
16 " convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] "19 """Convert note name to midi note number.
17 _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}20
18 _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2,21 Input string `note` should be composed of one note root
19 'b': -1, u'♭': -1, u'\ufffd': -2}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 }
20 _valid_octaves = range(-1, 10)68 _valid_octaves = range(-1, 10)
21 if not isinstance(note, str_instances):69 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)))
23 if len(note) not in range(2, 5):72 if len(note) not in range(2, 5):
24 raise ValueError("string of 2 to 4 characters expected, got %d (%s)" \73 msg = "string of 2 to 4 characters expected, got {:d} ({:s})"
25 % (len(note), note))74 raise ValueError(msg.format(len(note), note))
26 notename, modifier, octave = [None]*375 notename, modifier, octave = [None] * 3
27 76
28 if len(note) == 4:77 if len(note) == 4:
29 notename, modifier, octave_sign, octave = note78 notename, modifier, octave_sign, octave = note
@@ -46,21 +95,97 @@ def note2midi(note): · 16 unmodified lines
46 if octave not in _valid_octaves:95 if octave not in _valid_octaves:
47 raise ValueError("%s is not a valid octave" % octave)96 raise ValueError("%s is not a valid octave" % octave)
48 97
49 midi = 12 + octave * 12 + _valid_notenames[notename] + _valid_modifiers[modifier]98 midi = (octave + 1) * 12 + _valid_notenames[notename] \
99 + _valid_modifiers[modifier]
50 if midi > 127:100 if midi > 127:
51 raise ValueError("%s is outside of the range C-2 to G8" % note)101 raise ValueError("%s is outside of the range C-2 to G8" % note)
52 return midi102 return midi
53 103
104
54def midi2note(midi):105def 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 """
56 if not isinstance(midi, int_instances):136 if not isinstance(midi, int_instances):
57 raise TypeError("an integer is required, got %s" % midi)137 raise TypeError("an integer is required, got %s" % midi)
58 if midi not in range(0, 128):138 if midi not in range(0, 128):
59 raise ValueError("an integer between 0 and 127 is excepted, got %d" % midi)139 msg = "an integer between 0 and 127 is excepted, got {:d}"
60 _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']140 raise ValueError(msg.format(midi))
141 _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#',
142 'A', 'A#', 'B']
61 return _valid_notenames[midi % 12] + str(int(midi / 12) - 1)143 return _valid_notenames[midi % 12] + str(int(midi / 12) - 1)
62 144
145
63def freq2note(freq):146def freq2note(freq):
64 " convert frequency in Hz to nearest note name, e.g. [0, 22050.] -> [C-1, G9] "147 """Convert frequency in Hz to nearest note name.
65 from aubio import freqtomidi148
66 return midi2note(int(freqtomidi(freq)))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
170def 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
5 5
6_max_timestamp = 1e1206_max_timestamp = 1e120
7 7
8
8def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,9def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,
9 output_dir=None, samplerate=0, hopsize=256):10 output_dir=None, samplerate=0, hopsize=256,
10 """ slice a sound file at given timestamps """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 """
11 75
12 if timestamps is None or len(timestamps) == 0:76 if not timestamps:
13 raise ValueError("no timestamps given")77 raise ValueError("no timestamps given")
14 78
15 if timestamps[0] != 0:79 if timestamps[0] != 0 and create_first:
16 timestamps = [0] + timestamps80 timestamps = [0] + timestamps
17 if timestamps_end is not None:81 if timestamps_end is not None:
18 timestamps_end = [timestamps[1] - 1] + timestamps_end82 timestamps_end = [timestamps[1] - 1] + timestamps_end
19 83
20 if timestamps_end is not None:84 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):
22 raise ValueError("len(timestamps_end) != len(timestamps)")88 raise ValueError("len(timestamps_end) != len(timestamps)")
23 else:89 else:
24 timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp]90 timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp]
25 91
26 regions = list(zip(timestamps, timestamps_end))92 regions = list(zip(timestamps, timestamps_end))
27 #print regions
28 93
29 source_base_name, _ = os.path.splitext(os.path.basename(source_file))94 source_base_name, _ = os.path.splitext(os.path.basename(source_file))
30 if output_dir is not None:95 if output_dir is not None:
@@ -32,8 +97,8 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 1 unmodified line
32 os.makedirs(output_dir)97 os.makedirs(output_dir)
33 source_base_name = os.path.join(output_dir, source_base_name)98 source_base_name = os.path.join(output_dir, source_base_name)
34 99
35 def new_sink_name(source_base_name, timestamp, samplerate):100 def _new_sink_name(source_base_name, timestamp, samplerate):
36 """ create a sink based on a timestamp in samples, converted in seconds """101 # create name based on a timestamp in samples, converted in seconds
37 timestamp_seconds = timestamp / float(samplerate)102 timestamp_seconds = timestamp / float(samplerate)
38 return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'103 return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'
39 104
@@ -48,16 +113,17 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 8 unmodified lines
48 # get hopsize new samples from source113 # get hopsize new samples from source
49 vec, read = _source.do_multi()114 vec, read = _source.do_multi()
50 # if the total number of frames read will exceed the next region start115 # if the total number of frames read will exceed the next region start
51 if len(regions) and total_frames + read >= regions[0][0]:116 while regions and total_frames + read >= regions[0][0]:
52 #print "getting", regions[0], "at", total_frames
53 # get next region117 # get next region
54 start_stamp, end_stamp = regions.pop(0)118 start_stamp, end_stamp = regions.pop(0)
55 # create a name for the sink119 # 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)
57 # create its sink122 # create its sink
58 _sink = sink(new_sink_path, samplerate, _source.channels)123 _sink = sink(new_sink_path, samplerate, _source.channels)
59 # create a dictionary containing all this124 # 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}
61 # append the dictionary to the current list of slices127 # append the dictionary to the current list of slices
62 slices.append(new_slice)128 slices.append(new_slice)
63 129
@@ -69,18 +135,19 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 5 unmodified lines
69 start = max(start_stamp - total_frames, 0)135 start = max(start_stamp - total_frames, 0)
70 # number of samples yet to written be until end of region136 # number of samples yet to written be until end of region
71 remaining = end_stamp - total_frames + 1137 remaining = end_stamp - total_frames + 1
72 #print current_slice, remaining, start
73 # not enough frames remaining, time to split138 # not enough frames remaining, time to split
74 if remaining < read:139 if remaining < read:
75 if remaining > start:140 if remaining > start:
76 # write remaining samples from current region141 # write remaining samples from current region
77 _sink.do_multi(vec[:, start:remaining], remaining - start)142 _sink.do_multi(vec[:, start:remaining], remaining - start)
78 #print "closing region", "remaining", remaining
79 # close this file143 # close this file
80 _sink.close()144 _sink.close()
81 elif read > start:145 elif read > start:
82 # write all the samples146 # write all the samples
83 _sink.do_multi(vec[:, start:read], read - start)147 _sink.do_multi(vec[:, start:read], read - start)
84 total_frames += read148 total_frames += read
149 # remove old slices
150 slices = list(filter(lambda s: s['end_stamp'] > total_frames,
151 slices))
85 if read < hopsize:152 if read < hopsize:
86 break153 break
python/lib/gen_code.py+65−23
@@ -2,6 +2,7 @@ aubiodefvalue = { · 1 unmodified line
2 # we have some clean up to do2 # we have some clean up to do
3 'buf_size': 'Py_default_vector_length',3 'buf_size': 'Py_default_vector_length',
4 'win_s': 'Py_default_vector_length',4 'win_s': 'Py_default_vector_length',
5 'size': 'Py_default_vector_length',
5 # and here too6 # and here too
6 'hop_size': 'Py_default_vector_length / 2',7 'hop_size': 'Py_default_vector_length / 2',
7 'hop_s': 'Py_default_vector_length / 2',8 'hop_s': 'Py_default_vector_length / 2',
@@ -84,6 +85,7 @@ objoutsize = { · 76 unmodified lines
84 'filterbank': 'self->n_filters',85 'filterbank': 'self->n_filters',
85 'tss': 'self->buf_size',86 'tss': 'self->buf_size',
86 'pitchshift': 'self->hop_size',87 'pitchshift': 'self->hop_size',
88 'dct': 'self->size',
87 }89 }
88 90
89objinputsize = {91objinputsize = {
@@ -179,6 +181,10 @@ class MappedObject(object): · 89 unmodified lines
179 self.do_inputs = [get_params_types_names(self.do_proto)[1]]181 self.do_inputs = [get_params_types_names(self.do_proto)[1]]
180 self.do_outputs = get_params_types_names(self.do_proto)[2:]182 self.do_outputs = get_params_types_names(self.do_proto)[2:]
181 struct_output_str = ["PyObject *{0[name]}; {1} c_{0[name]}".format(i, i['type'][:-1]) for i in self.do_outputs]183 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
182 self.struct_outputs = ";\n ".join(struct_output_str)188 self.struct_outputs = ";\n ".join(struct_output_str)
183 189
184 #print ("input_params: ", map(split_type, get_input_params(self.do_proto)))190 #print ("input_params: ", map(split_type, get_input_params(self.do_proto)))
@@ -186,17 +192,26 @@ class MappedObject(object): · 1 unmodified line
186 192
187 def gen_code(self):193 def gen_code(self):
188 out = ""194 out = ""
189 out += self.gen_struct()195 try:
190 out += self.gen_doc()196 out += self.gen_struct()
191 out += self.gen_new()197 out += self.gen_doc()
192 out += self.gen_init()198 out += self.gen_new()
193 out += self.gen_del()199 out += self.gen_init()
194 out += self.gen_do()200 out += self.gen_del()
195 out += self.gen_memberdef()201 out += self.gen_do()
196 out += self.gen_set()202 if len(self.prototypes['rdo']):
197 out += self.gen_get()203 self.do_proto = self.prototypes['rdo'][0]
198 out += self.gen_methodef()204 self.do_inputs = [get_params_types_names(self.do_proto)[1]]
199 out += self.gen_typeobject()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
200 return out215 return out
201 216
202 def gen_struct(self):217 def gen_struct(self):
@@ -380,12 +395,12 @@ Py_{shortname}_del (Py_{shortname} * self, PyObject * unused) · 177 unmodified lines
380""".format(del_fn = del_fn)395""".format(del_fn = del_fn)
381 return out396 return out
382 397
383 def gen_do(self):398 def gen_do(self, method = 'do'):
384 out = """399 out = """
385// do {shortname}400// do {shortname}
386static PyObject*401static PyObject*
387Py_{shortname}_do (Py_{shortname} * self, PyObject * args)402Pyaubio_{shortname}_{method} (Py_{shortname} * self, PyObject * args)
388{{""".format(**self.__dict__)403{{""".format(method = method, **self.__dict__)
389 input_params = self.do_inputs404 input_params = self.do_inputs
390 output_params = self.do_outputs405 output_params = self.do_outputs
391 #print input_params406 #print input_params
@@ -461,30 +476,51 @@ Py_{shortname}_do (Py_{shortname} * self, PyObject * args) · 69 unmodified lines
461// {shortname} setters476// {shortname} setters
462""".format(**self.__dict__)477""".format(**self.__dict__)
463 for set_param in self.prototypes['set']:478 for set_param in self.prototypes['set']:
464 params = get_params_types_names(set_param)[1]479 params = get_params_types_names(set_param)[1:]
465 paramtype = params['type']480 param = self.shortname.split('_set_')[-1]
481 paramdecls = "".join(["""
482 {0} {1};""".format(p['type'], p['name']) for p in params])
466 method_name = get_name(set_param)483 method_name = get_name(set_param)
467 param = method_name.split('aubio_'+self.shortname+'_set_')[-1]484 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])
469 out += """490 out += """
470static PyObject *491static PyObject *
471Pyaubio_{shortname}_set_{param} (Py_{shortname} *self, PyObject *args)492Pyaubio_{shortname}_set_{param} (Py_{shortname} *self, PyObject *args)
472{{493{{
473 uint_t err = 0;494 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 += """
475 500
476 if (!PyArg_ParseTuple (args, "{pyparamtype}", &{param})) {{501 if (!PyArg_ParseTuple (args, "{pyparamtypes}", {refs})) {{
477 return NULL;502 return NULL;
478 }}503 }}
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});
480 508
481 if (err > 0) {{509 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 }}
483 return NULL;518 return NULL;
484 }}519 }}
485 Py_RETURN_NONE;520 Py_RETURN_NONE;
486}}521}}
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__)
488 return out524 return out
489 525
490 def gen_get(self):526 def gen_get(self):
@@ -525,6 +561,12 @@ static PyMethodDef Py_{shortname}_methods[] = {{""".format(**self.__dict__) · 34 unmodified lines
525 out += """561 out += """
526 {{"{shortname}", (PyCFunction) Py{name},562 {{"{shortname}", (PyCFunction) Py{name},
527 METH_NOARGS, ""}},""".format(name = name, shortname = shortname)563 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)
528 out += """570 out += """
529 {NULL} /* sentinel */571 {NULL} /* sentinel */
530};572};
@@ -550,7 +592,7 @@ PyTypeObject Py_{shortname}Type = {{ · 19 unmodified lines
550 0,592 0,
551 0,593 0,
552 0,594 0,
553 (ternaryfunc)Py_{shortname}_do,595 (ternaryfunc)Pyaubio_{shortname}_do,
554 0,596 0,
555 0,597 0,
556 0,598 0,
python/lib/gen_external.py+180−89
@@ -1,5 +1,10 @@
1import distutils.ccompiler1import distutils.ccompiler
2import sys, os, subprocess, glob2import sys
3import os
4import subprocess
5import glob
6from distutils.sysconfig import customize_compiler
7from gen_code import MappedObject
3 8
4header = os.path.join('src', 'aubio.h')9header = os.path.join('src', 'aubio.h')
5output_path = os.path.join('python', 'gen')10output_path = os.path.join('python', 'gen')
@@ -8,43 +13,44 @@ source_header = """// this file is generated! do not modify · 2 unmodified lines
8#include "aubio-types.h"13#include "aubio-types.h"
9"""14"""
10 15
11skip_objects = [16default_skip_objects = [
12 # already in ext/17 # already in ext/
13 'fft',18 'fft',
14 'pvoc',19 'pvoc',
15 'filter',20 'filter',
16 'filterbank',21 'filterbank',
17 #'resampler',22 # AUBIO_UNSTABLE
18 # AUBIO_UNSTABLE23 'hist',
19 'hist',24 'parameter',
20 'parameter',25 'scale',
21 'scale',26 'beattracking',
22 'beattracking',27 'resampler',
23 'resampler',28 'peakpicker',
24 'peakpicker',29 'pitchfcomb',
25 'pitchfcomb',30 'pitchmcomb',
26 'pitchmcomb',31 'pitchschmitt',
27 'pitchschmitt',32 'pitchspecacf',
28 'pitchspecacf',33 'pitchyin',
29 'pitchyin',34 'pitchyinfft',
30 'pitchyinfft',35 'pitchyinfast',
31 'sink',36 'sink',
32 'sink_apple_audio',37 'sink_apple_audio',
33 'sink_sndfile',38 'sink_sndfile',
34 'sink_wavwrite',39 'sink_wavwrite',
35 #'mfcc',40 #'mfcc',
36 'source',41 'source',
37 'source_apple_audio',42 'source_apple_audio',
38 'source_sndfile',43 'source_sndfile',
39 'source_avcodec',44 'source_avcodec',
40 'source_wavread',45 'source_wavread',
41 #'sampler',46 #'sampler',
42 'audio_unit',47 'audio_unit',
43 ]48 'spectral_whitening',
49]
50
44 51
45def get_preprocessor():52def get_preprocessor():
46 # findout which compiler to use53 # findout which compiler to use
47 from distutils.sysconfig import customize_compiler
48 compiler_name = distutils.ccompiler.get_default_compiler()54 compiler_name = distutils.ccompiler.get_default_compiler()
49 compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)55 compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)
50 try:56 try:
@@ -59,26 +65,50 @@ def get_preprocessor(): · 8 unmodified lines
59 print("Warning: failed initializing compiler ({:s})".format(repr(e)))65 print("Warning: failed initializing compiler ({:s})".format(repr(e)))
60 66
61 cpp_cmd = None67 cpp_cmd = None
62 if hasattr(compiler, 'preprocessor'): # for unixccompiler68 if hasattr(compiler, 'preprocessor'): # for unixccompiler
63 cpp_cmd = compiler.preprocessor69 cpp_cmd = compiler.preprocessor
64 elif hasattr(compiler, 'compiler'): # for ccompiler70 elif hasattr(compiler, 'compiler'): # for ccompiler
65 cpp_cmd = compiler.compiler.split()71 cpp_cmd = compiler.compiler.split()
66 cpp_cmd += ['-E']72 cpp_cmd += ['-E']
67 elif hasattr(compiler, 'cc'): # for msvccompiler73 elif hasattr(compiler, 'cc'): # for msvccompiler
68 cpp_cmd = compiler.cc.split()74 cpp_cmd = compiler.cc.split()
69 cpp_cmd += ['-E']75 cpp_cmd += ['-E']
70 76
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
71 if not cpp_cmd:89 if not cpp_cmd:
72 print("Warning: could not guess preprocessor, using env's CC")90 print("Warning: could not guess preprocessor, using env's CC")
73 cpp_cmd = os.environ.get('CC', 'cc').split()91 cpp_cmd = os.environ.get('CC', 'cc').split()
74 cpp_cmd += ['-E']92 cpp_cmd += ['-E']
75 93 if 'emcc' in cpp_cmd:
94 cpp_cmd += ['-x', 'c'] # emcc defaults to c++, force C language
76 return cpp_cmd95 return cpp_cmd
77 96
78def get_cpp_objects(header=header):97
98def 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
105def get_cpp_output(header=header, usedouble=False):
106 ''' find and run a C pre-processor on aubio.h '''
79 cpp_cmd = get_preprocessor()107 cpp_cmd = get_preprocessor()
80 108
81 macros = [('AUBIO_UNSTABLE', 1)]109 macros = [('AUBIO_UNSTABLE', 1)]
110 if usedouble:
111 macros += [('HAVE_AUBIO_DOUBLE', 1)]
82 112
83 if not os.path.isfile(header):113 if not os.path.isfile(header):
84 raise Exception("could not find include file " + header)114 raise Exception("could not find include file " + header)
@@ -89,56 +119,115 @@ def get_cpp_objects(header=header): · 4 unmodified lines
89 119
90 print("Running command: {:s}".format(" ".join(cpp_cmd)))120 print("Running command: {:s}".format(" ".join(cpp_cmd)))
91 proc = subprocess.Popen(cpp_cmd,121 proc = subprocess.Popen(cpp_cmd,
92 stderr=subprocess.PIPE,122 stderr=subprocess.PIPE,
93 stdout=subprocess.PIPE)123 stdout=subprocess.PIPE)
94 assert proc, 'Proc was none'124 assert proc, 'Proc was none'
95 cpp_output = proc.stdout.read()125 cpp_output = proc.stdout.read()
96 err_output = proc.stderr.read()126 err_output = proc.stderr.read()
127 if err_output:
128 print("Warning: preprocessor produced errors or warnings:\n%s" \
129 % err_output.decode('utf8'))
97 if not cpp_output:130 if not cpp_output:
98 raise Exception("preprocessor output is empty:\n%s" % err_output)131 raise_msg = "preprocessor output is empty! Running command " \
99 elif err_output:132 + "\"%s\" failed" % " ".join(cpp_cmd)
100 print ("Warning: preprocessor produced warnings:\n%s" % err_output)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)
101 if not isinstance(cpp_output, list):138 if not isinstance(cpp_output, list):
102 cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')]139 cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')]
103 140
104 cpp_output = filter(lambda y: len(y) > 1, cpp_output)141 return cpp_output
142
143def filter_cpp_output(cpp_raw_output):
144 ''' prepare cpp-output for parsing '''
145 cpp_output = filter(lambda y: len(y) > 1, cpp_raw_output)
105 cpp_output = list(filter(lambda y: not y.startswith('#'), cpp_output))146 cpp_output = list(filter(lambda y: not y.startswith('#'), cpp_output))
106 147
107 i = 1148 i = 1
108 while 1:149 while 1:
109 if i >= len(cpp_output): break150 if i >= len(cpp_output):
110 if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):151 break
111 cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]152 if ('{' in cpp_output[i - 1]) and ('}' not in cpp_output[i - 1]) or (';' not in cpp_output[i - 1]):
112 cpp_output.pop(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)
113 else:158 else:
114 i += 1159 i += 1
115 160
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
117 166
167 return cpp_output
168
169
170def 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)
118 cpp_objects = [a.split()[3][:-1] for a in typedefs]174 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
179def 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))
119 197
120 return cpp_output, cpp_objects198 return res
121 199
122 200
123def analyze_cpp_output(cpp_objects, cpp_output):201def 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 '''
124 lib = {}208 lib = {}
125 209
126 for o in cpp_objects:210 for o in cpp_objects:
127 if o[:6] != 'aubio_':211 shortname = o
128 continue212 if o[:6] == 'aubio_':
129 shortname = o[6:-2]213 shortname = o[6:-2] # without aubio_ prefix and _t suffix
130 if shortname in skip_objects:214
131 continue215 lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'rdo': [], 'get': [], 'set': [], 'other': []}
132 lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []}
133 lib[shortname]['longname'] = o216 lib[shortname]['longname'] = o
134 lib[shortname]['shortname'] = shortname217 lib[shortname]['shortname'] = shortname
135 for fn in cpp_output:218
136 if o[:-1] in fn:219 fullshortname = o[:-2] # name without _t suffix
137 #print "found", o[:-1], "in", fn220
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
138 if 'typedef struct ' in fn:225 if 'typedef struct ' in fn:
139 lib[shortname]['struct'].append(fn)226 lib[shortname]['struct'].append(fn)
140 elif '_do' in fn:227 elif '_do' in fn:
141 lib[shortname]['do'].append(fn)228 lib[shortname]['do'].append(fn)
229 elif '_rdo' in fn:
230 lib[shortname]['rdo'].append(fn)
142 elif 'new_' in fn:231 elif 'new_' in fn:
143 lib[shortname]['new'].append(fn)232 lib[shortname]['new'].append(fn)
144 elif 'del_' in fn:233 elif 'del_' in fn:
@@ -148,52 +237,52 @@ def analyze_cpp_output(cpp_objects, cpp_output): · 3 unmodified lines
148 elif '_set_' in fn:237 elif '_set_' in fn:
149 lib[shortname]['set'].append(fn)238 lib[shortname]['set'].append(fn)
150 else:239 else:
151 #print "no idea what to do about", fn240 # print "no idea what to do about", fn
152 lib[shortname]['other'].append(fn)241 lib[shortname]['other'].append(fn)
153 return lib242 return lib
154 243
155def print_cpp_output_results(lib, cpp_output):244
156 for fn in cpp_output:245def print_c_declarations_results(lib, c_declarations):
246 for fn in c_declarations:
157 found = 0247 found = 0
158 for o in lib:248 for o in lib:
159 for family in lib[o]:249 for family in lib[o]:
160 if fn in lib[o][family]:250 if fn in lib[o][family]:
161 found = 1251 found = 1
162 if found == 0:252 if found == 0:
163 print ("missing", fn)253 print("missing", fn)
164 254
165 for o in lib:255 for o in lib:
166 for family in lib[o]:256 for family in lib[o]:
167 if type(lib[o][family]) == str:257 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]))
169 elif len(lib[o][family]) == 1:259 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]))
171 else:261 else:
172 print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )262 print("{:15s} {:10s} {:s}".format(o, family, lib[o][family]))
173 263
174 264
175def generate_external(header=header, output_path=output_path, usedouble=False, overwrite=True):265def generate_external(header=header, output_path=output_path, usedouble=False, overwrite=True):
176 if not os.path.isdir(output_path): os.mkdir(output_path)266 if not os.path.isdir(output_path):
177 elif not overwrite: return glob.glob(os.path.join(output_path, '*.c'))267 os.mkdir(output_path)
268 elif not overwrite:
269 return sorted(glob.glob(os.path.join(output_path, '*.c')))
178 270
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)
180 273
181 lib = analyze_cpp_output(cpp_objects, cpp_output)274 lib = generate_lib_from_c_declarations(cpp_objects, c_declarations)
182 # print_cpp_output_results(lib, cpp_output)275 # print_c_declarations_results(lib, c_declarations)
183 276
184 sources_list = []277 sources_list = []
185 try:
186 from .gen_code import MappedObject
187 except (SystemError, ValueError):
188 from gen_code import MappedObject
189 for o in lib:278 for o in lib:
190 out = source_header279 out = source_header
191 mapped = MappedObject(lib[o], usedouble = usedouble)280 mapped = MappedObject(lib[o], usedouble=usedouble)
192 out += mapped.gen_code()281 out += mapped.gen_code()
193 output_file = os.path.join(output_path, 'gen-%s.c' % o)282 output_file = os.path.join(output_path, 'gen-%s.c' % o)
194 with open(output_file, 'w') as f:283 with open(output_file, 'w') as f:
195 f.write(out)284 f.write(out)
196 print ("wrote %s" % output_file )285 print("wrote %s" % output_file)
197 sources_list.append(output_file)286 sources_list.append(output_file)
198 287
199 out = source_header288 out = source_header
@@ -205,23 +294,23 @@ int generated_types_ready (void) · 5 unmodified lines
205{{294{{
206 return ({pycheck_types});295 return ({pycheck_types});
207}}296}}
208""".format(pycheck_types = check_types)297""".format(pycheck_types=check_types)
209 298
210 add_types = "".join(["""299 add_types = "".join(["""
211 Py_INCREF (&Py_{name}Type);300 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])
213 out += """302 out += """
214 303
215void add_generated_objects ( PyObject *m )304void add_generated_objects ( PyObject *m )
216{{305{{
217{add_types}306{add_types}
218}}307}}
219""".format(add_types = add_types)308""".format(add_types=add_types)
220 309
221 output_file = os.path.join(output_path, 'aubio-generated.c')310 output_file = os.path.join(output_path, 'aubio-generated.c')
222 with open(output_file, 'w') as f:311 with open(output_file, 'w') as f:
223 f.write(out)312 f.write(out)
224 print ("wrote %s" % output_file )313 print("wrote %s" % output_file)
225 sources_list.append(output_file)314 sources_list.append(output_file)
226 315
227 objlist = "".join(["extern PyTypeObject Py_%sType;\n" % p for p in lib])316 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
239{objlist}328{objlist}
240int generated_objects ( void );329int generated_objects ( void );
241void add_generated_objects( PyObject *m );330void add_generated_objects( PyObject *m );
242""".format(objlist = objlist)331""".format(objlist=objlist)
243 332
244 output_file = os.path.join(output_path, 'aubio-generated.h')333 output_file = os.path.join(output_path, 'aubio-generated.h')
245 with open(output_file, 'w') as f:334 with open(output_file, 'w') as f:
246 f.write(out)335 f.write(out)
247 print ("wrote %s" % output_file )336 print("wrote %s" % output_file)
248 # no need to add header to list of sources337 # no need to add header to list of sources
249 338
250 return sources_list339 return sorted(sources_list)
251 340
252if __name__ == '__main__':341if __name__ == '__main__':
253 if len(sys.argv) > 1: header = sys.argv[1]342 if len(sys.argv) > 1:
254 if len(sys.argv) > 2: output_path = sys.argv[2]343 header = sys.argv[1]
344 if len(sys.argv) > 2:
345 output_path = sys.argv[2]
255 generate_external(header, output_path)346 generate_external(header, output_path)
python/lib/moresetuptools.py+78−26
@@ -2,7 +2,9 @@ · 1 unmodified line
2#2#
3import sys, os, glob, subprocess3import sys, os, glob, subprocess
4import distutils, distutils.command.clean, distutils.dir_util4import distutils, distutils.command.clean, distutils.dir_util
5from .gen_external import generate_external, header, output_path5from gen_external import generate_external, header, output_path
6
7from this_version import get_aubio_version
6 8
7# inspired from https://gist.github.com/abergmeier/94889909# inspired from https://gist.github.com/abergmeier/9488990
8def add_packages(packages, ext=None, **kw):10def add_packages(packages, ext=None, **kw):
@@ -21,6 +23,7 @@ def add_packages(packages, ext=None, **kw): · 12 unmodified lines
21 }23 }
22 24
23 for package in packages:25 for package in packages:
26 print("checking for {:s}".format(package))
24 cmd = ['pkg-config', '--libs', '--cflags', package]27 cmd = ['pkg-config', '--libs', '--cflags', package]
25 try:28 try:
26 tokens = subprocess.check_output(cmd)29 tokens = subprocess.check_output(cmd)
@@ -54,13 +57,14 @@ def add_local_aubio_lib(ext): · 27 unmodified lines
54 57
55def add_local_aubio_sources(ext):58def add_local_aubio_sources(ext):
56 """ build aubio inside python module instead of linking against libaubio """59 """ build aubio inside python module instead of linking against libaubio """
57 print("Warning: libaubio was not built with waf, adding src/")60 print("Info: libaubio was not installed or built locally with waf, adding src/")
58 # create an empty header, macros will be passed on the command line61 aubio_sources = sorted(glob.glob(os.path.join('src', '**.c')))
59 fake_config_header = os.path.join('python', 'ext', 'config.h')62 aubio_sources += sorted(glob.glob(os.path.join('src', '*', '**.c')))
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'))
63 ext.sources += aubio_sources63 ext.sources += aubio_sources
64
65def add_local_macros(ext, usedouble = False):
66 if usedouble:
67 ext.define_macros += [('HAVE_AUBIO_DOUBLE', 1)]
64 # define macros (waf puts them in build/src/config.h)68 # define macros (waf puts them in build/src/config.h)
65 for define_macro in ['HAVE_STDLIB_H', 'HAVE_STDIO_H',69 for define_macro in ['HAVE_STDLIB_H', 'HAVE_STDIO_H',
66 'HAVE_MATH_H', 'HAVE_STRING_H',70 'HAVE_MATH_H', 'HAVE_STRING_H',
@@ -69,22 +73,31 @@ def add_local_aubio_sources(ext): · 2 unmodified lines
69 'HAVE_MEMCPY_HACKS']:73 'HAVE_MEMCPY_HACKS']:
70 ext.define_macros += [(define_macro, 1)]74 ext.define_macros += [(define_macro, 1)]
71 75
76def add_external_deps(ext, usedouble = False):
72 # loof for additional packages77 # loof for additional packages
73 print("Info: looking for *optional* additional packages")78 print("Info: looking for *optional* additional packages")
74 packages = ['libavcodec', 'libavformat', 'libavutil', 'libavresample',79 packages = ['libavcodec', 'libavformat', 'libavutil',
80 'libswresample', 'libavresample',
75 'jack',81 'jack',
76 'sndfile', 'samplerate',82 'sndfile',
77 'rubberband',83 'rubberband',
78 #'fftw3f',84 #'fftw3f',
79 ]85 ]
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")
80 add_packages(packages, ext=ext)91 add_packages(packages, ext=ext)
81 if 'avcodec' in ext.libraries \92 if 'avcodec' in ext.libraries \
82 and 'avformat' in ext.libraries \93 and 'avformat' in ext.libraries \
83 and 'avutil' in ext.libraries \94 and 'avutil' in ext.libraries:
84 and 'avresample' in ext.libraries:95 if 'swresample' in ext.libraries:
85 ext.define_macros += [('HAVE_LIBAV', 1)]96 ext.define_macros += [('HAVE_SWRESAMPLE', 1)]
86 if 'jack' in ext.libraries:97 elif 'avresample' in ext.libraries:
87 ext.define_macros += [('HAVE_JACK', 1)]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)]
88 if 'sndfile' in ext.libraries:101 if 'sndfile' in ext.libraries:
89 ext.define_macros += [('HAVE_SNDFILE', 1)]102 ext.define_macros += [('HAVE_SNDFILE', 1)]
90 if 'samplerate' in ext.libraries:103 if 'samplerate' in ext.libraries:
@@ -107,39 +120,78 @@ def add_local_aubio_sources(ext): · 16 unmodified lines
107 120
108 ext.define_macros += [('HAVE_WAVWRITE', 1)]121 ext.define_macros += [('HAVE_WAVWRITE', 1)]
109 ext.define_macros += [('HAVE_WAVREAD', 1)]122 ext.define_macros += [('HAVE_WAVREAD', 1)]
110 # TODO:123
111 # add cblas124 # TODO: add cblas
112 if 0:125 if 0:
113 ext.libraries += ['cblas']126 ext.libraries += ['cblas']
114 ext.define_macros += [('HAVE_ATLAS_CBLAS_H', 1)]127 ext.define_macros += [('HAVE_ATLAS_CBLAS_H', 1)]
115 128
116def add_system_aubio(ext):129def add_system_aubio(ext):
117 # use pkg-config to find aubio's location130 # 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)
119 if 'aubio' not in ext.libraries:133 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
138def 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)]
121 143
122class CleanGenerated(distutils.command.clean.clean):144class CleanGenerated(distutils.command.clean.clean):
123 def run(self):145 def run(self):
124 distutils.dir_util.remove_tree(output_path)146 if os.path.isdir(output_path):
125 distutils.command.clean.clean.run(self)147 distutils.dir_util.remove_tree(output_path)
148
149from distutils.command.build_ext import build_ext as _build_ext
150class build_ext(_build_ext):
126 151
127class GenerateCommand(distutils.cmd.Command):152 user_options = _build_ext.user_options + [
128 description = 'generate gen/gen-*.c files from ../src/aubio.h'
129 user_options = [
130 # The format is (long option, short option, description).153 # The format is (long option, short option, description).
131 ('enable-double', None, 'use HAVE_AUBIO_DOUBLE=1 (default: 0)'),154 ('enable-double', None, 'use HAVE_AUBIO_DOUBLE=1 (default: 0)'),
132 ]155 ]
133 156
134 def initialize_options(self):157 def initialize_options(self):
158 _build_ext.initialize_options(self)
135 self.enable_double = False159 self.enable_double = False
136 160
137 def finalize_options(self):161 def finalize_options(self):
162 _build_ext.finalize_options(self)
138 if self.enable_double:163 if self.enable_double:
139 self.announce(164 self.announce(
140 'will generate code for aubio compiled with HAVE_AUBIO_DOUBLE=1',165 'will generate code for aubio compiled with HAVE_AUBIO_DOUBLE=1',
141 level=distutils.log.INFO)166 level=distutils.log.INFO)
142 167
143 def run(self):168 def build_extension(self, extension):
144 self.announce( 'Generating code', level=distutils.log.INFO)169 if self.enable_double or 'HAVE_AUBIO_DOUBLE' in os.environ:
145 generated_object_files = generate_external(header, output_path, usedouble=self.enable_double)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
7import sys
8#from aubio.task import *
9
10usage = "usage: %s [options] -i soundfile" % sys.argv[0]
11usage += "\n help: %s -h" % sys.argv[0]
12
13def 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
141if __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
24import time24import time
25import os.path25import os.path
26import numpy26import numpy
27from utils import array_from_text_file, array_from_yaml_file27from .utils import array_from_text_file, array_from_yaml_file
28from aubio import source, pitch, freqtomidi28from aubio import source, pitch, freqtomidi
29 29
30start = time.time()30start = time.time()
python/tests/test_aubio.py+5−0
@@ -9,6 +9,11 @@ class aubiomodule_test_case(TestCase): · 8 unmodified lines
9 """ try importing aubio """9 """ try importing aubio """
10 import aubio10 import aubio
11 11
12 def test_version(self):
13 """ test aubio.version """
14 import aubio
15 self.assertEqual('0', aubio.version[0])
16
12if __name__ == '__main__':17if __name__ == '__main__':
13 main()18 main()
14 19
python/tests/test_aubio_cmd.py+34−0
@@ -0,0 +1,34 @@
1#! /usr/bin/env python
2
3import aubio.cmd
4from nose2 import main
5from numpy.testing import TestCase
6
7class 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
19class 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
33if __name__ == '__main__':
34 main()
python/tests/test_aubio_cut.py+16−0
@@ -0,0 +1,16 @@
1#! /usr/bin/env python
2
3import aubio.cut
4from nose2 import main
5from numpy.testing import TestCase
6
7class 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
15if __name__ == '__main__':
16 main()
python/tests/test_dct.py+68−0
@@ -0,0 +1,68 @@
1#! /usr/bin/env python
2
3
4import numpy as np
5from numpy.testing import TestCase, assert_almost_equal
6import aubio
7
8precomputed_arange = [ 9.89949512, -6.44232273, 0., -0.67345482, 0.,
9 -0.20090288, 0., -0.05070186]
10
11precomputed_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
16class 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
33 f = fft (win_s)33 f = fft (win_s)
34 fftgrain = f (timegrain)34 fftgrain = f (timegrain)
35 assert_equal ( fftgrain.norm, 0 )35 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.')
37 44
38 def test_impulse(self):45 def test_impulse(self):
39 """ check the transform of one impulse at a random place """46 """ check the transform of one impulse at a random place """
@@ -135,6 +142,37 @@ class aubio_fft_test_case(TestCase): · 95 unmodified lines
135 assert_almost_equal ( r[0], impulse, decimal = 6)142 assert_almost_equal ( r[0], impulse, decimal = 6)
136 assert_almost_equal ( r[1:], 0)143 assert_almost_equal ( r[1:], 0)
137 144
145class 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
174class aubio_fft_wrong_params(TestCase):
175
138 def test_large_input_timegrain(self):176 def test_large_input_timegrain(self):
139 win_s = 1024177 win_s = 1024
140 f = fft(win_s)178 f = fft(win_s)
@@ -163,22 +201,11 @@ class aubio_fft_test_case(TestCase): · 22 unmodified lines
163 with self.assertRaises(ValueError):201 with self.assertRaises(ValueError):
164 f.rdo(s)202 f.rdo(s)
165 203
166class aubio_fft_wrong_params(TestCase):
167
168 def test_wrong_buf_size(self):204 def test_wrong_buf_size(self):
169 win_s = -1205 win_s = -1
170 with self.assertRaises(ValueError):206 with self.assertRaises(ValueError):
171 fft(win_s)207 fft(win_s)
172 208
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
182 def test_buf_size_too_small(self):209 def test_buf_size_too_small(self):
183 win_s = 1210 win_s = 1
184 with self.assertRaises(RuntimeError):211 with self.assertRaises(RuntimeError):
python/tests/test_filter.py+11−1
@@ -3,7 +3,7 @@ · 2 unmodified lines
3from unittest import main3from unittest import main
4from numpy.testing import TestCase, assert_equal, assert_almost_equal4from numpy.testing import TestCase, assert_equal, assert_almost_equal
5from aubio import fvec, digital_filter5from aubio import fvec, digital_filter
6from utils import array_from_text_file6from .utils import array_from_text_file
7 7
8class aubio_filter_test_case(TestCase):8class aubio_filter_test_case(TestCase):
9 9
@@ -77,6 +77,16 @@ class aubio_filter_test_case(TestCase): · 67 unmodified lines
77 with self.assertRaises(ValueError):77 with self.assertRaises(ValueError):
78 f.set_biquad(0., 0., 0, 0., 0.)78 f.set_biquad(0., 0., 0, 0., 0.)
79 79
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
80class aubio_filter_wrong_params(TestCase):90class aubio_filter_wrong_params(TestCase):
81 91
82 def test_negative_order(self):92 def test_negative_order(self):
python/tests/test_filterbank.py+12−5
@@ -1,11 +1,10 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2 2
3from unittest import main
4from numpy.testing import TestCase
5from numpy.testing import assert_equal, assert_almost_equal
6import numpy as np3import numpy as np
4from numpy.testing import TestCase, assert_equal, assert_almost_equal
5
7from aubio import cvec, filterbank, float_type6from aubio import cvec, filterbank, float_type
8from utils import array_from_text_file7from .utils import array_from_text_file
9 8
10class aubio_filterbank_test_case(TestCase):9class aubio_filterbank_test_case(TestCase):
11 10
@@ -62,6 +61,13 @@ class aubio_filterbank_test_case(TestCase): · 50 unmodified lines
62 f.set_mel_coeffs_slaney(16000)61 f.set_mel_coeffs_slaney(16000)
63 assert_almost_equal ( expected, f.get_coeffs() )62 assert_almost_equal ( expected, f.get_coeffs() )
64 63
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
65class aubio_filterbank_wrong_values(TestCase):71class aubio_filterbank_wrong_values(TestCase):
66 72
67 def test_negative_window(self):73 def test_negative_window(self):
@@ -81,4 +87,5 @@ class aubio_filterbank_wrong_values(TestCase): · 13 unmodified lines
81 f(cvec(256))87 f(cvec(256))
82 88
83if __name__ == '__main__':89if __name__ == '__main__':
84 main()90 import nose2
91 nose2.main()
python/tests/test_filterbank_mel.py+136−13
@@ -1,10 +1,12 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2 2
3from unittest import main3import numpy as np
4from numpy.testing import TestCase4from numpy.testing import TestCase, assert_equal, assert_almost_equal
5from numpy.testing import assert_equal, assert_almost_equal5
6from numpy import array, shape6from aubio import fvec, cvec, filterbank, float_type
7from aubio import cvec, filterbank, float_type7
8import warnings
9warnings.filterwarnings('ignore', category=UserWarning, append=True)
8 10
9class aubio_filterbank_mel_test_case(TestCase):11class aubio_filterbank_mel_test_case(TestCase):
10 12
@@ -12,38 +14,159 @@ class aubio_filterbank_mel_test_case(TestCase): · 1 unmodified line
12 f = filterbank(40, 512)14 f = filterbank(40, 512)
13 f.set_mel_coeffs_slaney(16000)15 f.set_mel_coeffs_slaney(16000)
14 a = f.get_coeffs()16 a = f.get_coeffs()
15 assert_equal(shape (a), (40, 512/2 + 1) )17 assert_equal(np.shape (a), (40, 512/2 + 1) )
16 18
17 def test_other_slaney(self):19 def test_other_slaney(self):
18 f = filterbank(40, 512*2)20 f = filterbank(40, 512*2)
19 f.set_mel_coeffs_slaney(44100)21 f.set_mel_coeffs_slaney(44100)
20 _ = f.get_coeffs()22 self.assertIsInstance(f.get_coeffs(), np.ndarray)
21 #print "sum is", sum(sum(a))23 #print "sum is", sum(sum(a))
22 for win_s in [256, 512, 1024, 2048, 4096]:24 for win_s in [256, 512, 1024, 2048, 4096]:
23 f = filterbank(40, win_s)25 f = filterbank(40, win_s)
24 f.set_mel_coeffs_slaney(32000)26 f.set_mel_coeffs_slaney(32000)
25 _ = f.get_coeffs()
26 #print "sum is", sum(sum(a))27 #print "sum is", sum(sum(a))
28 self.assertIsInstance(f.get_coeffs(), np.ndarray)
27 29
28 def test_triangle_freqs_zeros(self):30 def test_triangle_freqs_zeros(self):
29 f = filterbank(9, 1024)31 f = filterbank(9, 1024)
30 freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]32 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)
32 f.set_triangle_bands(freqs, 48000)34 f.set_triangle_bands(freqs, 48000)
33 _ = f.get_coeffs().T
34 assert_equal ( f(cvec(1024)), 0)35 assert_equal ( f(cvec(1024)), 0)
36 self.assertIsInstance(f.get_coeffs(), np.ndarray)
35 37
36 def test_triangle_freqs_ones(self):38 def test_triangle_freqs_ones(self):
37 f = filterbank(9, 1024)39 f = filterbank(9, 1024)
38 freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000]40 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)
40 f.set_triangle_bands(freqs, 48000)42 f.set_triangle_bands(freqs, 48000)
41 _ = f.get_coeffs().T43 self.assertIsInstance(f.get_coeffs(), np.ndarray)
42 spec = cvec(1024)44 spec = cvec(1024)
43 spec.norm[:] = 145 spec.norm[:] = 1
44 assert_almost_equal ( f(spec),46 assert_almost_equal ( f(spec),
45 [ 0.02070313, 0.02138672, 0.02127604, 0.02135417,47 [ 0.02070313, 0.02138672, 0.02127604, 0.02135417,
46 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345])48 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345])
47 49
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
48if __name__ == '__main__':170if __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
60 self.assertRaises(IndexError, a.__getitem__, 3)60 self.assertRaises(IndexError, a.__getitem__, 3)
61 self.assertRaises(IndexError, a.__getitem__, 2)61 self.assertRaises(IndexError, a.__getitem__, 2)
62 62
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
63class aubio_wrong_fvec_input(TestCase):71class aubio_wrong_fvec_input(TestCase):
64 """ uses min_removal to test PyAubio_IsValidVector """72 """ uses min_removal to test PyAubio_IsValidVector """
65 73
python/tests/test_fvec_shift.py+35−0
@@ -0,0 +1,35 @@
1#! /usr/bin/env python
2
3import numpy as np
4from numpy.testing import TestCase, assert_equal
5import aubio
6
7class 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
33from unittest import main
34if __name__ == '__main__':
35 main()
python/tests/test_hztomel.py+109−0
@@ -0,0 +1,109 @@
1#! /usr/bin/env python
2
3from unittest import main
4from numpy.testing import TestCase
5from numpy.testing import assert_equal, assert_almost_equal
6import numpy as np
7import aubio
8
9from aubio import hztomel, meltohz
10from aubio import hztomel_htk, meltohz_htk
11
12
13class 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
48class 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
77class 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
107if __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
110 o(spec)110 o(spec)
111 #print coeffs111 #print coeffs
112 112
113
114class 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
113if __name__ == '__main__':150if __name__ == '__main__':
114 main()151 main()
python/tests/test_midi2note.py+6−4
@@ -2,6 +2,7 @@ · 1 unmodified line
2# -*- coding: utf-8 -*-2# -*- coding: utf-8 -*-
3 3
4from aubio import midi2note4from aubio import midi2note
5from nose2.tools import params
5import unittest6import unittest
6 7
7list_of_known_midis = (8list_of_known_midis = (
@@ -16,10 +17,10 @@ list_of_known_midis = ( · 8 unmodified lines
16 17
17class midi2note_good_values(unittest.TestCase):18class midi2note_good_values(unittest.TestCase):
18 19
19 def test_midi2note_known_values(self):20 @params(*list_of_known_midis)
21 def test_midi2note_known_values(self, midi, note):
20 " known values are correctly converted "22 " known values are correctly converted "
21 for midi, note in list_of_known_midis:23 self.assertEqual ( midi2note(midi), note )
22 self.assertEqual ( midi2note(midi), note )
23 24
24class midi2note_wrong_values(unittest.TestCase):25class midi2note_wrong_values(unittest.TestCase):
25 26
@@ -40,4 +41,5 @@ class midi2note_wrong_values(unittest.TestCase): · 14 unmodified lines
40 self.assertRaises(TypeError, midi2note, "a")41 self.assertRaises(TypeError, midi2note, "a")
41 42
42if __name__ == '__main__':43if __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
3 3
4from __future__ import unicode_literals4from __future__ import unicode_literals
5 5
6from aubio import note2midi, freq2note6from aubio import note2midi, freq2note, note2freq, float_type
7from nose2.tools import params
7import unittest8import unittest
8 9
9list_of_known_notes = (10list_of_known_notes = (
@@ -13,24 +14,57 @@ list_of_known_notes = ( · 3 unmodified lines
13 ( 'C3', 48 ),14 ( 'C3', 48 ),
14 ( 'B3', 59 ),15 ( 'B3', 59 ),
15 ( 'B#3', 60 ),16 ( 'B#3', 60 ),
17 ( 'C♯4', 61 ),
16 ( 'A4', 69 ),18 ( 'A4', 69 ),
17 ( 'A#4', 70 ),19 ( 'A#4', 70 ),
20 ( 'A♯4', 70 ),
21 ( 'A\u266f4', 70 ),
18 ( 'Bb4', 70 ),22 ( 'Bb4', 70 ),
19 ( 'B♭4', 70 ),23 ( 'B♭4', 70 ),
24 ( 'B\u266d4', 70 ),
20 ( 'G8', 115 ),25 ( 'G8', 115 ),
21 ( 'G♯8', 116 ),26 ( 'G♯8', 116 ),
22 ( 'G9', 127 ),27 ( 'G9', 127 ),
23 ( 'G\udd2a2', 45 ),
24 ( 'B\ufffd2', 45 ),
25 ( 'A♮2', 45 ),28 ( 'A♮2', 45 ),
26 )29 )
27 30
31list_of_known_notes_with_unicode_issues = (
32 ('C𝄪4', 62 ),
33 ('E𝄫4', 62 ),
34 )
35
36list_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
28class note2midi_good_values(unittest.TestCase):47class note2midi_good_values(unittest.TestCase):
29 48
30 def test_note2midi_known_values(self):49 @params(*list_of_known_notes)
50 def test_note2midi_known_values(self, note, midi):
31 " known values are correctly converted "51 " 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:
33 self.assertEqual ( note2midi(note), midi )58 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
34 68
35class note2midi_wrong_values(unittest.TestCase):69class note2midi_wrong_values(unittest.TestCase):
36 70
@@ -66,12 +100,38 @@ class note2midi_wrong_values(unittest.TestCase): · 29 unmodified lines
66 " fails when passed a non-string value "100 " fails when passed a non-string value "
67 self.assertRaises(TypeError, note2midi, 123)101 self.assertRaises(TypeError, note2midi, 123)
68 102
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)
69 111
70class freq2note_simple_test(unittest.TestCase):112class freq2note_simple_test(unittest.TestCase):
71 113
72 def test_freq2note(self):114 def test_freq2note_above(self):
73 " make sure freq2note(441) == A4 "115 " make sure freq2note(441) == A4 "
74 self.assertEqual("A4", freq2note(441))116 self.assertEqual("A4", freq2note(441))
75 117
118 def test_freq2note_under(self):
119 " make sure freq2note(439) == A4 "
120 self.assertEqual("A4", freq2note(439))
121
122class 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
76if __name__ == '__main__':135if __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
3from unittest import main
4from numpy.testing import TestCase, assert_equal, assert_almost_equal
5from aubio import notes
6
7AUBIO_DEFAULT_NOTES_SILENCE = -70.
8AUBIO_DEFAULT_NOTES_RELEASE_DROP = 10.
9AUBIO_DEFAULT_NOTES_MINIOI_MS = 30.
10
11class 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
19class 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
55from .utils import list_all_sounds
56list_of_sounds = list_all_sounds('sounds')
57
58class 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
94if __name__ == '__main__':
95 main()
python/tests/test_onset.py+40−8
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3from unittest import main3from unittest import main
4from numpy.testing import TestCase, assert_equal, assert_almost_equal4from numpy.testing import TestCase, assert_equal, assert_almost_equal
5from aubio import onset5from aubio import onset, fvec
6 6
7class aubio_onset_default(TestCase):7class aubio_onset_default(TestCase):
8 8
@@ -19,25 +19,25 @@ class aubio_onset_params(TestCase): · 10 unmodified lines
19 self.o = onset(samplerate = self.samplerate)19 self.o = onset(samplerate = self.samplerate)
20 20
21 def test_get_delay(self):21 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)
23 23
24 def test_get_delay_s(self):24 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.)
26 26
27 def test_get_delay_ms(self):27 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.)
29 29
30 def test_get_minioi(self):30 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)
32 32
33 def test_get_minioi_s(self):33 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.)
35 35
36 def test_get_minioi_ms(self):36 def test_get_minioi_ms(self):
37 assert_equal (self.o.get_minioi_ms(), 20.)37 self.assertGreater(self.o.get_minioi_ms(), 0.)
38 38
39 def test_get_threshold(self):39 def test_get_threshold(self):
40 assert_almost_equal (self.o.get_threshold(), 0.3)40 self.assertGreater(self.o.get_threshold(), 0.)
41 41
42 def test_set_delay(self):42 def test_set_delay(self):
43 val = 25643 val = 256
@@ -83,5 +83,37 @@ class aubio_onset_32000(aubio_onset_params): · 39 unmodified lines
83class aubio_onset_8000(aubio_onset_params):83class aubio_onset_8000(aubio_onset_params):
84 samplerate = 800084 samplerate = 8000
85 85
86class 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
86if __name__ == '__main__':118if __name__ == '__main__':
87 main()119 main()
python/tests/test_phasevoc.py+17−1
@@ -46,9 +46,25 @@ class aubio_pvoc_test_case(TestCase): · 45 unmodified lines
46 r = f.rdo(s)46 r = f.rdo(s)
47 assert_equal ( t, 0.)47 assert_equal ( t, 0.)
48 assert_equal ( s.norm, 0.)48 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.')
50 assert_equal ( r, 0.)57 assert_equal ( r, 0.)
51 58
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
52 @params(68 @params(
53 ( 256, 8),69 ( 256, 8),
54 ( 256, 4),70 ( 256, 4),
python/tests/test_pitch.py+2−2
@@ -70,8 +70,8 @@ class aubio_pitch_Sinusoid(TestCase): · 69 unmodified lines
70 #print 'len(pitches), cut:', len(pitches), cut70 #print 'len(pitches), cut:', len(pitches), cut
71 #print 'median errors: ', median(errors), 'median pitches: ', median(pitches)71 #print 'median errors: ', median(errors), 'median pitches: ', median(pitches)
72 72
73pitch_algorithms = [ "default", "yinfft", "yin", "schmitt", "mcomb", "fcomb" , "specacf" ]73pitch_algorithms = [ "default", "yinfft", "yin", "yinfast", "schmitt", "mcomb", "fcomb" , "specacf" ]
74pitch_algorithms = [ "default", "yinfft", "yin", "schmitt", "mcomb", "fcomb" ]74pitch_algorithms = [ "default", "yinfft", "yin", "yinfast", "schmitt", "mcomb", "fcomb" ]
75 75
76#freqs = [ 27.5, 55., 110., 220., 440., 880., 1760., 3520. ]76#freqs = [ 27.5, 55., 110., 220., 440., 880., 1760., 3520. ]
77freqs = [ 110., 220., 440., 880., 1760., 3520. ]77freqs = [ 110., 220., 440., 880., 1760., 3520. ]
python/tests/test_sink.py+32−1
@@ -4,7 +4,10 @@ from nose2 import main · 3 unmodified lines
4from nose2.tools import params4from nose2.tools import params
5from numpy.testing import TestCase5from numpy.testing import TestCase
6from aubio import fvec, source, sink6from aubio import fvec, source, sink
7from utils import list_all_sounds, get_tmp_sink_path, del_tmp_sink_path7from .utils import list_all_sounds, get_tmp_sink_path, del_tmp_sink_path
8
9import warnings
10warnings.filterwarnings('ignore', category=UserWarning, append=True)
8 11
9list_of_sounds = list_all_sounds('sounds')12list_of_sounds = list_all_sounds('sounds')
10samplerates = [0, 44100, 8000, 32000]13samplerates = [0, 44100, 8000, 32000]
@@ -26,6 +29,26 @@ class aubio_sink_test_case(TestCase): · 15 unmodified lines
26 if not len(list_of_sounds):29 if not len(list_of_sounds):
27 self.skipTest('add some sound files in \'python/tests/sounds\'')30 self.skipTest('add some sound files in \'python/tests/sounds\'')
28 31
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
29 def test_many_sinks(self):52 def test_many_sinks(self):
30 from tempfile import mkdtemp53 from tempfile import mkdtemp
31 import os.path54 import os.path
@@ -93,5 +116,13 @@ class aubio_sink_test_case(TestCase): · 61 unmodified lines
93 g.close()116 g.close()
94 del_tmp_sink_path(sink_path)117 del_tmp_sink_path(sink_path)
95 118
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
96if __name__ == '__main__':127if __name__ == '__main__':
97 main()128 main()
python/tests/test_slicing.py+27−6
@@ -3,8 +3,8 @@ · 2 unmodified lines
3from unittest import main3from unittest import main
4from numpy.testing import TestCase, assert_equal4from numpy.testing import TestCase, assert_equal
5from aubio import slice_source_at_stamps5from aubio import slice_source_at_stamps
6from utils import count_files_in_directory, get_default_test_sound6from .utils import count_files_in_directory, get_default_test_sound
7from utils import count_samples_in_directory, count_samples_in_file7from .utils import count_samples_in_directory, count_samples_in_file
8 8
9import tempfile9import tempfile
10import shutil10import shutil
@@ -23,19 +23,27 @@ class aubio_slicing_test_case(TestCase): · 12 unmodified lines
23 23
24 def test_slice_start_only_no_zero(self):24 def test_slice_start_only_no_zero(self):
25 regions_start = [i*1000 for i in range(1, n_slices)]25 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)
27 28
28 def test_slice_start_beyond_end(self):29 def test_slice_start_beyond_end(self):
29 regions_start = [i*1000 for i in range(1, n_slices)]30 regions_start = [i*1000 for i in range(1, n_slices)]
30 regions_start += [count_samples_in_file(self.source_file) + 1000]31 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)
32 34
33 def test_slice_start_every_blocksize(self):35 def test_slice_start_every_blocksize(self):
34 hopsize = 20036 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)]
36 slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir,38 slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir,
37 hopsize = 200)39 hopsize = 200)
38 40
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
39 def tearDown(self):47 def tearDown(self):
40 original_samples = count_samples_in_file(self.source_file)48 original_samples = count_samples_in_file(self.source_file)
41 written_samples = count_samples_in_directory(self.output_dir)49 written_samples = count_samples_in_directory(self.output_dir)
@@ -91,6 +99,19 @@ class aubio_slicing_with_ends_test_case(TestCase): · 49 unmodified lines
91 assert_equal(written_samples, expected_samples,99 assert_equal(written_samples, expected_samples,
92 "number of samples written different from number of original samples")100 "number of samples written different from number of original samples")
93 101
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
94 def tearDown(self):115 def tearDown(self):
95 shutil.rmtree(self.output_dir)116 shutil.rmtree(self.output_dir)
96 117
@@ -133,7 +154,7 @@ class aubio_slicing_wrong_ends_test_case(TestCase): · 36 unmodified lines
133 regions_start = [i*1000 for i in range(1, n_slices)]154 regions_start = [i*1000 for i in range(1, n_slices)]
134 regions_end = None155 regions_end = None
135 slice_source_at_stamps (self.source_file, regions_start, regions_end,156 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)
137 total_files = count_files_in_directory(self.output_dir)158 total_files = count_files_in_directory(self.output_dir)
138 assert_equal(n_slices, total_files,159 assert_equal(n_slices, total_files,
139 "number of slices created different from expected")160 "number of slices created different from expected")
python/tests/test_source.py+34−7
@@ -2,9 +2,9 @@ · 1 unmodified line
2 2
3from nose2 import main3from nose2 import main
4from nose2.tools import params4from nose2.tools import params
5from numpy.testing import TestCase5from numpy.testing import TestCase, assert_equal
6from aubio import source6from aubio import source
7from utils import list_all_sounds7from .utils import list_all_sounds
8 8
9import warnings9import warnings
10warnings.filterwarnings('ignore', category=UserWarning, append=True)10warnings.filterwarnings('ignore', category=UserWarning, append=True)
@@ -51,9 +51,11 @@ class aubio_source_read_test_case(aubio_source_test_case_base): · 40 unmodified lines
51 def read_from_source(self, f):51 def read_from_source(self, f):
52 total_frames = 052 total_frames = 0
53 while True:53 while True:
54 _ , read = f()54 samples , read = f()
55 total_frames += read55 total_frames += read
56 if read < f.hop_size: break56 if read < f.hop_size:
57 assert_equal(samples[read:], 0)
58 break
57 #result_str = "read {:.2f}s ({:d} frames in {:d} blocks at {:d}Hz) from {:s}"59 #result_str = "read {:.2f}s ({:d} frames in {:d} blocks at {:d}Hz) from {:s}"
58 #result_params = total_frames / float(f.samplerate), total_frames, total_frames//f.hop_size, f.samplerate, f.uri60 #result_params = total_frames / float(f.samplerate), total_frames, total_frames//f.hop_size, f.samplerate, f.uri
59 #print (result_str.format(*result_params))61 #print (result_str.format(*result_params))
@@ -66,7 +68,14 @@ class aubio_source_read_test_case(aubio_source_test_case_base): · 6 unmodified lines
66 except RuntimeError as e:68 except RuntimeError as e:
67 self.skipTest('failed opening with hop_s = {:d}, samplerate = {:d} ({:s})'.format(hop_size, samplerate, str(e)))69 self.skipTest('failed opening with hop_s = {:d}, samplerate = {:d} ({:s})'.format(hop_size, samplerate, str(e)))
68 assert f.samplerate != 070 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)
70 79
71 @params(*list_of_sounds)80 @params(*list_of_sounds)
72 def test_samplerate_none(self, p):81 def test_samplerate_none(self, p):
@@ -149,13 +158,31 @@ class aubio_source_readmulti_test_case(aubio_source_read_test_case): · 76 unmodified lines
149 def read_from_source(self, f):158 def read_from_source(self, f):
150 total_frames = 0159 total_frames = 0
151 while True:160 while True:
152 _, read = f.do_multi()161 samples, read = f.do_multi()
153 total_frames += read162 total_frames += read
154 if read < f.hop_size: break163 if read < f.hop_size:
164 assert_equal(samples[:,read:], 0)
165 break
155 #result_str = "read {:.2f}s ({:d} frames in {:d} channels and {:d} blocks at {:d}Hz) from {:s}"166 #result_str = "read {:.2f}s ({:d} frames in {:d} channels and {:d} blocks at {:d}Hz) from {:s}"
156 #result_params = total_frames / float(f.samplerate), total_frames, f.channels, int(total_frames/f.hop_size), f.samplerate, f.uri167 #result_params = total_frames / float(f.samplerate), total_frames, f.channels, int(total_frames/f.hop_size), f.samplerate, f.uri
157 #print (result_str.format(*result_params))168 #print (result_str.format(*result_params))
158 return total_frames169 return total_frames
159 170
171class 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
160if __name__ == '__main__':187if __name__ == '__main__':
161 main()188 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
4file, then `source` to check the correct content is read from the files."""
5
6import os.path
7import unittest
8import aubio
9import numpy as np
10from numpy.testing import assert_equal
11from .utils import get_tmp_sink_path
12
13class 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
92if __name__ == '__main__':
93 unittest.main()
python/tests/test_tempo.py+91−0
@@ -0,0 +1,91 @@
1#! /usr/bin/env python
2
3from unittest import main
4from numpy.testing import TestCase, assert_equal, assert_almost_equal
5import aubio
6
7class 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
14class 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
90if __name__ == '__main__':
91 main()
scripts/build_android+41−0
@@ -0,0 +1,41 @@
1#! /bin/bash
2
3set -e
4set -x
5
6# location of android NDK
7NDK_PATH=$PWD/../contrib/android-ndk-r12
8
9WAFOPTS="--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
17NDK_TOOLCHAINS=$PWD/contrib
18
19# location of the current toolchain
20CURRENT_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
29DESTDIR=$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
35CC=`ls $CURRENT_TOOLCHAIN/*-linux-android*/bin/gcc`
36
37CFLAGS="-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 @@
1#! /bin/sh1#! /bin/sh
2 2
3# cd to aubio directory for consistency
4cd `dirname $0`/..
5
3AUBIO_TMPDIR=`mktemp -d /var/tmp/aubio-build-XXXX`6AUBIO_TMPDIR=`mktemp -d /var/tmp/aubio-build-XXXX`
4PACKAGE=aubio7PACKAGE=aubio
5source VERSION8source VERSION
scripts/build_emscripten+4−7
@@ -1,4 +1,4 @@
1#! /bin/sh1#! /bin/bash
2 2
3function checkprog() {3function checkprog() {
4 type $1 >/dev/null 2>&1 || { echo >&2 "$1 required but not found, aborting."; exit 1; }4 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
9checkprog emmake9checkprog emmake
10 10
11# clean11# clean
12emmake ./waf distclean12./waf distclean
13 13
14# configure14# configure
15emconfigure ./waf configure --prefix=$EMSCRIPTEN/system/local/ --with-target-platform emscripten15emconfigure ./waf configure --with-target-platform emscripten $*
16 16
17# build17# build
18emmake ./waf --testcmd="node %s"18emmake ./waf build
19
20# intall
21#emmake ./waf install
scripts/build_mingw+109−18
@@ -1,28 +1,119 @@
1#! /bin/bash1#! /bin/bash
2 2
3# This script cross compiles aubio for windows using mingw, both for 32 and 643# This script cross compiles aubio for windows using mingw, four times:
4# bits. Built binaries will be placed in ./dist-win32 and ./dist-win64.4#
5 5# - 32 and 64 bits with no external dependencies
6# - 32 and 64 bits against ffmpeg
7#
6# On debian or ubuntu, you will want to 'apt-get install gcc-mingw-w64'8# On debian or ubuntu, you will want to 'apt-get install gcc-mingw-w64'
7 9
8set -e10set -e
9set -x11set -x
10 12
11WAFOPTS="-v --disable-avcodec --disable-samplerate --disable-jack --disable-sndfile"13python this_version.py -v
14VERSION=`python $PWD/this_version.py -v`
15
16FFMPEG_BUILDS_URL="https://ffmpeg.zeranoe.com/builds"
17FFMPEG_DEFAULT="3.3.3"
18
19# define some default CFLAGS
20DEF_CFLAGS="-Os -I/usr/share/mingw-w64"
21DEF_LDFLAGS=""
22
23WAFOPTS=""
24# disable external deps to make sure we don't try to use the host package
25WAFOPTS+=" --disable-samplerate --disable-jack --disable-sndfile"
26# enable ffmpeg build
27WAFOPTS+=" --disable-avcodec"
28# install without a prefix
29WAFOPTS+=" --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
39function 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
58function 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
71function 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
89function build_mingw32() {
90 TARGET=win32
91 export CC=i686-w64-mingw32-gcc
92 export NM=i686-w64-mingw32-nm
93 build_mingw
94}
95
96function 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
12 105
13[ -d dist-win32 ] && rm -rf dist-win32106# first build without ffmpeg
14[ -d dist-win64 ] && rm -rf dist-win64107build_mingw32
108build_mingw64
15 109
16CFLAGS="-Os" \110# then build against ffmpeg
17 LDFLAGS="" \111WITH_FFMEG=1
18 CC=x86_64-w64-mingw32-gcc \112build_mingw32
19 ./waf distclean configure build install --destdir=$PWD/dist-win64 \113build_mingw64
20 --testcmd="echo %s" \
21 $WAFOPTS --with-target-platform=win64
22 114
23CFLAGS="-Os" \115set +x
24 LDFLAGS="" \116echo ""
25 CC=i686-w64-mingw32-gcc \117echo "All done! The following files were generated:"
26 ./waf distclean configure build install --destdir=$PWD/dist-win32 \118echo ""
27 --testcmd="echo %s" \119ls -lart aubio*.zip*
28 $WAFOPTS --with-target-platform=win32
scripts/get_waf.sh+48−4
@@ -1,10 +1,54 @@
1#! /bin/sh1#! /bin/bash
2 2
3set -e3set -e
4set -x4#set -x
5 5
6WAFURL=https://waf.io/waf-1.8.226WAFVERSION=2.0.12
7WAFTARBALL=waf-$WAFVERSION.tar.bz2
8WAFURL=https://waf.io/$WAFTARBALL
9WAFUPSTREAMKEY=https://gitlab.com/ita1024/waf/raw/master/utils/pubkey.asc
7 10
8( which wget > /dev/null && wget -qO waf $WAFURL ) || ( which curl > /dev/null && curl $WAFURL > waf )11WAFBUILDDIR=`mktemp -d`
9 12
13function cleanup () {
14 rm -rf $WAFBUILDDIR
15}
16
17trap cleanup SIGINT SIGTERM
18
19function download () {
20 ( [[ -n `which wget` ]] && wget -qO $1 $2 ) || ( [[ -n `which curl` ]] && curl -so $1 $2 )
21}
22
23function 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
34function fetchwaf () {
35 download $WAFTARBALL $WAFURL
36 checkwaf
37}
38
39function buildwaf () {
40 tar xf $WAFTARBALL
41 pushd waf-$WAFVERSION
42 NOCLIMB=1 python waf-light --tools=c_emscripten $*
43 popd
44}
45
46pushd $WAFBUILDDIR
47fetchwaf
48buildwaf
49popd
50
51cp -prv $WAFBUILDDIR/waf-$WAFVERSION/waf $PWD
10chmod +x waf52chmod +x waf
53
54cleanup
scripts/setenv_local.sh+7−19
@@ -1,24 +1,15 @@
1#! /usr/bin/env bash1#! /usr/bin/env bash
2 2
3# This script sets the environment to execute aubio binaries and python code3# This script sets the LD_LIBRARY_PATH environment variable to ./build/src to
4# directly from build/ python/build/ without installing libaubio on the system4# execute aubio binaries without installing libaubio.
5 5#
6# Usage: $ source ./scripts/setenv_local.sh6# Usage: $ source scripts/setenv_local.sh
7 7#
8# WARNING: this script will *overwrite* existing (DY)LD_LIBRARY_PATH and8# Note: on macOs, the variable is DYLD_LIBRARY_PATH
9# PYTHONPATH variables.
10
11PYTHON_PLATFORM=`python -c "import pkg_resources, sys; print '%s-%s' % (pkg_resources.get_build_platform(), '.'.join(map(str, sys.version_info[0:2])))"`
12 9
13AUBIODIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"10AUBIODIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
14AUBIOLIB=$AUBIODIR/build/src
15AUBIOPYTHON=$AUBIODIR/build/lib.$PYTHON_PLATFORM
16 11
17if [ "$(dirname $PWD)" == "scripts" ]; then12AUBIOLIB=$AUBIODIR/build/src
18 AUBIODIR=$(basename $PWD)
19else
20 AUBIODIR=$(basename $PWD)
21fi
22 13
23if [ "$(uname)" == "Darwin" ]; then14if [ "$(uname)" == "Darwin" ]; then
24 export DYLD_LIBRARY_PATH=$AUBIOLIB15 export DYLD_LIBRARY_PATH=$AUBIOLIB
@@ -27,6 +18,3 @@ else · 2 unmodified lines
27 export LD_LIBRARY_PATH=$AUBIOLIB18 export LD_LIBRARY_PATH=$AUBIOLIB
28 echo export LD_LIBRARY_PATH=$LD_LIBRARY_PATH19 echo export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
29fi20fi
30
31export PYTHONPATH=$AUBIOPYTHON
32echo export PYTHONPATH=$PYTHONPATH
setup.py+41−50
@@ -1,43 +1,37 @@
1#! /usr/bin/env python1#! /usr/bin/env python
2 2
3import sys, os.path, glob3import sys
4import os.path
5import glob
4from setuptools import setup, Extension6from setuptools import setup, Extension
5from python.lib.moresetuptools import *
6# function to generate gen/*.{c,h}
7from python.lib.gen_external import generate_external, header, output_path
8 7
9# read from VERSION8# add ./python/lib to current path
10for l in open('VERSION').readlines(): exec (l.strip())9sys.path.append(os.path.join('python', 'lib')) # noqa
10from moresetuptools import build_ext, CleanGenerated
11 11
12if AUBIO_MAJOR_VERSION is None or AUBIO_MINOR_VERSION is None \12# function to generate gen/*.{c,h}
13 or AUBIO_PATCH_VERSION is None:13from this_version import get_aubio_version, get_aubio_pyversion
14 raise SystemError("Failed parsing VERSION file.")
15 14
16__version__ = '.'.join(map(str, [AUBIO_MAJOR_VERSION,15__version__ = get_aubio_pyversion()
17 AUBIO_MINOR_VERSION,16__aubio_version__ = get_aubio_version()
18 AUBIO_PATCH_VERSION]))
19if 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
23 17
24include_dirs = []18include_dirs = []
25library_dirs = []19library_dirs = []
26define_macros = []20define_macros = [('AUBIO_VERSION', '%s' % __aubio_version__)]
27extra_link_args = []21extra_link_args = []
28 22
29include_dirs += [ 'python/ext' ]23include_dirs += ['python/ext']
30include_dirs += [ output_path ] # aubio-generated.h
31try:24try:
32 import numpy25 import numpy
33 include_dirs += [ numpy.get_include() ]26 include_dirs += [numpy.get_include()]
34except ImportError:27except ImportError:
35 pass28 pass
36 29
37if sys.platform.startswith('darwin'):30if sys.platform.startswith('darwin'):
38 extra_link_args += ['-framework','CoreFoundation', '-framework','AudioToolbox']31 extra_link_args += ['-framework', 'CoreFoundation',
32 '-framework', 'AudioToolbox']
39 33
40sources = glob.glob(os.path.join('python', 'ext', '*.c'))34sources = sorted(glob.glob(os.path.join('python', 'ext', '*.c')))
41 35
42aubio_extension = Extension("aubio._aubio",36aubio_extension = Extension("aubio._aubio",
43 sources,37 sources,
@@ -46,21 +40,11 @@ aubio_extension = Extension("aubio._aubio", · 2 unmodified lines
46 extra_link_args = extra_link_args,40 extra_link_args = extra_link_args,
47 define_macros = define_macros)41 define_macros = define_macros)
48 42
49if os.path.isfile('src/aubio.h'):43# TODO: find a way to track if package is built against libaubio
50 # if aubio headers are found in this directory44# if os.path.isfile('src/aubio.h'):
51 add_local_aubio_header(aubio_extension)45# if not os.path.isdir(os.path.join('build','src')):
52 # was waf used to build the shared lib?46# pass
53 if os.path.isdir(os.path.join('build','src')):47# #__version__ += 'a2' # python only version
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
60else:
61 # look for aubio headers and lib using pkg-config
62 add_system_aubio(aubio_extension)
63
64 48
65classifiers = [49classifiers = [
66 'Development Status :: 4 - Beta',50 'Development Status :: 4 - Beta',
@@ -74,38 +58,45 @@ classifiers = [ · 7 unmodified lines
74 'Operating System :: Microsoft :: Windows',58 'Operating System :: Microsoft :: Windows',
75 'Programming Language :: C',59 'Programming Language :: C',
76 'Programming Language :: Python',60 '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+)',
78 ]63 ]
79 64
80from distutils.command.build_ext import build_ext as _build_ext65thisdir = os.path.abspath(os.path.dirname(__file__))
81class build_ext(_build_ext):66py_readme_file = os.path.join(thisdir, 'python', 'README.md')
82 67with open(py_readme_file, 'r') as fp:
83 def build_extension(self, extension):68 long_description = ''.join(fp.readlines()[3:])
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)
87 69
88distrib = setup(name='aubio',70distrib = setup(name='aubio',
89 version = __version__,71 version = __version__,
90 packages = ['aubio'],72 packages = ['aubio'],
91 package_dir = {'aubio':'python/lib/aubio'},73 package_dir = {'aubio': 'python/lib/aubio'},
92 scripts = ['python/scripts/aubiocut'],
93 ext_modules = [aubio_extension],74 ext_modules = [aubio_extension],
94 description = 'a collection of tools for music analysis',75 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',
96 license = 'GNU/GPL version 3',78 license = 'GNU/GPL version 3',
97 author = 'Paul Brossier',79 author = 'Paul Brossier',
98 author_email = 'piem@aubio.org',80 author_email = 'piem@aubio.org',
99 maintainer = 'Paul Brossier',81 maintainer = 'Paul Brossier',
100 maintainer_email = 'piem@aubio.org',82 maintainer_email = 'piem@aubio.org',
101 url = 'http://aubio.org/',83 url = 'https://aubio.org/',
102 platforms = 'any',84 platforms = 'any',
103 classifiers = classifiers,85 classifiers = classifiers,
104 install_requires = ['numpy'],86 install_requires = ['numpy'],
87 setup_requires = ['numpy'],
105 cmdclass = {88 cmdclass = {
106 'clean': CleanGenerated,89 'clean': CleanGenerated,
107 'generate': GenerateCommand,
108 'build_ext': build_ext,90 'build_ext': build_ext,
109 },91 },
92 entry_points = {
93 'console_scripts': [
94 'aubio = aubio.cmd:main',
95 'aubiocut = aubio.cut:main',
96 ],
97 },
110 test_suite = 'nose2.collector.collector',98 test_suite = 'nose2.collector.collector',
99 extras_require = {
100 'tests': ['numpy'],
101 },
111 )102 )
src/aubio.h+14−9
@@ -109,14 +109,16 @@ · 108 unmodified lines
109 \endcode109 \endcode
110 110
111 Several examples of C programs are available in the \p examples/ and \p tests/src111 Several examples of C programs are available in the \p examples/ and \p tests/src
112 directories of the source tree. See more examples:112 directories of the source tree.
113 @ref spectral/test-fft.c113
114 @ref spectral/test-phasevoc.c114 Some examples:
115 @ref onset/test-onset.c115 - @ref spectral/test-fft.c
116 @ref pitch/test-pitch.c116 - @ref spectral/test-phasevoc.c
117 @ref tempo/test-tempo.c117 - @ref onset/test-onset.c
118 @ref test-fvec.c118 - @ref pitch/test-pitch.c
119 @ref test-cvec.c119 - @ref tempo/test-tempo.c
120 - @ref test-fvec.c
121 - @ref test-cvec.c
120 122
121 \subsection unstable_api Unstable API123 \subsection unstable_api Unstable API
122 124
@@ -137,7 +139,7 @@ · 14 unmodified lines
137 \section download Download139 \section download Download
138 140
139 Latest versions, further documentation, examples, wiki, and mailing lists can141 Latest versions, further documentation, examples, wiki, and mailing lists can
140 be found at http://aubio.org .142 be found at https://aubio.org .
141 143
142 */144 */
143 145
@@ -180,11 +182,13 @@ extern "C" · 36 unmodified lines
180#include "temporal/a_weighting.h"182#include "temporal/a_weighting.h"
181#include "temporal/c_weighting.h"183#include "temporal/c_weighting.h"
182#include "spectral/fft.h"184#include "spectral/fft.h"
185#include "spectral/dct.h"
183#include "spectral/phasevoc.h"186#include "spectral/phasevoc.h"
184#include "spectral/filterbank.h"187#include "spectral/filterbank.h"
185#include "spectral/filterbank_mel.h"188#include "spectral/filterbank_mel.h"
186#include "spectral/mfcc.h"189#include "spectral/mfcc.h"
187#include "spectral/specdesc.h"190#include "spectral/specdesc.h"
191#include "spectral/awhitening.h"
188#include "spectral/tss.h"192#include "spectral/tss.h"
189#include "pitch/pitch.h"193#include "pitch/pitch.h"
190#include "onset/onset.h"194#include "onset/onset.h"
@@ -211,6 +215,7 @@ extern "C" · 20 unmodified lines
211#include "pitch/pitchmcomb.h"215#include "pitch/pitchmcomb.h"
212#include "pitch/pitchyin.h"216#include "pitch/pitchyin.h"
213#include "pitch/pitchyinfft.h"217#include "pitch/pitchyinfft.h"
218#include "pitch/pitchyinfast.h"
214#include "pitch/pitchschmitt.h"219#include "pitch/pitchschmitt.h"
215#include "pitch/pitchfcomb.h"220#include "pitch/pitchfcomb.h"
216#include "pitch/pitchspecacf.h"221#include "pitch/pitchspecacf.h"
src/aubio_priv.h+66−12
@@ -33,7 +33,9 @@ · 32 unmodified lines
33 *33 *
34 */34 */
35 35
36#ifdef HAVE_CONFIG_H
36#include "config.h"37#include "config.h"
38#endif
37 39
38#ifdef HAVE_STDLIB_H40#ifdef HAVE_STDLIB_H
39#include <stdlib.h>41#include <stdlib.h>
@@ -68,14 +70,20 @@ · 28 unmodified lines
68#include <stdarg.h>70#include <stdarg.h>
69#endif71#endif
70 72
71#ifdef HAVE_ACCELERATE73#if defined(HAVE_ACCELERATE)
72#define HAVE_ATLAS 174#define HAVE_ATLAS 1
75#define HAVE_BLAS 1
73#include <Accelerate/Accelerate.h>76#include <Accelerate/Accelerate.h>
74#elif defined(HAVE_ATLAS_CBLAS_H)77#elif defined(HAVE_ATLAS_CBLAS_H)
78#elif defined(HAVE_BLAS)
79#if defined(HAVE_ATLAS_CBLAS_H)
75#define HAVE_ATLAS 180#define HAVE_ATLAS 1
76#include <atlas/cblas.h>81#include <atlas/cblas.h>
77#else82#elif defined(HAVE_OPENBLAS_CBLAS_H)
78#undef HAVE_ATLAS83#include <openblas/cblas.h>
84#elif defined(HAVE_CBLAS_H)
85#include <cblas.h>
86#endif
79#endif87#endif
80 88
81#ifdef HAVE_ACCELERATE89#ifdef HAVE_ACCELERATE
@@ -83,6 +91,8 @@ · 1 unmodified line
83#ifndef HAVE_AUBIO_DOUBLE91#ifndef HAVE_AUBIO_DOUBLE
84#define aubio_vDSP_mmov vDSP_mmov92#define aubio_vDSP_mmov vDSP_mmov
85#define aubio_vDSP_vmul vDSP_vmul93#define aubio_vDSP_vmul vDSP_vmul
94#define aubio_vDSP_vsmul vDSP_vsmul
95#define aubio_vDSP_vsadd vDSP_vsadd
86#define aubio_vDSP_vfill vDSP_vfill96#define aubio_vDSP_vfill vDSP_vfill
87#define aubio_vDSP_meanv vDSP_meanv97#define aubio_vDSP_meanv vDSP_meanv
88#define aubio_vDSP_sve vDSP_sve98#define aubio_vDSP_sve vDSP_sve
@@ -91,9 +101,12 @@ · 2 unmodified lines
91#define aubio_vDSP_minv vDSP_minv101#define aubio_vDSP_minv vDSP_minv
92#define aubio_vDSP_minvi vDSP_minvi102#define aubio_vDSP_minvi vDSP_minvi
93#define aubio_vDSP_dotpr vDSP_dotpr103#define aubio_vDSP_dotpr vDSP_dotpr
104#define aubio_vDSP_vclr vDSP_vclr
94#else /* HAVE_AUBIO_DOUBLE */105#else /* HAVE_AUBIO_DOUBLE */
95#define aubio_vDSP_mmov vDSP_mmovD106#define aubio_vDSP_mmov vDSP_mmovD
96#define aubio_vDSP_vmul vDSP_vmulD107#define aubio_vDSP_vmul vDSP_vmulD
108#define aubio_vDSP_vsmul vDSP_vsmulD
109#define aubio_vDSP_vsadd vDSP_vsaddD
97#define aubio_vDSP_vfill vDSP_vfillD110#define aubio_vDSP_vfill vDSP_vfillD
98#define aubio_vDSP_meanv vDSP_meanvD111#define aubio_vDSP_meanv vDSP_meanvD
99#define aubio_vDSP_sve vDSP_sveD112#define aubio_vDSP_sve vDSP_sveD
@@ -102,27 +115,61 @@ · 2 unmodified lines
102#define aubio_vDSP_minv vDSP_minvD115#define aubio_vDSP_minv vDSP_minvD
103#define aubio_vDSP_minvi vDSP_minviD116#define aubio_vDSP_minvi vDSP_minviD
104#define aubio_vDSP_dotpr vDSP_dotprD117#define aubio_vDSP_dotpr vDSP_dotprD
118#define aubio_vDSP_vclr vDSP_vclrD
105#endif /* HAVE_AUBIO_DOUBLE */119#endif /* HAVE_AUBIO_DOUBLE */
106#endif /* HAVE_ACCELERATE */120#endif /* HAVE_ACCELERATE */
107 121
108#ifdef HAVE_ATLAS122#if defined(HAVE_BLAS)
109#ifndef HAVE_AUBIO_DOUBLE123#ifndef HAVE_AUBIO_DOUBLE
124#ifdef HAVE_ATLAS
110#define aubio_catlas_set catlas_sset125#define aubio_catlas_set catlas_sset
126#endif /* HAVE_ATLAS */
111#define aubio_cblas_copy cblas_scopy127#define aubio_cblas_copy cblas_scopy
112#define aubio_cblas_swap cblas_sswap128#define aubio_cblas_swap cblas_sswap
113#define aubio_cblas_dot cblas_sdot129#define aubio_cblas_dot cblas_sdot
114#else /* HAVE_AUBIO_DOUBLE */130#else /* HAVE_AUBIO_DOUBLE */
131#ifdef HAVE_ATLAS
115#define aubio_catlas_set catlas_dset132#define aubio_catlas_set catlas_dset
133#endif /* HAVE_ATLAS */
116#define aubio_cblas_copy cblas_dcopy134#define aubio_cblas_copy cblas_dcopy
117#define aubio_cblas_swap cblas_dswap135#define aubio_cblas_swap cblas_dswap
118#define aubio_cblas_dot cblas_ddot136#define aubio_cblas_dot cblas_ddot
119#endif /* HAVE_AUBIO_DOUBLE */137#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
121 170
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)
123#define HAVE_NOOPT 1172#define HAVE_NOOPT 1
124#else
125#undef HAVE_NOOPT
126#endif173#endif
127 174
128#include "types.h"175#include "types.h"
@@ -181,14 +228,16 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 52 unmodified lines
181 228
182#ifdef HAVE_C99_VARARGS_MACROS229#ifdef HAVE_C99_VARARGS_MACROS
183#define AUBIO_ERR(...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " __VA_ARGS__)230#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__)
184#define AUBIO_MSG(...) aubio_log(AUBIO_LOG_MSG, __VA_ARGS__)232#define AUBIO_MSG(...) aubio_log(AUBIO_LOG_MSG, __VA_ARGS__)
185#define AUBIO_DBG(...) aubio_log(AUBIO_LOG_DBG, __VA_ARGS__)233#define AUBIO_DBG(...) aubio_log(AUBIO_LOG_DBG, __VA_ARGS__)
186#define AUBIO_WRN(...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " __VA_ARGS__)234#define AUBIO_WRN(...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " __VA_ARGS__)
187#else235#else
188#define AUBIO_ERR(format, args...) aubio_log(stderr, "AUBIO ERROR: " format , ##args)236#define AUBIO_ERR(format, args...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " format , ##args)
189#define AUBIO_MSG(format, args...) aubio_log(stdout, format , ##args)237#define AUBIO_INF(format, args...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " format , ##args)
190#define AUBIO_DBG(format, args...) aubio_log(stderr, format , ##args)238#define AUBIO_MSG(format, args...) aubio_log(AUBIO_LOG_MSG, format , ##args)
191#define AUBIO_WRN(format, args...) aubio_log(stderr, "AUBIO WARNING: " 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)
192#endif241#endif
193 242
194#define AUBIO_ERROR AUBIO_ERR243#define AUBIO_ERROR AUBIO_ERR
@@ -196,6 +245,9 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 1 unmodified line
196#define AUBIO_QUIT(_s) exit(_s)245#define AUBIO_QUIT(_s) exit(_s)
197#define AUBIO_SPRINTF sprintf246#define AUBIO_SPRINTF sprintf
198 247
248#define AUBIO_MAX_SAMPLERATE (192000*8)
249#define AUBIO_MAX_CHANNELS 1024
250
199/* pi and 2*pi */251/* pi and 2*pi */
200#ifndef M_PI252#ifndef M_PI
201#define PI (3.14159265358979323846)253#define PI (3.14159265358979323846)
@@ -220,6 +272,7 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 18 unmodified lines
220#define LOG logf272#define LOG logf
221#define FLOOR floorf273#define FLOOR floorf
222#define CEIL ceilf274#define CEIL ceilf
275#define ATAN atanf
223#define ATAN2 atan2f276#define ATAN2 atan2f
224#else277#else
225#define EXP exp278#define EXP exp
@@ -232,6 +285,7 @@ uint_t aubio_log(sint_t level, const char_t *fmt, ...); · 6 unmodified lines
232#define LOG log285#define LOG log
233#define FLOOR floor286#define FLOOR floor
234#define CEIL ceil287#define CEIL ceil
288#define ATAN atan
235#define ATAN2 atan2289#define ATAN2 atan2
236#endif290#endif
237#define ROUND(x) FLOOR(x+.5)291#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
85 s->length, t->length);85 s->length, t->length);
86 return;86 return;
87 }87 }
88#ifdef HAVE_MEMCPY_HACKS88#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)
89 memcpy(t->norm, s->norm, t->length * sizeof(smpl_t));92 memcpy(t->norm, s->norm, t->length * sizeof(smpl_t));
90 memcpy(t->phas, s->phas, t->length * sizeof(smpl_t));93 memcpy(t->phas, s->phas, t->length * sizeof(smpl_t));
91#else /* HAVE_MEMCPY_HACKS */94#else
92 uint_t j;95 uint_t j;
93 for (j=0; j< t->length; j++) {96 for (j=0; j< t->length; j++) {
94 t->norm[j] = s->norm[j];97 t->norm[j] = s->norm[j];
95 t->phas[j] = s->phas[j];98 t->phas[j] = s->phas[j];
96 }99 }
97#endif /* HAVE_MEMCPY_HACKS */100#endif
98}101}
99 102
100void cvec_norm_set_all (cvec_t *s, smpl_t val) {103void 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
101 uint_t j;107 uint_t j;
102 for (j=0; j< s->length; j++) {108 for (j=0; j< s->length; j++) {
103 s->norm[j] = val;109 s->norm[j] = val;
104 }110 }
111#endif
105}112}
106 113
107void cvec_norm_zeros(cvec_t *s) {114void cvec_norm_zeros(cvec_t *s) {
108#ifdef HAVE_MEMCPY_HACKS115#if defined(HAVE_INTEL_IPP)
116 aubio_ippsZero(s->norm, (int)s->length);
117#elif defined(HAVE_MEMCPY_HACKS)
109 memset(s->norm, 0, s->length * sizeof(smpl_t));118 memset(s->norm, 0, s->length * sizeof(smpl_t));
110#else /* HAVE_MEMCPY_HACKS */119#else
111 cvec_norm_set_all (s, 0.);120 cvec_norm_set_all (s, 0.);
112#endif /* HAVE_MEMCPY_HACKS */121#endif
113}122}
114 123
115void cvec_norm_ones(cvec_t *s) {124void cvec_norm_ones(cvec_t *s) {
@@ -117,14 +126,20 @@ void cvec_norm_ones(cvec_t *s) { · 1 unmodified line
117}126}
118 127
119void cvec_phas_set_all (cvec_t *s, smpl_t val) {128void 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
120 uint_t j;132 uint_t j;
121 for (j=0; j< s->length; j++) {133 for (j=0; j< s->length; j++) {
122 s->phas[j] = val;134 s->phas[j] = val;
123 }135 }
136#endif
124}137}
125 138
126void cvec_phas_zeros(cvec_t *s) {139void cvec_phas_zeros(cvec_t *s) {
127#ifdef HAVE_MEMCPY_HACKS140#if defined(HAVE_INTEL_IPP)
141 aubio_ippsZero(s->phas, (int)s->length);
142#elif defined(HAVE_MEMCPY_HACKS)
128 memset(s->phas, 0, s->length * sizeof(smpl_t));143 memset(s->phas, 0, s->length * sizeof(smpl_t));
129#else144#else
130 cvec_phas_set_all (s, 0.);145 cvec_phas_set_all (s, 0.);
@@ -139,3 +154,16 @@ void cvec_zeros(cvec_t *s) { · 8 unmodified lines
139 cvec_norm_zeros(s);154 cvec_norm_zeros(s);
140 cvec_phas_zeros(s);155 cvec_phas_zeros(s);
141}156}
157
158void 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
230*/230*/
231void cvec_zeros(cvec_t *s);231void cvec_zeros(cvec_t *s);
232 232
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*/
241void cvec_logmag(cvec_t *s, smpl_t lambda);
242
233#ifdef __cplusplus243#ifdef __cplusplus
234}244}
235#endif245#endif
src/fmat.c+3−3
@@ -110,7 +110,7 @@ void fmat_ones(fmat_t *s) { · 109 unmodified lines
110void fmat_rev(fmat_t *s) {110void fmat_rev(fmat_t *s) {
111 uint_t i,j;111 uint_t i,j;
112 for (i=0; i< s->height; i++) {112 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++) {
114 ELEM_SWAP(s->data[i][j], s->data[i][s->length-1-j]);114 ELEM_SWAP(s->data[i][j], s->data[i][s->length-1-j]);
115 }115 }
116 }116 }
@@ -160,7 +160,7 @@ void fmat_vecmul(const fmat_t *s, const fvec_t *scale, fvec_t *output) { · 43 unmodified lines
160 assert(s->height == output->length);160 assert(s->height == output->length);
161 assert(s->length == scale->length);161 assert(s->length == scale->length);
162#endif162#endif
163#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)163#if !defined(HAVE_ACCELERATE) && !defined(HAVE_BLAS)
164 uint_t j;164 uint_t j;
165 fvec_zeros(output);165 fvec_zeros(output);
166 for (j = 0; j < s->length; j++) {166 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
169 * s->data[k][j];169 * s->data[k][j];
170 }170 }
171 }171 }
172#elif defined(HAVE_ATLAS)172#elif defined(HAVE_BLAS)
173 for (k = 0; k < s->height; k++) {173 for (k = 0; k < s->height; k++) {
174 output->data[k] = aubio_cblas_dot( s->length, scale->data, 1, s->data[k], 1);174 output->data[k] = aubio_cblas_dot( s->length, scale->data, 1, s->data[k], 1);
175 }175 }
src/fvec.c+40−31
@@ -60,27 +60,30 @@ void fvec_print(const fvec_t *s) { · 59 unmodified lines
60}60}
61 61
62void fvec_set_all (fvec_t *s, smpl_t val) {62void fvec_set_all (fvec_t *s, smpl_t val) {
63#if !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS)63#if defined(HAVE_INTEL_IPP)
64 uint_t j;64 aubio_ippsSet(val, s->data, (int)s->length);
65 for (j=0; j< s->length; j++) {
66 s->data[j] = val;
67 }
68#elif defined(HAVE_ATLAS)65#elif defined(HAVE_ATLAS)
69 aubio_catlas_set(s->length, val, s->data, 1);66 aubio_catlas_set(s->length, val, s->data, 1);
70#elif defined(HAVE_ACCELERATE)67#elif defined(HAVE_ACCELERATE)
71 aubio_vDSP_vfill(&val, s->data, 1, s->length);68 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 }
72#endif75#endif
73}76}
74 77
75void fvec_zeros(fvec_t *s) {78void fvec_zeros(fvec_t *s) {
76#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE)79#if defined(HAVE_INTEL_IPP)
77 fvec_set_all (s, 0.);80 aubio_ippsZero(s->data, (int)s->length);
78#else81#elif defined(HAVE_ACCELERATE)
79#if defined(HAVE_MEMCPY_HACKS)82 aubio_vDSP_vclr(s->data, 1, s->length);
83#elif defined(HAVE_MEMCPY_HACKS)
80 memset(s->data, 0, s->length * sizeof(smpl_t));84 memset(s->data, 0, s->length * sizeof(smpl_t));
81#else85#else
82 aubio_vDSP_vclr(s->data, 1, s->length);86 fvec_set_all(s, 0.);
83#endif
84#endif87#endif
85}88}
86 89
@@ -90,33 +93,37 @@ void fvec_ones(fvec_t *s) { · 3 unmodified lines
90 93
91void fvec_rev(fvec_t *s) {94void fvec_rev(fvec_t *s) {
92 uint_t j;95 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++) {
94 ELEM_SWAP(s->data[j], s->data[s->length-1-j]);97 ELEM_SWAP(s->data[j], s->data[s->length-1-j]);
95 }98 }
96}99}
97 100
98void fvec_weight(fvec_t *s, const fvec_t *weight) {101void fvec_weight(fvec_t *s, const fvec_t *weight) {
99#ifndef HAVE_ACCELERATE
100 uint_t j;
101 uint_t length = MIN(s->length, weight->length);102 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++) {
103 s->data[j] *= weight->data[j];110 s->data[j] *= weight->data[j];
104 }111 }
105#else
106 aubio_vDSP_vmul(s->data, 1, weight->data, 1, s->data, 1, s->length);
107#endif /* HAVE_ACCELERATE */112#endif /* HAVE_ACCELERATE */
108}113}
109 114
110void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) {115void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) {
111#ifndef HAVE_ACCELERATE116 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
112 uint_t j;122 uint_t j;
113 uint_t length = MIN(out->length, weight->length);123 for (j = 0; j < length; j++) {
114 for (j=0; j< length; j++) {
115 out->data[j] = in->data[j] * weight->data[j];124 out->data[j] = in->data[j] * weight->data[j];
116 }125 }
117#else126#endif
118 aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, out->length);
119#endif /* HAVE_ACCELERATE */
120}127}
121 128
122void fvec_copy(const fvec_t *s, fvec_t *t) {129void 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
125 s->length, t->length);132 s->length, t->length);
126 return;133 return;
127 }134 }
128#ifdef HAVE_NOOPT135#if defined(HAVE_INTEL_IPP)
129 uint_t j;136 aubio_ippsCopy(s->data, t->data, (int)s->length);
130 for (j=0; j< t->length; j++) {137#elif defined(HAVE_BLAS)
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)
136 aubio_cblas_copy(s->length, s->data, 1, t->data, 1);138 aubio_cblas_copy(s->length, s->data, 1, t->data, 1);
137#elif defined(HAVE_ACCELERATE)139#elif defined(HAVE_ACCELERATE)
138 aubio_vDSP_mmov(s->data, t->data, 1, s->length, 1, 1);140 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 }
139#endif148#endif
140}149}
src/io/audio_unit.c+1−2
@@ -18,9 +18,8 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21#include "config.h"
22#ifdef HAVE_AUDIO_UNIT
23#include "aubio_priv.h"21#include "aubio_priv.h"
22#ifdef HAVE_AUDIO_UNIT
24 23
25#include "fvec.h"24#include "fvec.h"
26#include "fmat.h"25#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
23uint_t
24aubio_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
39uint_t
40aubio_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
31extern "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 */
42uint_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 */
53uint_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
18 18
19*/19*/
20 20
21#include "config.h"
22#include "aubio_priv.h"21#include "aubio_priv.h"
23#include "fvec.h"22#include "fvec.h"
24#include "fmat.h"23#include "fmat.h"
@@ -98,8 +97,11 @@ aubio_sink_t * new_aubio_sink(const char_t * uri, uint_t samplerate) { · 73 unmodified lines
98 return s;97 return s;
99 }98 }
100#endif /* HAVE_WAVWRITE */99#endif /* HAVE_WAVWRITE */
101 AUBIO_ERROR("sink: failed creating %s with samplerate %dHz\n",100#if !defined(HAVE_WAVWRITE) && \
102 uri, samplerate);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
103 AUBIO_FREE(s);105 AUBIO_FREE(s);
104 return NULL;106 return NULL;
105}107}
src/io/sink_apple_audio.c+16−9
@@ -18,14 +18,13 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21#include "config.h"21#include "aubio_priv.h"
22 22
23#ifdef HAVE_SINK_APPLE_AUDIO23#ifdef HAVE_SINK_APPLE_AUDIO
24
25#include "aubio_priv.h"
26#include "fvec.h"24#include "fvec.h"
27#include "fmat.h"25#include "fmat.h"
28#include "io/sink_apple_audio.h"26#include "io/sink_apple_audio.h"
27#include "io/ioutils.h"
29 28
30// CFURLRef, CFURLCreateWithFileSystemPath, ...29// CFURLRef, CFURLCreateWithFileSystemPath, ...
31#include <CoreFoundation/CoreFoundation.h>30#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
62 s->max_frames = MAX_SIZE;61 s->max_frames = MAX_SIZE;
63 s->async = false;62 s->async = false;
64 63
65 if (uri == NULL) {64 if ( (uri == NULL) || (strlen(uri) < 1) ) {
66 AUBIO_ERROR("sink_apple_audio: Aborted opening null path\n");65 AUBIO_ERROR("sink_apple_audio: Aborted opening null path\n");
67 goto beach;66 goto beach;
68 }67 }
@@ -73,10 +72,14 @@ aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(const char_t * uri, uint_t · 4 unmodified lines
73 s->samplerate = 0;72 s->samplerate = 0;
74 s->channels = 0;73 s->channels = 0;
75 74
76 // negative samplerate given, abort
77 if ((sint_t)samplerate < 0) goto beach;
78 // zero samplerate given. do not open yet75 // 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 }
80 83
81 s->samplerate = samplerate;84 s->samplerate = samplerate;
82 s->channels = 1;85 s->channels = 1;
@@ -94,7 +97,9 @@ beach: · 11 unmodified lines
94 97
95uint_t aubio_sink_apple_audio_preset_samplerate(aubio_sink_apple_audio_t *s, uint_t samplerate)98uint_t aubio_sink_apple_audio_preset_samplerate(aubio_sink_apple_audio_t *s, uint_t samplerate)
96{99{
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 }
98 s->samplerate = samplerate;103 s->samplerate = samplerate;
99 // automatically open when both samplerate and channels have been set104 // automatically open when both samplerate and channels have been set
100 if (s->samplerate != 0 && s->channels != 0) {105 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
105 110
106uint_t aubio_sink_apple_audio_preset_channels(aubio_sink_apple_audio_t *s, uint_t channels)111uint_t aubio_sink_apple_audio_preset_channels(aubio_sink_apple_audio_t *s, uint_t channels)
107{112{
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 }
109 s->channels = channels;116 s->channels = channels;
110 // automatically open when both samplerate and channels have been set117 // automatically open when both samplerate and channels have been set
111 if (s->samplerate != 0 && s->channels != 0) {118 if (s->samplerate != 0 && s->channels != 0) {
src/io/sink_sndfile.c+20−11
@@ -19,18 +19,17 @@ · 18 unmodified lines
19*/19*/
20 20
21 21
22#include "config.h"22#include "aubio_priv.h"
23 23
24#ifdef HAVE_SNDFILE24#ifdef HAVE_SNDFILE
25 25
26#include <sndfile.h>26#include <sndfile.h>
27 27
28#include "aubio_priv.h"
29#include "fvec.h"28#include "fvec.h"
30#include "fmat.h"29#include "fmat.h"
31#include "io/sink_sndfile.h"30#include "io/sink_sndfile.h"
31#include "io/ioutils.h"
32 32
33#define MAX_CHANNELS 6
34#define MAX_SIZE 409633#define MAX_SIZE 4096
35 34
36#if !HAVE_AUBIO_DOUBLE35#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
69 s->samplerate = 0;68 s->samplerate = 0;
70 s->channels = 0;69 s->channels = 0;
71 70
72 // negative samplerate given, abort
73 if ((sint_t)samplerate < 0) goto beach;
74 // zero samplerate given. do not open yet71 // 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 }
76 79
77 s->samplerate = samplerate;80 s->samplerate = samplerate;
78 s->channels = 1;81 s->channels = 1;
@@ -89,7 +92,9 @@ beach: · 10 unmodified lines
89 92
90uint_t aubio_sink_sndfile_preset_samplerate(aubio_sink_sndfile_t *s, uint_t samplerate)93uint_t aubio_sink_sndfile_preset_samplerate(aubio_sink_sndfile_t *s, uint_t samplerate)
91{94{
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 }
93 s->samplerate = samplerate;98 s->samplerate = samplerate;
94 // automatically open when both samplerate and channels have been set99 // automatically open when both samplerate and channels have been set
95 if (s->samplerate != 0 && s->channels != 0) {100 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
100 105
101uint_t aubio_sink_sndfile_preset_channels(aubio_sink_sndfile_t *s, uint_t channels)106uint_t aubio_sink_sndfile_preset_channels(aubio_sink_sndfile_t *s, uint_t channels)
102{107{
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 }
104 s->channels = channels;111 s->channels = channels;
105 // automatically open when both samplerate and channels have been set112 // automatically open when both samplerate and channels have been set
106 if (s->samplerate != 0 && s->channels != 0) {113 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
132 139
133 if (s->handle == NULL) {140 if (s->handle == NULL) {
134 /* show libsndfile err msg */141 /* 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));
136 return AUBIO_FAIL;144 return AUBIO_FAIL;
137 }145 }
138 146
139 s->scratch_size = s->max_size*s->channels;147 s->scratch_size = s->max_size*s->channels;
140 /* allocate data for de/interleaving reallocated when needed. */148 /* 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();
142 AUBIO_ERR("sink_sndfile: %d x %d exceeds maximum aubio_sink_sndfile buffer size %d\n",151 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);
144 return AUBIO_FAIL;153 return AUBIO_FAIL;
145 }154 }
146 s->scratch_data = AUBIO_ARRAY(smpl_t,s->scratch_size);155 s->scratch_data = AUBIO_ARRAY(smpl_t,s->scratch_size);
src/io/sink_wavwrite.c+17−12
@@ -19,18 +19,17 @@ · 18 unmodified lines
19*/19*/
20 20
21 21
22#include "config.h"22#include "aubio_priv.h"
23 23
24#ifdef HAVE_WAVWRITE24#ifdef HAVE_WAVWRITE
25 25
26#include "aubio_priv.h"
27#include "fvec.h"26#include "fvec.h"
28#include "fmat.h"27#include "fmat.h"
29#include "io/sink_wavwrite.h"28#include "io/sink_wavwrite.h"
29#include "io/ioutils.h"
30 30
31#include <errno.h>31#include <errno.h>
32 32
33#define MAX_CHANNELS 6
34#define MAX_SIZE 409633#define MAX_SIZE 4096
35 34
36#define FLOAT_TO_SHORT(x) (short)(x * 32768)35#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
104 s->samplerate = 0;103 s->samplerate = 0;
105 s->channels = 0;104 s->channels = 0;
106 105
107 // negative samplerate given, abort
108 if ((sint_t)samplerate < 0) goto beach;
109 // zero samplerate given. do not open yet106 // zero samplerate given. do not open yet
110 if ((sint_t)samplerate == 0) return s;107 if ((sint_t)samplerate == 0) {
111 // samplerate way too large, fail108 return s;
112 if ((sint_t)samplerate > 192000 * 4) goto beach;109 }
110 // invalid samplerate given, abort
111 if (aubio_io_validate_samplerate("sink_wavwrite", s->path, samplerate)) {
112 goto beach;
113 }
113 114
114 s->samplerate = samplerate;115 s->samplerate = samplerate;
115 s->channels = 1;116 s->channels = 1;
@@ -129,7 +130,9 @@ beach: · 13 unmodified lines
129 130
130uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t samplerate)131uint_t aubio_sink_wavwrite_preset_samplerate(aubio_sink_wavwrite_t *s, uint_t samplerate)
131{132{
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 }
133 s->samplerate = samplerate;136 s->samplerate = samplerate;
134 // automatically open when both samplerate and channels have been set137 // automatically open when both samplerate and channels have been set
135 if (s->samplerate != 0 && s->channels != 0) {138 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
140 143
141uint_t aubio_sink_wavwrite_preset_channels(aubio_sink_wavwrite_t *s, uint_t channels)144uint_t aubio_sink_wavwrite_preset_channels(aubio_sink_wavwrite_t *s, uint_t channels)
142{145{
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 }
144 s->channels = channels;149 s->channels = channels;
145 // automatically open when both samplerate and channels have been set150 // automatically open when both samplerate and channels have been set
146 if (s->samplerate != 0 && s->channels != 0) {151 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
213 218
214 s->scratch_size = s->max_size * s->channels;219 s->scratch_size = s->max_size * s->channels;
215 /* allocate data for de/interleaving reallocated when needed. */220 /* 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) {
217 AUBIO_ERR("sink_wavwrite: %d x %d exceeds SIZE maximum buffer size %d\n",222 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);
219 goto beach;224 goto beach;
220 }225 }
221 s->scratch_data = AUBIO_ARRAY(unsigned short,s->scratch_size);226 s->scratch_data = AUBIO_ARRAY(unsigned short,s->scratch_size);
src/io/source.c+7−3
@@ -18,7 +18,6 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21#include "config.h"
22#include "aubio_priv.h"21#include "aubio_priv.h"
23#include "fvec.h"22#include "fvec.h"
24#include "fmat.h"23#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
115 return s;114 return s;
116 }115 }
117#endif /* HAVE_WAVREAD */116#endif /* HAVE_WAVREAD */
118 AUBIO_ERROR("source: failed creating aubio source with %s"117#if !defined(HAVE_WAVREAD) && \
119 " at samplerate %d with hop_size %d\n", uri, samplerate, hop_size);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
120 AUBIO_FREE(s);124 AUBIO_FREE(s);
121 return NULL;125 return NULL;
122}126}
src/io/source_apple_audio.c+2−3
@@ -18,11 +18,10 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21#include "config.h"21#include "aubio_priv.h"
22 22
23#ifdef HAVE_SOURCE_APPLE_AUDIO23#ifdef HAVE_SOURCE_APPLE_AUDIO
24 24
25#include "aubio_priv.h"
26#include "fvec.h"25#include "fvec.h"
27#include "fmat.h"26#include "fmat.h"
28#include "io/source_apple_audio.h"27#include "io/source_apple_audio.h"
@@ -280,7 +279,7 @@ beach: · 251 unmodified lines
280uint_t aubio_source_apple_audio_close (aubio_source_apple_audio_t *s)279uint_t aubio_source_apple_audio_close (aubio_source_apple_audio_t *s)
281{280{
282 OSStatus err = noErr;281 OSStatus err = noErr;
283 if (!s->audioFile) { return AUBIO_FAIL; }282 if (!s->audioFile) { return AUBIO_OK; }
284 err = ExtAudioFileDispose(s->audioFile);283 err = ExtAudioFileDispose(s->audioFile);
285 s->audioFile = NULL;284 s->audioFile = NULL;
286 if (err) {285 if (err) {
src/io/source_avcodec.c+266−81
@@ -18,32 +18,51 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21 21#include "aubio_priv.h"
22#include "config.h"
23 22
24#ifdef HAVE_LIBAV23#ifdef HAVE_LIBAV
25 24
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
26// determine whether we use libavformat from ffmpeg or from libav35// determine whether we use libavformat from ffmpeg or from libav
27#define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99 )36#define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99 )
28// max_analyze_duration2 was used from ffmpeg libavformat 55.43.100 through 57.2.10037// max_analyze_duration2 was used from ffmpeg libavformat 55.43.100 -> 57.2.100
29#define FFMPEG_LIBAVFORMAT_MAX_DUR2 FFMPEG_LIBAVFORMAT && ( \38#define FFMPEG_LIBAVFORMAT_MAX_DUR2 FFMPEG_LIBAVFORMAT && ( \
30 (LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR >= 43) \39 (LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR >= 43) \
31 || (LIBAVFORMAT_VERSION_MAJOR == 56) \40 || (LIBAVFORMAT_VERSION_MAJOR == 56) \
32 || (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR < 2) \41 || (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR < 2) \
33 )42 )
34 43
35#include <libavcodec/avcodec.h>44// backward compatibility with libavcodec55
36#include <libavformat/avformat.h>45#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,0,0)
37#include <libavresample/avresample.h>46#define HAVE_AUBIO_LIBAVCODEC_DEPRECATED 1
38#include <libavutil/opt.h>47#endif
39#include <stdlib.h>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
40 55
41#include "aubio_priv.h"56#include "aubio_priv.h"
42#include "fvec.h"57#include "fvec.h"
43#include "fmat.h"58#include "fmat.h"
44#include "source_avcodec.h"59#include "source_avcodec.h"
45 60
61#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 0)
46#define AUBIO_AVCODEC_MAX_BUFFER_SIZE FF_MIN_BUFFER_SIZE62#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
47 66
48struct _aubio_source_avcodec_t {67struct _aubio_source_avcodec_t {
49 uint_t hop_size;68 uint_t hop_size;
@@ -59,18 +78,24 @@ struct _aubio_source_avcodec_t { · 9 unmodified lines
59 AVFormatContext *avFormatCtx;78 AVFormatContext *avFormatCtx;
60 AVCodecContext *avCodecCtx;79 AVCodecContext *avCodecCtx;
61 AVFrame *avFrame;80 AVFrame *avFrame;
81 AVPacket avPacket;
82#ifdef HAVE_AVRESAMPLE
62 AVAudioResampleContext *avr;83 AVAudioResampleContext *avr;
63 float *output;84#elif defined(HAVE_SWRESAMPLE)
85 SwrContext *avr;
86#endif
87 smpl_t *output;
64 uint_t read_samples;88 uint_t read_samples;
65 uint_t read_index;89 uint_t read_index;
66 sint_t selected_stream;90 sint_t selected_stream;
67 uint_t eof;91 uint_t eof;
68 uint_t multi;
69};92};
70 93
71// hack to create or re-create the context the first time _do or _do_multi is called94// create or re-create the context when _do or _do_multi is called
72void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s, uint_t multi);95void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s);
73void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_samples);96// actually read a frame
97void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s,
98 uint_t * read_samples);
74 99
75uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s);100uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s);
76 101
@@ -87,19 +112,31 @@ uint_t aubio_source_avcodec_has_network_url(aubio_source_avcodec_t *s) { · 10 unmodified lines
87}112}
88 113
89 114
90aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t samplerate, uint_t hop_size) {115aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path,
116 uint_t samplerate, uint_t hop_size) {
91 aubio_source_avcodec_t * s = AUBIO_NEW(aubio_source_avcodec_t);117 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;
92 int err;127 int err;
93 if (path == NULL) {128 if (path == NULL) {
94 AUBIO_ERR("source_avcodec: Aborted opening null path\n");129 AUBIO_ERR("source_avcodec: Aborted opening null path\n");
95 goto beach;130 goto beach;
96 }131 }
97 if ((sint_t)samplerate < 0) {132 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);
99 goto beach;135 goto beach;
100 }136 }
101 if ((sint_t)hop_size <= 0) {137 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);
103 goto beach;140 goto beach;
104 }141 }
105 142
@@ -110,15 +147,16 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 4 unmodified lines
110 s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);147 s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
111 strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);148 strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
112 149
150#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,0,0)
113 // register all formats and codecs151 // register all formats and codecs
114 av_register_all();152 av_register_all();
153#endif
115 154
116 if (aubio_source_avcodec_has_network_url(s)) {155 if (aubio_source_avcodec_has_network_url(s)) {
117 avformat_network_init();156 avformat_network_init();
118 }157 }
119 158
120 // try opening the file and get some info about it159 // try opening the file and get some info about it
121 AVFormatContext *avFormatCtx = s->avFormatCtx;
122 avFormatCtx = NULL;160 avFormatCtx = NULL;
123 if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, NULL) ) < 0 ) {161 if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, NULL) ) < 0 ) {
124 char errorstr[256];162 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
138 if ( (err = avformat_find_stream_info(avFormatCtx, NULL)) < 0 ) {176 if ( (err = avformat_find_stream_info(avFormatCtx, NULL)) < 0 ) {
139 char errorstr[256];177 char errorstr[256];
140 av_strerror (err, errorstr, sizeof(errorstr));178 av_strerror (err, errorstr, sizeof(errorstr));
141 AUBIO_ERR("source_avcodec: Could not find stream information " "for %s (%s)\n", s->path,179 AUBIO_ERR("source_avcodec: Could not find stream information "
142 errorstr);180 "for %s (%s)\n", s->path, errorstr);
143 goto beach;181 goto beach;
144 }182 }
145 183
@@ -147,10 +185,12 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 1 unmodified line
147 //av_dump_format(avFormatCtx, 0, s->path, 0);185 //av_dump_format(avFormatCtx, 0, s->path, 0);
148 186
149 // look for the first audio stream187 // look for the first audio stream
150 uint_t i;
151 sint_t selected_stream = -1;
152 for (i = 0; i < avFormatCtx->nb_streams; i++) {188 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
153 if (avFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {192 if (avFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
193#endif
154 if (selected_stream == -1) {194 if (selected_stream == -1) {
155 selected_stream = i;195 selected_stream = i;
156 } else {196 } else {
@@ -166,18 +206,46 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 9 unmodified lines
166 //AUBIO_DBG("Taking stream %d in file %s\n", selected_stream, s->path);206 //AUBIO_DBG("Taking stream %d in file %s\n", selected_stream, s->path);
167 s->selected_stream = selected_stream;207 s->selected_stream = selected_stream;
168 208
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
170 avCodecCtx = avFormatCtx->streams[selected_stream]->codec;226 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
172 if (codec == NULL) {229 if (codec == NULL) {
173 AUBIO_ERR("source_avcodec: Could not find decoder for %s", s->path);230 AUBIO_ERR("source_avcodec: Could not find decoder for %s", s->path);
174 goto beach;231 goto beach;
175 }232 }
176 233
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
177 if ( ( err = avcodec_open2(avCodecCtx, codec, NULL) ) < 0) {244 if ( ( err = avcodec_open2(avCodecCtx, codec, NULL) ) < 0) {
178 char errorstr[256];245 char errorstr[256];
179 av_strerror (err, errorstr, sizeof(errorstr));246 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);
181 goto beach;249 goto beach;
182 }250 }
183 251
@@ -198,14 +266,14 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path, uint_t sa · 14 unmodified lines
198 s->input_samplerate, s->samplerate);266 s->input_samplerate, s->samplerate);
199 }267 }
200 268
201 AVFrame *avFrame = s->avFrame;
202 avFrame = av_frame_alloc();269 avFrame = av_frame_alloc();
203 if (!avFrame) {270 if (!avFrame) {
204 AUBIO_ERR("source_avcodec: Could not allocate frame for (%s)\n", s->path);271 AUBIO_ERR("source_avcodec: Could not allocate frame for (%s)\n", s->path);
205 }272 }
206 273
207 /* allocate output for avr */274 /* 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));
209 277
210 s->read_samples = 0;278 s->read_samples = 0;
211 s->read_index = 0;279 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
214 s->avCodecCtx = avCodecCtx;282 s->avCodecCtx = avCodecCtx;
215 s->avFrame = avFrame;283 s->avFrame = avFrame;
216 284
217 // default to mono output285 aubio_source_avcodec_reset_resampler(s);
218 aubio_source_avcodec_reset_resampler(s, 0);286
287 if (s->avr == NULL) goto beach;
219 288
220 s->eof = 0;289 s->eof = 0;
221 s->multi = 0;
222 290
223 //av_log_set_level(AV_LOG_QUIET);291 //av_log_set_level(AV_LOG_QUIET);
224 292
@@ -231,47 +299,78 @@ beach: · 6 unmodified lines
231 return NULL;299 return NULL;
232}300}
233 301
234void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s, uint_t multi) {302void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s)
235 if ( (multi != s->multi) || (s->avr == NULL) ) {303{
304 // create or reset resampler to/from mono/multi-channel
305 if ( s->avr == NULL ) {
306 int err;
236 int64_t input_layout = av_get_default_channel_layout(s->input_channels);307 int64_t input_layout = av_get_default_channel_layout(s->input_channels);
237 uint_t output_channels = multi ? s->input_channels : 1;308 int64_t output_layout = av_get_default_channel_layout(s->input_channels);
238 int64_t output_layout = av_get_default_channel_layout(output_channels);309#ifdef HAVE_AVRESAMPLE
239 if (s->avr != NULL) {310 AVAudioResampleContext *avr = avresample_alloc_context();
240 avresample_close( s->avr );311#elif defined(HAVE_SWRESAMPLE)
241 av_free ( s->avr );312 SwrContext *avr = swr_alloc();
242 s->avr = NULL;313#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
243 }314
244 AVAudioResampleContext *avr = s->avr;315 av_opt_set_int(avr, "in_channel_layout", input_layout, 0);
245 avr = avresample_alloc_context();316 av_opt_set_int(avr, "out_channel_layout", output_layout, 0);
246 317 av_opt_set_int(avr, "in_sample_rate", s->input_samplerate, 0);
247 av_opt_set_int(avr, "in_channel_layout", input_layout, 0);318 av_opt_set_int(avr, "out_sample_rate", s->samplerate, 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);
251 av_opt_set_int(avr, "in_sample_fmt", s->avCodecCtx->sample_fmt, 0);319 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);320#if HAVE_AUBIO_DOUBLE
253 int err;321 av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_DBL, 0);
254 if ( ( err = avresample_open(avr) ) < 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 {
255 char errorstr[256];333 char errorstr[256];
256 av_strerror (err, errorstr, sizeof(errorstr));334 av_strerror (err, errorstr, sizeof(errorstr));
257 AUBIO_ERR("source_avcodec: Could not open AVAudioResampleContext for %s (%s)\n",335 AUBIO_ERR("source_avcodec: Could not open resampling context"
258 s->path, errorstr);336 " for %s (%s)\n", s->path, errorstr);
259 //goto beach;
260 return;337 return;
261 }338 }
262 s->avr = avr;339 s->avr = avr;
263 s->multi = multi;
264 }340 }
265}341}
266 342
267void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_samples) {343void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s,
344 uint_t * read_samples)
345{
268 AVFormatContext *avFormatCtx = s->avFormatCtx;346 AVFormatContext *avFormatCtx = s->avFormatCtx;
269 AVCodecContext *avCodecCtx = s->avCodecCtx;347 AVCodecContext *avCodecCtx = s->avCodecCtx;
270 AVFrame *avFrame = s->avFrame;348 AVFrame *avFrame = s->avFrame;
271 AVPacket avPacket;349 AVPacket avPacket = s->avPacket;
272 av_init_packet (&avPacket);350#ifdef HAVE_AVRESAMPLE
273 AVAudioResampleContext *avr = s->avr;351 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);
275 *read_samples = 0;374 *read_samples = 0;
276 375
277 do376 do
@@ -284,34 +383,81 @@ void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_sam · 6 unmodified lines
284 if (err != 0) {383 if (err != 0) {
285 char errorstr[256];384 char errorstr[256];
286 av_strerror (err, errorstr, sizeof(errorstr));385 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;
288 goto beach;389 goto beach;
289 }390 }
290 } while (avPacket.stream_index != s->selected_stream);391 } while (avPacket.stream_index != s->selected_stream);
291 392
292 int got_frame = 0;393#if FF_API_LAVF_AVCTX
293 int len = avcodec_decode_audio4(avCodecCtx, avFrame, &got_frame, &avPacket);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);
294 418
295 if (len < 0) {419 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);
297 goto beach;421 goto beach;
298 }422 }
423#endif
299 if (got_frame == 0) {424 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);
301 goto beach;427 goto beach;
302 }428 }
303 429
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;
305 av_samples_get_buffer_size(&in_linesize, avCodecCtx->channels,443 av_samples_get_buffer_size(&in_linesize, avCodecCtx->channels,
306 avFrame->nb_samples, avCodecCtx->sample_fmt, 1);444 avFrame->nb_samples, avCodecCtx->sample_fmt, 1);
307 int in_samples = avFrame->nb_samples;445 in_samples = avFrame->nb_samples;
308 int out_linesize = 0;446 out_linesize = 0;
309 int max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE;447 max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE;
310 int out_samples = avresample_convert ( avr,448 out_samples = avresample_convert ( avr,
311 (uint8_t **)&output, out_linesize, max_out_samples,449 (uint8_t **)&output, out_linesize, max_out_samples,
312 (uint8_t **)avFrame->data, in_linesize, in_samples);450 (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 */
313 if (out_samples <= 0) {458 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);
315 goto beach;461 goto beach;
316 }462 }
317 463
@@ -321,21 +467,28 @@ beach: · 3 unmodified lines
321 s->avFormatCtx = avFormatCtx;467 s->avFormatCtx = avFormatCtx;
322 s->avCodecCtx = avCodecCtx;468 s->avCodecCtx = avCodecCtx;
323 s->avFrame = avFrame;469 s->avFrame = avFrame;
470#if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
324 s->avr = avr;471 s->avr = avr;
472#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
325 s->output = output;473 s->output = output;
326 474
327 av_packet_unref(&avPacket);475 av_packet_unref(&avPacket);
328}476}
329 477
330void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data, uint_t * read){478void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data,
331 if (s->multi == 1) aubio_source_avcodec_reset_resampler(s, 0);479 uint_t * read) {
332 uint_t i;480 uint_t i, j;
333 uint_t end = 0;481 uint_t end = 0;
334 uint_t total_wrote = 0;482 uint_t total_wrote = 0;
335 while (total_wrote < s->hop_size) {483 while (total_wrote < s->hop_size) {
336 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);484 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
337 for (i = 0; i < end; i++) {485 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;
339 }492 }
340 total_wrote += end;493 total_wrote += end;
341 if (total_wrote < s->hop_size) {494 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
351 }504 }
352 }505 }
353 if (total_wrote < s->hop_size) {506 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++) {
355 read_data->data[i] = 0.;508 read_data->data[i] = 0.;
356 }509 }
357 }510 }
358 *read = total_wrote;511 *read = total_wrote;
359}512}
360 513
361void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s, fmat_t * read_data, uint_t * read){514void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s,
362 if (s->multi == 0) aubio_source_avcodec_reset_resampler(s, 1);515 fmat_t * read_data, uint_t * read) {
363 uint_t i,j;516 uint_t i,j;
364 uint_t end = 0;517 uint_t end = 0;
365 uint_t total_wrote = 0;518 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
386 }539 }
387 if (total_wrote < s->hop_size) {540 if (total_wrote < s->hop_size) {
388 for (j = 0; j < read_data->height; j++) {541 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++) {
390 read_data->data[j][i] = 0.;543 read_data->data[j][i] = 0.;
391 }544 }
392 }545 }
@@ -403,22 +556,42 @@ uint_t aubio_source_avcodec_get_channels(const aubio_source_avcodec_t * s) { · 10 unmodified lines
403}556}
404 557
405uint_t aubio_source_avcodec_seek (aubio_source_avcodec_t * s, uint_t pos) {558uint_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));
407 int64_t min_ts = MAX(resampled_pos - 2000, 0);561 int64_t min_ts = MAX(resampled_pos - 2000, 0);
408 int64_t max_ts = MIN(resampled_pos + 2000, INT64_MAX);562 int64_t max_ts = MIN(resampled_pos + 2000, INT64_MAX);
409 int seek_flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY;563 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,
411 min_ts, resampled_pos, max_ts, seek_flags);578 min_ts, resampled_pos, max_ts, seek_flags);
412 if (ret < 0) {579 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);
414 }582 }
415 // reset read status583 // reset read status
416 s->eof = 0;584 s->eof = 0;
417 s->read_index = 0;585 s->read_index = 0;
418 s->read_samples = 0;586 s->read_samples = 0;
587#ifdef HAVE_AVRESAMPLE
419 // reset the AVAudioResampleContext588 // reset the AVAudioResampleContext
420 avresample_close(s->avr);589 avresample_close(s->avr);
421 avresample_open(s->avr);590 avresample_open(s->avr);
591#elif defined(HAVE_SWRESAMPLE)
592 swr_close(s->avr);
593 swr_init(s->avr);
594#endif
422 return ret;595 return ret;
423}596}
424 597
@@ -432,18 +605,27 @@ uint_t aubio_source_avcodec_get_duration (aubio_source_avcodec_t * s) { · 7 unmodified lines
432 605
433uint_t aubio_source_avcodec_close(aubio_source_avcodec_t * s) {606uint_t aubio_source_avcodec_close(aubio_source_avcodec_t * s) {
434 if (s->avr != NULL) {607 if (s->avr != NULL) {
608#ifdef HAVE_AVRESAMPLE
435 avresample_close( s->avr );609 avresample_close( s->avr );
610#elif defined(HAVE_SWRESAMPLE)
611 swr_close ( s->avr );
612#endif
436 av_free ( s->avr );613 av_free ( s->avr );
437 }614 }
438 s->avr = NULL;615 s->avr = NULL;
439 if (s->avCodecCtx != NULL) {616 if (s->avCodecCtx != NULL) {
617#ifndef HAVE_AUBIO_LIBAVCODEC_DEPRECATED
618 avcodec_free_context( &s->avCodecCtx );
619#else
440 avcodec_close ( s->avCodecCtx );620 avcodec_close ( s->avCodecCtx );
621#endif
441 }622 }
442 s->avCodecCtx = NULL;623 s->avCodecCtx = NULL;
443 if (s->avFormatCtx != NULL) {624 if (s->avFormatCtx != NULL) {
444 avformat_close_input ( &(s->avFormatCtx) );625 avformat_close_input(&s->avFormatCtx);
626 s->avFormatCtx = NULL;
445 }627 }
446 s->avFormatCtx = NULL;628 av_packet_unref(&s->avPacket);
447 return AUBIO_OK;629 return AUBIO_OK;
448}630}
449 631
@@ -457,8 +639,11 @@ void del_aubio_source_avcodec(aubio_source_avcodec_t * s){ · 7 unmodified lines
457 if (s->avFrame != NULL) {639 if (s->avFrame != NULL) {
458 av_frame_free( &(s->avFrame) );640 av_frame_free( &(s->avFrame) );
459 }641 }
460 if (s->path) AUBIO_FREE(s->path);
461 s->avFrame = NULL;642 s->avFrame = NULL;
643 if (s->path) {
644 AUBIO_FREE(s->path);
645 }
646 s->path = NULL;
462 AUBIO_FREE(s);647 AUBIO_FREE(s);
463}648}
464 649
src/io/source_sndfile.c+17−8
@@ -18,23 +18,20 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21 21#include "aubio_priv.h"
22#include "config.h"
23 22
24#ifdef HAVE_SNDFILE23#ifdef HAVE_SNDFILE
25 24
26#include <sndfile.h>25#include <sndfile.h>
27 26
28#include "aubio_priv.h"
29#include "fvec.h"27#include "fvec.h"
30#include "fmat.h"28#include "fmat.h"
31#include "source_sndfile.h"29#include "source_sndfile.h"
32 30
33#include "temporal/resampler.h"31#include "temporal/resampler.h"
34 32
35#define MAX_CHANNELS 6
36#define MAX_SIZE 409633#define MAX_SIZE 4096
37#define MAX_SAMPLES MAX_CHANNELS * MAX_SIZE34#define MAX_SAMPLES AUBIO_MAX_CHANNELS * MAX_SIZE
38 35
39#if !HAVE_AUBIO_DOUBLE36#if !HAVE_AUBIO_DOUBLE
40#define aubio_sf_read_smpl sf_read_float37#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
140 }137 }
141 if (s->ratio > 1) {138 if (s->ratio > 1) {
142 // we would need to add a ring buffer for these139 // 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 ) {
144 AUBIO_ERR("source_sndfile: can not upsample %s from %d to %d\n", s->path,141 AUBIO_ERR("source_sndfile: can not upsample %s from %d to %d\n", s->path,
145 s->input_samplerate, s->samplerate);142 s->input_samplerate, s->samplerate);
146 goto beach;143 goto beach;
@@ -297,7 +294,18 @@ uint_t aubio_source_sndfile_get_duration (const aubio_source_sndfile_t * s) { · 150 unmodified lines
297 294
298uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) {295uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) {
299 uint_t resampled_pos = (uint_t)ROUND(pos / s->ratio);296 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);
301 if (sf_ret == -1) {309 if (sf_ret == -1) {
302 AUBIO_ERR("source_sndfile: Failed seeking %s at %d: %s\n", s->path, pos, sf_strerror (NULL));310 AUBIO_ERR("source_sndfile: Failed seeking %s at %d: %s\n", s->path, pos, sf_strerror (NULL));
303 return AUBIO_FAIL;311 return AUBIO_FAIL;
@@ -312,12 +320,13 @@ uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) { · 8 unmodified lines
312 320
313uint_t aubio_source_sndfile_close (aubio_source_sndfile_t *s) {321uint_t aubio_source_sndfile_close (aubio_source_sndfile_t *s) {
314 if (!s->handle) {322 if (!s->handle) {
315 return AUBIO_FAIL;323 return AUBIO_OK;
316 }324 }
317 if(sf_close(s->handle)) {325 if(sf_close(s->handle)) {
318 AUBIO_ERR("source_sndfile: Error closing file %s: %s\n", s->path, sf_strerror (NULL));326 AUBIO_ERR("source_sndfile: Error closing file %s: %s\n", s->path, sf_strerror (NULL));
319 return AUBIO_FAIL;327 return AUBIO_FAIL;
320 }328 }
329 s->handle = NULL;
321 return AUBIO_OK;330 return AUBIO_OK;
322}331}
323 332
src/io/source_wavread.c+48−14
@@ -18,11 +18,10 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21#include "config.h"21#include "aubio_priv.h"
22 22
23#ifdef HAVE_WAVREAD23#ifdef HAVE_WAVREAD
24 24
25#include "aubio_priv.h"
26#include "fvec.h"25#include "fvec.h"
27#include "fmat.h"26#include "fmat.h"
28#include "source_wavread.h"27#include "source_wavread.h"
@@ -76,7 +75,7 @@ static unsigned int read_little_endian (unsigned char *buf, · 47 unmodified lines
76aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t samplerate, uint_t hop_size) {75aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t samplerate, uint_t hop_size) {
77 aubio_source_wavread_t * s = AUBIO_NEW(aubio_source_wavread_t);76 aubio_source_wavread_t * s = AUBIO_NEW(aubio_source_wavread_t);
78 size_t bytes_read = 0, bytes_junk = 0, bytes_expected = 44;77 size_t bytes_read = 0, bytes_junk = 0, bytes_expected = 44;
79 unsigned char buf[5];78 unsigned char buf[5] = "\0";
80 unsigned int format, channels, sr, byterate, blockalign, duration, bitspersample;//, data_size;79 unsigned int format, channels, sr, byterate, blockalign, duration, bitspersample;//, data_size;
81 80
82 if (path == NULL) {81 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
109 bytes_read += fread(buf, 1, 4, s->fid);108 bytes_read += fread(buf, 1, 4, s->fid);
110 buf[4] = '\0';109 buf[4] = '\0';
111 if ( strcmp((const char *)buf, "RIFF") != 0 ) {110 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);
113 goto beach;112 goto beach;
114 }113 }
115 114
@@ -120,7 +119,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 4 unmodified lines
120 bytes_read += fread(buf, 1, 4, s->fid);119 bytes_read += fread(buf, 1, 4, s->fid);
121 buf[4] = '\0';120 buf[4] = '\0';
122 if ( strcmp((const char *)buf, "WAVE") != 0 ) {121 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);
124 goto beach;123 goto beach;
125 }124 }
126 125
@@ -134,7 +133,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 7 unmodified lines
134 buf[4] = '\0';133 buf[4] = '\0';
135 bytes_junk += read_little_endian(buf, 4);134 bytes_junk += read_little_endian(buf, 4);
136 if (fseek(s->fid, bytes_read + bytes_junk, SEEK_SET) != 0) {135 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",
138 s->path, strerror(errno));137 s->path, strerror(errno));
139 goto beach;138 goto beach;
140 }139 }
@@ -147,7 +146,7 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 6 unmodified lines
147 146
148 // get the fmt chunk147 // get the fmt chunk
149 if ( strcmp((const char *)buf, "fmt ") != 0 ) {148 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);
151 goto beach;150 goto beach;
152 }151 }
153 152
@@ -156,18 +155,18 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 2 unmodified lines
156 format = read_little_endian(buf, 4);155 format = read_little_endian(buf, 4);
157 if ( format != 16 ) {156 if ( format != 16 ) {
158 // TODO accept format 18157 // 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);
160 goto beach;159 goto beach;
161 }160 }
162 if ( buf[1] || buf[2] | buf[3] ) {161 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);
164 goto beach;163 goto beach;
165 }164 }
166 165
167 // AudioFormat166 // AudioFormat
168 bytes_read += fread(buf, 1, 2, s->fid);167 bytes_read += fread(buf, 1, 2, s->fid);
169 if ( buf[0] != 1 || buf[1] != 0) {168 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);
171 goto beach;170 goto beach;
172 }171 }
173 172
@@ -190,6 +189,26 @@ aubio_source_wavread_t * new_aubio_source_wavread(const char_t * path, uint_t sa · 16 unmodified lines
190 // BitsPerSample189 // BitsPerSample
191 bytes_read += fread(buf, 1, 2, s->fid);190 bytes_read += fread(buf, 1, 2, s->fid);
192 bitspersample = read_little_endian(buf, 2);191 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 }
193#if 0212#if 0
194 if ( bitspersample != 16 ) {213 if ( bitspersample != 16 ) {
195 AUBIO_ERR("source_wavread: can not process %dbit file %s\n",214 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
199#endif218#endif
200 219
201 if ( byterate * 8 != sr * channels * bitspersample ) {220 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);
203 goto beach;222 goto beach;
204 }223 }
205 224
206 if ( blockalign * 8 != channels * bitspersample ) {225 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);
208 goto beach;227 goto beach;
209 }228 }
210 229
@@ -329,6 +348,11 @@ void aubio_source_wavread_do(aubio_source_wavread_t * s, fvec_t * read_data, uin · 118 unmodified lines
329 uint_t i, j;348 uint_t i, j;
330 uint_t end = 0;349 uint_t end = 0;
331 uint_t total_wrote = 0;350 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 }
332 while (total_wrote < s->hop_size) {356 while (total_wrote < s->hop_size) {
333 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);357 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
334 for (i = 0; i < end; i++) {358 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
363 uint_t i,j;387 uint_t i,j;
364 uint_t end = 0;388 uint_t end = 0;
365 uint_t total_wrote = 0;389 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 }
366 while (total_wrote < s->hop_size) {395 while (total_wrote < s->hop_size) {
367 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);396 end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
368 for (j = 0; j < read_data->height; j++) {397 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
403 432
404uint_t aubio_source_wavread_seek (aubio_source_wavread_t * s, uint_t pos) {433uint_t aubio_source_wavread_seek (aubio_source_wavread_t * s, uint_t pos) {
405 uint_t ret = 0;434 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 }
406 if ((sint_t)pos < 0) {439 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);
407 return AUBIO_FAIL;441 return AUBIO_FAIL;
408 }442 }
409 ret = fseek(s->fid, s->seek_start + pos * s->blockalign, SEEK_SET);443 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
425}459}
426 460
427uint_t aubio_source_wavread_close (aubio_source_wavread_t * s) {461uint_t aubio_source_wavread_close (aubio_source_wavread_t * s) {
428 if (!s->fid) {462 if (s->fid == NULL) {
429 return AUBIO_FAIL;463 return AUBIO_OK;
430 }464 }
431 if (fclose(s->fid)) {465 if (fclose(s->fid)) {
432 AUBIO_ERR("source_wavread: could not close %s (%s)\n", s->path, strerror(errno));466 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"
2 2
3#if defined(HAVE_SOURCE_APPLE_AUDIO) || defined(HAVE_SINK_APPLE_AUDIO)3#if defined(HAVE_SOURCE_APPLE_AUDIO) || defined(HAVE_SINK_APPLE_AUDIO)
4 4
@@ -6,7 +6,6 @@ · 1 unmodified line
6#include <CoreFoundation/CoreFoundation.h>6#include <CoreFoundation/CoreFoundation.h>
7// ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...7// ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
8#include <AudioToolbox/AudioToolbox.h>8#include <AudioToolbox/AudioToolbox.h>
9#include "aubio_priv.h"
10 9
11int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);10int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
12void freeAudioBufferList(AudioBufferList *bufferList);11void freeAudioBufferList(AudioBufferList *bufferList);
src/mathutils.c+90−36
@@ -24,11 +24,11 @@ · 23 unmodified lines
24#include "fvec.h"24#include "fvec.h"
25#include "mathutils.h"25#include "mathutils.h"
26#include "musicutils.h"26#include "musicutils.h"
27#include "config.h"
28 27
29/** Window types */28/** Window types */
30typedef enum29typedef enum
31{30{
31 aubio_win_ones,
32 aubio_win_rectangle,32 aubio_win_rectangle,
33 aubio_win_hamming,33 aubio_win_hamming,
34 aubio_win_hanning,34 aubio_win_hanning,
@@ -64,7 +64,9 @@ uint_t fvec_set_window (fvec_t *win, char_t *window_type) { · 29 unmodified lines
64 if (window_type == NULL) {64 if (window_type == NULL) {
65 AUBIO_ERR ("window type can not be null.\n");65 AUBIO_ERR ("window type can not be null.\n");
66 return 1;66 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)
68 wintype = aubio_win_rectangle;70 wintype = aubio_win_rectangle;
69 else if (strcmp (window_type, "hamming") == 0)71 else if (strcmp (window_type, "hamming") == 0)
70 wintype = aubio_win_hamming;72 wintype = aubio_win_hamming;
@@ -89,9 +91,11 @@ uint_t fvec_set_window (fvec_t *win, char_t *window_type) { · 18 unmodified lines
89 return 1;91 return 1;
90 }92 }
91 switch(wintype) {93 switch(wintype) {
94 case aubio_win_ones:
95 fvec_ones(win);
96 break;
92 case aubio_win_rectangle:97 case aubio_win_rectangle:
93 for (i=0;i<size;i++)98 fvec_set_all(win, .5);
94 w[i] = 0.5;
95 break;99 break;
96 case aubio_win_hamming:100 case aubio_win_hamming:
97 for (i=0;i<size;i++)101 for (i=0;i<size;i++)
@@ -155,45 +159,53 @@ smpl_t · 57 unmodified lines
155fvec_mean (fvec_t * s)159fvec_mean (fvec_t * s)
156{160{
157 smpl_t tmp = 0.0;161 smpl_t tmp = 0.0;
158#ifndef HAVE_ACCELERATE162#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
159 uint_t j;169 uint_t j;
160 for (j = 0; j < s->length; j++) {170 for (j = 0; j < s->length; j++) {
161 tmp += s->data[j];171 tmp += s->data[j];
162 }172 }
163 return tmp / (smpl_t) (s->length);173 return tmp / (smpl_t)(s->length);
164#else174#endif
165 aubio_vDSP_meanv(s->data, 1, &tmp, s->length);
166 return tmp;
167#endif /* HAVE_ACCELERATE */
168}175}
169 176
170smpl_t177smpl_t
171fvec_sum (fvec_t * s)178fvec_sum (fvec_t * s)
172{179{
173 smpl_t tmp = 0.0;180 smpl_t tmp = 0.0;
174#ifndef HAVE_ACCELERATE181#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
175 uint_t j;186 uint_t j;
176 for (j = 0; j < s->length; j++) {187 for (j = 0; j < s->length; j++) {
177 tmp += s->data[j];188 tmp += s->data[j];
178 }189 }
179#else190#endif
180 aubio_vDSP_sve(s->data, 1, &tmp, s->length);
181#endif /* HAVE_ACCELERATE */
182 return tmp;191 return tmp;
183}192}
184 193
185smpl_t194smpl_t
186fvec_max (fvec_t * s)195fvec_max (fvec_t * s)
187{196{
188#ifndef HAVE_ACCELERATE197#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
189 uint_t j;204 uint_t j;
190 smpl_t tmp = 0.0;205 smpl_t tmp = s->data[0];
191 for (j = 0; j < s->length; j++) {206 for (j = 1; j < s->length; j++) {
192 tmp = (tmp > s->data[j]) ? tmp : s->data[j];207 tmp = (tmp > s->data[j]) ? tmp : s->data[j];
193 }208 }
194#else
195 smpl_t tmp = 0.;
196 aubio_vDSP_maxv(s->data, 1, &tmp, s->length);
197#endif209#endif
198 return tmp;210 return tmp;
199}211}
@@ -201,15 +213,18 @@ fvec_max (fvec_t * s) · 1 unmodified line
201smpl_t213smpl_t
202fvec_min (fvec_t * s)214fvec_min (fvec_t * s)
203{215{
204#ifndef HAVE_ACCELERATE216#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
205 uint_t j;223 uint_t j;
206 smpl_t tmp = s->data[0];224 smpl_t tmp = s->data[0];
207 for (j = 0; j < s->length; j++) {225 for (j = 1; j < s->length; j++) {
208 tmp = (tmp < s->data[j]) ? tmp : s->data[j];226 tmp = (tmp < s->data[j]) ? tmp : s->data[j];
209 }227 }
210#else
211 smpl_t tmp = 0.;
212 aubio_vDSP_minv(s->data, 1, &tmp, s->length);
213#endif228#endif
214 return tmp;229 return tmp;
215}230}
@@ -226,10 +241,10 @@ fvec_min_elem (fvec_t * s) · 10 unmodified lines
226 }241 }
227#else242#else
228 smpl_t tmp = 0.;243 smpl_t tmp = 0.;
229 uint_t pos = 0.;244 vDSP_Length pos = 0;
230 aubio_vDSP_minvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);245 aubio_vDSP_minvi(s->data, 1, &tmp, &pos, s->length);
231#endif246#endif
232 return pos;247 return (uint_t)pos;
233}248}
234 249
235uint_t250uint_t
@@ -244,10 +259,10 @@ fvec_max_elem (fvec_t * s) · 8 unmodified lines
244 }259 }
245#else260#else
246 smpl_t tmp = 0.;261 smpl_t tmp = 0.;
247 uint_t pos = 0.;262 vDSP_Length pos = 0;
248 aubio_vDSP_maxvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length);263 aubio_vDSP_maxvi(s->data, 1, &tmp, &pos, s->length);
249#endif264#endif
250 return pos;265 return (uint_t)pos;
251}266}
252 267
253void268void
@@ -256,7 +271,7 @@ fvec_shift (fvec_t * s) · 2 unmodified lines
256 uint_t half = s->length / 2, start = half, j;271 uint_t half = s->length / 2, start = half, j;
257 // if length is odd, middle element is moved to the end272 // if length is odd, middle element is moved to the end
258 if (2 * half < s->length) start ++;273 if (2 * half < s->length) start ++;
259#ifndef HAVE_ATLAS274#ifndef HAVE_BLAS
260 for (j = 0; j < half; j++) {275 for (j = 0; j < half; j++) {
261 ELEM_SWAP (s->data[j], s->data[j + start]);276 ELEM_SWAP (s->data[j], s->data[j + start]);
262 }277 }
@@ -276,7 +291,7 @@ fvec_ishift (fvec_t * s) · 13 unmodified lines
276 uint_t half = s->length / 2, start = half, j;291 uint_t half = s->length / 2, start = half, j;
277 // if length is odd, middle element is moved to the beginning292 // if length is odd, middle element is moved to the beginning
278 if (2 * half < s->length) start ++;293 if (2 * half < s->length) start ++;
279#ifndef HAVE_ATLAS294#ifndef HAVE_BLAS
280 for (j = 0; j < half; j++) {295 for (j = 0; j < half; j++) {
281 ELEM_SWAP (s->data[j], s->data[j + start]);296 ELEM_SWAP (s->data[j], s->data[j + start]);
282 }297 }
@@ -290,11 +305,30 @@ fvec_ishift (fvec_t * s) · 7 unmodified lines
290 }305 }
291}306}
292 307
308void 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
316void 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
293smpl_t327smpl_t
294aubio_level_lin (const fvec_t * f)328aubio_level_lin (const fvec_t * f)
295{329{
296 smpl_t energy = 0.;330 smpl_t energy = 0.;
297#ifndef HAVE_ATLAS331#ifndef HAVE_BLAS
298 uint_t j;332 uint_t j;
299 for (j = 0; j < f->length; j++) {333 for (j = 0; j < f->length; j++) {
300 energy += SQR (f->data[j]);334 energy += SQR (f->data[j]);
@@ -353,6 +387,15 @@ fvec_add (fvec_t * o, smpl_t val) · 52 unmodified lines
353 }387 }
354}388}
355 389
390void
391fvec_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
356void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp,399void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp,
357 uint_t post, uint_t pre) {400 uint_t post, uint_t pre) {
358 uint_t length = vec->length, j;401 uint_t length = vec->length, j;
@@ -488,7 +531,7 @@ aubio_freqtomidi (smpl_t freq) · 129 unmodified lines
488 if (freq < 2. || freq > 100000.) return 0.; // avoid nans and infs531 if (freq < 2. || freq > 100000.) return 0.; // avoid nans and infs
489 /* log(freq/A-2)/log(2) */532 /* log(freq/A-2)/log(2) */
490 midi = freq / 6.875;533 midi = freq / 6.875;
491 midi = LOG (midi) / 0.69314718055995;534 midi = LOG (midi) / 0.6931471805599453;
492 midi *= 12;535 midi *= 12;
493 midi -= 3;536 midi -= 3;
494 return midi;537 return midi;
@@ -500,7 +543,7 @@ aubio_miditofreq (smpl_t midi) · 5 unmodified lines
500 smpl_t freq;543 smpl_t freq;
501 if (midi > 140.) return 0.; // avoid infs544 if (midi > 140.) return 0.; // avoid infs
502 freq = (midi + 3.) / 12.;545 freq = (midi + 3.) / 12.;
503 freq = EXP (freq * 0.69314718055995);546 freq = EXP (freq * 0.6931471805599453);
504 freq *= 6.875;547 freq *= 6.875;
505 return freq;548 return freq;
506}549}
@@ -551,6 +594,17 @@ aubio_next_power_of_two (uint_t a) · 44 unmodified lines
551 return i;594 return i;
552}595}
553 596
597uint_t
598aubio_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
554smpl_t608smpl_t
555aubio_db_spl (const fvec_t * o)609aubio_db_spl (const fvec_t * o)
556{610{
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
117*/117*/
118void fvec_ishift (fvec_t * v);118void fvec_ishift (fvec_t * v);
119 119
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*/
129void fvec_push(fvec_t *in, smpl_t new_elem);
130
120/** compute the sum of all elements of a vector131/** compute the sum of all elements of a vector
121 132
122 \param v vector to compute the sum of133 \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
182*/193*/
183void fvec_add (fvec_t * v, smpl_t c);194void fvec_add (fvec_t * v, smpl_t c);
184 195
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*/
202void fvec_mul (fvec_t * v, smpl_t s);
203
185/** remove the minimum value of the vector to each elements204/** remove the minimum value of the vector to each elements
186 205
187 \param v vector to remove minimum from206 \param v vector to remove minimum from
@@ -301,6 +320,9 @@ uint_t aubio_is_power_of_two(uint_t a); · 113 unmodified lines
301/** return the next power of power of 2 greater than a */320/** return the next power of power of 2 greater than a */
302uint_t aubio_next_power_of_two(uint_t a);321uint_t aubio_next_power_of_two(uint_t a);
303 322
323/** return the log2 factor of the given power of 2 value a */
324uint_t aubio_power_of_two_order(uint_t a);
325
304/** compute normalised autocorrelation function326/** compute normalised autocorrelation function
305 327
306 \param input vector to compute autocorrelation from328 \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
24smpl_t
25aubio_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
44smpl_t
45aubio_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
62smpl_t
63aubio_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
74smpl_t
75aubio_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
86/** convert frequency (Hz) to frequency bin */86/** convert frequency (Hz) to frequency bin */
87smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize);87smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize);
88 88
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*/
110smpl_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*/
138smpl_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 */
166smpl_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*/
186smpl_t aubio_meltohz_htk (smpl_t mel);
187
89/** convert frequency (Hz) to midi value (0-128) */188/** convert frequency (Hz) to midi value (0-128) */
90smpl_t aubio_freqtomidi (smpl_t freq);189smpl_t aubio_freqtomidi (smpl_t freq);
91 190
@@ -156,6 +255,14 @@ uint_t aubio_silence_detection (const fvec_t * v, smpl_t threshold); · 64 unmodified lines
156*/255*/
157smpl_t aubio_level_detection (const fvec_t * v, smpl_t threshold);256smpl_t aubio_level_detection (const fvec_t * v, smpl_t threshold);
158 257
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*/
264void fvec_clamp(fvec_t *in, smpl_t absmax);
265
159#ifdef __cplusplus266#ifdef __cplusplus
160}267}
161#endif268#endif
src/notes/notes.c+97−11
@@ -1,5 +1,5 @@
1/*1/*
2 Copyright (C) 2014 Paul Brossier <piem@aubio.org>2 Copyright (C) 2014-2018 Paul Brossier <piem@aubio.org>
3 3
4 This file is part of aubio.4 This file is part of aubio.
5 5
@@ -24,6 +24,13 @@ · 18 unmodified lines
24#include "onset/onset.h"24#include "onset/onset.h"
25#include "notes/notes.h"25#include "notes/notes.h"
26 26
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
27struct _aubio_notes_t {34struct _aubio_notes_t {
28 35
29 uint_t onset_buf_size;36 uint_t onset_buf_size;
@@ -50,6 +57,9 @@ struct _aubio_notes_t { · 20 unmodified lines
50 smpl_t silence_threshold;57 smpl_t silence_threshold;
51 58
52 uint_t isready;59 uint_t isready;
60
61 smpl_t last_onset_level;
62 smpl_t release_drop_level;
53};63};
54 64
55aubio_notes_t * new_aubio_notes (const char_t * method,65aubio_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
73 o->isready = 0;83 o->isready = 0;
74 84
75 o->onset = new_aubio_onset (onset_method, o->onset_buf_size, o->hop_size, o->samplerate);85 o->onset = new_aubio_onset (onset_method, o->onset_buf_size, o->hop_size, o->samplerate);
86 if (o->onset == NULL) goto fail;
76 if (o->onset_threshold != 0.) aubio_onset_set_threshold (o->onset, o->onset_threshold);87 if (o->onset_threshold != 0.) aubio_onset_set_threshold (o->onset, o->onset_threshold);
77 o->onset_output = new_fvec (1);88 o->onset_output = new_fvec (1);
78 89
79 o->pitch = new_aubio_pitch (pitch_method, o->pitch_buf_size, o->hop_size, o->samplerate);90 o->pitch = new_aubio_pitch (pitch_method, o->pitch_buf_size, o->hop_size, o->samplerate);
91 if (o->pitch == NULL) goto fail;
80 if (o->pitch_tolerance != 0.) aubio_pitch_set_tolerance (o->pitch, o->pitch_tolerance);92 if (o->pitch_tolerance != 0.) aubio_pitch_set_tolerance (o->pitch, o->pitch_tolerance);
93 aubio_pitch_set_unit (o->pitch, "midi");
81 o->pitch_output = new_fvec (1);94 o->pitch_output = new_fvec (1);
82 95
83 if (strcmp(method, "default") != 0) {96 if (strcmp(method, "default") != 0) {
@@ -87,10 +100,17 @@ aubio_notes_t * new_aubio_notes (const char_t * method, · 3 unmodified lines
87 o->note_buffer = new_fvec(o->median);100 o->note_buffer = new_fvec(o->median);
88 o->note_buffer2 = new_fvec(o->median);101 o->note_buffer2 = new_fvec(o->median);
89 102
103 if (!o->onset_output || !o->pitch_output ||
104 !o->note_buffer || !o->note_buffer2) goto fail;
105
90 o->curnote = -1.;106 o->curnote = -1.;
91 o->newnote = 0.;107 o->newnote = 0.;
92 108
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;
94 114
95 return o;115 return o;
96 116
@@ -99,6 +119,55 @@ fail: · 2 unmodified lines
99 return NULL;119 return NULL;
100}120}
101 121
122uint_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
135smpl_t aubio_notes_get_silence(const aubio_notes_t *o)
136{
137 return aubio_pitch_get_silence(o->pitch);
138}
139
140uint_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
149smpl_t aubio_notes_get_minioi_ms(const aubio_notes_t *o)
150{
151 return aubio_onset_get_minioi_ms(o->onset);
152}
153
154uint_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
166smpl_t aubio_notes_get_release_drop(const aubio_notes_t *o)
167{
168 return o->release_drop_level;
169}
170
102/** append new note candidate to the note_buffer and return filtered value. we171/** append new note candidate to the note_buffer and return filtered value. we
103 * need to copy the input array as fvec_median destroy its input data.*/172 * need to copy the input array as fvec_median destroy its input data.*/
104static void173static void
@@ -108,18 +177,16 @@ note_append (fvec_t * note_buffer, smpl_t curnote) · 3 unmodified lines
108 for (i = 0; i < note_buffer->length - 1; i++) {177 for (i = 0; i < note_buffer->length - 1; i++) {
109 note_buffer->data[i] = note_buffer->data[i + 1];178 note_buffer->data[i] = note_buffer->data[i + 1];
110 }179 }
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);
112 return;182 return;
113}183}
114 184
115static uint_t185static smpl_t
116aubio_notes_get_latest_note (aubio_notes_t *o)186aubio_notes_get_latest_note (aubio_notes_t *o)
117{187{
118 uint_t i;188 fvec_copy(o->note_buffer, o->note_buffer2);
119 for (i = 0; i < o->note_buffer->length; i++) {189 return fvec_median (o->note_buffer2) / AUBIO_DEFAULT_CENT_PRECISION;
120 o->note_buffer2->data[i] = o->note_buffer->data[i];
121 }
122 return fvec_median (o->note_buffer2);
123}190}
124 191
125 192
@@ -145,6 +212,7 @@ void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * notes) · 19 unmodified lines
145 //send_noteon(o->curnote,0);212 //send_noteon(o->curnote,0);
146 //notes->data[0] = o->curnote;213 //notes->data[0] = o->curnote;
147 //notes->data[1] = 0.;214 //notes->data[1] = 0.;
215 //AUBIO_WRN("notes: sending note-off at onset, not enough level\n");
148 notes->data[2] = o->curnote;216 notes->data[2] = o->curnote;
149 } else {217 } else {
150 if (o->median) {218 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
152 } else {220 } else {
153 /* kill old note */221 /* kill old note */
154 //send_noteon(o->curnote,0, o->samplerate);222 //send_noteon(o->curnote,0, o->samplerate);
223 //AUBIO_WRN("notes: sending note-off at onset, new onset detected\n");
155 notes->data[2] = o->curnote;224 notes->data[2] = o->curnote;
156 /* get and send new one */225 /* get and send new one */
157 //send_noteon(new_pitch,127+(int)floor(curlevel), o->samplerate);226 //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
159 notes->data[1] = 127 + (int)floor(curlevel);228 notes->data[1] = 127 + (int)floor(curlevel);
160 o->curnote = new_pitch;229 o->curnote = new_pitch;
161 }230 }
231 o->last_onset_level = curlevel;
162 }232 }
163 } else {233 } 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 {
165 if (o->isready > 0)247 if (o->isready > 0)
166 o->isready++;248 o->isready++;
167 if (o->isready == o->median)249 if (o->isready == o->median)
168 {250 {
169 /* kill old note */251 /* kill old note */
170 //send_noteon(curnote,0);252 //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 }
172 o->newnote = aubio_notes_get_latest_note(o);258 o->newnote = aubio_notes_get_latest_note(o);
173 o->curnote = o->newnote;259 o->curnote = o->newnote;
174 /* get and send new one */260 /* get and send new one */
src/notes/notes.h+81−2
@@ -18,6 +18,12 @@ · 17 unmodified lines
18 18
19*/19*/
20 20
21/** \file
22
23 Note detection object
24
25*/
26
21#ifndef _AUBIO_NOTES_H27#ifndef _AUBIO_NOTES_H
22#define _AUBIO_NOTES_H28#define _AUBIO_NOTES_H
23 29
@@ -51,12 +57,85 @@ void del_aubio_notes(aubio_notes_t * o); · 27 unmodified lines
51/** execute note detection on an input signal frame57/** execute note detection on an input signal frame
52 58
53 \param o note detection object as returned by new_aubio_notes()59 \param o note detection object as returned by new_aubio_notes()
54 \param in input signal of size [hop_size]60 \param input input signal of size [hop_size]
55 \param out output notes of size [3] ? FIXME61 \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
56 67
57*/68*/
58void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * output);69void aubio_notes_do (aubio_notes_t *o, const fvec_t * input, fvec_t * output);
59 70
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*/
79uint_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*/
88smpl_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 */
97smpl_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*/
107uint_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 */
116smpl_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*/
137uint_t aubio_notes_set_release_drop (aubio_notes_t *o, smpl_t release_drop);
138
60#ifdef __cplusplus139#ifdef __cplusplus
61}140}
62#endif141#endif
src/onset/onset.c+135−19
@@ -23,10 +23,13 @@ · 22 unmodified lines
23#include "cvec.h"23#include "cvec.h"
24#include "spectral/specdesc.h"24#include "spectral/specdesc.h"
25#include "spectral/phasevoc.h"25#include "spectral/phasevoc.h"
26#include "spectral/awhitening.h"
26#include "onset/peakpicker.h"27#include "onset/peakpicker.h"
27#include "mathutils.h"28#include "mathutils.h"
28#include "onset/onset.h"29#include "onset/onset.h"
29 30
31void aubio_onset_default_parameters (aubio_onset_t *o, const char_t * method);
32
30/** structure to store object state */33/** structure to store object state */
31struct _aubio_onset_t {34struct _aubio_onset_t {
32 aubio_pvoc_t * pv; /**< phase vocoder */35 aubio_pvoc_t * pv; /**< phase vocoder */
@@ -42,6 +45,11 @@ struct _aubio_onset_t { · 9 unmodified lines
42 45
43 uint_t total_frames; /**< total number of frames processed since the beginning */46 uint_t total_frames; /**< total number of frames processed since the beginning */
44 uint_t last_onset; /**< last detected onset location, in frames */47 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;
45};53};
46 54
47/* execute onset detection function on iput buffer */55/* 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
49{57{
50 smpl_t isonset = 0;58 smpl_t isonset = 0;
51 aubio_pvoc_do (o->pv,input, o->fftgrain);59 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 }
52 aubio_specdesc_do (o->od, o->fftgrain, o->desc);70 aubio_specdesc_do (o->od, o->fftgrain, o->desc);
53 aubio_peakpicker_do(o->pp, o->desc, onset);71 aubio_peakpicker_do(o->pp, o->desc, onset);
54 isonset = onset->data[0];72 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
57 //AUBIO_DBG ("silent onset, not marking as onset\n");75 //AUBIO_DBG ("silent onset, not marking as onset\n");
58 isonset = 0;76 isonset = 0;
59 } else {77 } else {
78 // we have an onset
60 uint_t new_onset = o->total_frames + (uint_t)ROUND(isonset * o->hop_size);79 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
61 if (o->last_onset + o->minioi < new_onset) {81 if (o->last_onset + o->minioi < new_onset) {
62 //AUBIO_DBG ("accepted detection, marking as onset\n");82 // start of file: make sure (new_onset - delay) >= 0
63 o->last_onset = new_onset;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 }
64 } else {89 } else {
65 //AUBIO_DBG ("doubled onset, not marking as onset\n");90 //AUBIO_DBG ("doubled onset, not marking as onset\n");
66 isonset = 0;91 isonset = 0;
@@ -99,6 +124,32 @@ smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o) · 32 unmodified lines
99 return aubio_onset_get_last_s (o) * 1000.;124 return aubio_onset_get_last_s (o) * 1000.;
100}125}
101 126
127uint_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
133smpl_t aubio_onset_get_awhitening (aubio_onset_t *o)
134{
135 return o->apply_awhitening;
136}
137
138uint_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
148smpl_t aubio_onset_get_compression (aubio_onset_t *o)
149{
150 return o->apply_compression ? o->lambda_compression : 0;
151}
152
102uint_t aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence) {153uint_t aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence) {
103 o->silence = silence;154 o->silence = silence;
104 return AUBIO_OK;155 return AUBIO_OK;
@@ -205,35 +256,100 @@ aubio_onset_t * new_aubio_onset (const char_t * onset_mode, · 100 unmodified lines
205 o->pv = new_aubio_pvoc(buf_size, o->hop_size);256 o->pv = new_aubio_pvoc(buf_size, o->hop_size);
206 o->pp = new_aubio_peakpicker();257 o->pp = new_aubio_peakpicker();
207 o->od = new_aubio_specdesc(onset_mode,buf_size);258 o->od = new_aubio_specdesc(onset_mode,buf_size);
208 if (o->od == NULL) goto beach_specdesc;
209 o->fftgrain = new_cvec(buf_size);259 o->fftgrain = new_cvec(buf_size);
210 o->desc = new_fvec(1);260 o->desc = new_fvec(1);
261 o->spectral_whitening = new_aubio_spectral_whitening(buf_size, hop_size, samplerate);
211 262
212 /* set some default parameter */263 if (!o->pv || !o->pp || !o->od || !o->fftgrain
213 aubio_onset_set_threshold (o, 0.3);264 || !o->desc || !o->spectral_whitening)
214 aubio_onset_set_delay(o, 4.3 * hop_size);265 goto beach;
215 aubio_onset_set_minioi_ms(o, 20.);
216 aubio_onset_set_silence(o, -70.);
217 266
218 /* initialize internal variables */267 /* initialize internal variables */
219 o->last_onset = 0;268 aubio_onset_set_default_parameters (o, onset_mode);
220 o->total_frames = 0;269
270 aubio_onset_reset(o);
221 return o;271 return o;
222 272
223beach_specdesc:
224 del_aubio_peakpicker(o->pp);
225 del_aubio_pvoc(o->pv);
226beach:273beach:
227 AUBIO_FREE(o);274 del_aubio_onset(o);
228 return NULL;275 return NULL;
229}276}
230 277
278void aubio_onset_reset (aubio_onset_t *o) {
279 o->last_onset = 0;
280 o->total_frames = 0;
281}
282
283uint_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
231void del_aubio_onset (aubio_onset_t *o)340void del_aubio_onset (aubio_onset_t *o)
232{341{
233 del_aubio_specdesc(o->od);342 if (o->spectral_whitening)
234 del_aubio_peakpicker(o->pp);343 del_aubio_spectral_whitening(o->spectral_whitening);
235 del_aubio_pvoc(o->pv);344 if (o->od)
236 del_fvec(o->desc);345 del_aubio_specdesc(o->od);
237 del_cvec(o->fftgrain);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);
238 AUBIO_FREE(o);354 AUBIO_FREE(o);
239}355}
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
117*/117*/
118smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o);118smpl_t aubio_onset_get_last_ms (const aubio_onset_t *o);
119 119
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*/
128uint_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*/
137smpl_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 */
147uint_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 */
156smpl_t aubio_onset_get_compression(aubio_onset_t *o);
157
120/** set onset detection silence threshold158/** set onset detection silence threshold
121 159
122 \param o onset detection object as returned by new_aubio_onset()160 \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
274*/312*/
275smpl_t aubio_onset_get_threshold(const aubio_onset_t * o);313smpl_t aubio_onset_get_threshold(const aubio_onset_t * o);
276 314
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 */
323uint_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 */
334void aubio_onset_reset(aubio_onset_t * o);
335
277/** delete onset detection object336/** delete onset detection object
278 337
279 \param o onset detection object to delete338 \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
92 fvec_t *thresholded = p->thresholded;92 fvec_t *thresholded = p->thresholded;
93 fvec_t *scratch = p->scratch;93 fvec_t *scratch = p->scratch;
94 smpl_t mean = 0., median = 0.;94 smpl_t mean = 0., median = 0.;
95 uint_t length = p->win_post + p->win_pre + 1;
96 uint_t j = 0;95 uint_t j = 0;
97 96
98 /* store onset in onset_keep */97 /* push new novelty to the end */
99 /* shift all elements but last, then write last */98 fvec_push(onset_keep, onset->data[0]);
100 for (j = 0; j < length - 1; j++) {99 /* store a copy */
101 onset_keep->data[j] = onset_keep->data[j + 1];100 fvec_copy(onset_keep, onset_proc);
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];
106 101
107 /* filter onset_proc */102 /* filter this copy */
108 /** \bug filtfilt calculated post+pre times, should be only once !? */
109 aubio_filter_do_filtfilt (p->biquad, onset_proc, scratch);103 aubio_filter_do_filtfilt (p->biquad, onset_proc, scratch);
110 104
111 /* calculate mean and median for onset_proc */105 /* calculate mean and median for onset_proc */
112 mean = fvec_mean (onset_proc);106 mean = fvec_mean (onset_proc);
113 /* copy to scratch */107
114 for (j = 0; j < length; j++)108 /* copy to scratch and compute its median */
115 scratch->data[j] = onset_proc->data[j];109 fvec_copy(onset_proc, scratch);
116 median = p->thresholdfn (scratch);110 median = p->thresholdfn (scratch);
117 111
118 /* shift peek array */112 /* shift peek array */
@@ -185,7 +179,9 @@ new_aubio_peakpicker (void) · 66 unmodified lines
185 generated with octave butter function: [b,a] = butter(2, 0.34);179 generated with octave butter function: [b,a] = butter(2, 0.34);
186 */180 */
187 t->biquad = new_aubio_filter_biquad (0.15998789, 0.31997577, 0.15998789,181 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);
189 185
190 return t;186 return t;
191}187}
src/pitch/pitch.c+50−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include "pitch/pitchfcomb.h"32#include "pitch/pitchfcomb.h"
33#include "pitch/pitchschmitt.h"33#include "pitch/pitchschmitt.h"
34#include "pitch/pitchyinfft.h"34#include "pitch/pitchyinfft.h"
35#include "pitch/pitchyinfast.h"
35#include "pitch/pitchspecacf.h"36#include "pitch/pitchspecacf.h"
36#include "pitch/pitch.h"37#include "pitch/pitch.h"
37 38
@@ -45,6 +46,7 @@ typedef enum · 7 unmodified lines
45 aubio_pitcht_schmitt, /**< `schmitt`, Schmitt trigger */46 aubio_pitcht_schmitt, /**< `schmitt`, Schmitt trigger */
46 aubio_pitcht_fcomb, /**< `fcomb`, Fast comb filter */47 aubio_pitcht_fcomb, /**< `fcomb`, Fast comb filter */
47 aubio_pitcht_yinfft, /**< `yinfft`, Spectral YIN */48 aubio_pitcht_yinfft, /**< `yinfft`, Spectral YIN */
49 aubio_pitcht_yinfast, /**< `yinfast`, YIN fast */
48 aubio_pitcht_specacf, /**< `specacf`, Spectral autocorrelation */50 aubio_pitcht_specacf, /**< `specacf`, Spectral autocorrelation */
49 aubio_pitcht_default51 aubio_pitcht_default
50 = aubio_pitcht_yinfft, /**< `default` */52 = 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
94static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);96static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
95static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);97static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
96static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);98static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
99static void aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
97static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);100static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
98 101
99/* internal functions for frequency conversion */102/* internal functions for frequency conversion */
@@ -111,8 +114,14 @@ new_aubio_pitch (const char_t * pitch_mode, · 11 unmodified lines
111{114{
112 aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t);115 aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t);
113 aubio_pitch_type pitch_type;116 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 }
114 if (strcmp (pitch_mode, "mcomb") == 0)121 if (strcmp (pitch_mode, "mcomb") == 0)
115 pitch_type = aubio_pitcht_mcomb;122 pitch_type = aubio_pitcht_mcomb;
123 else if (strcmp (pitch_mode, "yinfast") == 0)
124 pitch_type = aubio_pitcht_yinfast;
116 else if (strcmp (pitch_mode, "yinfft") == 0)125 else if (strcmp (pitch_mode, "yinfft") == 0)
117 pitch_type = aubio_pitcht_yinfft;126 pitch_type = aubio_pitcht_yinfft;
118 else if (strcmp (pitch_mode, "yin") == 0)127 else if (strcmp (pitch_mode, "yin") == 0)
@@ -138,7 +147,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 19 unmodified lines
138 AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize);147 AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize);
139 goto beach;148 goto beach;
140 } else if (bufsize < hopsize) {149 } 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);
142 goto beach;151 goto beach;
143 } else if ((sint_t)samplerate < 1) {152 } else if ((sint_t)samplerate < 1) {
144 AUBIO_ERR("pitch: samplerate (%d) can not be < 1\n", samplerate);153 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
155 case aubio_pitcht_yin:164 case aubio_pitcht_yin:
156 p->buf = new_fvec (bufsize);165 p->buf = new_fvec (bufsize);
157 p->p_object = new_aubio_pitchyin (bufsize);166 p->p_object = new_aubio_pitchyin (bufsize);
167 if (!p->p_object) goto beach;
158 p->detect_cb = aubio_pitch_do_yin;168 p->detect_cb = aubio_pitch_do_yin;
159 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence;169 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence;
160 aubio_pitchyin_set_tolerance (p->p_object, 0.15);170 aubio_pitchyin_set_tolerance (p->p_object, 0.15);
@@ -162,6 +172,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 1 unmodified line
162 case aubio_pitcht_mcomb:172 case aubio_pitcht_mcomb:
163 p->filtered = new_fvec (hopsize);173 p->filtered = new_fvec (hopsize);
164 p->pv = new_aubio_pvoc (bufsize, hopsize);174 p->pv = new_aubio_pvoc (bufsize, hopsize);
175 if (!p->pv) goto beach;
165 p->fftgrain = new_cvec (bufsize);176 p->fftgrain = new_cvec (bufsize);
166 p->p_object = new_aubio_pitchmcomb (bufsize, hopsize);177 p->p_object = new_aubio_pitchmcomb (bufsize, hopsize);
167 p->filter = new_aubio_filter_c_weighting (samplerate);178 p->filter = new_aubio_filter_c_weighting (samplerate);
@@ -170,6 +181,7 @@ new_aubio_pitch (const char_t * pitch_mode, · 2 unmodified lines
170 case aubio_pitcht_fcomb:181 case aubio_pitcht_fcomb:
171 p->buf = new_fvec (bufsize);182 p->buf = new_fvec (bufsize);
172 p->p_object = new_aubio_pitchfcomb (bufsize, hopsize);183 p->p_object = new_aubio_pitchfcomb (bufsize, hopsize);
184 if (!p->p_object) goto beach;
173 p->detect_cb = aubio_pitch_do_fcomb;185 p->detect_cb = aubio_pitch_do_fcomb;
174 break;186 break;
175 case aubio_pitcht_schmitt:187 case aubio_pitcht_schmitt:
@@ -180,13 +192,23 @@ new_aubio_pitch (const char_t * pitch_mode, · 4 unmodified lines
180 case aubio_pitcht_yinfft:192 case aubio_pitcht_yinfft:
181 p->buf = new_fvec (bufsize);193 p->buf = new_fvec (bufsize);
182 p->p_object = new_aubio_pitchyinfft (samplerate, bufsize);194 p->p_object = new_aubio_pitchyinfft (samplerate, bufsize);
195 if (!p->p_object) goto beach;
183 p->detect_cb = aubio_pitch_do_yinfft;196 p->detect_cb = aubio_pitch_do_yinfft;
184 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence;197 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence;
185 aubio_pitchyinfft_set_tolerance (p->p_object, 0.85);198 aubio_pitchyinfft_set_tolerance (p->p_object, 0.85);
186 break;199 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;
187 case aubio_pitcht_specacf:208 case aubio_pitcht_specacf:
188 p->buf = new_fvec (bufsize);209 p->buf = new_fvec (bufsize);
189 p->p_object = new_aubio_pitchspecacf (bufsize);210 p->p_object = new_aubio_pitchspecacf (bufsize);
211 if (!p->p_object) goto beach;
190 p->detect_cb = aubio_pitch_do_specacf;212 p->detect_cb = aubio_pitch_do_specacf;
191 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance;213 p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance;
192 aubio_pitchspecacf_set_tolerance (p->p_object, 0.85);214 aubio_pitchspecacf_set_tolerance (p->p_object, 0.85);
@@ -197,6 +219,8 @@ new_aubio_pitch (const char_t * pitch_mode, · 4 unmodified lines
197 return p;219 return p;
198 220
199beach:221beach:
222 if (p->filtered) del_fvec(p->filtered);
223 if (p->buf) del_fvec(p->buf);
200 AUBIO_FREE(p);224 AUBIO_FREE(p);
201 return NULL;225 return NULL;
202}226}
@@ -228,6 +252,10 @@ del_aubio_pitch (aubio_pitch_t * p) · 25 unmodified lines
228 del_fvec (p->buf);252 del_fvec (p->buf);
229 del_aubio_pitchyinfft (p->p_object);253 del_aubio_pitchyinfft (p->p_object);
230 break;254 break;
255 case aubio_pitcht_yinfast:
256 del_fvec (p->buf);
257 del_aubio_pitchyinfast (p->p_object);
258 break;
231 case aubio_pitcht_specacf:259 case aubio_pitcht_specacf:
232 del_fvec (p->buf);260 del_fvec (p->buf);
233 del_aubio_pitchspecacf (p->p_object);261 del_aubio_pitchspecacf (p->p_object);
@@ -318,6 +346,9 @@ aubio_pitch_set_tolerance (aubio_pitch_t * p, smpl_t tol) · 84 unmodified lines
318 case aubio_pitcht_yinfft:346 case aubio_pitcht_yinfft:
319 aubio_pitchyinfft_set_tolerance (p->p_object, tol);347 aubio_pitchyinfft_set_tolerance (p->p_object, tol);
320 break;348 break;
349 case aubio_pitcht_yinfast:
350 aubio_pitchyinfast_set_tolerance (p->p_object, tol);
351 break;
321 default:352 default:
322 break;353 break;
323 }354 }
@@ -335,6 +366,9 @@ aubio_pitch_get_tolerance (aubio_pitch_t * p) · 11 unmodified lines
335 case aubio_pitcht_yinfft:366 case aubio_pitcht_yinfft:
336 tolerance = aubio_pitchyinfft_get_tolerance (p->p_object);367 tolerance = aubio_pitchyinfft_get_tolerance (p->p_object);
337 break;368 break;
369 case aubio_pitcht_yinfast:
370 tolerance = aubio_pitchyinfast_get_tolerance (p->p_object);
371 break;
338 default:372 default:
339 break;373 break;
340 }374 }
@@ -412,6 +446,21 @@ aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) · 71 unmodified lines
412 obuf->data[0] = pitch;446 obuf->data[0] = pitch;
413}447}
414 448
449void
450aubio_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
415void464void
416aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)465aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
417{466{
src/pitch/pitch.h+7−0
@@ -81,6 +81,11 @@ extern "C" { · 80 unmodified lines
81 81
82 see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html82 see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
83 83
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
84 \b \p yinfft : Yinfft algorithm89 \b \p yinfft : Yinfft algorithm
85 90
86 This algorithm was derived from the YIN algorithm. In this implementation, a91 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
150 \param o pitch detection object as returned by new_aubio_pitch()155 \param o pitch detection object as returned by new_aubio_pitch()
151 \param mode set pitch units for output156 \param mode set pitch units for output
152 157
158 mode can be one of "Hz", "midi", "cent", or "bin". Defaults to "Hz".
159
153 \return 0 if successfull, non-zero otherwise160 \return 0 if successfull, non-zero otherwise
154 161
155*/162*/
src/pitch/pitchfcomb.c+6−1
@@ -53,12 +53,17 @@ new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize) · 52 unmodified lines
53 aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t);53 aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t);
54 p->fftSize = bufsize;54 p->fftSize = bufsize;
55 p->stepSize = hopsize;55 p->stepSize = hopsize;
56 p->fft = new_aubio_fft (bufsize);
57 if (!p->fft) goto beach;
56 p->winput = new_fvec (bufsize);58 p->winput = new_fvec (bufsize);
57 p->fftOut = new_cvec (bufsize);59 p->fftOut = new_cvec (bufsize);
58 p->fftLastPhase = new_fvec (bufsize);60 p->fftLastPhase = new_fvec (bufsize);
59 p->fft = new_aubio_fft (bufsize);
60 p->win = new_aubio_window ("hanning", bufsize);61 p->win = new_aubio_window ("hanning", bufsize);
61 return p;62 return p;
63
64beach:
65 AUBIO_FREE(p);
66 return NULL;
62}67}
63 68
64/* input must be stepsize long */69/* 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
37/* not used but useful : sort by amplitudes (or anything else)37/* not used but useful : sort by amplitudes (or anything else)
38 * sort_pitchpeak(peaks, length);38 * sort_pitchpeak(peaks, length);
39 */39 */
40#if 0
40/** spectral_peak comparison function (must return signed int) */41/** spectral_peak comparison function (must return signed int) */
41static sint_t aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y);42static sint_t aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y);
42/** sort spectral_peak against their mag */43/** 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
44/** select the best candidates */45/** select the best candidates */
45uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain,46uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain,
46 smpl_t * cands);47 smpl_t * cands);
48#endif
47 49
48/** sort spectral_candidate against their comb ene */50/** sort spectral_candidate against their comb ene */
49void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates,51void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates,
50 uint_t nbins);52 uint_t nbins);
53#if 0
51/** sort spectral_candidate against their frequency */54/** sort spectral_candidate against their frequency */
52void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,55void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
53 uint_t nbins);56 uint_t nbins);
57#endif
54 58
55struct _aubio_pitchmcomb_t59struct _aubio_pitchmcomb_t
56{60{
@@ -133,6 +137,7 @@ aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, fvec_t * o · 76 unmodified lines
133 } */137 } */
134}138}
135 139
140#if 0
136uint_t141uint_t
137aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands)142aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands)
138{143{
@@ -163,6 +168,7 @@ aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * can · 24 unmodified lines
163 return 0;168 return 0;
164 }169 }
165}170}
171#endif
166 172
167void173void
168aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag)174aubio_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
313 return pos;319 return pos;
314}320}
315 321
322#if 0
316void323void
317aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins)324aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins)
318{325{
@@ -342,7 +349,6 @@ aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates, · 23 unmodified lines
342 }349 }
343}350}
344 351
345
346void352void
347aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,353aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
348 uint_t nbins)354 uint_t nbins)
@@ -356,6 +362,7 @@ aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates, · 7 unmodified lines
356 }362 }
357 }363 }
358}364}
365#endif
359 366
360aubio_pitchmcomb_t *367aubio_pitchmcomb_t *
361new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize)368new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize)
src/pitch/pitchspecacf.c+6−1
@@ -42,15 +42,20 @@ aubio_pitchspecacf_t * · 41 unmodified lines
42new_aubio_pitchspecacf (uint_t bufsize)42new_aubio_pitchspecacf (uint_t bufsize)
43{43{
44 aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t);44 aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t);
45 p->fft = new_aubio_fft (bufsize);
46 if (!p->fft) goto beach;
45 p->win = new_aubio_window ("hanningz", bufsize);47 p->win = new_aubio_window ("hanningz", bufsize);
46 p->winput = new_fvec (bufsize);48 p->winput = new_fvec (bufsize);
47 p->fft = new_aubio_fft (bufsize);
48 p->fftout = new_fvec (bufsize);49 p->fftout = new_fvec (bufsize);
49 p->sqrmag = new_fvec (bufsize);50 p->sqrmag = new_fvec (bufsize);
50 p->acf = new_fvec (bufsize / 2 + 1);51 p->acf = new_fvec (bufsize / 2 + 1);
51 p->tol = 1.;52 p->tol = 1.;
52 p->confidence = 0.;53 p->confidence = 0.;
53 return p;54 return p;
55
56beach:
57 AUBIO_FREE(p);
58 return NULL;
54}59}
55 60
56void61void
src/pitch/pitchyin.c+29−22
@@ -36,9 +36,10 @@ struct _aubio_pitchyin_t · 35 unmodified lines
36{36{
37 fvec_t *yin;37 fvec_t *yin;
38 smpl_t tol;38 smpl_t tol;
39 smpl_t confidence;39 uint_t peak_pos;
40};40};
41 41
42#if 0
42/** compute difference function43/** compute difference function
43 44
44 \param input input signal45 \param input input signal
@@ -60,6 +61,7 @@ void aubio_pitchyin_getcum (fvec_t * yinbuf); · 15 unmodified lines
60 61
61*/62*/
62uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf);63uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf);
64#endif
63 65
64aubio_pitchyin_t *66aubio_pitchyin_t *
65new_aubio_pitchyin (uint_t bufsize)67new_aubio_pitchyin (uint_t bufsize)
@@ -67,6 +69,7 @@ new_aubio_pitchyin (uint_t bufsize) · 1 unmodified line
67 aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t);69 aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t);
68 o->yin = new_fvec (bufsize / 2);70 o->yin = new_fvec (bufsize / 2);
69 o->tol = 0.15;71 o->tol = 0.15;
72 o->peak_pos = 0;
70 return o;73 return o;
71}74}
72 75
@@ -77,6 +80,7 @@ del_aubio_pitchyin (aubio_pitchyin_t * o) · 4 unmodified lines
77 AUBIO_FREE (o);80 AUBIO_FREE (o);
78}81}
79 82
83#if 0
80/* outputs the difference function */84/* outputs the difference function */
81void85void
82aubio_pitchyin_diff (fvec_t * input, fvec_t * yin)86aubio_pitchyin_diff (fvec_t * input, fvec_t * yin)
@@ -126,46 +130,49 @@ aubio_pitchyin_getpitch (const fvec_t * yin) · 43 unmodified lines
126 //AUBIO_DBG("No pitch found");130 //AUBIO_DBG("No pitch found");
127 return 0;131 return 0;
128}132}
129 133#endif
130 134
131/* all the above in one */135/* all the above in one */
132void136void
133aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out)137aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out)
134{138{
135 smpl_t tol = o->tol;139 const smpl_t tol = o->tol;
136 fvec_t *yin = o->yin;140 fvec_t* yin = o->yin;
137 uint_t j, tau = 0;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;
138 sint_t period;145 sint_t period;
139 smpl_t tmp = 0., tmp2 = 0.;146 smpl_t tmp, tmp2 = 0.;
140 yin->data[0] = 1.;147
141 for (tau = 1; tau < yin->length; tau++) {148 yin_data[0] = 1.;
142 yin->data[tau] = 0.;149 for (tau = 1; tau < length; tau++) {
143 for (j = 0; j < yin->length; j++) {150 yin_data[tau] = 0.;
144 tmp = input->data[j] - input->data[j + tau];151 for (j = 0; j < length; j++) {
145 yin->data[tau] += SQR (tmp);152 tmp = input_data[j] - input_data[j + tau];
153 yin_data[tau] += SQR (tmp);
146 }154 }
147 tmp2 += yin->data[tau];155 tmp2 += yin_data[tau];
148 if (tmp2 != 0) {156 if (tmp2 != 0) {
149 yin->data[tau] *= tau / tmp2;157 yin->data[tau] *= tau / tmp2;
150 } else {158 } else {
151 yin->data[tau] = 1.;159 yin->data[tau] = 1.;
152 }160 }
153 period = tau - 3;161 period = tau - 3;
154 if (tau > 4 && (yin->data[period] < tol) &&162 if (tau > 4 && (yin_data[period] < tol) &&
155 (yin->data[period] < yin->data[period + 1])) {163 (yin_data[period] < yin_data[period + 1])) {
156 out->data[0] = fvec_quadratic_peak_pos (yin, period);164 o->peak_pos = (uint_t)period;
157 goto beach;165 out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
166 return;
158 }167 }
159 }168 }
160 out->data[0] = fvec_quadratic_peak_pos (yin, fvec_min_elem (yin));169 o->peak_pos = (uint_t)fvec_min_elem (yin);
161beach:170 out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
162 return;
163}171}
164 172
165smpl_t173smpl_t
166aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) {174aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) {
167 o->confidence = 1. - fvec_min (o->yin);175 return 1. - o->yin->data[o->peak_pos];
168 return o->confidence;
169}176}
170 177
171uint_t178uint_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
37struct _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
50aubio_pitchyinfast_t *
51new_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
72void
73del_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 */
93void
94aubio_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
185smpl_t
186aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o) {
187 return 1. - o->yin->data[o->peak_pos];
188}
189
190uint_t
191aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol)
192{
193 o->tol = tol;
194 return 0;
195}
196
197smpl_t
198aubio_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
43extern "C" {
44#endif
45
46/** pitch detection object */
47typedef 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*/
54aubio_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*/
61void 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*/
70void 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*/
79uint_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*/
87smpl_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*/
95smpl_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
36 aubio_fft_t *fft; /**< fft object to compute square difference function */36 aubio_fft_t *fft; /**< fft object to compute square difference function */
37 fvec_t *yinfft; /**< Yin function */37 fvec_t *yinfft; /**< Yin function */
38 smpl_t tol; /**< Yin tolerance */38 smpl_t tol; /**< Yin tolerance */
39 smpl_t confidence; /**< confidence */39 uint_t peak_pos; /**< currently selected peak pos*/
40 uint_t short_period; /** shortest period under which to check for octave error */40 uint_t short_period; /** shortest period under which to check for octave error */
41};41};
42 42
@@ -44,7 +44,7 @@ static const smpl_t freqs[] = { · 1 unmodified line
44 0., 20., 25., 31.5, 40., 50., 63., 80., 100., 125.,44 0., 20., 25., 31.5, 40., 50., 63., 80., 100., 125.,
45 160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250.,45 160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250.,
46 1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000.,46 1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000.,
47 12500., 15000., 20000., 2510047 12500., 15000., 20000., 25100., -1.
48};48};
49 49
50static const smpl_t weight[] = {50static const smpl_t weight[] = {
@@ -62,15 +62,20 @@ new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize) · 11 unmodified lines
62 aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t);62 aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t);
63 p->winput = new_fvec (bufsize);63 p->winput = new_fvec (bufsize);
64 p->fft = new_aubio_fft (bufsize);64 p->fft = new_aubio_fft (bufsize);
65 if (!p->fft) goto beach;
65 p->fftout = new_fvec (bufsize);66 p->fftout = new_fvec (bufsize);
66 p->sqrmag = new_fvec (bufsize);67 p->sqrmag = new_fvec (bufsize);
67 p->yinfft = new_fvec (bufsize / 2 + 1);68 p->yinfft = new_fvec (bufsize / 2 + 1);
68 p->tol = 0.85;69 p->tol = 0.85;
70 p->peak_pos = 0;
69 p->win = new_aubio_window ("hanningz", bufsize);71 p->win = new_aubio_window ("hanningz", bufsize);
70 p->weight = new_fvec (bufsize / 2 + 1);72 p->weight = new_fvec (bufsize / 2 + 1);
71 for (i = 0; i < p->weight->length; i++) {73 for (i = 0; i < p->weight->length; i++) {
72 freq = (smpl_t) i / (smpl_t) bufsize *(smpl_t) samplerate;74 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);
74 j += 1;79 j += 1;
75 }80 }
76 a0 = weight[j - 1];81 a0 = weight[j - 1];
@@ -95,6 +100,11 @@ new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize) · 18 unmodified lines
95 // check for octave errors above 1300 Hz100 // check for octave errors above 1300 Hz
96 p->short_period = (uint_t)ROUND(samplerate / 1300.);101 p->short_period = (uint_t)ROUND(samplerate / 1300.);
97 return p;102 return p;
103
104beach:
105 if (p->winput) del_fvec(p->winput);
106 AUBIO_FREE(p);
107 return NULL;
98}108}
99 109
100void110void
@@ -155,11 +165,13 @@ aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, const fvec_t * input, fvec_t * ou · 54 unmodified lines
155 /* should compare the minimum value of each interpolated peaks */165 /* should compare the minimum value of each interpolated peaks */
156 halfperiod = FLOOR (tau / 2 + .5);166 halfperiod = FLOOR (tau / 2 + .5);
157 if (yin->data[halfperiod] < p->tol)167 if (yin->data[halfperiod] < p->tol)
158 output->data[0] = fvec_quadratic_peak_pos (yin, halfperiod);168 p->peak_pos = halfperiod;
159 else169 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);
161 }172 }
162 } else {173 } else {
174 p->peak_pos = 0;
163 output->data[0] = 0.;175 output->data[0] = 0.;
164 }176 }
165}177}
@@ -179,8 +191,7 @@ del_aubio_pitchyinfft (aubio_pitchyinfft_t * p) · 13 unmodified lines
179 191
180smpl_t192smpl_t
181aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) {193aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) {
182 o->confidence = 1. - fvec_min (o->yinfft);194 return 1. - o->yinfft->data[o->peak_pos];
183 return o->confidence;
184}195}
185 196
186uint_t197uint_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 */
32struct _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
42void
43aubio_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
53aubio_spectral_whitening_t *
54new_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
76beach:
77 AUBIO_FREE(o);
78 return NULL;
79}
80
81uint_t
82aubio_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
90smpl_t
91aubio_spectral_whitening_get_relax_time (aubio_spectral_whitening_t * o)
92{
93 return o->relax_time;
94}
95
96uint_t
97aubio_spectral_whitening_set_floor (aubio_spectral_whitening_t *o, smpl_t floor)
98{
99 o->floor = floor;
100 return AUBIO_OK;
101}
102
103smpl_t aubio_spectral_whitening_get_floor (aubio_spectral_whitening_t *o)
104{
105 return o->floor;
106}
107
108void
109aubio_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
115void
116del_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
47extern "C" {
48#endif
49
50/** spectral whitening structure */
51typedef 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*/
59void 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*/
69aubio_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 */
78void 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 */
86uint_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*/
95smpl_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 */
103uint_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*/
112smpl_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*/
119void 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
38typedef void (*aubio_dct_do_t)(aubio_dct_t * s, const fvec_t * input, fvec_t * output);
39typedef void (*aubio_dct_rdo_t)(aubio_dct_t * s, const fvec_t * input, fvec_t * output);
40typedef void (*del_aubio_dct_t)(aubio_dct_t * s);
41
42#if defined(HAVE_ACCELERATE)
43typedef struct _aubio_dct_accelerate_t aubio_dct_accelerate_t;
44extern aubio_dct_accelerate_t * new_aubio_dct_accelerate (uint_t size);
45extern void aubio_dct_accelerate_do(aubio_dct_accelerate_t *s, const fvec_t *input, fvec_t *output);
46extern void aubio_dct_accelerate_rdo(aubio_dct_accelerate_t *s, const fvec_t *input, fvec_t *output);
47extern void del_aubio_dct_accelerate (aubio_dct_accelerate_t *s);
48#elif defined(HAVE_FFTW3)
49typedef struct _aubio_dct_fftw_t aubio_dct_fftw_t;
50extern aubio_dct_fftw_t * new_aubio_dct_fftw (uint_t size);
51extern void aubio_dct_fftw_do(aubio_dct_fftw_t *s, const fvec_t *input, fvec_t *output);
52extern void aubio_dct_fftw_rdo(aubio_dct_fftw_t *s, const fvec_t *input, fvec_t *output);
53extern void del_aubio_dct_fftw (aubio_dct_fftw_t *s);
54#elif defined(HAVE_INTEL_IPP)
55typedef struct _aubio_dct_ipp_t aubio_dct_ipp_t;
56extern aubio_dct_ipp_t * new_aubio_dct_ipp (uint_t size);
57extern void aubio_dct_ipp_do(aubio_dct_ipp_t *s, const fvec_t *input, fvec_t *output);
58extern void aubio_dct_ipp_rdo(aubio_dct_ipp_t *s, const fvec_t *input, fvec_t *output);
59extern void del_aubio_dct_ipp (aubio_dct_ipp_t *s);
60#else
61typedef struct _aubio_dct_ooura_t aubio_dct_ooura_t;
62extern aubio_dct_ooura_t * new_aubio_dct_ooura (uint_t size);
63extern void aubio_dct_ooura_do(aubio_dct_ooura_t *s, const fvec_t *input, fvec_t *output);
64extern void aubio_dct_ooura_rdo(aubio_dct_ooura_t *s, const fvec_t *input, fvec_t *output);
65extern void del_aubio_dct_ooura (aubio_dct_ooura_t *s);
66#endif
67
68// plain mode
69typedef struct _aubio_dct_plain_t aubio_dct_plain_t;
70extern aubio_dct_plain_t * new_aubio_dct_plain (uint_t size);
71extern void aubio_dct_plain_do(aubio_dct_plain_t *s, const fvec_t *input, fvec_t *output);
72extern void aubio_dct_plain_rdo(aubio_dct_plain_t *s, const fvec_t *input, fvec_t *output);
73extern void del_aubio_dct_plain (aubio_dct_plain_t *s);
74
75struct _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
82aubio_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);
147plain:
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 }
157beach:
158 AUBIO_ERROR("dct: failed creating with size %d, should be > 0\n", size);
159 del_aubio_dct(s);
160 return NULL;
161}
162
163void 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
168void 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
172void 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
37extern "C" {
38#endif
39
40/** DCT object
41
42 This object computes forward and backward DCT type 2 with orthonormal
43 scaling.
44
45*/
46typedef struct _aubio_dct_t aubio_dct_t;
47
48/** create new DCT computation object
49
50 \param size length of the DCT
51
52*/
53aubio_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*/
62void 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*/
71void 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*/
79void 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
31struct _aubio_dct_accelerate_t {
32 uint_t size;
33 fvec_t *tmp;
34 vDSP_DFT_Setup setup;
35 vDSP_DFT_Setup setupInv;
36};
37
38typedef struct _aubio_dct_accelerate_t aubio_dct_accelerate_t;
39
40void del_aubio_dct_accelerate (aubio_dct_accelerate_t *s);
41
42aubio_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
61beach:
62 del_aubio_dct_accelerate(s);
63 return NULL;
64}
65
66void 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
72void 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
85void 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
52extern pthread_mutex_t aubio_fftw_mutex;
53
54typedef struct _aubio_dct_fftw_t aubio_dct_fftw_t;
55
56struct _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
64aubio_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;
87beach:
88 AUBIO_FREE(s);
89 return NULL;
90}
91
92void 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
103void 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
115void 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
49typedef struct _aubio_dct_ipp_t aubio_dct_ipp_t;
50
51struct _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
61void del_aubio_dct_ipp (aubio_dct_ipp_t *s);
62
63aubio_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
123beach:
124 del_aubio_dct_ipp(s);
125 return NULL;
126}
127
128void 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
136void 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
143void 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
27typedef struct _aubio_dct_ooura_t aubio_dct_ooura_t;
28
29extern void aubio_ooura_ddct(int, int, smpl_t *, int *, smpl_t *);
30
31struct _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
39aubio_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;
57beach:
58 AUBIO_FREE(s);
59 return NULL;
60}
61
62void 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
69void 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
81void 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
26typedef struct _aubio_dct_plain_t aubio_dct_plain_t;
27
28struct _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
34void del_aubio_dct_plain (aubio_dct_plain_t *s);
35
36aubio_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;
78failure:
79 del_aubio_dct_plain(s);
80 return NULL;
81}
82
83void 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
91void 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
99void 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
77// a global mutex for FFTW thread safety77// a global mutex for FFTW thread safety
78pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER;78pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER;
79 79
80#else80#elif defined HAVE_ACCELERATE // using ACCELERATE
81#ifdef HAVE_ACCELERATE // using ACCELERATE
82// https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html81// https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html
83#include <Accelerate/Accelerate.h>82#include <Accelerate/Accelerate.h>
84 83
@@ -90,11 +89,12 @@ pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER; · 5 unmodified lines
90#define aubio_vDSP_zvphas vDSP_zvphas89#define aubio_vDSP_zvphas vDSP_zvphas
91#define aubio_vDSP_vsadd vDSP_vsadd90#define aubio_vDSP_vsadd vDSP_vsadd
92#define aubio_vDSP_vsmul vDSP_vsmul91#define aubio_vDSP_vsmul vDSP_vsmul
93#define aubio_vDSP_create_fftsetup vDSP_create_fftsetup
94#define aubio_vDSP_destroy_fftsetup vDSP_destroy_fftsetup
95#define aubio_DSPComplex DSPComplex92#define aubio_DSPComplex DSPComplex
96#define aubio_DSPSplitComplex DSPSplitComplex93#define aubio_DSPSplitComplex DSPSplitComplex
97#define aubio_FFTSetup FFTSetup94#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
98#define aubio_vvsqrt vvsqrtf98#define aubio_vvsqrt vvsqrtf
99#else99#else
100#define aubio_vDSP_ctoz vDSP_ctozD100#define aubio_vDSP_ctoz vDSP_ctozD
@@ -104,40 +104,74 @@ pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER; · 3 unmodified lines
104#define aubio_vDSP_zvphas vDSP_zvphasD104#define aubio_vDSP_zvphas vDSP_zvphasD
105#define aubio_vDSP_vsadd vDSP_vsaddD105#define aubio_vDSP_vsadd vDSP_vsaddD
106#define aubio_vDSP_vsmul vDSP_vsmulD106#define aubio_vDSP_vsmul vDSP_vsmulD
107#define aubio_vDSP_create_fftsetup vDSP_create_fftsetupD
108#define aubio_vDSP_destroy_fftsetup vDSP_destroy_fftsetupD
109#define aubio_DSPComplex DSPDoubleComplex107#define aubio_DSPComplex DSPDoubleComplex
110#define aubio_DSPSplitComplex DSPDoubleSplitComplex108#define aubio_DSPSplitComplex DSPDoubleSplitComplex
111#define aubio_FFTSetup FFTSetupD109#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
112#define aubio_vvsqrt vvsqrt113#define aubio_vvsqrt vvsqrt
113#endif /* HAVE_AUBIO_DOUBLE */114#endif /* HAVE_AUBIO_DOUBLE */
114 115
115#else // using OOURA116#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
116// let's use ooura instead142// let's use ooura instead
117extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *);143extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *);
118 144
119#endif /* HAVE_ACCELERATE */145#endif
120#endif /* HAVE_FFTW3 */
121 146
122struct _aubio_fft_t {147struct _aubio_fft_t {
123 uint_t winsize;148 uint_t winsize;
124 uint_t fft_size;149 uint_t fft_size;
150
125#ifdef HAVE_FFTW3 // using FFTW3151#ifdef HAVE_FFTW3 // using FFTW3
126 real_t *in, *out;152 real_t *in, *out;
127 fftw_plan pfw, pbw;153 fftw_plan pfw, pbw;
128 fft_data_t * specdata; /* complex spectral data */154 fft_data_t * specdata; /* complex spectral data */
129#else155
130#ifdef HAVE_ACCELERATE // using ACCELERATE156#elif defined HAVE_ACCELERATE // using ACCELERATE
131 int log2fftsize;157 aubio_vDSP_DFT_Setup fftSetupFwd;
132 aubio_FFTSetup fftSetup;158 aubio_vDSP_DFT_Setup fftSetupBwd;
133 aubio_DSPSplitComplex spec;159 aubio_DSPSplitComplex spec;
134 smpl_t *in, *out;160 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;
135#else // using OOURA169#else // using OOURA
136 smpl_t *in, *out;170 smpl_t *in, *out;
137 smpl_t *w;171 smpl_t *w;
138 int *ip;172 int *ip;
139#endif /* HAVE_ACCELERATE */173#endif /* using OOURA */
140#endif /* HAVE_FFTW3 */174
141 fvec_t * compspec;175 fvec_t * compspec;
142};176};
143 177
@@ -147,6 +181,7 @@ aubio_fft_t * new_aubio_fft (uint_t winsize) { · 3 unmodified lines
147 AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize);181 AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize);
148 goto beach;182 goto beach;
149 }183 }
184
150#ifdef HAVE_FFTW3185#ifdef HAVE_FFTW3
151 uint_t i;186 uint_t i;
152 s->winsize = winsize;187 s->winsize = winsize;
@@ -175,17 +210,72 @@ aubio_fft_t * new_aubio_fft (uint_t winsize) { · 22 unmodified lines
175 for (i = 0; i < s->fft_size; i++) {210 for (i = 0; i < s->fft_size; i++) {
176 s->specdata[i] = 0.;211 s->specdata[i] = 0.;
177 }212 }
178#else213
179#ifdef HAVE_ACCELERATE // using ACCELERATE214#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 }
180 s->winsize = winsize;230 s->winsize = winsize;
181 s->fft_size = winsize;231 s->fft_size = winsize;
182 s->compspec = new_fvec(winsize);232 s->compspec = new_fvec(winsize);
183 s->log2fftsize = (uint_t)log2f(s->fft_size);
184 s->in = AUBIO_ARRAY(smpl_t, s->fft_size);233 s->in = AUBIO_ARRAY(smpl_t, s->fft_size);
185 s->out = AUBIO_ARRAY(smpl_t, s->fft_size);234 s->out = AUBIO_ARRAY(smpl_t, s->fft_size);
186 s->spec.realp = AUBIO_ARRAY(smpl_t, s->fft_size/2);235 s->spec.realp = AUBIO_ARRAY(smpl_t, s->fft_size/2);
187 s->spec.imagp = AUBIO_ARRAY(smpl_t, s->fft_size/2);236 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
189#else // using OOURA279#else // using OOURA
190 if (aubio_is_power_of_two(winsize) != 1) {280 if (aubio_is_power_of_two(winsize) != 1) {
191 AUBIO_ERR("fft: can only create with sizes power of two, requested %d,"281 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
200 s->ip = AUBIO_ARRAY(int , s->fft_size);290 s->ip = AUBIO_ARRAY(int , s->fft_size);
201 s->w = AUBIO_ARRAY(smpl_t, s->fft_size);291 s->w = AUBIO_ARRAY(smpl_t, s->fft_size);
202 s->ip[0] = 0;292 s->ip[0] = 0;
203#endif /* HAVE_ACCELERATE */293#endif /* using OOURA */
204#endif /* HAVE_FFTW3 */294
205 return s;295 return s;
296
206beach:297beach:
207 AUBIO_FREE(s);298 AUBIO_FREE(s);
208 return NULL;299 return NULL;
@@ -210,25 +301,33 @@ beach: · 1 unmodified line
210 301
211void del_aubio_fft(aubio_fft_t * s) {302void del_aubio_fft(aubio_fft_t * s) {
212 /* destroy data */303 /* destroy data */
213 del_fvec(s->compspec);
214#ifdef HAVE_FFTW3 // using FFTW3304#ifdef HAVE_FFTW3 // using FFTW3
215 pthread_mutex_lock(&aubio_fftw_mutex);305 pthread_mutex_lock(&aubio_fftw_mutex);
216 fftw_destroy_plan(s->pfw);306 fftw_destroy_plan(s->pfw);
217 fftw_destroy_plan(s->pbw);307 fftw_destroy_plan(s->pbw);
218 fftw_free(s->specdata);308 fftw_free(s->specdata);
219 pthread_mutex_unlock(&aubio_fftw_mutex);309 pthread_mutex_unlock(&aubio_fftw_mutex);
220#else /* HAVE_FFTW3 */310
221#ifdef HAVE_ACCELERATE // using ACCELERATE311#elif defined HAVE_ACCELERATE // using ACCELERATE
222 AUBIO_FREE(s->spec.realp);312 AUBIO_FREE(s->spec.realp);
223 AUBIO_FREE(s->spec.imagp);313 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
225#else // using OOURA323#else // using OOURA
226 AUBIO_FREE(s->w);324 AUBIO_FREE(s->w);
227 AUBIO_FREE(s->ip);325 AUBIO_FREE(s->ip);
228#endif /* HAVE_ACCELERATE */326#endif
229#endif /* HAVE_FFTW3 */327
230 AUBIO_FREE(s->out);328 del_fvec(s->compspec);
231 AUBIO_FREE(s->in);329 AUBIO_FREE(s->in);
330 AUBIO_FREE(s->out);
232 AUBIO_FREE(s);331 AUBIO_FREE(s);
233}332}
234 333
@@ -251,6 +350,7 @@ void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compsp · 16 unmodified lines
251#else350#else
252 memcpy(s->in, input->data, s->winsize * sizeof(smpl_t));351 memcpy(s->in, input->data, s->winsize * sizeof(smpl_t));
253#endif /* HAVE_MEMCPY_HACKS */352#endif /* HAVE_MEMCPY_HACKS */
353
254#ifdef HAVE_FFTW3 // using FFTW3354#ifdef HAVE_FFTW3 // using FFTW3
255 fftw_execute(s->pfw);355 fftw_execute(s->pfw);
256#ifdef HAVE_COMPLEX_H356#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
265 compspec->data[i] = s->specdata[i];365 compspec->data[i] = s->specdata[i];
266 }366 }
267#endif /* HAVE_COMPLEX_H */367#endif /* HAVE_COMPLEX_H */
268#else /* HAVE_FFTW3 */368
269#ifdef HAVE_ACCELERATE // using ACCELERATE369#elif defined HAVE_ACCELERATE // using ACCELERATE
270 // convert real data to even/odd format used in vDSP370 // convert real data to even/odd format used in vDSP
271 aubio_vDSP_ctoz((aubio_DSPComplex*)s->in, 2, &s->spec, 1, s->fft_size/2);371 aubio_vDSP_ctoz((aubio_DSPComplex*)s->in, 2, &s->spec, 1, s->fft_size/2);
272 // compute the FFT372 // 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);
274 // convert from vDSP complex split to [ r0, r1, ..., rN, iN-1, .., i2, i1]375 // convert from vDSP complex split to [ r0, r1, ..., rN, iN-1, .., i2, i1]
275 compspec->data[0] = s->spec.realp[0];376 compspec->data[0] = s->spec.realp[0];
276 compspec->data[s->fft_size / 2] = s->spec.imagp[0];377 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
281 // apply scaling382 // apply scaling
282 smpl_t scale = 1./2.;383 smpl_t scale = 1./2.;
283 aubio_vDSP_vsmul(compspec->data, 1, &scale, compspec->data, 1, s->fft_size);384 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
284#else // using OOURA398#else // using OOURA
285 aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w);399 aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w);
286 compspec->data[0] = s->in[0];400 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
289 compspec->data[i] = s->in[2 * i];403 compspec->data[i] = s->in[2 * i];
290 compspec->data[s->winsize - i] = - s->in[2 * i + 1];404 compspec->data[s->winsize - i] = - s->in[2 * i + 1];
291 }405 }
292#endif /* HAVE_ACCELERATE */406#endif /* using OOURA */
293#endif /* HAVE_FFTW3 */
294}407}
295 408
296void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * output) {409void 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
313 for (i = 0; i < output->length; i++) {426 for (i = 0; i < output->length; i++) {
314 output->data[i] = s->out[i]*renorm;427 output->data[i] = s->out[i]*renorm;
315 }428 }
316#else /* HAVE_FFTW3 */429
317#ifdef HAVE_ACCELERATE // using ACCELERATE430#elif defined HAVE_ACCELERATE // using ACCELERATE
318 // convert from real imag [ r0, r1, ..., rN, iN-1, .., i2, i1]431 // convert from real imag [ r0, r1, ..., rN, iN-1, .., i2, i1]
319 // to vDSP packed format [ r0, rN, r1, i1, ..., rN-1, iN-1 ]432 // to vDSP packed format [ r0, rN, r1, i1, ..., rN-1, iN-1 ]
320 s->out[0] = compspec->data[0];433 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
326 // convert to split complex format used in vDSP439 // convert to split complex format used in vDSP
327 aubio_vDSP_ctoz((aubio_DSPComplex*)s->out, 2, &s->spec, 1, s->fft_size/2);440 aubio_vDSP_ctoz((aubio_DSPComplex*)s->out, 2, &s->spec, 1, s->fft_size/2);
328 // compute the FFT441 // 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);
330 // convert result to real output444 // convert result to real output
331 aubio_vDSP_ztoc(&s->spec, 1, (aubio_DSPComplex*)output->data, 2, s->fft_size/2);445 aubio_vDSP_ztoc(&s->spec, 1, (aubio_DSPComplex*)output->data, 2, s->fft_size/2);
332 // apply scaling446 // apply scaling
333 smpl_t scale = 1.0 / s->winsize;447 smpl_t scale = 1.0 / s->winsize;
334 aubio_vDSP_vsmul(output->data, 1, &scale, output->data, 1, s->fft_size);448 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
335#else // using OOURA466#else // using OOURA
336 smpl_t scale = 2.0 / s->winsize;467 smpl_t scale = 2.0 / s->winsize;
337 s->out[0] = compspec->data[0];468 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
344 for (i=0; i < s->winsize; i++) {475 for (i=0; i < s->winsize; i++) {
345 output->data[i] = s->out[i] * scale;476 output->data[i] = s->out[i] * scale;
346 }477 }
347#endif /* HAVE_ACCELERATE */478#endif
348#endif /* HAVE_FFTW3 */
349}479}
350 480
351void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum) {481void 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
365 } else {495 } else {
366 spectrum->phas[0] = 0.;496 spectrum->phas[0] = 0.;
367 }497 }
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
368 for (i=1; i < spectrum->length - 1; i++) {513 for (i=1; i < spectrum->length - 1; i++) {
369 spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i],514 spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i],
370 compspec->data[i]);515 compspec->data[i]);
371 }516 }
372 if (compspec->data[compspec->length/2] < 0) {517#endif
373 spectrum->phas[spectrum->length - 1] = PI;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
374 } else {528 } 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]);
376 }532 }
533#endif
377}534}
378 535
379void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum) {536void 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
383 spectrum->norm[i] = SQRT(SQR(compspec->data[i])540 spectrum->norm[i] = SQRT(SQR(compspec->data[i])
384 + SQR(compspec->data[compspec->length - i]) );541 + SQR(compspec->data[compspec->length - i]) );
385 }542 }
386 spectrum->norm[spectrum->length-1] =543#ifdef HAVE_FFTW3
387 ABS(compspec->data[compspec->length/2]);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
388}556}
389 557
390void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec) {558void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec) {
src/spectral/filterbank.c+48−0
@@ -23,6 +23,7 @@ · 22 unmodified lines
23#include "fvec.h"23#include "fvec.h"
24#include "fmat.h"24#include "fmat.h"
25#include "cvec.h"25#include "cvec.h"
26#include "vecutils.h"
26#include "spectral/filterbank.h"27#include "spectral/filterbank.h"
27#include "mathutils.h"28#include "mathutils.h"
28 29
@@ -32,6 +33,8 @@ struct _aubio_filterbank_t · 3 unmodified lines
32 uint_t win_s;33 uint_t win_s;
33 uint_t n_filters;34 uint_t n_filters;
34 fmat_t *filters;35 fmat_t *filters;
36 smpl_t norm;
37 smpl_t power;
35};38};
36 39
37aubio_filterbank_t *40aubio_filterbank_t *
@@ -39,13 +42,29 @@ new_aubio_filterbank (uint_t n_filters, uint_t win_s) · 1 unmodified line
39{42{
40 /* allocate space for filterbank object */43 /* allocate space for filterbank object */
41 aubio_filterbank_t *fb = AUBIO_NEW (aubio_filterbank_t);44 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 }
42 fb->win_s = win_s;54 fb->win_s = win_s;
43 fb->n_filters = n_filters;55 fb->n_filters = n_filters;
44 56
45 /* allocate filter tables, a matrix of length win_s and of height n_filters */57 /* allocate filter tables, a matrix of length win_s and of height n_filters */
46 fb->filters = new_fmat (n_filters, win_s / 2 + 1);58 fb->filters = new_fmat (n_filters, win_s / 2 + 1);
47 59
60 fb->norm = 1;
61
62 fb->power = 1;
63
48 return fb;64 return fb;
65fail:
66 AUBIO_FREE (fb);
67 return NULL;
49}68}
50 69
51void70void
@@ -67,6 +86,8 @@ aubio_filterbank_do (aubio_filterbank_t * f, const cvec_t * in, fvec_t * out) · 15 unmodified lines
67 tmp.length = in->length;86 tmp.length = in->length;
68 tmp.data = in->norm;87 tmp.data = in->norm;
69 88
89 if (f->power != 1.) fvec_pow(&tmp, f->power);
90
70 fmat_vecmul(f->filters, &tmp, out);91 fmat_vecmul(f->filters, &tmp, out);
71 92
72 return;93 return;
@@ -84,3 +105,30 @@ aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filter_coeff · 11 unmodified lines
84 fmat_copy(filter_coeffs, f->filters);105 fmat_copy(filter_coeffs, f->filters);
85 return 0;106 return 0;
86}107}
108
109uint_t
110aubio_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
117smpl_t
118aubio_filterbank_get_norm (aubio_filterbank_t *f)
119{
120 return f->norm;
121}
122
123uint_t
124aubio_filterbank_set_power (aubio_filterbank_t *f, smpl_t power)
125{
126 f->power = power;
127 return AUBIO_OK;
128}
129
130smpl_t
131aubio_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
83 */83 */
84uint_t aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filters);84uint_t aubio_filterbank_set_coeffs (aubio_filterbank_t * f, const fmat_t * filters);
85 85
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 */
100uint_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 */
108smpl_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 */
117uint_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 */
125smpl_t aubio_filterbank_get_power (aubio_filterbank_t *f);
126
86#ifdef __cplusplus127#ifdef __cplusplus
87}128}
88#endif129#endif
src/spectral/filterbank_mel.c+126−35
@@ -54,9 +54,21 @@ aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb, · 53 unmodified lines
54 n_filters, freqs->length - 2);54 n_filters, freqs->length - 2);
55 }55 }
56 56
57 if (freqs->data[freqs->length - 1] > samplerate / 2) {57 for (fn = 0; fn < freqs->length; fn++) {
58 AUBIO_WRN ("Nyquist frequency is %fHz, but highest frequency band ends at \58 if (freqs->data[fn] < 0) {
59%fHz\n", samplerate / 2, freqs->data[freqs->length - 1]);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 }
60 }72 }
61 73
62 /* convenience reference to lower/center/upper frequency for each triangle */74 /* 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