Skip to content

Commit

Permalink
track playhead time
Browse files Browse the repository at this point in the history
  • Loading branch information
yuxshao committed Nov 20, 2022
1 parent 6f64e22 commit 7b34da6
Show file tree
Hide file tree
Showing 21 changed files with 116 additions and 89 deletions.
8 changes: 3 additions & 5 deletions src/editor/EditorWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ EditorWindow::EditorWindow(QWidget *parent)

m_key_splitter = new QSplitter(Qt::Vertical, m_splitter);
m_scroll_area = new EditorScrollArea(m_key_splitter, true);
m_keyboard_view = new KeyboardView(m_client, m_moo_clock, m_scroll_area);
m_keyboard_view = new KeyboardView(m_client, m_scroll_area);
m_scroll_area->setWidget(m_keyboard_view);

// TODO: find a better place for this.
Expand Down Expand Up @@ -185,14 +185,12 @@ EditorWindow::EditorWindow(QWidget *parent)

m_param_scroll_area = new EditorScrollArea(m_key_splitter, false);
m_param_scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_param_scroll_area->setWidget(
new ParamView(m_client, m_moo_clock, m_param_scroll_area));
m_param_scroll_area->setWidget(new ParamView(m_client, m_param_scroll_area));

m_measure_scroll_area = new EditorScrollArea(m_splitter, false);
m_measure_scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_measure_scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_measure_view =
new MeasureView(m_client, m_moo_clock, m_measure_scroll_area);
m_measure_view = new MeasureView(m_client, m_measure_scroll_area);
m_measure_scroll_area->setWidget(m_measure_view);
m_measure_scroll_area->setSizePolicy(
QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
Expand Down
4 changes: 2 additions & 2 deletions src/editor/EditorWindow.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QEvent>
#include <QFile>
#include <QLabel>
#include <QMainWindow>
Expand All @@ -27,7 +28,6 @@
#include "sidemenu/UnitListModel.h"
#include "views/KeyboardView.h"
#include "views/MeasureView.h"
#include <QEvent>

QT_BEGIN_NAMESPACE
namespace Ui {
Expand Down Expand Up @@ -55,7 +55,7 @@ class EditorWindow : public QMainWindow {
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void closeEvent(QCloseEvent* event) override;
bool eventFilter(QObject *watched, QEvent *event) override;
bool eventFilter(QObject* watched, QEvent* event) override;
KeyboardView* m_keyboard_view;
MeasureView* m_measure_view;
pxtnService m_pxtn;
Expand Down
10 changes: 5 additions & 5 deletions src/editor/PxtoneClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ void PxtoneClient::loadDescriptor(pxtnDescriptor &desc) {
}
{
bool ok;
double v = Settings::value(BUFFER_LENGTH_KEY, DEFAULT_BUFFER_LENGTH)
.toDouble(&ok);
double v =
Settings::value(BUFFER_LENGTH_KEY, DEFAULT_BUFFER_LENGTH).toDouble(&ok);
if (ok) setBufferSize(v);
}
m_pxtn_device->setPlaying(false);
Expand Down Expand Up @@ -156,13 +156,13 @@ void PxtoneClient::togglePlayState() {
}

void PxtoneClient::sendPlayState(bool from_action) {
sendAction(PlayState{pxtn()->moo_get_now_clock(*moo()),
m_pxtn_device->playing(), from_action});
sendAction(
PlayState{moo()->get_now_clock(), m_pxtn_device->playing(), from_action});
}

void PxtoneClient::resetAndSuspendAudio() {
m_pxtn_device->setPlaying(false);
if (pxtn()->moo_get_now_clock(*moo()) > m_last_seek)
if (moo()->get_now_clock() > m_last_seek)
seekMoo(m_last_seek);
else
seekMoo(0);
Expand Down
10 changes: 4 additions & 6 deletions src/editor/PxtoneController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
#include <QDialog>
#include <QTextCodec>

#include "audio/RtAudioRenderer.h"

const QTextCodec *shift_jis_codec = QTextCodec::codecForName("Shift-JIS");

PxtoneController::PxtoneController(int uid, pxtnService *pxtn,
mooState *moo_state, QObject *parent)
: QObject(parent),
m_audio_renderer(std::make_unique<RtAudioRenderer>(pxtn)),
m_uid(uid),
m_pxtn(pxtn),
m_moo_state(moo_state),
Expand Down Expand Up @@ -398,9 +397,7 @@ void PxtoneController::seekMoo(int64_t clock) {
emit seeked(clock);
}

void PxtoneController::refreshMoo() {
seekMoo(m_pxtn->moo_get_now_clock(*m_moo_state));
}
void PxtoneController::refreshMoo() { seekMoo(m_moo_state->get_now_clock()); }

void PxtoneController::setVolume(int volume) {
double v = volume / 100.0;
Expand All @@ -420,6 +417,7 @@ void PxtoneController::setSongComment(const QString &comment) {
}

bool PxtoneController::loadDescriptor(pxtnDescriptor &desc) {
m_audio_renderer.reset();
emit beginRefresh();
if (desc.get_size_bytes() > 0) {
if (m_pxtn->read(&desc) != pxtnOK) {
Expand Down Expand Up @@ -450,7 +448,7 @@ bool PxtoneController::loadDescriptor(pxtnDescriptor &desc) {
emit tempoBeatChanged();
emit newSong();

new RtAudioRenderer(m_pxtn);
m_audio_renderer = std::make_unique<RtAudioRenderer>(m_pxtn);

return true;
}
Expand Down
3 changes: 3 additions & 0 deletions src/editor/PxtoneController.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <list>

#include "audio/PxtoneIODevice.h"
#include "audio/RtAudioRenderer.h"
#include "protocol/PxtoneEditAction.h"
#include "protocol/RemoteAction.h"

Expand Down Expand Up @@ -62,6 +63,8 @@ class PxtoneController : public QObject {
return true;
}) const;

std::unique_ptr<RtAudioRenderer> m_audio_renderer;

public slots:
// Maybe these types could be grouped.
void applyRemoteAction(const EditAction &a, qint64 uid);
Expand Down
16 changes: 14 additions & 2 deletions src/editor/audio/RtAudioRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

#include <QDebug>

int MooTiming::now_no_wrap(const pxtnMaster *master) {
return MasterExtended::unwrapClock(master, now_clock, num_loops);
}

const unsigned int BUFFER_FRAMES =
256; // At higher buffers, this does stuttter. So you will need a
// MooClock-like thing anyway.
int rtAudioMoo(void *outputBuffer, void * /*inputBuffer*/,
unsigned int nBufferFrames, double /*streamTime*/,
RtAudioStreamStatus status, void *userData) {
Expand All @@ -17,6 +24,8 @@ int rtAudioMoo(void *outputBuffer, void * /*inputBuffer*/,
if (!renderer->m_pxtn->Moo(renderer->m_moo_state, outputBuffer, size, nullptr,
nullptr))
return 1;
renderer->m_moo_timing.store(
{renderer->m_moo_state.get_now_clock(), renderer->m_moo_state.num_loop});

return 0;
}
Expand All @@ -26,6 +35,7 @@ RtAudioRenderer::RtAudioRenderer(const pxtnService *pxtn)
if (m_dac.getDeviceCount() < 1)
throw std::runtime_error("No audio devices found");

qDebug() << "lock free" << m_moo_timing.is_lock_free();
RtAudio::StreamParameters parameters;
parameters.deviceId = m_dac.getDefaultOutputDevice();
parameters.nChannels = 2;
Expand All @@ -40,13 +50,15 @@ RtAudioRenderer::RtAudioRenderer(const pxtnService *pxtn)
}

int sampleRate = 44100;
unsigned int bufferFrames = 256; // 256 sample frames
unsigned int bufferFrames = BUFFER_FRAMES;
m_dac.openStream(&parameters, NULL, RTAUDIO_SINT16, sampleRate, &bufferFrames,
&rtAudioMoo, this);
m_dac.startStream();
qDebug() << "started stream";
qDebug() << "started stream" << bufferFrames;
}

MooTiming RtAudioRenderer::moo_timing() const { return m_moo_timing.load(); }

RtAudioRenderer::~RtAudioRenderer() {
try {
m_dac.stopStream();
Expand Down
12 changes: 12 additions & 0 deletions src/editor/audio/RtAudioRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,29 @@

#include <RtAudio.h>

#include <atomic>

#include "pxtone/pxtnService.h"

struct MooTiming {
int now_clock;
int num_loops;

int now_no_wrap(const pxtnMaster *master);
};

class RtAudioRenderer {
const pxtnService *m_pxtn;
std::atomic<MooTiming> m_moo_timing;
mooState m_moo_state;
RtAudio m_dac;
friend int rtAudioMoo(void *, void *, unsigned int, double,
RtAudioStreamStatus, void *);

public:
RtAudioRenderer(const pxtnService *pxtn);
MooTiming moo_timing() const;

~RtAudioRenderer();
};

Expand Down
24 changes: 13 additions & 11 deletions src/editor/views/KeyboardView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ void KeyboardView::setHoveredUnitNo(std::optional<int> new_unit_no) {
}
}

KeyboardView::KeyboardView(PxtoneClient *client, MooClock *moo_clock,
QScrollArea *parent)
KeyboardView::KeyboardView(PxtoneClient *client, QScrollArea *parent)
: QWidget(parent),
m_scrollarea(parent),
m_pxtn(client->pxtn()),
Expand All @@ -50,7 +49,6 @@ KeyboardView::KeyboardView(PxtoneClient *client, MooClock *moo_clock,
m_audio_note_preview(nullptr),
m_anim(new Animation(this)),
m_client(client),
m_moo_clock(moo_clock),
m_select_unit_enabled(false),
m_last_left_kb_pitch(0),
m_test_activity(false) {
Expand Down Expand Up @@ -87,7 +85,9 @@ KeyboardView::KeyboardView(PxtoneClient *client, MooClock *moo_clock,
void KeyboardView::ensurePlayheadFollowed() {
bool follow_exactly =
m_client->editState().m_follow_playhead == FollowPlayhead::Follow;
double logicalX = m_moo_clock->now() / m_client->editState().scale.clockPerPx;
double logicalX =
m_client->controller()->m_audio_renderer->moo_timing().now_clock /
m_client->editState().scale.clockPerPx;
double x = worldTransform().map(QPointF(logicalX, 0)).x();
emit ensureVisibleX(x, follow_exactly);
}
Expand Down Expand Up @@ -579,7 +579,7 @@ void KeyboardView::paintEvent(QPaintEvent *raw_event) {
std::vector<DrawState> drawStates;
for (int i = 0; i < m_pxtn->Unit_Num(); ++i) drawStates.emplace_back();

int clock = m_moo_clock->now();
int clock = m_client->controller()->m_audio_renderer->moo_timing().now_clock;

// Draw the note blocks! Upon hitting an event, see if we are able to draw a
// previous block.
Expand Down Expand Up @@ -659,7 +659,7 @@ void KeyboardView::paintEvent(QPaintEvent *raw_event) {
}

double on_strength = 0;
if (m_client->isPlaying()) {
if (m_client->isPlaying() || true) {
if (clock >= on.start) {
if (!m_dark)
on_strength = clock < on.end ? 1 : 0;
Expand Down Expand Up @@ -788,13 +788,15 @@ void KeyboardView::paintEvent(QPaintEvent *raw_event) {
m_client->editState().scale.clockPerPx, size().height(),
mySelectionAlphaMultiplier);
if (!m_select_unit_enabled)
drawOngoingAction(m_client->editState(), m_edit_state, painter, width(),
height(), m_moo_clock->nowNoWrap(), m_pxtn->master, 1, 1,
displayEdo);
drawOngoingAction(
m_client->editState(), m_edit_state, painter, width(), height(),
m_client->controller()->m_audio_renderer->moo_timing().now_no_wrap(
m_pxtn->master),
m_pxtn->master, 1, 1, displayEdo);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);

drawLastSeek(painter, m_client, height(), false);
drawRepeatAndEndBars(painter, m_moo_clock,
drawRepeatAndEndBars(painter, m_pxtn->master,
m_client->editState().scale.clockPerPx, height());

// Left piano
Expand Down Expand Up @@ -863,7 +865,7 @@ void KeyboardView::paintEvent(QPaintEvent *raw_event) {
painter.setTransform(t);
}

drawCurrentPlayerPosition(painter, m_moo_clock, height(),
drawCurrentPlayerPosition(painter, clock, height(),
m_client->editState().scale.clockPerPx, false);

// Draw cursors
Expand Down
4 changes: 1 addition & 3 deletions src/editor/views/KeyboardView.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ struct LocalEditState {
class KeyboardView : public QWidget {
Q_OBJECT
public:
explicit KeyboardView(PxtoneClient *client, MooClock *moo_clock,
QScrollArea *parent = nullptr);
explicit KeyboardView(PxtoneClient *client, QScrollArea *parent = nullptr);
void cycleCurrentUnit(int offset, bool selectedOnly);
void setCurrentUnitNo(int unit_no, bool preserve_follow);

Expand Down Expand Up @@ -78,7 +77,6 @@ class KeyboardView : public QWidget {
std::unique_ptr<NotePreview> m_audio_note_preview;
Animation *m_anim;
PxtoneClient *m_client;
MooClock *m_moo_clock;
std::optional<int> m_focused_unit_no;
std::optional<int> m_hovered_unit_no;
std::map<int, int> m_midi_notes;
Expand Down
33 changes: 17 additions & 16 deletions src/editor/views/MeasureView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ constexpr int UNIT_EDIT_MARGIN = 1;
constexpr int UNIT_EDIT_INCREMENT = UNIT_EDIT_MARGIN + UNIT_EDIT_HEIGHT;
inline int unit_edit_y(int i) { return UNIT_EDIT_Y + UNIT_EDIT_INCREMENT * i; }

MeasureView::MeasureView(PxtoneClient *client, MooClock *moo_clock,
QWidget *parent)
MeasureView::MeasureView(PxtoneClient *client, QWidget *parent)
: QWidget(parent),
m_client(client),
m_anim(new Animation(this)),
m_moo_clock(moo_clock),
m_label_font(QFont()),
m_label_font_metrics(m_label_font),
m_audio_note_preview(nullptr),
Expand Down Expand Up @@ -356,16 +354,15 @@ void MeasureView::paintEvent(QPaintEvent *raw_event) {
StyleEditor::config.color.MeasureBeat);
}
drawFlag(&painter, FlagType::Top, false, 0, FLAG_Y);
if (m_moo_clock->repeat_clock() > 0) {
drawFlag(
&painter, FlagType::Repeat, false,
m_moo_clock->repeat_clock() / m_client->editState().scale.clockPerPx,
FLAG_Y);
int repeat_clock = MasterExtended::repeat_clock(m_client->pxtn()->master);
if (repeat_clock > 0) {
drawFlag(&painter, FlagType::Repeat, false,
repeat_clock / m_client->editState().scale.clockPerPx, FLAG_Y);
}
if (m_moo_clock->has_last()) {
int last_clock = MasterExtended::last_clock(m_client->pxtn()->master);
if (last_clock > 0) {
drawFlag(&painter, FlagType::Last, false,
m_moo_clock->last_clock() / m_client->editState().scale.clockPerPx,
FLAG_Y);
last_clock / m_client->editState().scale.clockPerPx, FLAG_Y);
}

double scaleX = m_client->editState().scale.clockPerPx;
Expand Down Expand Up @@ -414,7 +411,7 @@ void MeasureView::paintEvent(QPaintEvent *raw_event) {

double seconds_per_clock = 60 / m_client->pxtn()->master->get_beat_tempo() /
m_client->pxtn()->master->get_beat_clock();
int now = m_moo_clock->now();
int now = m_client->controller()->m_audio_renderer->moo_timing().now_clock;
auto drawLastOn = [&](int no, bool erase) {
if (last_on_by_no.count(no) > 0) {
const Interval &i = last_on_by_no[no];
Expand Down Expand Up @@ -466,7 +463,7 @@ void MeasureView::paintEvent(QPaintEvent *raw_event) {
drawLastOn(it->first, false);

drawLastSeek(painter, m_client, height, true);
drawCurrentPlayerPosition(painter, m_moo_clock, height,
drawCurrentPlayerPosition(painter, now, height,
m_client->editState().scale.clockPerPx, true);
// Draw text labels
if (Settings::PinnedUnitLabels::get()) {
Expand Down Expand Up @@ -566,11 +563,15 @@ void MeasureView::paintEvent(QPaintEvent *raw_event) {
}
drawExistingSelection(painter, m_client->editState().mouse_edit_state,
m_client->editState().scale.clockPerPx, height, 1);
if (!m_jump_to_unit_enabled)
if (!m_jump_to_unit_enabled) {
int now_no_wrap =
m_client->controller()->m_audio_renderer->moo_timing().now_no_wrap(
master);
drawOngoingAction(m_client->editState(), unit_draw_params_map,
m_client->unitIdMap(), painter, height,
m_client->quantizeClock(), clockPerMeas,
m_moo_clock->nowNoWrap(), m_client->pxtn()->master, 1, 1);
m_client->quantizeClock(), clockPerMeas, now_no_wrap,
m_client->pxtn()->master, 1, 1);
}

// Draw cursors
for (const auto &[uid, remote_state] : m_client->remoteEditStates()) {
Expand Down
Loading

0 comments on commit 7b34da6

Please sign in to comment.