Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / server / plugins / Onsets.cpp
blob719b87c492a18f7756ebd73740070f769c91c66d
1 /*
2 Onset detector for SuperCollider
3 Copyright (c) 2007 Dan Stowell. All rights reserved.
4 http://onsetsds.sourceforge.net
6 Now part of:
8 SuperCollider real time audio synthesis system
9 Copyright (c) 2002 James McCartney. All rights reserved.
10 http://www.audiosynth.com
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "SC_PlugIn.h"
28 #include "SCComplex.h"
29 #include "FFT_UGens.h"
31 #include "Onsets.h"
33 //////////////////////////////////////////////////////////////////////////////////////////////////
35 // for operation on one buffer
36 // almost like PV_GET_BUF except it outputs unit->outval rather than -1 when FFT not triggered
37 #define Onsets_GET_BUF \
38 float fbufnum = ZIN0(0); \
39 if (fbufnum < 0.f) { ZOUT0(0) = unit->outval; return; } \
40 ZOUT0(0) = fbufnum; \
41 uint32 ibufnum = (uint32)fbufnum; \
42 World *world = unit->mWorld; \
43 SndBuf *buf; \
44 if (ibufnum >= world->mNumSndBufs) { \
45 int localBufNum = ibufnum - world->mNumSndBufs; \
46 Graph *parent = unit->mParent; \
47 if(localBufNum <= parent->localBufNum) { \
48 buf = parent->mLocalSndBufs + localBufNum; \
49 } else { \
50 buf = world->mSndBufs; \
51 } \
52 } else { \
53 buf = world->mSndBufs + ibufnum; \
54 } \
55 LOCK_SNDBUF(buf); \
58 //////////////////////////////////////////////////////////////////////////////////////////////////
61 ////////////////////////////////////////////////////////////////////////////////////////////////////////
63 void Onsets_Ctor(Onsets *unit)
65 if(ZIN0(8)>0)
66 SETCALC(Onsets_next_rawodf);
67 else
68 SETCALC(Onsets_next);
70 unit->m_needsinit = true;
71 unit->m_ods = (OnsetsDS*) RTAlloc(unit->mWorld, sizeof(OnsetsDS) );
73 ZOUT0(0) = unit->outval = 0.f;
76 void Onsets_next(Onsets *unit, int inNumSamples)
78 Onsets_GET_BUF
80 // In practice, making the polar conversion here in SC is more efficient because SC provides a lookup table method.
81 SCPolarBuf *p = ToPolarApx(buf);
83 OnsetsDS *ods = unit->m_ods;
85 int odftype = (int)ZIN0(2);
86 float relaxtime = ZIN0(3);
87 int medspan = (int)ZIN0(6);
89 if(unit->m_needsinit){
90 // Init happens here because we need to be sure about FFT size.
91 unit->m_odsdata = (float*) RTAlloc(unit->mWorld, onsetsds_memneeded(odftype, buf->samples, medspan) );
93 onsetsds_init(ods, unit->m_odsdata, ODS_FFT_SC3_POLAR, odftype, buf->samples, medspan, FULLRATE);
94 onsetsds_setrelax(ods, relaxtime, buf->samples>>1);
96 unit->m_needsinit = false;
99 // Here is the best place to set parameters - after init is ensured
100 // These are "painless" to set:
101 ods->thresh = ZIN0(1);
102 ods->floor = ZIN0(4);
103 ods->mingap = (int)ZIN0(5);
104 ods->whtype = (int)ZIN0(7);
106 // Now to process
107 unit->outval = onsetsds_process(ods, (float*) p);
109 ZOUT0(0) = unit->outval;
112 void Onsets_next_rawodf(Onsets *unit, int inNumSamples)
114 Onsets_GET_BUF
116 // In practice, making the polar conversion here in SC is more efficient because SC provides a lookup table method.
117 SCPolarBuf *p = ToPolarApx(buf);
119 OnsetsDS *ods = unit->m_ods;
121 int odftype = (int)ZIN0(2);
122 float relaxtime = ZIN0(3);
123 int medspan = (int)ZIN0(6);
125 if(unit->m_needsinit){
126 // Init happens here because we need to be sure about FFT size.
127 unit->m_odsdata = (float*) RTAlloc(unit->mWorld, onsetsds_memneeded(odftype, buf->samples, medspan) );
129 onsetsds_init(ods, unit->m_odsdata, ODS_FFT_SC3_POLAR, odftype, buf->samples, medspan, FULLRATE);
130 onsetsds_setrelax(ods, relaxtime, buf->samples>>1);
132 unit->m_needsinit = false;
135 // Here is the best place to set parameters - after init is ensured
136 // These are "painless" to set:
137 ods->thresh = ZIN0(1);
138 ods->floor = ZIN0(4);
139 ods->mingap = (int)ZIN0(5);
140 ods->whtype = (int)ZIN0(7);
142 // Now to process
143 onsetsds_process(ods, (float*) p);
144 // But we want the ODF, not the triggers, for this special mode...
145 //unit->outval = ods->odfvalpost;
146 unit->outval = ods->odfvals[0];
148 ZOUT0(0) = unit->outval;
151 void Onsets_Dtor(Onsets *unit)
153 if(!unit->m_needsinit){
154 RTFree(unit->mWorld, unit->m_odsdata);
156 RTFree(unit->mWorld, unit->m_ods);