diff --git a/src/editor/EditorWindow.cpp b/src/editor/EditorWindow.cpp index 2bd9d888..2adaeac7 100644 --- a/src/editor/EditorWindow.cpp +++ b/src/editor/EditorWindow.cpp @@ -806,8 +806,7 @@ void EditorWindow::recordInput(const Input::Event::Event &e) { Settings::ChordPreview::get() && !m_client->isPlaying(); m_record_note_preview[e.key] = std::make_unique( &m_pxtn, &m_client->moo()->params, unit_no, start, e.key, - e.vel(), m_client->audioState()->bufferSize(), chordPreview, - this); + e.vel(), m_client->bufferSize(), chordPreview, this); m_keyboard_view->currentMidiNotes()[e.key] = e.vel(); } diff --git a/src/editor/NewWoiceDialog.cpp b/src/editor/NewWoiceDialog.cpp index a037095d..980eeac3 100644 --- a/src/editor/NewWoiceDialog.cpp +++ b/src/editor/NewWoiceDialog.cpp @@ -214,7 +214,7 @@ void NewWoiceDialog::previewWoice(const QString &path) { ui->previewVolSlider->value() * 128 / ui->previewVolSlider->maximum(); m_note_preview = std::make_unique( m_client->pxtn(), &m_client->moo()->params, key, vel, 48000, - m_preview_woice, m_client->audioState()->bufferSize(), this); + m_preview_woice, m_client->bufferSize(), this); } NewWoiceDialog::NewWoiceDialog(bool multi, const PxtoneClient *client, @@ -330,8 +330,7 @@ void NewWoiceDialog::inputMidi(const Input::Event::Event &e) { if (m_preview_woice == nullptr) return; m_record_note_preview[e.key] = std::make_unique( m_client->pxtn(), &m_client->moo()->params, e.key, - e.vel(), 100000000, m_preview_woice, - m_client->audioState()->bufferSize(), this); + e.vel(), 100000000, m_preview_woice, 0 /* TODO */, this); }, [this](const Input::Event::Off &e) { if (m_record_note_preview[e.key]) diff --git a/src/editor/PxtoneClient.cpp b/src/editor/PxtoneClient.cpp index aafa7aa4..c9943091 100644 --- a/src/editor/PxtoneClient.cpp +++ b/src/editor/PxtoneClient.cpp @@ -6,7 +6,6 @@ #include "ComboOptions.h" #include "Settings.h" -#include "audio/AudioFormat.h" QList getUserList( const std::map &users) { @@ -29,22 +28,6 @@ PxtoneClient::PxtoneClient(pxtnService *pxtn, m_ping_timer(new QTimer(this)), m_last_seek(0), m_clipboard(new Clipboard(this)) { - QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); - if (!info.isFormatSupported(pxtoneAudioFormat())) { - qWarning() - << "Raw audio format not supported by backend, cannot play audio."; - return; - } - m_pxtn_device = new PxtoneIODevice(this, m_controller->pxtn(), &m_moo_state); - m_audio = new QAudioOutput(pxtoneAudioFormat(), this); - - // Apparently this reduces latency in pulseaudio, but also makes - // some sounds choppier - // m_audio->setCategory("game"); - m_audio->setVolume(1.0); - connect(m_pxtn_device, &PxtoneIODevice::playingChanged, this, - &PxtoneClient::playStateChanged); - connect(m_ping_timer, &QTimer::timeout, [this]() { sendPlayState(false); sendAction(Ping{QDateTime::currentMSecsSinceEpoch(), m_last_ping}); @@ -88,14 +71,13 @@ PxtoneClient::PxtoneClient(pxtnService *pxtn, &PxtoneClient::processRemoteAction); } -PxtoneClient::~PxtoneClient() { - m_audio->stop(); - m_pxtn_device->setPlaying(false); -} +PxtoneClient::~PxtoneClient() {} void PxtoneClient::loadDescriptor(pxtnDescriptor &desc) { // An empty desc is interpreted as an empty file so we don't error. - m_controller->loadDescriptor(desc); + double bufferLength = + Settings::value(BUFFER_LENGTH_KEY, DEFAULT_BUFFER_LENGTH).toDouble(); + m_controller->loadDescriptor(desc, bufferLength); changeEditState( [this](EditState &e) { e.m_current_unit_id = @@ -104,64 +86,48 @@ void PxtoneClient::loadDescriptor(pxtnDescriptor &desc) { }, false); m_following_user.reset(); - m_pxtn_device->setPlaying(false); seekMoo(0); - m_pxtn_device->open(QIODevice::ReadOnly); { bool ok; int v = Settings::value(VOLUME_KEY, QVariant()).toInt(&ok); if (ok) setVolume(v); } - { - bool ok; - double v = - Settings::value(BUFFER_LENGTH_KEY, DEFAULT_BUFFER_LENGTH).toDouble(&ok); - if (ok) setBufferSize(v); - } - m_pxtn_device->setPlaying(false); - m_audio->start(m_pxtn_device); - qDebug() << "Actual" << m_audio->bufferSize(); } void PxtoneClient::setBufferSize(double secs) { - bool started = (m_audio->state() != QAudio::StoppedState && - m_audio->state() != QAudio::IdleState); - QAudioFormat fmt = pxtoneAudioFormat(); - - if (started) { - m_audio->stop(); - m_pxtn_device->setPlaying(false); - } - if (secs < 0.01) secs = 0.01; if (secs > 10) secs = 10; qDebug() << "Setting buffer size: " << secs; - m_audio->setBufferSize(fmt.bytesForDuration(secs * 1e6)); - if (started) m_audio->start(m_pxtn_device); + m_controller->m_audio_renderer->setBufferFrames(secs * 44100); } -bool PxtoneClient::isPlaying() { return m_pxtn_device->playing(); } +bool PxtoneClient::isPlaying() { + return m_controller->m_audio_renderer->isPlaying(); +} // TODO: Factor this out into a PxtoneAudioPlayer class. Setting play state, // seeking. Unfortunately start / stop don't even fix this because stopping // still waits for the buffer to drain (instead of flushing and throwing away) void PxtoneClient::togglePlayState() { - if (Settings::SpacebarStop::get() && m_pxtn_device->playing()) + if (Settings::SpacebarStop::get() && + m_controller->m_audio_renderer->isPlaying()) resetAndSuspendAudio(); else { - m_pxtn_device->setPlaying(!m_pxtn_device->playing()); + m_controller->m_audio_renderer->setPlaying( + !m_controller->m_audio_renderer->isPlaying()); sendPlayState(true); } } void PxtoneClient::sendPlayState(bool from_action) { - sendAction( - PlayState{moo()->get_now_clock(), m_pxtn_device->playing(), from_action}); + sendAction(PlayState{moo()->get_now_clock(), + m_controller->m_audio_renderer->isPlaying(), + from_action}); } void PxtoneClient::resetAndSuspendAudio() { - m_pxtn_device->setPlaying(false); + m_controller->m_audio_renderer->setPlaying(false); if (moo()->get_now_clock() > m_last_seek) seekMoo(m_last_seek); else @@ -184,7 +150,7 @@ void PxtoneClient::setFollowing(std::optional following) { if (it != m_remote_edit_states.end() && it->second.state.has_value()) { // stop audio, so that the next playstate msg causes us to sync if the // other user's playing. - m_pxtn_device->setPlaying(false); + m_controller->m_audio_renderer->setPlaying(false); emit followActivity(it->second.state.value()); } } @@ -332,10 +298,11 @@ void PxtoneClient::processRemoteAction(const ServerAction &a) { // Since playstates come with heartbeats, we only reset // the moo for non-heartbeat updates or if there's a // drastic diff. - if (m_pxtn_device->playing() != s.playing || + if (m_controller->m_audio_renderer->isPlaying() != + s.playing || s.from_action) m_controller->seekMoo(s.clock); - m_pxtn_device->setPlaying(s.playing); + m_controller->m_audio_renderer->setPlaying(s.playing); } }, [this, uid](const EditAction &s) { @@ -558,6 +525,4 @@ void PxtoneClient::removeUnusedUnitsAndWoices() { } } -const std::vector &PxtoneClient::volumeLevels() const { - return m_pxtn_device->volumeLevels(); -} +std::vector PxtoneClient::volumeLevels() const { return {0, 0}; } diff --git a/src/editor/PxtoneClient.h b/src/editor/PxtoneClient.h index b4fc14d3..a81eaf1a 100644 --- a/src/editor/PxtoneClient.h +++ b/src/editor/PxtoneClient.h @@ -34,8 +34,6 @@ class PxtoneClient : public QObject { std::optional m_following_user; mooState m_moo_state; EditState m_edit_state; - QAudioOutput *m_audio; - PxtoneIODevice *m_pxtn_device; std::optional m_last_ping; QTimer *m_ping_timer; qint32 m_last_seek; @@ -43,7 +41,6 @@ class PxtoneClient : public QObject { signals: void editStateChanged(const EditState &m_edit_state); - void playStateChanged(bool playing); void followActivity(const EditState &r); void updatePing(std::optional ping_length); void connected(); @@ -78,7 +75,7 @@ class PxtoneClient : public QObject { const pxtnService *pxtn() const { return m_controller->pxtn(); } const EditState &editState() const { return m_edit_state; } const mooState *moo() const { return m_controller->moo(); } - const QAudioOutput *audioState() const { return m_audio; } + int bufferSize() const { return 256; } // TODO const NoIdMap &unitIdMap() const { return m_controller->unitIdMap(); } const std::map &remoteEditStates() { @@ -106,7 +103,7 @@ class PxtoneClient : public QObject { void setUnitOperated(int unit_no, bool operated); void cycleSolo(int unit_no); void removeUnusedUnitsAndWoices(); - const std::vector &volumeLevels() const; + std::vector volumeLevels() const; private: void processRemoteAction(const ServerAction &a); diff --git a/src/editor/PxtoneController.cpp b/src/editor/PxtoneController.cpp index f27680aa..dfc0412f 100644 --- a/src/editor/PxtoneController.cpp +++ b/src/editor/PxtoneController.cpp @@ -4,12 +4,15 @@ #include #include +#include "editor/Settings.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(pxtn)), + m_audio_renderer(std::make_unique( + pxtn, 256 /* TODO: change this away from default */)), m_uid(uid), m_pxtn(pxtn), m_moo_state(moo_state), @@ -416,7 +419,8 @@ void PxtoneController::setSongComment(const QString &comment) { m_pxtn->text->set_comment_buf(str.data(), str.length()); } -bool PxtoneController::loadDescriptor(pxtnDescriptor &desc) { +bool PxtoneController::loadDescriptor(pxtnDescriptor &desc, + double bufferLength) { m_audio_renderer.reset(); emit beginRefresh(); if (desc.get_size_bytes() > 0) { @@ -448,7 +452,10 @@ bool PxtoneController::loadDescriptor(pxtnDescriptor &desc) { emit tempoBeatChanged(); emit newSong(); - m_audio_renderer = std::make_unique(m_pxtn); + m_audio_renderer = + std::make_unique(m_pxtn, bufferLength * 44100); + connect(m_audio_renderer.get(), &RtAudioRenderer::playingChanged, this, + &PxtoneController::playStateChanged); return true; } diff --git a/src/editor/PxtoneController.h b/src/editor/PxtoneController.h index f19dc097..ce1b4e19 100644 --- a/src/editor/PxtoneController.h +++ b/src/editor/PxtoneController.h @@ -36,7 +36,7 @@ class PxtoneController : public QObject { qint64 uid(); const NoIdMap &unitIdMap() const { return m_unit_id_map; } const NoIdMap &woiceIdMap() const { return m_woice_id_map; } - bool loadDescriptor(pxtnDescriptor &desc); + bool loadDescriptor(pxtnDescriptor &desc, double bufferLength); bool applyAddUnit(const AddUnit &a, qint64 uid); bool applyAddWoice(const AddWoice &a, qint64 uid); bool applyRemoveWoice(const RemoveWoice &a, qint64 uid); @@ -84,6 +84,7 @@ class PxtoneController : public QObject { void tempoBeatChanged(); void playedToggled(int unit_no); void operatedToggled(int unit_no, bool operated); + void playStateChanged(bool playing); void soloToggled(); void newSong(); void edited(); @@ -120,7 +121,6 @@ class PxtoneController : public QObject { qint64 m_uid; pxtnService *m_pxtn; mooState *m_moo_state; - PxtoneIODevice *m_moo_io_device; std::vector m_log; std::list> m_uncommitted; diff --git a/src/editor/audio/RtAudioRenderer.cpp b/src/editor/audio/RtAudioRenderer.cpp index 819797b7..8d894c54 100644 --- a/src/editor/audio/RtAudioRenderer.cpp +++ b/src/editor/audio/RtAudioRenderer.cpp @@ -9,38 +9,46 @@ int MooTiming::now_no_wrap(const pxtnMaster *master) { } const unsigned int BUFFER_FRAMES = - 256; // At higher buffers, this does stuttter. So you will need a + 256; // At higher buffers, this does stutter. So you will need a // MooClock-like thing anyway. int rtAudioMoo(void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames, double /*streamTime*/, RtAudioStreamStatus status, void *userData) { RtAudioRenderer *renderer = (RtAudioRenderer *)userData; if (status) qWarning() << "Stream underflow detected!"; - int byte_per_smp; if (!renderer->m_pxtn->get_byte_per_smp(&byte_per_smp)) return 1; - int size = nBufferFrames * byte_per_smp; - 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}); + + if (renderer->m_playing.load()) { + 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}); + } else { + memset(outputBuffer, 0, size); + } return 0; } -RtAudioRenderer::RtAudioRenderer(const pxtnService *pxtn) - : m_pxtn(pxtn), m_dac() { - if (m_dac.getDeviceCount() < 1) - throw std::runtime_error("No audio devices found"); +void RtAudioRenderer::setPlaying(bool playing) { + bool not_playing = !playing; + bool changed = m_playing.compare_exchange_strong(not_playing, playing); + if (changed) emit playingChanged(playing); +} - qDebug() << "lock free" << m_moo_timing.is_lock_free(); - RtAudio::StreamParameters parameters; - parameters.deviceId = m_dac.getDefaultOutputDevice(); - parameters.nChannels = 2; - parameters.firstChannel = 0; +void RtAudioRenderer::setBufferFrames(unsigned int numFrames) { + stopStream(); + startStream(numFrames); +} + +bool RtAudioRenderer::isPlaying() { return m_playing.load(); } +RtAudioRenderer::RtAudioRenderer(const pxtnService *pxtn, + unsigned int numFrames) + : m_pxtn(pxtn), m_dac(), m_playing(false) { pxtnVOMITPREPARATION prep{}; prep.flags |= pxtnVOMITPREPFLAG_loop | pxtnVOMITPREPFLAG_unit_mute; prep.start_pos_sample = 0; @@ -48,18 +56,25 @@ RtAudioRenderer::RtAudioRenderer(const pxtnService *pxtn) if (!m_pxtn->moo_preparation(&prep, m_moo_state)) { throw std::runtime_error("moo prep failed"); } + startStream(numFrames); +} + +void RtAudioRenderer::startStream(unsigned int numFrames) { + if (m_dac.getDeviceCount() < 1) + throw std::runtime_error("No audio devices found"); + + RtAudio::StreamParameters parameters; + parameters.deviceId = m_dac.getDefaultOutputDevice(); + parameters.nChannels = 2; + parameters.firstChannel = 0; int sampleRate = 44100; - unsigned int bufferFrames = BUFFER_FRAMES; - m_dac.openStream(¶meters, NULL, RTAUDIO_SINT16, sampleRate, &bufferFrames, + m_dac.openStream(¶meters, NULL, RTAUDIO_SINT16, sampleRate, &numFrames, &rtAudioMoo, this); m_dac.startStream(); - qDebug() << "started stream" << bufferFrames; } -MooTiming RtAudioRenderer::moo_timing() const { return m_moo_timing.load(); } - -RtAudioRenderer::~RtAudioRenderer() { +void RtAudioRenderer::stopStream() { try { m_dac.stopStream(); } catch (RtAudioError &e) { @@ -67,3 +82,7 @@ RtAudioRenderer::~RtAudioRenderer() { } if (m_dac.isStreamOpen()) m_dac.closeStream(); } + +MooTiming RtAudioRenderer::moo_timing() const { return m_moo_timing.load(); } + +RtAudioRenderer::~RtAudioRenderer() { stopStream(); } diff --git a/src/editor/audio/RtAudioRenderer.h b/src/editor/audio/RtAudioRenderer.h index fea8b491..26702787 100644 --- a/src/editor/audio/RtAudioRenderer.h +++ b/src/editor/audio/RtAudioRenderer.h @@ -3,6 +3,7 @@ #include +#include #include #include "pxtone/pxtnService.h" @@ -14,19 +15,31 @@ struct MooTiming { int now_no_wrap(const pxtnMaster *master); }; -class RtAudioRenderer { +class RtAudioRenderer : public QObject { + Q_OBJECT + const pxtnService *m_pxtn; std::atomic m_moo_timing; mooState m_moo_state; RtAudio m_dac; + std::atomic m_playing; friend int rtAudioMoo(void *, void *, unsigned int, double, RtAudioStreamStatus, void *); + signals: + void playingChanged(bool); public: - RtAudioRenderer(const pxtnService *pxtn); + RtAudioRenderer(const pxtnService *pxtn, unsigned int numFrames); MooTiming moo_timing() const; ~RtAudioRenderer(); + void setPlaying(bool playing); + void setBufferFrames(unsigned int); + bool isPlaying(); + + private: + void startStream(unsigned int numFrames); + void stopStream(); }; #endif // RTAUDIORENDERER_H diff --git a/src/editor/sidemenu/PxtoneSideMenu.cpp b/src/editor/sidemenu/PxtoneSideMenu.cpp index 75a32eee..f03505ee 100644 --- a/src/editor/sidemenu/PxtoneSideMenu.cpp +++ b/src/editor/sidemenu/PxtoneSideMenu.cpp @@ -35,7 +35,8 @@ PxtoneSideMenu::PxtoneSideMenu(PxtoneClient *client, MooClock *moo_clock, [this]() { setEditWidgetsEnabled(true); }); connect(m_client->controller(), &PxtoneController::tempoBeatChanged, this, &PxtoneSideMenu::refreshTempoBeat); - connect(m_client, &PxtoneClient::playStateChanged, this, &SideMenu::setPlay); + connect(m_client->controller(), &PxtoneController::playStateChanged, this, + &SideMenu::setPlay); /*connect(m_client, &PxtoneClient::volumeLevelChanged, this, [this](const std::vector &levels) { qDebug() << QString("Volume: (%1dbfs,%2dbfs), peak (%3dbfs,%4dbfs)") @@ -106,8 +107,7 @@ PxtoneSideMenu::PxtoneSideMenu(PxtoneClient *client, MooClock *moo_clock, m_client->pxtn(), &m_client->moo()->params, m_client->editState().mouse_edit_state.last_pitch, m_client->editState().mouse_edit_state.base_velocity, 48000, - m_client->pxtn()->Woice_Get(idx), - m_client->audioState()->bufferSize(), this); + m_client->pxtn()->Woice_Get(idx), m_client->bufferSize(), this); else m_note_preview = nullptr; } @@ -119,7 +119,7 @@ PxtoneSideMenu::PxtoneSideMenu(PxtoneClient *client, MooClock *moo_clock, if (idx >= 0) m_note_preview = std::make_unique( m_client->pxtn(), &m_client->moo()->params, idx, m_moo_clock->now(), - 48000, std::list(), m_client->audioState()->bufferSize(), + 48000, std::list(), m_client->bufferSize(), false, this); else m_note_preview = nullptr; diff --git a/src/editor/sidemenu/SelectWoiceDialog.cpp b/src/editor/sidemenu/SelectWoiceDialog.cpp index 713ab399..979aed75 100644 --- a/src/editor/sidemenu/SelectWoiceDialog.cpp +++ b/src/editor/sidemenu/SelectWoiceDialog.cpp @@ -19,8 +19,7 @@ SelectWoiceDialog::SelectWoiceDialog(QAbstractListModel *model, m_client->pxtn(), &m_client->moo()->params, m_client->editState().mouse_edit_state.last_pitch, m_client->editState().mouse_edit_state.base_velocity, 48000, - m_client->pxtn()->Woice_Get(idx), - m_client->audioState()->bufferSize(), this); + m_client->pxtn()->Woice_Get(idx), m_client->bufferSize(), this); else m_note_preview = nullptr; QString name = ui->unitName->text(); diff --git a/src/editor/sidemenu/VolumeMeterWidget.cpp b/src/editor/sidemenu/VolumeMeterWidget.cpp index 51352f9e..79eac936 100644 --- a/src/editor/sidemenu/VolumeMeterWidget.cpp +++ b/src/editor/sidemenu/VolumeMeterWidget.cpp @@ -47,10 +47,10 @@ void VolumeMeterFrame::paintEvent(QPaintEvent *e) { p.fillRect(e->rect(), StyleEditor::config.color.MeterBackground); // int w_limit = dbToX(-3); - const auto &levels = m_client->volumeLevels(); + const auto levels = m_client->volumeLevels(); while (levels.size() > m_peaks.size()) m_peaks.push_back(-INFINITY); for (uint i = 0; i < levels.size(); ++i) { - int w = dbToX(levels[i].current_volume_dbfs()); + int w = dbToX(levels[i]); // TODO cur vol int y = (height() + 1) * i / levels.size(); int h = (height() + 1) / levels.size() - 1; p.fillRect(QRect(0, y, width(), h), barGradient()); @@ -66,7 +66,7 @@ void VolumeMeterFrame::paintEvent(QPaintEvent *e) { p.fillRect(dbToX(-3), y, 1, h, StyleEditor::config.color.MeterBackgroundSoft); - double peak = levels[i].last_peak_dbfs(); + double peak = levels[i]; // TODO peak p.fillRect(QRect(dbToX(peak) - 1, y, 2, h), colAtDb(peak)); if (peak > m_peaks[i]) m_peaks[i] = peak; if (m_peaks[i] > HIGH_DB) diff --git a/src/editor/views/KeyboardView.cpp b/src/editor/views/KeyboardView.cpp index 84c5bbce..907e0e8f 100644 --- a/src/editor/views/KeyboardView.cpp +++ b/src/editor/views/KeyboardView.cpp @@ -1054,7 +1054,7 @@ void KeyboardView::mousePressEvent(QMouseEvent *event) { m_audio_note_preview = std::make_unique( m_pxtn, &m_client->moo()->params, unit_no, clock, pitch, vel, - m_client->audioState()->bufferSize(), chord_preview, this); + 0 /* TODO */, chord_preview, this); } } }, diff --git a/src/editor/views/MeasureView.cpp b/src/editor/views/MeasureView.cpp index 21ece72e..12f8efbd 100644 --- a/src/editor/views/MeasureView.cpp +++ b/src/editor/views/MeasureView.cpp @@ -705,7 +705,7 @@ void MeasureView::mousePressEvent(QMouseEvent *event) { m_audio_note_preview = std::make_unique( m_client->pxtn(), &m_client->moo()->params, unit_no.value(), clock, std::list(), - m_client->audioState()->bufferSize(), + 0 /* TODO */, Settings::ChordPreview::get() && !m_client->isPlaying(), this); s.mouse_edit_state.base_velocity = diff --git a/src/editor/views/MooClock.cpp b/src/editor/views/MooClock.cpp index adc36fce..866ba464 100644 --- a/src/editor/views/MooClock.cpp +++ b/src/editor/views/MooClock.cpp @@ -47,7 +47,7 @@ void MooClock::tick() { } int64_t offset_from_buffer = - m_client->audioState()->bufferSize(); // - m_audio_output->bytesFree() + m_client->bufferSize(); // - m_audio_output->bytesFree() double estimated_buffer_offset = -offset_from_buffer / double(bytes_per_second); diff --git a/src/editor/views/ParamView.cpp b/src/editor/views/ParamView.cpp index 5f7ad866..5587d2bb 100644 --- a/src/editor/views/ParamView.cpp +++ b/src/editor/views/ParamView.cpp @@ -54,7 +54,7 @@ ParamView::ParamView(PxtoneClient *client, QWidget *parent) m_audio_note_preview = std::make_unique( m_client->pxtn(), &m_client->moo()->params, maybe_unit_no.value(), m_client->editState().mouse_edit_state.start_clock, 48000, - std::list({e}), m_client->audioState()->bufferSize(), + std::list({e}), m_client->bufferSize(), Settings::ChordPreview::get() && !m_client->isPlaying(), this); } }); @@ -599,7 +599,7 @@ void ParamView::mousePressEvent(QMouseEvent *event) { m_client->quantizeClock()); m_audio_note_preview = std::make_unique( m_client->pxtn(), &m_client->moo()->params, unit_no, clock, - std::list({e}), m_client->audioState()->bufferSize(), + std::list({e}), m_client->bufferSize(), Settings::ChordPreview::get() && !m_client->isPlaying(), this); } }