deep, somewhat subtle changes for transport control. Everything should use Session...
[ardour.git] / libs / soundtouch / BPMDetect.h
1 ////////////////////////////////////////////////////////////////////////////////
2 ///
3 /// Beats-per-minute (BPM) detection routine.
4 ///
5 /// The beat detection algorithm works as follows:
6 /// - Use function 'inputSamples' to input a chunks of samples to the class for
7 ///   analysis. It's a good idea to enter a large sound file or stream in smallish
8 ///   chunks of around few kilosamples in order not to extinguish too much RAM memory.
9 /// - Input sound data is decimated to approx 500 Hz to reduce calculation burden,
10 ///   which is basically ok as low (bass) frequencies mostly determine the beat rate.
11 ///   Simple averaging is used for anti-alias filtering because the resulting signal
12 ///   quality isn't of that high importance.
13 /// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
14 ///   taking absolute value that's smoothed by sliding average. Signal levels that
15 ///   are below a couple of times the general RMS amplitude level are cut away to
16 ///   leave only notable peaks there.
17 /// - Repeating sound patterns (e.g. beats) are detected by calculating short-term 
18 ///   autocorrelation function of the enveloped signal.
19 /// - After whole sound data file has been analyzed as above, the bpm level is 
20 ///   detected by function 'getBpm' that finds the highest peak of the autocorrelation 
21 ///   function, calculates it's precise location and converts this reading to bpm's.
22 ///
23 /// Author        : Copyright (c) Olli Parviainen
24 /// Author e-mail : oparviai @ iki.fi
25 /// SoundTouch WWW: http://www.iki.fi/oparviai/soundtouch
26 ///
27 ////////////////////////////////////////////////////////////////////////////////
28 //
29 // Last changed  : $Date$
30 // File revision : $Revision$
31 //
32 // $Id$
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 //
36 // License :
37 //
38 //  SoundTouch audio processing library
39 //  Copyright (c) Olli Parviainen
40 //
41 //  This library is free software; you can redistribute it and/or
42 //  modify it under the terms of the GNU Lesser General Public
43 //  License as published by the Free Software Foundation; either
44 //  version 2.1 of the License, or (at your option) any later version.
45 //
46 //  This library is distributed in the hope that it will be useful,
47 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
48 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
49 //  Lesser General Public License for more details.
50 //
51 //  You should have received a copy of the GNU Lesser General Public
52 //  License along with this library; if not, write to the Free Software
53 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
54 //
55 ////////////////////////////////////////////////////////////////////////////////
56
57 #ifndef _BPMDetect_H_
58 #define _BPMDetect_H_
59
60 #include "STTypes.h"
61 #include "FIFOSampleBuffer.h"
62
63 /// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
64 #define MIN_BPM 45
65
66 /// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit.
67 #define MAX_BPM 230
68
69
70 /// Class for calculating BPM rate for audio data.
71 class BPMDetect
72 {
73 protected:
74     /// Auto-correlation accumulator bins.
75     float *xcorr;
76     
77     /// Amplitude envelope sliding average approximation level accumulator
78     float envelopeAccu;
79
80     /// RMS volume sliding average approximation level accumulator
81     float RMSVolumeAccu;
82
83     /// Sample average counter.
84     int decimateCount;
85
86     /// Sample average accumulator for FIFO-like decimation.
87     soundtouch::LONG_SAMPLETYPE decimateSum;
88
89     /// Decimate sound by this coefficient to reach approx. 500 Hz.
90     int decimateBy;
91
92     /// Auto-correlation window length
93     int windowLen;
94
95     /// Number of channels (1 = mono, 2 = stereo)
96     int channels;
97
98     /// sample rate
99     int sampleRate;
100
101     /// Beginning of auto-correlation window: Autocorrelation isn't being updated for
102     /// the first these many correlation bins.
103     int windowStart;
104  
105     /// FIFO-buffer for decimated processing samples.
106     soundtouch::FIFOSampleBuffer *buffer;
107
108     /// Initialize the class for processing.
109     void init(int numChannels, int sampleRate);
110
111     /// Updates auto-correlation function for given number of decimated samples that 
112     /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe 
113     /// though).
114     void updateXCorr(int process_samples      /// How many samples are processed.
115                      );
116
117     /// Decimates samples to approx. 500 Hz.
118     ///
119     /// \return Number of output samples.
120     int decimate(soundtouch::SAMPLETYPE *dest,      ///< Destination buffer
121                  const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
122                  int numsamples                     ///< Number of source samples.
123                  );
124
125     /// Calculates amplitude envelope for the buffer of samples.
126     /// Result is output to 'samples'.
127     void calcEnvelope(soundtouch::SAMPLETYPE *samples,  ///< Pointer to input/output data buffer
128                       int numsamples                    ///< Number of samples in buffer
129                       );
130
131 public:
132     /// Constructor.
133     BPMDetect(int numChannels,  ///< Number of channels in sample data.
134               int sampleRate    ///< Sample rate in Hz.
135               );
136
137     /// Destructor.
138     virtual ~BPMDetect();
139
140     /// Inputs a block of samples for analyzing: Envelopes the samples and then
141     /// updates the autocorrelation estimation. When whole song data has been input
142     /// in smaller blocks using this function, read the resulting bpm with 'getBpm' 
143     /// function. 
144     /// 
145     /// Notice that data in 'samples' array can be disrupted in processing.
146     void inputSamples(soundtouch::SAMPLETYPE *samples,  ///< Pointer to input/working data buffer
147                       int numSamples                    ///< Number of samples in buffer
148                       );
149
150
151     /// Analyzes the results and returns the BPM rate. Use this function to read result
152     /// after whole song data has been input to the class by consecutive calls of
153     /// 'inputSamples' function.
154     ///
155     /// \return Beats-per-minute rate, or zero if detection failed.
156     float getBpm();
157 };
158
159 #endif // _BPMDetect_H_