Skip to content

Commit

Permalink
Update tempo label data
Browse files Browse the repository at this point in the history
  • Loading branch information
FangCunWuChang committed Jul 17, 2024
1 parent e33fcc6 commit 29d2566
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 66 deletions.
7 changes: 2 additions & 5 deletions src/audioCore/AudioCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,9 @@ bool AudioCore::parse(const google::protobuf::Message* data) {

{
juce::ScopedTryWriteLock locker(audioLock::getPositionLock());
auto& tempos = PlayPosition::getInstance()->getTempoSequence();
tempos.clear();
if (tempoFile.getNumTracks() > 0) {
tempos = *(tempoFile.getTrack(0));
PlayPosition::getInstance()->setTempoSequence(*(tempoFile.getTrack(0)));
}
PlayPosition::getInstance()->updateTempoTemp();
}
}

Expand All @@ -381,7 +378,7 @@ std::unique_ptr<google::protobuf::Message> AudioCore::serialize() const {

/** Get Tempo */
{
auto& tempos = PlayPosition::getInstance()->getTempoSequence();
auto tempos = PlayPosition::getInstance()->getTempoSequence();
juce::MidiFile tempoFile;
tempoFile.addTrack(tempos);

Expand Down
157 changes: 111 additions & 46 deletions src/audioCore/misc/PlayPosition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,24 @@ std::tuple<int, double> MovablePlayHead::toBarQ(double timeQuarter) const {
return { barCount, timeQuarter - quarterInBar };
}

juce::MidiMessageSequence& MovablePlayHead::getTempoSequence() {
return this->tempos;
void MovablePlayHead::setTempoSequence(const juce::MidiMessageSequence& seq) {
this->tempos.clear();
this->insertTempoSequence(seq);
}

void MovablePlayHead::insertTempoSequence(const juce::MidiMessageSequence& seq) {
for (auto i : seq) {
this->insert(i->message);
}
this->updateTempoTemp();
}

const juce::MidiMessageSequence MovablePlayHead::getTempoSequence() const {
juce::MidiMessageSequence result;
for (auto& event : this->tempos) {
result.addEvent(event, 0);
}
return result;
}

void MovablePlayHead::updateTempoTemp() {
Expand Down Expand Up @@ -191,15 +207,14 @@ const juce::Array<MovablePlayHead::TempoLabelData> MovablePlayHead::getTempoData
int numeratorTemp = 4, denominatorTemp = 4;

/** Get Each Label */
for (auto i : this->tempos) {
auto& mes = i->message;
if (mes.isTempoMetaEvent()) {
tempoTemp = 1.0 / mes.getTempoSecondsPerQuarterNote() * 60.0;
result.add({ mes.getTimeStamp(), tempoTemp, numeratorTemp, denominatorTemp, true });
for (auto &i : this->tempos) {
if (i.isTempoMetaEvent()) {
tempoTemp = 1.0 / i.getTempoSecondsPerQuarterNote() * 60.0;
result.add({ i.getTimeStamp(), tempoTemp, numeratorTemp, denominatorTemp, true });
}
else if (mes.isTimeSignatureMetaEvent()) {
mes.getTimeSignatureInfo(numeratorTemp, denominatorTemp);
result.add({ mes.getTimeStamp(), tempoTemp, numeratorTemp, denominatorTemp, false });
else if (i.isTimeSignatureMetaEvent()) {
i.getTimeSignatureInfo(numeratorTemp, denominatorTemp);
result.add({ i.getTimeStamp(), tempoTemp, numeratorTemp, denominatorTemp, false });
}
}

Expand Down Expand Up @@ -228,12 +243,8 @@ bool MovablePlayHead::checkOverflow() const {
}

int MovablePlayHead::addTempoLabelTempo(double time, double tempo) {
/** Get Index */
time = std::max(time, 0.0);
int index = this->getTempoInsertIndex(time);

/** Insert Label */
this->tempos.addEvent(juce::MidiMessage::tempoMetaEvent(
int index = this->insert(juce::MidiMessage::tempoMetaEvent(
1000000.0 / (tempo / 60.0)).withTimeStamp(time));
this->updateTempoTemp();

Expand All @@ -242,12 +253,8 @@ int MovablePlayHead::addTempoLabelTempo(double time, double tempo) {
}

int MovablePlayHead::addTempoLabelBeat(double time, int numerator, int denominator) {
/** Get Index */
time = std::max(time, 0.0);
int index = this->getTempoInsertIndex(time);

/** Insert Label */
this->tempos.addEvent(juce::MidiMessage::timeSignatureMetaEvent(
int index = this->insert(juce::MidiMessage::timeSignatureMetaEvent(
numerator, denominator).withTimeStamp(time));
this->updateTempoTemp();

Expand All @@ -256,41 +263,52 @@ int MovablePlayHead::addTempoLabelBeat(double time, int numerator, int denominat
}

void MovablePlayHead::removeTempoLabel(int index) {
this->tempos.deleteEvent(index, false);
this->remove(index);

/** Update Temp */
this->updateTempoTemp();
}

int MovablePlayHead::getTempoLabelNum() const {
return this->tempos.getNumEvents();
return this->tempos.size();
}

bool MovablePlayHead::isTempoLabelTempoEvent(int index) const {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
return ptrEvent->message.isTempoMetaEvent();
if (index >= 0 && index < this->tempos.size()) {
auto& event = this->tempos.getReference(index);
return event.isTempoMetaEvent();
}
return false;
}

void MovablePlayHead::setTempoLabelTime(int index, double time) {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
int MovablePlayHead::setTempoLabelTime(int index, double time) {
if (index >= 0 && index < this->tempos.size()) {
/** Remove */
auto event = this->remove(index);

/** Set Message Time */
time = std::max(time, 0.0);
ptrEvent->message.setTimeStamp(time);
this->tempos.sort();
event.setTimeStamp(time);

/** Add */
int newIndex = this->insert(event);

/** Update Temp */
this->updateTempoTemp();

/** Return */
return newIndex;
}
return index;
}

void MovablePlayHead::setTempoLabelTempo(int index, double tempo) {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
if (ptrEvent->message.isTempoMetaEvent()) {
if (index >= 0 && index < this->tempos.size()) {
auto& event = this->tempos.getReference(index);
if (event.isTempoMetaEvent()) {
/** Set Message Tempo */
double time = ptrEvent->message.getTimeStamp();
ptrEvent->message = juce::MidiMessage::tempoMetaEvent(
double time = event.getTimeStamp();
event = juce::MidiMessage::tempoMetaEvent(
1000000.0 / (tempo / 60.0)).withTimeStamp(time);

/** Update Temp */
Expand All @@ -301,11 +319,12 @@ void MovablePlayHead::setTempoLabelTempo(int index, double tempo) {

void MovablePlayHead::setTempoLabelBeat(
int index, int numerator, int denominator) {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
if (ptrEvent->message.isTimeSignatureMetaEvent()) {
if (index >= 0 && index < this->tempos.size()) {
auto& event = this->tempos.getReference(index);
if (event.isTimeSignatureMetaEvent()) {
/** Set Message Beat */
double time = ptrEvent->message.getTimeStamp();
ptrEvent->message = juce::MidiMessage::timeSignatureMetaEvent(
double time = event.getTimeStamp();
event = juce::MidiMessage::timeSignatureMetaEvent(
numerator, denominator).withTimeStamp(time);

/** Update Temp */
Expand All @@ -315,28 +334,48 @@ void MovablePlayHead::setTempoLabelBeat(
}

double MovablePlayHead::getTempoLabelTime(int index) const {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
return ptrEvent->message.getTimeStamp();
if (index >= 0 && index < this->tempos.size()) {
auto& event = this->tempos.getReference(index);
return event.getTimeStamp();
}
return 0;
}

double MovablePlayHead::getTempoLabelTempo(int index) const {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
return 1 / ptrEvent->message.getTempoSecondsPerQuarterNote() * 60;
if (index >= 0 && index < this->tempos.size()) {
auto& event = this->tempos.getReference(index);

return 1 / event.getTempoSecondsPerQuarterNote() * 60;
}
return 120;
}

std::tuple<int, int> MovablePlayHead::getTempoLabelBeat(int index) const {
if (auto ptrEvent = this->tempos.getEventPointer(index)) {
if (index >= 0 && index < this->tempos.size()) {
auto& event = this->tempos.getReference(index);

int numeratorTemp = 4, denominatorTemp = 4;
ptrEvent->message.getTimeSignatureInfo(numeratorTemp, denominatorTemp);
event.getTimeSignatureInfo(numeratorTemp, denominatorTemp);
return { numeratorTemp, denominatorTemp };
}
return { 4, 4 };
}

int MovablePlayHead::insert(const juce::MidiMessage& mes) {
int index = this->getTempoInsertIndex(mes.getTimeStamp());
this->tempos.insert(index, mes);
return index;
}

const juce::MidiMessage MovablePlayHead::remove(int index) {
if (index >= 0 && index < this->tempos.size()) {
auto event = this->tempos.getUnchecked(index);
this->tempos.remove(index);
return event;
}
return {};
}

void MovablePlayHead::updatePositionByTimeInSecond() {
double time = this->position.getTimeInSeconds().orFallback(0);
this->position.setTimeInSamples((int64_t)std::floor(time * this->sampleRate));
Expand All @@ -361,13 +400,39 @@ void MovablePlayHead::updatePositionByTimeInSample() {
}

int MovablePlayHead::getTempoInsertIndex(double time) const {
for (int i = this->tempos.getNumEvents() - 1; i >= 0; i--) {
auto ptrEvent = this->tempos.getEventPointer(i);
if (ptrEvent->message.getTimeStamp() >= time) {
/** No Events */
if (this->tempos.size() == 0) {
return 0;
}

/** Last */
{
auto& last = this->tempos.getReference(this->tempos.size() - 1);
if (last.getTimeStamp() <= time) {
return this->tempos.size();
}
}

/** First */
{
auto& first = this->tempos.getReference(0);
if (first.getTimeStamp() > time) {
return 0;
}
}

/** Insert */
for (int i = 0; i < this->tempos.size() - 1; i++) {
auto& last = this->tempos.getReference(i);
auto& next = this->tempos.getReference(i + 1);
if (last.getTimeStamp() <= time &&
next.getTimeStamp() > time) {
return i + 1;
}
}
return 0;

/** Error */
return -1;
}

PlayPosition* PlayPosition::getInstance() {
Expand Down
11 changes: 8 additions & 3 deletions src/audioCore/misc/PlayPosition.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class MovablePlayHead : public juce::AudioPlayHead {
/** BarCount, BarStartQuarter */
std::tuple<int, double> toBarQ(double timeQuarter) const;

juce::MidiMessageSequence& getTempoSequence();
void setTempoSequence(const juce::MidiMessageSequence& seq);
void insertTempoSequence(const juce::MidiMessageSequence& seq);
const juce::MidiMessageSequence getTempoSequence() const;
void updateTempoTemp();
int getTempoTempIndexBySec(double timeSec) const;
int getTempoTempIndexByQuarter(double timeQuarter) const;
Expand All @@ -55,7 +57,7 @@ class MovablePlayHead : public juce::AudioPlayHead {
void removeTempoLabel(int index);
int getTempoLabelNum() const;
bool isTempoLabelTempoEvent(int index) const;
void setTempoLabelTime(int index, double time);
int setTempoLabelTime(int index, double time);
void setTempoLabelTempo(int index, double tempo);
void setTempoLabelBeat(int index, int numerator, int denominator);
double getTempoLabelTime(int index) const;
Expand All @@ -66,13 +68,16 @@ class MovablePlayHead : public juce::AudioPlayHead {

protected:
mutable juce::AudioPlayHead::PositionInfo position;
juce::MidiMessageSequence tempos;
juce::Array<juce::MidiMessage> tempos;
TempoTemp tempoTemp;
std::atomic_short timeFormat = 480;
std::atomic<double> sampleRate = 48000;
std::atomic_bool overflowFlag = false;
std::atomic<double> loopStartSec = 0, loopEndSec = 0;

int insert(const juce::MidiMessage& mes);
const juce::MidiMessage remove(int index);

void updatePositionByTimeInSecond();
void updatePositionByTimeInSample();

Expand Down
16 changes: 8 additions & 8 deletions src/audioCore/misc/TempoTemp.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#include "TempoTemp.h"

TempoTemp::TempoTemp() {
this->update(juce::MidiMessageSequence{});
this->update(juce::Array<juce::MidiMessage>{});
}

void TempoTemp::update(
const juce::MidiMessageSequence& tempoMessages) {
const juce::Array<juce::MidiMessage>& tempoMessages) {
/** Clear Temp */
this->temp.clear();
this->lastIndex = -1;
Expand All @@ -22,10 +22,10 @@ void TempoTemp::update(
tempoTemp.add({ thisSec, thisQuarter, thisSPQ });

/** Get Each Tempo Meta */
int numEvents = tempoMessages.getNumEvents();
int numEvents = tempoMessages.size();
for (int i = 0; i < numEvents; i++) {
/** Get Event */
auto& m = tempoMessages.getEventPointer(i)->message;
auto& m = tempoMessages.getReference(i);
double eventTime = m.getTimeStamp();

/** Store Event */
Expand All @@ -52,7 +52,7 @@ void TempoTemp::update(

/** Skip Same Time Forward */
while (i + 1 < numEvents) {
auto& m2 = tempoMessages.getEventPointer(i + 1)->message;
auto& m2 = tempoMessages.getReference(i + 1);

if (!juce::approximatelyEqual(m2.getTimeStamp(), eventTime))
break;
Expand Down Expand Up @@ -100,10 +100,10 @@ void TempoTemp::update(
thisNumerator, thisDenominator });

/** Get Each Beat Meta */
int numEvents = tempoMessages.getNumEvents();
int numEvents = tempoMessages.size();
for (int i = 0; i < numEvents; i++) {
/** Get Event */
auto& m = tempoMessages.getEventPointer(i)->message;
auto& m = tempoMessages.getReference(i);
double eventTime = m.getTimeStamp();

/** Store Event */
Expand Down Expand Up @@ -185,7 +185,7 @@ void TempoTemp::update(

/** Skip Same Time Forward */
while (i + 1 < numEvents) {
auto& m2 = tempoMessages.getEventPointer(i + 1)->message;
auto& m2 = tempoMessages.getReference(i + 1);

if (!juce::approximatelyEqual(m2.getTimeStamp(), eventTime))
break;
Expand Down
2 changes: 1 addition & 1 deletion src/audioCore/misc/TempoTemp.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class TempoTemp final {
public:
TempoTemp();

void update(const juce::MidiMessageSequence& tempoMessages);
void update(const juce::Array<juce::MidiMessage>& tempoMessages);
int selectBySec(double time) const;
int selectByTick(double timeTick, short timeFormat) const;
int selectByQuarter(double timeQuarter) const;
Expand Down
4 changes: 1 addition & 3 deletions src/audioCore/source/SourceIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ void SourceIO::run() {
if (getTempo) {
juce::MessageManager::callAsync(
[tempo] {
auto& tempoSeq = PlayPosition::getInstance()->getTempoSequence();
tempoSeq.addSequence(tempo, 0);
PlayPosition::getInstance()->updateTempoTemp();
PlayPosition::getInstance()->insertTempoSequence(tempo);
}
);
}
Expand Down

0 comments on commit 29d2566

Please sign in to comment.