To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / BeatRootProcessor.h @ 22:6afcb5edd7ab

History | View | Annotate | Download (5.3 KB)

1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

    
3
/*
4
  Vamp feature extraction plugin for the BeatRoot beat tracker.
5

6
  Centre for Digital Music, Queen Mary, University of London.
7
  This file copyright 2011 Simon Dixon, Chris Cannam and QMUL.
8
    
9
  This program is free software; you can redistribute it and/or
10
  modify it under the terms of the GNU General Public License as
11
  published by the Free Software Foundation; either version 2 of the
12
  License, or (at your option) any later version.  See the file
13
  COPYING included with this distribution for more information.
14
*/
15

    
16
#ifndef _BEATROOT_PROCESSOR_H_
17
#define _BEATROOT_PROCESSOR_H_
18

    
19
#include "Peaks.h"
20
#include "Event.h"
21
#include "BeatTracker.h"
22

    
23
#include <vector>
24
#include <cmath>
25

    
26
#ifdef DEBUG_BEATROOT
27
#include <iostream>
28
#endif
29

    
30
using std::vector;
31

    
32
class BeatRootProcessor
33
{
34
public:
35
    int getFFTSize() const { return fftSize; }
36
    int getHopSize() const { return hopSize; }
37

    
38
protected:
39
    /** Sample rate of audio */
40
    float sampleRate;
41
        
42
    /** Spacing of audio frames (determines the amount of overlap or
43
     *  skip between frames). This value is expressed in
44
     *  seconds. (Default = 0.020s) */
45
    double hopTime;
46

    
47
    /** The approximate size of an FFT frame in seconds. (Default =
48
     *  0.04644s).  The value is adjusted so that <code>fftSize</code>
49
     *  is always power of 2. */
50
    double fftTime;
51

    
52
    /** Spacing of audio frames in samples (see <code>hopTime</code>) */
53
    int hopSize;
54

    
55
    /** The size of an FFT frame in samples (see <code>fftTime</code>) */
56
    int fftSize;
57

    
58
    /** Spectral flux onset detection function, indexed by frame. */
59
    vector<double> spectralFlux;
60
        
61
    /** A mapping function for mapping FFT bins to final frequency bins.
62
     *  The mapping is linear (1-1) until the resolution reaches 2 points per
63
     *  semitone, then logarithmic with a semitone resolution.  e.g. for
64
     *  44.1kHz sampling rate and fftSize of 2048 (46ms), bin spacing is
65
     *  21.5Hz, which is mapped linearly for bins 0-34 (0 to 732Hz), and
66
     *  logarithmically for the remaining bins (midi notes 79 to 127, bins 35 to
67
     *  83), where all energy above note 127 is mapped into the final bin. */
68
    vector<int> freqMap;
69

    
70
    /** The number of entries in <code>freqMap</code>. Note that the length of
71
     *  the array is greater, because its size is not known at creation time. */
72
    int freqMapSize;
73

    
74
    /** The magnitude spectrum of the most recent frame.  Used for
75
     *  calculating the spectral flux. */
76
    vector<double> prevFrame;
77

    
78
    /** The estimated onset times from peak-picking the onset
79
     * detection function(s). */
80
    vector<double> onsets;
81
        
82
    /** The estimated onset times and their saliences. */        
83
    EventList onsetList;
84
        
85
    /** Flag for suppressing all standard output messages except results. */
86
    static bool silent;
87
        
88
public:
89

    
90
    /** Constructor: note that streams are not opened until the input
91
     *  file is set (see <code>setInputFile()</code>). */
92
    BeatRootProcessor(float sr) :
93
        sampleRate(sr) {
94
        hopSize = 0;
95
        fftSize = 0;
96
        hopTime = 0.010;
97
        fftTime = 0.04644;
98
        hopSize = lrint(sampleRate * hopTime);
99
        fftSize = lrint(pow(2, lrint( log(fftTime * sampleRate) / log(2))));
100
    } // constructor
101

    
102
    void reset() {
103
        init();
104
    }
105

    
106
    /** Processes a frame of frequency-domain audio data by mapping
107
     *  the frequency bins into a part-linear part-logarithmic array,
108
     *  then computing the spectral flux then (optionally) normalising
109
     *  and calculating onsets.
110
     */
111
    void processFrame(const float *const *inputBuffers);
112

    
113
    /** Tracks beats once all frames have been processed by processFrame
114
     */
115
    EventList beatTrack();
116

    
117
protected:
118
    /** Allocates memory for arrays, based on parameter settings */
119
    void init() {
120
#ifdef DEBUG_BEATROOT
121
        std::cerr << "BeatRootProcessor::init()" << std::endl;
122
#endif
123
        makeFreqMap(fftSize, sampleRate);
124
        prevFrame.clear();
125
        for (int i = 0; i <= fftSize/2; i++) prevFrame.push_back(0);
126
        spectralFlux.clear();
127
        onsets.clear();
128
        onsetList.clear();
129
    } // init()
130

    
131
    /** Creates a map of FFT frequency bins to comparison bins.
132
     *  Where the spacing of FFT bins is less than 0.5 semitones, the mapping is
133
     *  one to one. Where the spacing is greater than 0.5 semitones, the FFT
134
     *  energy is mapped into semitone-wide bins. No scaling is performed; that
135
     *  is the energy is summed into the comparison bins. See also
136
     *  processFrame()
137
     */
138
    void makeFreqMap(int fftSize, float sampleRate) {
139
        freqMap.resize(fftSize/2+1);
140
        double binWidth = sampleRate / fftSize;
141
        int crossoverBin = (int)(2 / (pow(2, 1/12.0) - 1));
142
        int crossoverMidi = (int)lrint(log(crossoverBin*binWidth/440)/
143
                                       log(2) * 12 + 69);
144
        int i = 0;
145
        while (i <= crossoverBin && i <= fftSize/2) {
146
            freqMap[i] = i;
147
            ++i;
148
        }
149
        while (i <= fftSize/2) {
150
            double midi = log(i*binWidth/440) / log(2) * 12 + 69;
151
            if (midi > 127)
152
                midi = 127;
153
            freqMap[i] = crossoverBin + (int)lrint(midi) - crossoverMidi;
154
            ++i;
155
        }
156
        freqMapSize = freqMap[i-1] + 1;
157
    } // makeFreqMap()
158

    
159
}; // class AudioProcessor
160

    
161

    
162
#endif