summaryrefslogtreecommitdiffstats
path: root/src/track/beatgrid.h
blob: 0aa7a3b7aa7f3c94432c3c56474dba44dd5b4391 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#pragma once

#include "proto/beats.pb.h"
#include "track/beats.h"

#define BEAT_GRID_1_VERSION "BeatGrid-1.0"
#define BEAT_GRID_2_VERSION "BeatGrid-2.0"

class Track;

namespace mixxx {

// BeatGrid is an implementation of the Beats interface that implements an
// infinite grid of beats, aligned to a song simply by a starting offset of the
// first beat and the song's average beats-per-minute.
class BeatGrid final : public Beats {
  public:
    ~BeatGrid() override = default;

    static BeatsPointer makeBeatGrid(
            audio::SampleRate sampleRate,
            mixxx::Bpm bpm,
            mixxx::audio::FramePos firstBeatPositionOnFrameBoundary,
            const QString& subVersion = QString());

    static BeatsPointer fromByteArray(
            audio::SampleRate sampleRate,
            const QString& subVersion,
            const QByteArray& byteArray);

    // The following are all methods from the Beats interface, see method
    // comments in beats.h

    bool hasConstantTempo() const override {
        return true;
    }

    QByteArray toByteArray() const override;
    QString getVersion() const override;
    QString getSubVersion() const override;

    ////////////////////////////////////////////////////////////////////////////
    // Beat calculations
    ////////////////////////////////////////////////////////////////////////////

    bool findPrevNextBeats(audio::FramePos position,
            audio::FramePos* prevBeatPosition,
            audio::FramePos* nextBeatPosition,
            bool snapToNearBeats) const override;
    audio::FramePos findNthBeat(audio::FramePos position, int n) const override;
    std::unique_ptr<BeatIterator> findBeats(audio::FramePos startPosition,
            audio::FramePos endPosition) const override;
    bool hasBeatInRange(audio::FramePos startPosition, audio::FramePos endPosition) const override;
    mixxx::Bpm getBpm() const override;
    mixxx::Bpm getBpmAroundPosition(audio::FramePos position, int n) const override;

    audio::SampleRate getSampleRate() const override {
        return m_sampleRate;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Beat mutations
    ////////////////////////////////////////////////////////////////////////////

    BeatsPointer translate(audio::FrameDiff_t offset) const override;
    BeatsPointer scale(BpmScale scale) const override;
    BeatsPointer setBpm(mixxx::Bpm bpm) override;

  private:
    BeatGrid(
            audio::SampleRate sampleRate,
            const QString& subVersion,
            const mixxx::track::io::BeatGrid& grid,
            double beatLength);
    // Constructor to update the beat grid
    BeatGrid(const BeatGrid& other, const mixxx::track::io::BeatGrid& grid, double beatLength);
    BeatGrid(const BeatGrid& other);

    audio::FramePos firstBeatPosition() const;
    mixxx::Bpm bpm() const;

    bool isValid() const override;

    // The sub-version of this beatgrid.
    const QString m_subVersion;
    // The number of samples per second
    const audio::SampleRate m_sampleRate;
    // Data storage for BeatGrid
    const mixxx::track::io::BeatGrid m_grid;
    // The length of a beat in samples
    const audio::FrameDiff_t m_beatLengthFrames;
};

} // namespace mixxx