Revision 0:635e8745ccc9

View differences:

.hgsub
1
onsetsds = [git]https://github.com/danstowell/onsetsds
2

  
.hgsubstate
1
3b5daceeb8f419e95c72ed767765714177ff275f onsetsds
Makefile
1 1

  
2
CXXFLAGS	:= -I../vamp-plugin-sdk -O3 -Wall -fPIC
3
CFLAGS		:= -O3 -Wall -fPIC
2
CXXFLAGS	:= -I../vamp-plugin-sdk -O3 -Wall
3
#CXXFLAGS	:= -I../vamp-plugin-sdk -g -Wall -march=pentium4 -msse -msse2 -ffast-math
4
#CXXFLAGS	:= -I../vamp-plugin-sdk -O3 -Wall -march=pentium4 -msse -msse2 -fomit-frame-pointer -ffast-math
4 5

  
5
vamp-onsetsds.so:	onsetsdsplugin.o onsetsds/src/onsetsds.o
6
vamp-onsetsds.so:	onsetsdsplugin.o onsetsds/onsetsds.o
6 7
	g++ -shared $^ -o $@ -L../vamp-plugin-sdk/vamp-sdk -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -lpthread
7 8

  
8 9
clean:	
9
	rm -f *.o */src/*.o
10
	rm -f *.o */*.o
10 11

  
11
onsetsdsplugin.o: onsetsdsplugin.h onsetsds/src/onsetsds.h 
12
onsetsds/onsetsds.o: onsetsds/src/onsetsds.h 
12
onsetsdsplugin.o: onsetsdsplugin.h onsetsds/onsetsds.h 
13
onsetsds/onsetsds.o: onsetsds/onsetsds.h 
Makefile.osx
1
PLUGIN_LIBRARY_NAME = onsetsdsplugin
2
VAMP_SDK_DIR = ../vamp-plugin-sdk
3

  
4
PLUGIN_CODE_OBJECTS = onsetsdsplugin.o onsetsds/src/onsetsds.o
5

  
6
ARCHFLAGS = -mmacosx-version-min=10.7 -arch x86_64 -stdlib=libc++
7
CFLAGS = $(ARCHFLAGS) -Wall -fPIC -g -O3
8
CXXFLAGS = $(CFLAGS) -I$(VAMP_SDK_DIR) -I.
9
PLUGIN_EXT = .dylib
10
PLUGIN = $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT)
11
LDFLAGS = $(ARCHFLAGS) -dynamiclib -install_name $(PLUGIN) $(VAMP_SDK_DIR)/libvamp-sdk.a  -framework Accelerate
12

  
13

  
14
$(PLUGIN): $(PLUGIN_CODE_OBJECTS)
15
	$(CXX) -o $@ $^ $(LDFLAGS)
16

  
17
clean:  
18
	rm -f *.o */src/*.o
19

  
20
onsetsdsplugin.o: onsetsdsplugin.h onsetsds/src/onsetsds.h 
21
onsetsds/onsetsds.o: onsetsds/src/onsetsds.h 
README
1
This is a Vamp plugin of the OnsetsDS note onset detection library.
2
See https://github.com/danstowell/onsetsds, http://vamp-plugins.org/,
3
https://code.soundsoftware.ac.uk/projects/vamp-onsetsds-plugin
onsetsds/AUTHORS
1

  
2
Dan Stowell, dan.stowell@elec.qmul.ac.uk
onsetsds/COPYING
1
		    GNU GENERAL PUBLIC LICENSE
2
		       Version 2, June 1991
3

  
4
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
6
 Everyone is permitted to copy and distribute verbatim copies
7
 of this license document, but changing it is not allowed.
8

  
9
			    Preamble
10

  
11
  The licenses for most software are designed to take away your
12
freedom to share and change it.  By contrast, the GNU General Public
13
License is intended to guarantee your freedom to share and change free
14
software--to make sure the software is free for all its users.  This
15
General Public License applies to most of the Free Software
16
Foundation's software and to any other program whose authors commit to
17
using it.  (Some other Free Software Foundation software is covered by
18
the GNU Library General Public License instead.)  You can apply it to
19
your programs, too.
20

  
21
  When we speak of free software, we are referring to freedom, not
22
price.  Our General Public Licenses are designed to make sure that you
23
have the freedom to distribute copies of free software (and charge for
24
this service if you wish), that you receive source code or can get it
25
if you want it, that you can change the software or use pieces of it
26
in new free programs; and that you know you can do these things.
27

  
28
  To protect your rights, we need to make restrictions that forbid
29
anyone to deny you these rights or to ask you to surrender the rights.
30
These restrictions translate to certain responsibilities for you if you
31
distribute copies of the software, or if you modify it.
32

  
33
  For example, if you distribute copies of such a program, whether
34
gratis or for a fee, you must give the recipients all the rights that
35
you have.  You must make sure that they, too, receive or can get the
36
source code.  And you must show them these terms so they know their
37
rights.
38

  
39
  We protect your rights with two steps: (1) copyright the software, and
40
(2) offer you this license which gives you legal permission to copy,
41
distribute and/or modify the software.
42

  
43
  Also, for each author's protection and ours, we want to make certain
44
that everyone understands that there is no warranty for this free
45
software.  If the software is modified by someone else and passed on, we
46
want its recipients to know that what they have is not the original, so
47
that any problems introduced by others will not reflect on the original
48
authors' reputations.
49

  
50
  Finally, any free program is threatened constantly by software
51
patents.  We wish to avoid the danger that redistributors of a free
52
program will individually obtain patent licenses, in effect making the
53
program proprietary.  To prevent this, we have made it clear that any
54
patent must be licensed for everyone's free use or not licensed at all.
55

  
56
  The precise terms and conditions for copying, distribution and
57
modification follow.
58

59
		    GNU GENERAL PUBLIC LICENSE
60
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61

  
62
  0. This License applies to any program or other work which contains
63
a notice placed by the copyright holder saying it may be distributed
64
under the terms of this General Public License.  The "Program", below,
65
refers to any such program or work, and a "work based on the Program"
66
means either the Program or any derivative work under copyright law:
67
that is to say, a work containing the Program or a portion of it,
68
either verbatim or with modifications and/or translated into another
69
language.  (Hereinafter, translation is included without limitation in
70
the term "modification".)  Each licensee is addressed as "you".
71

  
72
Activities other than copying, distribution and modification are not
73
covered by this License; they are outside its scope.  The act of
74
running the Program is not restricted, and the output from the Program
75
is covered only if its contents constitute a work based on the
76
Program (independent of having been made by running the Program).
77
Whether that is true depends on what the Program does.
78

  
79
  1. You may copy and distribute verbatim copies of the Program's
80
source code as you receive it, in any medium, provided that you
81
conspicuously and appropriately publish on each copy an appropriate
82
copyright notice and disclaimer of warranty; keep intact all the
83
notices that refer to this License and to the absence of any warranty;
84
and give any other recipients of the Program a copy of this License
85
along with the Program.
86

  
87
You may charge a fee for the physical act of transferring a copy, and
88
you may at your option offer warranty protection in exchange for a fee.
89

  
90
  2. You may modify your copy or copies of the Program or any portion
91
of it, thus forming a work based on the Program, and copy and
92
distribute such modifications or work under the terms of Section 1
93
above, provided that you also meet all of these conditions:
94

  
95
    a) You must cause the modified files to carry prominent notices
96
    stating that you changed the files and the date of any change.
97

  
98
    b) You must cause any work that you distribute or publish, that in
99
    whole or in part contains or is derived from the Program or any
100
    part thereof, to be licensed as a whole at no charge to all third
101
    parties under the terms of this License.
102

  
103
    c) If the modified program normally reads commands interactively
104
    when run, you must cause it, when started running for such
105
    interactive use in the most ordinary way, to print or display an
106
    announcement including an appropriate copyright notice and a
107
    notice that there is no warranty (or else, saying that you provide
108
    a warranty) and that users may redistribute the program under
109
    these conditions, and telling the user how to view a copy of this
110
    License.  (Exception: if the Program itself is interactive but
111
    does not normally print such an announcement, your work based on
112
    the Program is not required to print an announcement.)
113

114
These requirements apply to the modified work as a whole.  If
115
identifiable sections of that work are not derived from the Program,
116
and can be reasonably considered independent and separate works in
117
themselves, then this License, and its terms, do not apply to those
118
sections when you distribute them as separate works.  But when you
119
distribute the same sections as part of a whole which is a work based
120
on the Program, the distribution of the whole must be on the terms of
121
this License, whose permissions for other licensees extend to the
122
entire whole, and thus to each and every part regardless of who wrote it.
123

  
124
Thus, it is not the intent of this section to claim rights or contest
125
your rights to work written entirely by you; rather, the intent is to
126
exercise the right to control the distribution of derivative or
127
collective works based on the Program.
128

  
129
In addition, mere aggregation of another work not based on the Program
130
with the Program (or with a work based on the Program) on a volume of
131
a storage or distribution medium does not bring the other work under
132
the scope of this License.
133

  
134
  3. You may copy and distribute the Program (or a work based on it,
135
under Section 2) in object code or executable form under the terms of
136
Sections 1 and 2 above provided that you also do one of the following:
137

  
138
    a) Accompany it with the complete corresponding machine-readable
139
    source code, which must be distributed under the terms of Sections
140
    1 and 2 above on a medium customarily used for software interchange; or,
141

  
142
    b) Accompany it with a written offer, valid for at least three
143
    years, to give any third party, for a charge no more than your
144
    cost of physically performing source distribution, a complete
145
    machine-readable copy of the corresponding source code, to be
146
    distributed under the terms of Sections 1 and 2 above on a medium
147
    customarily used for software interchange; or,
148

  
149
    c) Accompany it with the information you received as to the offer
150
    to distribute corresponding source code.  (This alternative is
151
    allowed only for noncommercial distribution and only if you
152
    received the program in object code or executable form with such
153
    an offer, in accord with Subsection b above.)
154

  
155
The source code for a work means the preferred form of the work for
156
making modifications to it.  For an executable work, complete source
157
code means all the source code for all modules it contains, plus any
158
associated interface definition files, plus the scripts used to
159
control compilation and installation of the executable.  However, as a
160
special exception, the source code distributed need not include
161
anything that is normally distributed (in either source or binary
162
form) with the major components (compiler, kernel, and so on) of the
163
operating system on which the executable runs, unless that component
164
itself accompanies the executable.
165

  
166
If distribution of executable or object code is made by offering
167
access to copy from a designated place, then offering equivalent
168
access to copy the source code from the same place counts as
169
distribution of the source code, even though third parties are not
170
compelled to copy the source along with the object code.
171

172
  4. You may not copy, modify, sublicense, or distribute the Program
173
except as expressly provided under this License.  Any attempt
174
otherwise to copy, modify, sublicense or distribute the Program is
175
void, and will automatically terminate your rights under this License.
176
However, parties who have received copies, or rights, from you under
177
this License will not have their licenses terminated so long as such
178
parties remain in full compliance.
179

  
180
  5. You are not required to accept this License, since you have not
181
signed it.  However, nothing else grants you permission to modify or
182
distribute the Program or its derivative works.  These actions are
183
prohibited by law if you do not accept this License.  Therefore, by
184
modifying or distributing the Program (or any work based on the
185
Program), you indicate your acceptance of this License to do so, and
186
all its terms and conditions for copying, distributing or modifying
187
the Program or works based on it.
188

  
189
  6. Each time you redistribute the Program (or any work based on the
190
Program), the recipient automatically receives a license from the
191
original licensor to copy, distribute or modify the Program subject to
192
these terms and conditions.  You may not impose any further
193
restrictions on the recipients' exercise of the rights granted herein.
194
You are not responsible for enforcing compliance by third parties to
195
this License.
196

  
197
  7. If, as a consequence of a court judgment or allegation of patent
198
infringement or for any other reason (not limited to patent issues),
199
conditions are imposed on you (whether by court order, agreement or
200
otherwise) that contradict the conditions of this License, they do not
201
excuse you from the conditions of this License.  If you cannot
202
distribute so as to satisfy simultaneously your obligations under this
203
License and any other pertinent obligations, then as a consequence you
204
may not distribute the Program at all.  For example, if a patent
205
license would not permit royalty-free redistribution of the Program by
206
all those who receive copies directly or indirectly through you, then
207
the only way you could satisfy both it and this License would be to
208
refrain entirely from distribution of the Program.
209

  
210
If any portion of this section is held invalid or unenforceable under
211
any particular circumstance, the balance of the section is intended to
212
apply and the section as a whole is intended to apply in other
213
circumstances.
214

  
215
It is not the purpose of this section to induce you to infringe any
216
patents or other property right claims or to contest validity of any
217
such claims; this section has the sole purpose of protecting the
218
integrity of the free software distribution system, which is
219
implemented by public license practices.  Many people have made
220
generous contributions to the wide range of software distributed
221
through that system in reliance on consistent application of that
222
system; it is up to the author/donor to decide if he or she is willing
223
to distribute software through any other system and a licensee cannot
224
impose that choice.
225

  
226
This section is intended to make thoroughly clear what is believed to
227
be a consequence of the rest of this License.
228

229
  8. If the distribution and/or use of the Program is restricted in
230
certain countries either by patents or by copyrighted interfaces, the
231
original copyright holder who places the Program under this License
232
may add an explicit geographical distribution limitation excluding
233
those countries, so that distribution is permitted only in or among
234
countries not thus excluded.  In such case, this License incorporates
235
the limitation as if written in the body of this License.
236

  
237
  9. The Free Software Foundation may publish revised and/or new versions
238
of the General Public License from time to time.  Such new versions will
239
be similar in spirit to the present version, but may differ in detail to
240
address new problems or concerns.
241

  
242
Each version is given a distinguishing version number.  If the Program
243
specifies a version number of this License which applies to it and "any
244
later version", you have the option of following the terms and conditions
245
either of that version or of any later version published by the Free
246
Software Foundation.  If the Program does not specify a version number of
247
this License, you may choose any version ever published by the Free Software
248
Foundation.
249

  
250
  10. If you wish to incorporate parts of the Program into other free
251
programs whose distribution conditions are different, write to the author
252
to ask for permission.  For software which is copyrighted by the Free
253
Software Foundation, write to the Free Software Foundation; we sometimes
254
make exceptions for this.  Our decision will be guided by the two goals
255
of preserving the free status of all derivatives of our free software and
256
of promoting the sharing and reuse of software generally.
257

  
258
			    NO WARRANTY
259

  
260
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
REPAIR OR CORRECTION.
269

  
270
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
POSSIBILITY OF SUCH DAMAGES.
279

  
280
		     END OF TERMS AND CONDITIONS
281

282
	    How to Apply These Terms to Your New Programs
283

  
284
  If you develop a new program, and you want it to be of the greatest
285
possible use to the public, the best way to achieve this is to make it
286
free software which everyone can redistribute and change under these terms.
287

  
288
  To do so, attach the following notices to the program.  It is safest
289
to attach them to the start of each source file to most effectively
290
convey the exclusion of warranty; and each file should have at least
291
the "copyright" line and a pointer to where the full notice is found.
292

  
293
    <one line to give the program's name and a brief idea of what it does.>
294
    Copyright (C) <year>  <name of author>
295

  
296
    This program is free software; you can redistribute it and/or modify
297
    it under the terms of the GNU General Public License as published by
298
    the Free Software Foundation; either version 2 of the License, or
299
    (at your option) any later version.
300

  
301
    This program is distributed in the hope that it will be useful,
302
    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
    GNU General Public License for more details.
305

  
306
    You should have received a copy of the GNU General Public License
307
    along with this program; if not, write to the Free Software
308
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
309

  
310

  
311
Also add information on how to contact you by electronic and paper mail.
312

  
313
If the program is interactive, make it output a short notice like this
314
when it starts in an interactive mode:
315

  
316
    Gnomovision version 69, Copyright (C) year  name of author
317
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
    This is free software, and you are welcome to redistribute it
319
    under certain conditions; type `show c' for details.
320

  
321
The hypothetical commands `show w' and `show c' should show the appropriate
322
parts of the General Public License.  Of course, the commands you use may
323
be called something other than `show w' and `show c'; they could even be
324
mouse-clicks or menu items--whatever suits your program.
325

  
326
You should also get your employer (if you work as a programmer) or your
327
school, if any, to sign a "copyright disclaimer" for the program, if
328
necessary.  Here is a sample; alter the names:
329

  
330
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332

  
333
  <signature of Ty Coon>, 1 April 1989
334
  Ty Coon, President of Vice
335

  
336
This General Public License does not permit incorporating your program into
337
proprietary programs.  If your program is a subroutine library, you may
338
consider it more useful to permit linking proprietary applications with the
339
library.  If this is what you want to do, use the GNU Library General
340
Public License instead of this License.
onsetsds/ChangeLog
1
2007-11  Dan Stowell
2
    * Significant refactoring from v0.1, which was a set of SuperCollider UGens.
3
    * VERSION: 0.2.0
onsetsds/README
1

  
2
 ----------------------------------------------------------
3
 OnsetsDS
4
 
5
 Musical onset detection library
6
 (c) 2007 Dan Stowell
7
 Made available under the GPL v2 - see COPYING for details.
8
 ----------------------------------------------------------
9

  
10

  
11

  
12
USAGE
13

  
14
If your system can provide frequency-domain data (e.g. by performing FFT on the
15
input audio), then to perform onset detection you only need onsetsds.h and 
16
onsetsds.c. These need no additional libraries beyond the standard C libraries.
17

  
18
If you aren't already doing the FFT then you can also use onsetsdshelpers.c
19
and onsetsdshelpers.h, which can process raw audio, from a buffer or from a 
20
file. These require two additional libraries:
21

  
22
 * libsndfile - I used version 1.0.17
23
   http://www.meganerd.com/libsndfile
24
   
25
 * FFTW 3 (floating-point version) - I used version 3.1.2
26
   http://www.fftw.org 
27

  
28
See the HTML documentation for a worked example.
29

  
onsetsds/doc/Doxyfile
1
# Doxyfile 1.5.3
2

  
3
#---------------------------------------------------------------------------
4
# Project related configuration options
5
#---------------------------------------------------------------------------
6
DOXYFILE_ENCODING      = UTF-8
7
PROJECT_NAME           = OnsetsDS
8
PROJECT_NUMBER         = v0.2
9
OUTPUT_DIRECTORY       = .
10
CREATE_SUBDIRS         = NO
11
OUTPUT_LANGUAGE        = English
12
BRIEF_MEMBER_DESC      = YES
13
REPEAT_BRIEF           = YES
14
ABBREVIATE_BRIEF       = "The $name class    " \
15
                         "The $name widget    " \
16
                         "The $name file    " \
17
                         is \
18
                         provides \
19
                         specifies \
20
                         contains \
21
                         represents \
22
                         a \
23
                         an \
24
                         the
25
ALWAYS_DETAILED_SEC    = NO
26
INLINE_INHERITED_MEMB  = NO
27
FULL_PATH_NAMES        = NO
28
STRIP_FROM_PATH        = /Applications/
29
STRIP_FROM_INC_PATH    = 
30
SHORT_NAMES            = NO
31
JAVADOC_AUTOBRIEF      = NO
32
QT_AUTOBRIEF           = NO
33
MULTILINE_CPP_IS_BRIEF = NO
34
DETAILS_AT_TOP         = NO
35
INHERIT_DOCS           = YES
36
SEPARATE_MEMBER_PAGES  = NO
37
TAB_SIZE               = 8
38
ALIASES                = 
39
OPTIMIZE_OUTPUT_FOR_C  = YES
40
OPTIMIZE_OUTPUT_JAVA   = NO
41
BUILTIN_STL_SUPPORT    = NO
42
CPP_CLI_SUPPORT        = NO
43
DISTRIBUTE_GROUP_DOC   = NO
44
SUBGROUPING            = YES
45
#---------------------------------------------------------------------------
46
# Build related configuration options
47
#---------------------------------------------------------------------------
48
EXTRACT_ALL            = YES
49
EXTRACT_PRIVATE        = YES
50
EXTRACT_STATIC         = YES
51
EXTRACT_LOCAL_CLASSES  = YES
52
EXTRACT_LOCAL_METHODS  = NO
53
EXTRACT_ANON_NSPACES   = NO
54
HIDE_UNDOC_MEMBERS     = NO
55
HIDE_UNDOC_CLASSES     = NO
56
HIDE_FRIEND_COMPOUNDS  = NO
57
HIDE_IN_BODY_DOCS      = NO
58
INTERNAL_DOCS          = NO
59
CASE_SENSE_NAMES       = NO
60
HIDE_SCOPE_NAMES       = NO
61
SHOW_INCLUDE_FILES     = YES
62
INLINE_INFO            = YES
63
SORT_MEMBER_DOCS       = NO
64
SORT_BRIEF_DOCS        = NO
65
SORT_BY_SCOPE_NAME     = NO
66
GENERATE_TODOLIST      = NO
67
GENERATE_TESTLIST      = NO
68
GENERATE_BUGLIST       = NO
69
GENERATE_DEPRECATEDLIST= NO
70
ENABLED_SECTIONS       = 
71
MAX_INITIALIZER_LINES  = 30
72
SHOW_USED_FILES        = YES
73
SHOW_DIRECTORIES       = NO
74
FILE_VERSION_FILTER    = 
75
#---------------------------------------------------------------------------
76
# configuration options related to warning and progress messages
77
#---------------------------------------------------------------------------
78
QUIET                  = NO
79
WARNINGS               = YES
80
WARN_IF_UNDOCUMENTED   = YES
81
WARN_IF_DOC_ERROR      = YES
82
WARN_NO_PARAMDOC       = NO
83
WARN_FORMAT            = "$file:$line: $text    "
84
WARN_LOGFILE           = 
85
#---------------------------------------------------------------------------
86
# configuration options related to the input files
87
#---------------------------------------------------------------------------
88
INPUT                  = ..
89
INPUT_ENCODING         = UTF-8
90
FILE_PATTERNS          = *.c \
91
                         *.cc \
92
                         *.cxx \
93
                         *.cpp \
94
                         *.c++ \
95
                         *.d \
96
                         *.java \
97
                         *.ii \
98
                         *.ixx \
99
                         *.ipp \
100
                         *.i++ \
101
                         *.inl \
102
                         *.h \
103
                         *.hh \
104
                         *.hxx \
105
                         *.hpp \
106
                         *.h++ \
107
                         *.idl \
108
                         *.odl \
109
                         *.cs \
110
                         *.php \
111
                         *.php3 \
112
                         *.inc \
113
                         *.m \
114
                         *.mm \
115
                         *.dox \
116
                         *.py
117
RECURSIVE              = YES
118
EXCLUDE                = 
119
EXCLUDE_SYMLINKS       = NO
120
EXCLUDE_PATTERNS       = */.svn* */doc/html*
121
EXCLUDE_SYMBOLS        = 
122
EXAMPLE_PATH           = 
123
EXAMPLE_PATTERNS       = *
124
EXAMPLE_RECURSIVE      = NO
125
IMAGE_PATH             = 
126
INPUT_FILTER           = 
127
FILTER_PATTERNS        = 
128
FILTER_SOURCE_FILES    = NO
129
#---------------------------------------------------------------------------
130
# configuration options related to source browsing
131
#---------------------------------------------------------------------------
132
SOURCE_BROWSER         = NO
133
INLINE_SOURCES         = NO
134
STRIP_CODE_COMMENTS    = YES
135
REFERENCED_BY_RELATION = NO
136
REFERENCES_RELATION    = NO
137
REFERENCES_LINK_SOURCE = YES
138
USE_HTAGS              = NO
139
VERBATIM_HEADERS       = NO
140
#---------------------------------------------------------------------------
141
# configuration options related to the alphabetical class index
142
#---------------------------------------------------------------------------
143
ALPHABETICAL_INDEX     = NO
144
COLS_IN_ALPHA_INDEX    = 5
145
IGNORE_PREFIX          = 
146
#---------------------------------------------------------------------------
147
# configuration options related to the HTML output
148
#---------------------------------------------------------------------------
149
GENERATE_HTML          = YES
150
HTML_OUTPUT            = html
151
HTML_FILE_EXTENSION    = .html
152
HTML_HEADER            = 
153
HTML_FOOTER            = footer.html
154
HTML_STYLESHEET        = 
155
HTML_ALIGN_MEMBERS     = YES
156
GENERATE_HTMLHELP      = NO
157
HTML_DYNAMIC_SECTIONS  = NO
158
CHM_FILE               = 
159
HHC_LOCATION           = 
160
GENERATE_CHI           = NO
161
BINARY_TOC             = NO
162
TOC_EXPAND             = NO
163
DISABLE_INDEX          = NO
164
ENUM_VALUES_PER_LINE   = 4
165
GENERATE_TREEVIEW      = NO
166
TREEVIEW_WIDTH         = 250
167
#---------------------------------------------------------------------------
168
# configuration options related to the LaTeX output
169
#---------------------------------------------------------------------------
170
GENERATE_LATEX         = NO
171
LATEX_OUTPUT           = latex
172
LATEX_CMD_NAME         = latex
173
MAKEINDEX_CMD_NAME     = makeindex
174
COMPACT_LATEX          = NO
175
PAPER_TYPE             = a4wide
176
EXTRA_PACKAGES         = 
177
LATEX_HEADER           = 
178
PDF_HYPERLINKS         = NO
179
USE_PDFLATEX           = NO
180
LATEX_BATCHMODE        = NO
181
LATEX_HIDE_INDICES     = NO
182
#---------------------------------------------------------------------------
183
# configuration options related to the RTF output
184
#---------------------------------------------------------------------------
185
GENERATE_RTF           = NO
186
RTF_OUTPUT             = rtf
187
COMPACT_RTF            = NO
188
RTF_HYPERLINKS         = NO
189
RTF_STYLESHEET_FILE    = 
190
RTF_EXTENSIONS_FILE    = 
191
#---------------------------------------------------------------------------
192
# configuration options related to the man page output
193
#---------------------------------------------------------------------------
194
GENERATE_MAN           = NO
195
MAN_OUTPUT             = man
196
MAN_EXTENSION          = .3
197
MAN_LINKS              = NO
198
#---------------------------------------------------------------------------
199
# configuration options related to the XML output
200
#---------------------------------------------------------------------------
201
GENERATE_XML           = NO
202
XML_OUTPUT             = xml
203
XML_SCHEMA             = 
204
XML_DTD                = 
205
XML_PROGRAMLISTING     = YES
206
#---------------------------------------------------------------------------
207
# configuration options for the AutoGen Definitions output
208
#---------------------------------------------------------------------------
209
GENERATE_AUTOGEN_DEF   = NO
210
#---------------------------------------------------------------------------
211
# configuration options related to the Perl module output
212
#---------------------------------------------------------------------------
213
GENERATE_PERLMOD       = NO
214
PERLMOD_LATEX          = NO
215
PERLMOD_PRETTY         = YES
216
PERLMOD_MAKEVAR_PREFIX = 
217
#---------------------------------------------------------------------------
218
# Configuration options related to the preprocessor   
219
#---------------------------------------------------------------------------
220
ENABLE_PREPROCESSING   = YES
221
MACRO_EXPANSION        = NO
222
EXPAND_ONLY_PREDEF     = NO
223
SEARCH_INCLUDES        = YES
224
INCLUDE_PATH           = 
225
INCLUDE_FILE_PATTERNS  = 
226
PREDEFINED             = 
227
EXPAND_AS_DEFINED      = 
228
SKIP_FUNCTION_MACROS   = YES
229
#---------------------------------------------------------------------------
230
# Configuration::additions related to external references   
231
#---------------------------------------------------------------------------
232
TAGFILES               = 
233
GENERATE_TAGFILE       = 
234
ALLEXTERNALS           = NO
235
EXTERNAL_GROUPS        = YES
236
PERL_PATH              = /usr/bin/perl
237
#---------------------------------------------------------------------------
238
# Configuration options related to the dot tool   
239
#---------------------------------------------------------------------------
240
CLASS_DIAGRAMS         = NO
241
MSCGEN_PATH            = /Applications/Doxygen.app/Contents/Resources/
242
HIDE_UNDOC_RELATIONS   = YES
243
HAVE_DOT               = YES
244
CLASS_GRAPH            = YES
245
COLLABORATION_GRAPH    = YES
246
GROUP_GRAPHS           = YES
247
UML_LOOK               = NO
248
TEMPLATE_RELATIONS     = NO
249
INCLUDE_GRAPH          = NO
250
INCLUDED_BY_GRAPH      = NO
251
CALL_GRAPH             = NO
252
CALLER_GRAPH           = NO
253
GRAPHICAL_HIERARCHY    = YES
254
DIRECTORY_GRAPH        = YES
255
DOT_IMAGE_FORMAT       = png
256
DOT_PATH               = /Applications/Doxygen.app/Contents/Resources/
257
DOTFILE_DIRS           = 
258
DOT_GRAPH_MAX_NODES    = 50
259
MAX_DOT_GRAPH_DEPTH    = 1000
260
DOT_TRANSPARENT        = NO
261
DOT_MULTI_TARGETS      = NO
262
GENERATE_LEGEND        = YES
263
DOT_CLEANUP            = YES
264
#---------------------------------------------------------------------------
265
# Configuration::additions related to the search engine   
266
#---------------------------------------------------------------------------
267
SEARCHENGINE           = NO
onsetsds/doc/footer.html
1
</body></html>
onsetsds/doc/mainpage.dox
1
/** \mainpage OnsetsDS - real time musical onset detection C/C++ library
2

  
3
<small>Copyright (c) 2007 Dan Stowell (Published under the GNU Public License v2). 
4
http://onsetsds.sourceforge.net/</small>
5
	
6
<h2>Introduction</h2>
7

  
8
The purpose of %OnsetsDS is to provide capabilities for FFT-based onset 
9
detection that works very efficiently in real-time, and can detect onsets 
10
pretty well in a broad variety of musical signals, with a fast reaction 
11
time.
12

  
13
It is not specialised for any particular type of signal. Nor is it 
14
particularly tailored towards non-real-time use (if we were working in 
15
non-real-time there are extra things we could do to improve the precision). 
16
Its efficiency and fast reaction are designed with general real-time musical
17
applications in mind.
18

  
19
<h2>Download</h2>
20

  
21
<ul>
22
	<li><a href="http://sourceforge.net/">Download the sourcecode bundle</a></li>
23
	<li>Or access the current development version using subversion [<small><a href="http://sourceforge.net/svn/?group_id=54622" title="What is subversion, and how to use it">info</a></small>]: <br />
24
	  <tt>svn co %https://onsetsds.svn.sourceforge.net/svnroot/onsetsds onsetsds</tt></li>
25
</ul>
26

  
27
<h2>Typical usage</h2>
28

  
29
\code
30

  
31
// This example uses the recommended settings of an FFT size of 512 (@44.1kHz),
32
// and a median span of 11. It also uses the "rectified complex deviation"
33
// onset detection function - your choice of function may be down to taste,
34
// or to performance on the particular type of sound you're using.
35

  
36
#include "onsetsds.h"
37

  
38
// An instance of the OnsetsDS struct, declared/allocated somewhere in your code,
39
// however you want to do it.
40
OnsetsDS ods;
41

  
42

  
43
///////// (1) INITIALISATION: /////////
44

  
45
// Allocate contiguous memory using malloc or whatever is reasonable.
46
float* odsdata = (float*) malloc( onsetsds_memneeded(odftype, 512, 11) );
47

  
48
// There are various types of onset detector available, we must choose one
49
odftype = ODS_ODF_RCOMPLEX;
50

  
51
// Now initialise the OnsetsDS struct and its associated memory
52
onsetsds_init(ods, odsdata, ODS_FFT_FFTW3_HC, odftype, 512, 11);
53

  
54

  
55
///////// (2) EXECUTION:      /////////
56

  
57
bool onset;
58
while(running){
59
   // Grab your 512-point, 50%-overlap, nicely-windowed FFT data, into "fftdata"
60
   
61
   // Then detect. "onset" will be true when there's an onset, false otherwise
62
   onset = onsetsds_process(ods, fftdata);
63
}
64

  
65

  
66
///////// (3) TIDYING UP:     /////////
67

  
68
free(ods->data); // Or free(odsdata), they point to the same thing in this case
69

  
70
\endcode
71

  
72
<h2>Research background</h2>
73

  
74
%OnsetsDS is based on research into musical onset detection
75
carried out by Dan Stowell, with Dr Mark Plumbley, at 
76
Queen Mary University of London's 
77
<a href="http://www.elec.qmul.ac.uk/digitalmusic/">Centre for Digital Music</a>.
78

  
79
Relevant publications:
80

  
81
\li D. Stowell and M. D. Plumbley. 
82
<a href="http://www.elec.qmul.ac.uk/digitalmusic/papers/2007/StowellPlumbley07-icmc.pdf">
83
Adaptive whitening for improved real-time audio onset detection.</a> 
84
To appear in: 
85
Proceedings of the International Computer Music Conference (ICMC'07), 
86
Copenhagen, Denmark, August 2007.
87

  
88
The research stands on the shoulders of other onset detection research, and uses
89
some concepts from that research - see the ICMC'07 paper and its bibliography
90
for more details.
91

  
92

  
93
*/
onsetsds/onsetsds.c
1
/*
2
	OnsetsDS - real time musical onset detection library.
3
    Copyright (c) 2007 Dan Stowell. All rights reserved.
4

  
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9

  
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14

  
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
19

  
20

  
21
#include "onsetsds.h"
22

  
23

  
24
#define ODS_DEBUG_POST_CSV 0
25

  
26
// Inline
27
inline float onsetsds_phase_rewrap(float phase);
28
inline float onsetsds_phase_rewrap(float phase){
29
	return (phase>MINUSPI && phase<PI) ? phase : phase + TWOPI * (1.f + floorf((MINUSPI - phase) * INV_TWOPI));
30
}
31

  
32

  
33
size_t onsetsds_memneeded (int odftype, size_t fftsize, unsigned int medspan){
34
	
35
	/*
36
	Need memory for:
37
	- median calculation (2 * medspan floats)
38
	- storing old values (whether as OdsPolarBuf or as weirder float lists)
39
	- storing the OdsPolarBuf (size is NOT sizeof(OdsPolarBuf) but is fftsize)
40
	- storing the PSP (numbins + 2 values)
41
	All these are floats.
42
	*/
43
	
44
	int numbins = (fftsize >> 1) - 1; // No of bins, not counting DC/nyq
45
	
46
	switch(odftype){
47
		case ODS_ODF_POWER:
48
		case ODS_ODF_MAGSUM:
49
			
50
			// No old FFT frames needed, easy:
51
			return (medspan+medspan + fftsize + numbins + 2) * sizeof(float);
52

  
53
		case ODS_ODF_COMPLEX:
54
		case ODS_ODF_RCOMPLEX:
55
	
56
			return (medspan+medspan + fftsize + numbins + 2
57
					// For each bin (NOT dc/nyq) we store mag, phase and d_phase
58
					+ numbins + numbins + numbins
59
				) * sizeof(float);
60

  
61
		case ODS_ODF_PHASE:
62
		case ODS_ODF_WPHASE:
63
	
64
			return (medspan+medspan + fftsize + numbins + 2
65
					// For each bin (NOT dc/nyq) we store phase and d_phase
66
					+ numbins + numbins
67
				) * sizeof(float);
68

  
69
		case ODS_ODF_MKL:
70
	
71
			return (medspan+medspan + fftsize + numbins + 2
72
					// For each bin (NOT dc/nyq) we store mag
73
					+ numbins
74
				) * sizeof(float);
75

  
76

  
77
			break;
78
	
79
	}
80
	return -1; //bleh
81
}
82

  
83

  
84
void onsetsds_init(OnsetsDS *ods, float *odsdata, int fftformat, 
85
                           int odftype, size_t fftsize, unsigned int medspan, float srate){
86

  
87
	// The main pointer to the processing area - other pointers will indicate areas within this
88
	ods->data = odsdata;
89
	// Set all vals in processing area to zero
90
	memset(odsdata, 0, onsetsds_memneeded(odftype, fftsize, medspan));
91
	
92
	ods->srate = srate;
93
	
94
	int numbins  = (fftsize >> 1) - 1; // No of bins, not counting DC/nyq
95
	int realnumbins = numbins + 2;
96

  
97
	// Also point the other pointers to the right places
98
	ods->curr     = (OdsPolarBuf*) odsdata;
99
	ods->psp      = odsdata + fftsize;
100
	ods->odfvals  = odsdata + fftsize + realnumbins;
101
	ods->sortbuf  = odsdata + fftsize + realnumbins + medspan;
102
	ods->other    = odsdata + fftsize + realnumbins + medspan + medspan;
103
	
104
	// Default settings for Adaptive Whitening, user can set own values after init
105
	onsetsds_setrelax(ods, 1.f, fftsize>>1);
106
	ods->floor    = 0.1;
107
	
108
	switch(odftype){
109
		case ODS_ODF_POWER:
110
			ods->odfparam = 0.01; // "powthresh" in SC code
111
			ods->normfactor = 2560.f / (realnumbins * fftsize);
112
			break;
113
		case ODS_ODF_MAGSUM:
114
			ods->odfparam = 0.01; // "powthresh" in SC code
115
			ods->normfactor = 113.137085f / (realnumbins * sqrt(fftsize));
116
			break;
117
		case ODS_ODF_COMPLEX:
118
			ods->odfparam = 0.01; // "powthresh" in SC code
119
			ods->normfactor = 231.70475f / pow(fftsize, 1.5);// / fftsize;
120
			break;
121
		case ODS_ODF_RCOMPLEX:
122
			ods->odfparam = 0.01; // "powthresh" in SC code
123
			ods->normfactor = 231.70475f / pow(fftsize, 1.5);// / fftsize;
124
			break;
125
		case ODS_ODF_PHASE:
126
			ods->odfparam = 0.01; // "powthresh" in SC code
127
			ods->normfactor = 5.12f / fftsize;// / fftsize;
128
			break;
129
		case ODS_ODF_WPHASE:
130
			ods->odfparam = 0.0001; // "powthresh" in SC code. For WPHASE it's kind of superfluous.
131
			ods->normfactor = 115.852375f / pow(fftsize, 1.5);// / fftsize;
132
			break;
133
		case ODS_ODF_MKL:
134
			ods->odfparam = 0.01; // EPSILON parameter. Brossier recommends 1e-6 but I (ICMC 2007) found larger vals (e.g 0.01) to work better
135
			ods->normfactor = 7.68f * 0.25f / fftsize;
136
			break;
137
		default:
138
			printf("onsetsds_init ERROR: \"odftype\" is not a recognised value\n");
139
	}
140
	
141
	ods->odfvalpost = 0.f;
142
	ods->odfvalpostprev = 0.f;
143
	ods->thresh   = 0.5f;
144
	ods->logmags = false;
145
	
146
	ods->odftype  = odftype;
147
	ods->whtype   = ODS_WH_ADAPT_MAX1;
148
	ods->fftformat = fftformat;
149
	
150
	ods->whiten   = (odftype != ODS_ODF_MKL); // Deactivate whitening for MKL by default
151
	ods->detected = false;
152
	ods->med_odd  = (medspan & 1) != 0;
153
	
154
	ods->medspan  = medspan;
155
	
156
	ods->mingap   = 0;
157
	ods->gapleft  = 0;
158

  
159
	ods->fftsize  = fftsize;
160
	ods->numbins  = numbins;
161

  
162
	//printf("End of _init: normfactor is %g\n", ods->normfactor);
163

  
164
}
165

  
166
bool onsetsds_process(OnsetsDS* ods, float* fftbuf){
167
	onsetsds_loadframe(ods, fftbuf);
168

  
169
	onsetsds_whiten(ods);
170
	onsetsds_odf(ods);
171
	onsetsds_detect(ods);
172
	
173
	return ods->detected;
174
}
175

  
176

  
177
void onsetsds_setrelax(OnsetsDS* ods, float time, size_t hopsize){
178
	ods->relaxtime = time;
179
	ods->relaxcoef = (time == 0.0f) ? 0.0f : exp((ods_log1 * hopsize)/(time * ods->srate));
180
}
181

  
182

  
183

  
184
void onsetsds_loadframe(OnsetsDS* ods, float* fftbuf){
185
	
186
	float *pos, *pos2, imag, real;
187
	int i;
188
	
189
	switch(ods->fftformat){
190
		case ODS_FFT_SC3_POLAR:
191
			// The format is the same! dc, nyq, mag[1], phase[1], ...
192
			memcpy(ods->curr, fftbuf, ods->fftsize * sizeof(float));
193
			break;
194
			
195
		case ODS_FFT_SC3_COMPLEX:
196
		
197
			ods->curr->dc  = fftbuf[0];
198
			ods->curr->nyq = fftbuf[1];
199
			
200
			// Then convert cartesian to polar:
201
			pos = fftbuf + 2;
202
			for(i=0; i< (ods->numbins << 1); i += 2){
203
				real = pos[i];
204
				imag = pos[i+1]; // Plus 1 rather than increment; seems to avoid LSU reject on my PPC
205
				ods->curr->bin[i].mag   = hypotf(imag, real);
206
				ods->curr->bin[i].phase = atan2f(imag, real);
207
			}
208
			break;
209
			
210
		case ODS_FFT_FFTW3_HC:
211
			
212
			ods->curr->dc  = fftbuf[0];
213
			ods->curr->nyq = fftbuf[ods->fftsize>>1];
214
			
215
			// Then convert cartesian to polar:
216
			// (Starting positions: real and imag for bin 1)
217
			pos  = fftbuf + 1;
218
			pos2 = fftbuf + ods->fftsize - 1;
219
			for(i=0; i<ods->numbins; i++){
220
				real = *(pos++);
221
				imag = *(pos2--);
222
				ods->curr->bin[i].mag   = hypotf(imag, real);
223
				ods->curr->bin[i].phase = atan2f(imag, real);
224
			}
225
			break;
226
			
227
		case ODS_FFT_FFTW3_R2C:
228
		
229
			ods->curr->dc  = fftbuf[0];
230
			ods->curr->nyq = fftbuf[ods->fftsize];
231
			
232
			// Then convert cartesian to polar:
233
			pos = fftbuf + 2;
234
			for(i=0; i<ods->numbins; i++){
235
				real = *(pos++);
236
				imag = *(pos++);
237
				ods->curr->bin[i].mag   = hypotf(imag, real);
238
				ods->curr->bin[i].phase = atan2f(imag, real);
239
			}
240
			break;
241
			
242
	}
243
	
244
	// Conversion to log-domain magnitudes, including re-scaling to aim back at the zero-to-one range.
245
	// Not well tested yet.
246
	if(ods->logmags){
247
		for(i=0; i<ods->numbins; i++){
248
			ods->curr->bin[i].mag = 
249
				(log(ods_max(ods->curr->bin[i].mag, ODS_LOG_LOWER_LIMIT)) - ODS_LOGOF_LOG_LOWER_LIMIT) * ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT;
250
		}
251
		ods->curr->dc = 
252
			(log(ods_max(ods_abs(ods->curr->dc ), ODS_LOG_LOWER_LIMIT)) - ODS_LOGOF_LOG_LOWER_LIMIT) * ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT;
253
		ods->curr->nyq = 
254
			(log(ods_max(ods_abs(ods->curr->nyq), ODS_LOG_LOWER_LIMIT)) - ODS_LOGOF_LOG_LOWER_LIMIT) * ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT;
255
	}
256
	
257
}
258

  
259
void onsetsds_whiten(OnsetsDS* ods){
260
	
261
	if(ods->whtype == ODS_WH_NONE){
262
		//printf("onsetsds_whiten(): ODS_WH_NONE, skipping\n");
263
		return;
264
	}
265
	
266
	// NB: Apart from the above, ods->whtype is currently IGNORED and only one mode is used.
267
	
268
	
269
	float val,oldval, relaxcoef, floor;
270
	int numbins, i;
271
	OdsPolarBuf *curr;
272
	float *psp;
273
	float *pspp1; // Offset by 1, avoids quite a lot of "+1"s in the following code
274
	
275
	relaxcoef = ods->relaxcoef;
276
	numbins = ods->numbins;
277
	curr = ods->curr;
278
	psp = ods->psp;
279
	pspp1 = psp + 1;
280
	floor = ods->floor;
281

  
282
	//printf("onsetsds_whiten: relaxcoef=%g, relaxtime=%g, floor=%g\n", relaxcoef, ods->relaxtime, floor);
283

  
284
	////////////////////// For each bin, update the record of the peak value /////////////////////
285
	
286
	val = fabs(curr->dc);	// Grab current magnitude
287
	oldval = psp[0];
288
	// If it beats the amplitude stored then that's our new amplitude;
289
	// otherwise our new amplitude is a decayed version of the old one
290
	if(val < oldval) {
291
		val = val + (oldval - val) * relaxcoef;
292
	}
293
	psp[0] = val; // Store the "amplitude trace" back
294
	
295
	val = fabs(curr->nyq);
296
	oldval = pspp1[numbins];
297
	if(val < oldval) {
298
		val = val + (oldval - val) * relaxcoef;
299
	}
300
	pspp1[numbins] = val;
301
	
302
	for(i=0; i<numbins; ++i){
303
		val = fabs(curr->bin[i].mag);
304
		oldval = pspp1[i];
305
		if(val < oldval) {
306
			val = val + (oldval - val) * relaxcoef;
307
		}
308
		pspp1[i] = val;
309
	}
310
	
311
	//////////////////////////// Now for each bin, rescale the current magnitude ////////////////////////////
312
	curr->dc  /= ods_max(floor, psp[0]);
313
	curr->nyq /= ods_max(floor, pspp1[numbins]);
314
	for(i=0; i<numbins; ++i){
315
		curr->bin[i].mag /= ods_max(floor, pspp1[i]);
316
	}
317
}
318

  
319
void onsetsds_odf(OnsetsDS* ods){
320
	
321
	int numbins = ods->numbins;
322
	OdsPolarBuf *curr = ods->curr;
323
	float* val = ods->odfvals;
324
	int i, tbpointer;
325
	float deviation, diff, curmag;
326
	double totdev;
327
	
328
	bool rectify = true;
329
	
330
	// Here we shunt the "old" ODF values down one place
331
	memcpy(val + 1, val, (ods->medspan - 1)*sizeof(float));
332
	
333
	// Now calculate a new value and store in ods->odfvals[0]
334
	switch(ods->odftype){
335
		case ODS_ODF_POWER:
336
			
337
			*val = (curr->nyq  *  curr->nyq)  +  (curr->dc  *  curr->dc);
338
			for(i=0; i<numbins; i++){
339
				*val += curr->bin[i].mag  *  curr->bin[i].mag;
340
			}
341
			break;
342
			
343
		case ODS_ODF_MAGSUM:
344
	
345
			*val = ods_abs(curr->nyq) + ods_abs(curr->dc);
346
			
347
			for(i=0; i<numbins; i++){
348
				*val += ods_abs(curr->bin[i].mag);
349
			}
350
			break;
351
			
352
		case ODS_ODF_COMPLEX:
353
			rectify = false;
354
			// ...and then drop through to:
355
		case ODS_ODF_RCOMPLEX:
356
			
357
			// Note: "other" buf is stored in this format: mag[0],phase[0],d_phase[0],mag[1],phase[1],d_phase[1], ...
358
			
359
			// Iterate through, calculating the deviation from expected value.
360
			totdev = 0.0;
361
			tbpointer = 0;
362
			float predmag, predphase, yesterphase, yesterphasediff;
363
			for (i=0; i<numbins; ++i) {
364
				curmag = ods_abs(curr->bin[i].mag);
365
			
366
				// Predict mag as yestermag
367
				predmag         = ods->other[tbpointer++];
368
				yesterphase     = ods->other[tbpointer++];
369
				yesterphasediff = ods->other[tbpointer++];
370
				
371
				// Thresholding as Brossier did - discard (ignore) bin's deviation if bin's power is minimal
372
				if(curmag > ods->odfparam) {
373
					// If rectifying, ignore decreasing bins
374
					if((!rectify) || !(curmag < predmag)){
375
						
376
						// Predict phase as yesterval + yesterfirstdiff
377
						predphase = yesterphase + yesterphasediff;
378
						
379
						// Here temporarily using the "deviation" var to store the phase difference
380
						//  so that the rewrap macro can use it more efficiently
381
						deviation = predphase - curr->bin[i].phase;
382
						
383
						// Deviation is Euclidean distance between predicted and actual.
384
						// In polar coords: sqrt(r1^2 +  r2^2 - r1r2 cos (theta1 - theta2))
385
						deviation = sqrtf(predmag * predmag + curmag * curmag
386
										  - predmag * curmag * cosf(onsetsds_phase_rewrap(deviation))
387
										);			
388
						
389
						totdev += deviation;
390
					}
391
				}
392
			}
393
			
394
			// totdev will be the output, but first we need to fill tempbuf with today's values, ready for tomorrow.
395
			tbpointer = 0;
396
			for (i=0; i<numbins; ++i) {
397
				ods->other[tbpointer++] = ods_abs(curr->bin[i].mag); // Storing mag
398
				diff = curr->bin[i].phase - ods->other[tbpointer]; // Retrieving yesterphase from buf
399
				ods->other[tbpointer++] = curr->bin[i].phase; // Storing phase
400
				// Wrap onto +-PI range
401
				diff = onsetsds_phase_rewrap(diff);
402
				
403
				ods->other[tbpointer++] = diff; // Storing first diff to buf
404
				
405
			}
406
			*val = (float)totdev;
407
			
408
			break;
409
			
410
			
411
		case ODS_ODF_PHASE:
412
			rectify = false; // So, actually, "rectify" means "useweighting" in this context
413
			// ...and then drop through to:
414
		case ODS_ODF_WPHASE:
415
			
416
			// Note: "other" buf is stored in this format: phase[0],d_phase[0],phase[1],d_phase[1], ...
417
			
418
			// Iterate through, calculating the deviation from expected value.
419
			totdev = 0.0;
420
			tbpointer = 0;
421
			for (i=0; i<numbins; ++i) {
422
				// Thresholding as Brossier did - discard (ignore) bin's phase deviation if bin's power is low
423
				if(ods_abs(curr->bin[i].mag) > ods->odfparam) {
424
					
425
					// Deviation is the *second difference* of the phase, which is calc'ed as curval - yesterval - yesterfirstdiff
426
					deviation = curr->bin[i].phase - ods->other[tbpointer++] - ods->other[tbpointer++];
427
					// Wrap onto +-PI range
428
					deviation = onsetsds_phase_rewrap(deviation);
429
					
430
					if(rectify){ // "rectify" meaning "useweighting"...
431
						totdev += fabs(deviation * ods_abs(curr->bin[i].mag));
432
					} else {
433
						totdev += fabs(deviation);
434
					}
435
				}
436
			}
437
			
438
			// totdev will be the output, but first we need to fill tempbuf with today's values, ready for tomorrow.
439
			tbpointer = 0;
440
			for (i=0; i<numbins; ++i) {
441
				diff = curr->bin[i].phase - ods->other[tbpointer]; // Retrieving yesterphase from buf
442
				ods->other[tbpointer++] = curr->bin[i].phase; // Storing phase
443
				// Wrap onto +-PI range
444
				diff = onsetsds_phase_rewrap(diff);
445
				
446
				ods->other[tbpointer++] = diff; // Storing first diff to buf
447
				
448
			}
449
			*val = (float)totdev;
450
			break;
451
			
452
			
453
		case ODS_ODF_MKL:
454
			
455
			// Iterate through, calculating the Modified Kullback-Liebler distance
456
			totdev = 0.0;
457
			tbpointer = 0;
458
			float yestermag;
459
			for (i=0; i<numbins; ++i) {
460
				curmag = ods_abs(curr->bin[i].mag);
461
				yestermag = ods->other[tbpointer];
462
				
463
				// Here's the main implementation of Brossier's MKL eq'n (eqn 2.9 from his thesis):
464
				deviation = ods_abs(curmag) / (ods_abs(yestermag) + ods->odfparam);
465
				totdev += log(1.f + deviation);
466
				
467
				// Store the mag as yestermag
468
				ods->other[tbpointer++] = curmag;
469
			}
470
			*val = (float)totdev;
471
			break;
472
	
473
	}
474
		
475
#if ODS_DEBUG_POST_CSV
476
	printf("%g,", *val);
477
	printf("%g,", ods->odfvals[0] * ods->normfactor);
478
#endif
479
	
480
	ods->odfvals[0] *= ods->normfactor;
481
}
482
// End of ODF function
483

  
484
void SelectionSort(float *array, int length);
485
void SelectionSort(float *array, int length)
486
{
487
  // Algo is simply based on http://en.wikibooks.org/wiki/Algorithm_implementation/Sorting/Selection_sort
488
  int max, i;
489
  float temp;
490
  while(length > 0)
491
  {
492
    max = 0;
493
    for(i = 1; i < length; i++)
494
      if(array[i] > array[max])
495
        max = i;
496
    temp = array[length-1];
497
    array[length-1] = array[max];
498
    array[max] = temp;
499
    length--;
500
  }
501
}
502

  
503

  
504
void onsetsds_detect(OnsetsDS* ods){
505
	
506
	// Shift the yesterval to its rightful place
507
	ods->odfvalpostprev = ods->odfvalpost;
508
	
509
	///////// MEDIAN REMOVAL ////////////
510
	
511
	float* sortbuf = ods->sortbuf;
512
	int medspan = ods->medspan;
513
	
514
	// Copy odfvals to sortbuf
515
	memcpy(sortbuf, ods->odfvals, medspan * sizeof(float));
516
	
517
	// Sort sortbuf
518
	SelectionSort(sortbuf, medspan);
519
			
520
	// Subtract the middlest value === the median
521
	if(ods->med_odd){
522
		ods->odfvalpost = ods->odfvals[0] 
523
			   - sortbuf[(medspan - 1) >> 1];
524
	}else{
525
		ods->odfvalpost = ods->odfvals[0] 
526
			   - ((sortbuf[medspan >> 1]
527
				 + sortbuf[(medspan >> 1) - 1]) * 0.5f);
528
			   
529
	}
530

  
531
	// Detection not allowed if we're too close to a previous detection.
532
	if(ods->gapleft != 0) {
533
		ods->gapleft--;
534
		ods->detected = false;
535
	} else {
536
		// Now do the detection.
537
		ods->detected = (ods->odfvalpost > ods->thresh) && (ods->odfvalpostprev <= ods->thresh);
538
		if(ods->detected){
539
			ods->gapleft = ods->mingap;
540
		}
541
	}
542
#if ODS_DEBUG_POST_CSV
543
	printf("%g\n", ods->odfvalpost);
544
#endif
545
}
546

  
547

  
onsetsds/onsetsds.h
1
/*
2
    OnsetsDS - real time musical onset detection library.
3
    Copyright (c) 2007 Dan Stowell. All rights reserved.
4

  
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9

  
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14

  
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
19

  
20
/** \file */
21

  
22
#ifndef _OnsetsDS_
23
#define _OnsetsDS_
24

  
25
#ifdef __cplusplus
26
extern "C" {
27
#endif
28

  
29
#include <stdio.h>
30
#include <string.h>
31
#include <stdbool.h>
32
#include <math.h>
33

  
34

  
35
////////////////////////////////////////////////////////////////////////////////
36
// Macros and consts
37

  
38
//log(0.1)
39
#define ods_log1 -2.30258509
40

  
41
#define PI 3.1415926535898f
42
#define MINUSPI -3.1415926535898f
43
#define TWOPI 6.28318530717952646f 
44
#define INV_TWOPI 0.1591549430919f
45

  
46
#define ods_abs(a)  ((a)<0? -(a) : (a))
47
#define ods_max(a,b) (((a) > (b)) ? (a) : (b))
48
#define ods_min(a,b) (((a) < (b)) ? (a) : (b))
49

  
50
#define ODS_LOG_LOWER_LIMIT 2e-42
51
#define ODS_LOGOF_LOG_LOWER_LIMIT -96.0154267
52
#define ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT 0.010414993
53

  
54
////////////////////////////////////////////////////////////////////////////////
55
// Constants
56

  
57
/**
58
* Types of incoming FFT data format. OnsetsDS needs to know where the FFT
59
* data comes from in order to interpret it correctly.
60
*/
61
enum onsetsds_fft_types {
62
	ODS_FFT_SC3_COMPLEX,	  ///< SuperCollider, cartesian co-ords ("SCComplexBuf") - NB it's more efficient to provide polar data from SC
63
	ODS_FFT_SC3_POLAR,	  ///< SuperCollider, polar co-ords ("SCPolarBuf")
64
	ODS_FFT_FFTW3_HC, ///< FFTW <a href="http://www.fftw.org/fftw3_doc/The-Halfcomplex_002dformat-DFT.html">"halfcomplex"</a> format 
65
	ODS_FFT_FFTW3_R2C   ///< FFTW regular format, typically produced using <a href="http://www.fftw.org/fftw3_doc/One_002dDimensional-DFTs-of-Real-Data.html#One_002dDimensional-DFTs-of-Real-Data">real-to-complex</a> transform
66
};
67

  
68
/**
69
* Types of onset detection function
70
*/
71
enum onsetsds_odf_types {
72
	ODS_ODF_POWER,    ///< Power
73
	ODS_ODF_MAGSUM,   ///< Sum of magnitudes
74
	ODS_ODF_COMPLEX,  ///< Complex-domain deviation
75
	ODS_ODF_RCOMPLEX, ///< Complex-domain deviation, rectified (only increases counted)
76
	ODS_ODF_PHASE,    ///< Phase deviation
77
	ODS_ODF_WPHASE,   ///< Weighted phase deviation
78
	ODS_ODF_MKL       ///< Modified Kullback-Liebler deviation
79
};
80

  
81
/**
82
* Types of whitening - may not all be implemented yet.
83
*/
84
enum onsetsds_wh_types {
85
	ODS_WH_NONE, ///< No whitening - onsetsds_whiten() becomes a no-op
86
	ODS_WH_ADAPT_MAX1, ///< Adaptive whitening - tracks recent-peak-magnitude in each bin, normalises that to 1
87
	ODS_WH_NORMMAX, ///< Simple normalisation - each frame is normalised (independent of others) so largest magnitude becomes 1. Not implemented.
88
	ODS_WH_NORMMEAN ///< Simple normalisation - each frame is normalised (independent of others) so mean magnitude becomes 1. Not implemented.
89
};
90

  
91
////////////////////////////////////////////////////////////////////////////////
92
// Structs
93

  
94
typedef struct OdsPolarBin { float mag, phase; } OdsPolarBin;
95

  
96
typedef struct OdsPolarBuf {
97
	float dc, nyq;
98
	OdsPolarBin bin[1];
99
} OdsPolarBuf;
100

  
101
/// The main data structure for the onset detection routine
102
typedef struct OnsetsDS {
103
	/// "data" is a pointer to the memory that must be EXTERNALLY allocated.
104
	/// Other pointers will point to locations within this memory.
105
	float  *data, 
106
		   *psp,     ///< Peak Spectral Profile - size is numbins+2, data is stored in order dc through to nyquist
107
		   *odfvals, // odfvals[0] will be the current val, odfvals[1] prev, etc
108
		   *sortbuf, // Used to calculate the median
109
		   *other; // Typically stores data about the previous frame
110
	OdsPolarBuf*  curr; // Current FFT frame, as polar
111
	
112
	float 
113
		srate, ///< The sampling rate of the input audio. Set by onsetsds_init()
114
		// Adaptive whitening params
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff