1 #pragma once 2 3 #include <QByteArray> 4 #include <QList> 5 #include <QSharedPointer> 6 #include <QString> 7 8 #include "audio/types.h" 9 #include "util/memory.h" 10 #include "util/types.h" 11 12 namespace { 13 double kMaxBpm = 500; 14 } 15 16 namespace mixxx { 17 18 class Beats; 19 typedef QSharedPointer<Beats> BeatsPointer; 20 21 class BeatIterator { 22 public: 23 virtual ~BeatIterator() = default; 24 virtual bool hasNext() const = 0; 25 virtual double next() = 0; 26 }; 27 28 // Beats is the base class for BPM and beat management classes. It 29 // provides a specification of all methods a beat-manager class must provide, as 30 // well as a capability model for representing optional features. 31 class Beats { 32 public: 33 virtual ~Beats() = default; 34 35 enum Capabilities { 36 BEATSCAP_NONE = 0x0000, 37 BEATSCAP_ADDREMOVE = 0x0001, // Add or remove a single beat 38 BEATSCAP_TRANSLATE = 0x0002, // Move all beat markers earlier or later 39 BEATSCAP_SCALE = 0x0004, // Scale beat distance by a fixed ratio 40 BEATSCAP_MOVEBEAT = 0x0008, // Move a single Beat 41 BEATSCAP_SETBPM = 0x0010 // Set new bpm, beat grid only 42 }; 43 typedef int CapabilitiesFlags; // Allows us to do ORing 44 45 enum BPMScale { 46 DOUBLE, 47 HALVE, 48 TWOTHIRDS, 49 THREEFOURTHS, 50 FOURTHIRDS, 51 THREEHALVES, 52 }; 53 54 virtual Beats::CapabilitiesFlags getCapabilities() const = 0; 55 56 // Serialization 57 virtual QByteArray toByteArray() const = 0; 58 59 // A string representing the version of the beat-processing code that 60 // produced this Beats instance. Used by BeatsFactory for associating a 61 // given serialization with the version that produced it. 62 virtual QString getVersion() const = 0; 63 // A sub-version can be used to represent the preferences used to generate 64 // the beats object. 65 virtual QString getSubVersion() const = 0; 66 67 //////////////////////////////////////////////////////////////////////////// 68 // Beat calculations 69 //////////////////////////////////////////////////////////////////////////// 70 71 // TODO: We may want all of these find functions to return an integer 72 // instead of a double. 73 // TODO: We may want to implement these with common code that returns 74 // the triple of closest, next, and prev. 75 76 // Starting from sample dSamples, return the sample of the next beat in the 77 // track, or -1 if none exists. If dSamples refers to the location of a 78 // beat, dSamples is returned. 79 virtual double findNextBeat(double dSamples) const = 0; 80 81 // Starting from sample dSamples, return the sample of the previous beat in 82 // the track, or -1 if none exists. If dSamples refers to the location of 83 // beat, dSamples is returned. 84 virtual double findPrevBeat(double dSamples) const = 0; 85 86 // Starting from sample dSamples, fill the samples of the previous beat 87 // and next beat. Either can be -1 if none exists. If dSamples refers 88 // to the location of the beat, the first value is dSamples, and the second 89 // value is the next beat position. Non- -1 values are guaranteed to be 90 // even. Returns false if *at least one* sample is -1. (Can return false 91 // with one beat successfully filled) 92 virtual bool findPrevNextBeats(double dSamples, 93 double* dpPrevBeatSamples, 94 double* dpNextBeatSamples) const = 0; 95 96 // Starting from sample dSamples, return the sample of the closest beat in 97 // the track, or -1 if none exists. Non- -1 values are guaranteed to be 98 // even. 99 virtual double findClosestBeat(double dSamples) const = 0; 100 101 // Find the Nth beat from sample dSamples. Works with both positive and 102 // negative values of n. Calling findNthBeat with n=0 is invalid. Calling 103 // findNthBeat with n=1 or n=-1 is equivalent to calling findNextBeat and 104 // findPrevBeat, respectively. If dSamples refers to the location of a beat, 105 // then dSamples is returned. If no beat can be found, returns -1. 106 virtual double findNthBeat(double dSamples, int n) const = 0; 107 108 int numBeatsInRange(double dStartSample, double dEndSample) const; 109 110 // Find the sample N beats away from dSample. The number of beats may be 111 // negative and does not need to be an integer. 112 double findNBeatsFromSample(double fromSample, double beats) const; 113 114 115 // Adds to pBeatsList the position in samples of every beat occurring between 116 // startPosition and endPosition. BeatIterator must be iterated while 117 // holding a strong references to the Beats object to ensure that the Beats 118 // object is not deleted. Caller takes ownership of the returned BeatIterator; 119 virtual std::unique_ptr<BeatIterator> findBeats(double startSample, double stopSample) const = 0; 120 121 // Return whether or not a sample lies between startPosition and endPosition 122 virtual bool hasBeatInRange(double startSample, double stopSample) const = 0; 123 124 // Return the average BPM over the entire track if the BPM is 125 // valid, otherwise returns -1 126 virtual double getBpm() const = 0; 127 128 // Return the average BPM over the range of n*2 beats centered around 129 // curSample. (An n of 4 results in an averaging of 8 beats). Invalid 130 // BPM returns -1. 131 virtual double getBpmAroundPosition(double curSample, int n) const = 0; 132 getMaxBpm()133 virtual double getMaxBpm() const { 134 return kMaxBpm; 135 } 136 137 virtual audio::SampleRate getSampleRate() const = 0; 138 139 //////////////////////////////////////////////////////////////////////////// 140 // Beat mutations 141 //////////////////////////////////////////////////////////////////////////// 142 143 // Translate all beats in the song by dNumSamples samples. Beats that lie 144 // before the start of the track or after the end of the track are not 145 // removed. Beats instance must have the capability BEATSCAP_TRANSLATE. 146 virtual BeatsPointer translate(double dNumSamples) const = 0; 147 148 // Scale the position of every beat in the song by dScalePercentage. Beats 149 // class must have the capability BEATSCAP_SCALE. 150 virtual BeatsPointer scale(enum BPMScale scale) const = 0; 151 152 // Adjust the beats so the global average BPM matches dBpm. Beats class must 153 // have the capability BEATSCAP_SET. 154 virtual BeatsPointer setBpm(double dBpm) = 0; 155 }; 156 157 } // namespace mixxx 158