From 1be7bb81b5278d1b38f94ce40a25da7f3c78cc97 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 18 Dec 2024 06:44:59 +0100 Subject: [PATCH 01/32] LmmsExporterSample_adding_class --- include/LmmsExporterSample.h | 74 +++++++++++++ src/core/LmmsExporterSample.cpp | 188 ++++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 include/LmmsExporterSample.h create mode 100644 src/core/LmmsExporterSample.cpp diff --git a/include/LmmsExporterSample.h b/include/LmmsExporterSample.h new file mode 100644 index 00000000000..e432bc40c84 --- /dev/null +++ b/include/LmmsExporterSample.h @@ -0,0 +1,74 @@ +/* + * LmmsExporterSample.h - exports .flac files outside of AudioEngine + * + * Copyright (c) 2024 - 2025 szeli1 + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_LMMS_EXPORTER_H +#define LMMS_LMMS_EXPORTER_H + +#include +#include +#include +#include +#include +#include + +#include + +namespace lmms +{ + +class SampleBuffer; + +class LmmsExporterSample +{ +public: + LmmsExporterSample(); + ~LmmsExporterSample(); + + //! outputLocationAndName: should include path and name, could include ".flac" + void startExporting(const QString& outputLocationAndName, std::shared_ptr buffer); + void stopExporting(); + + //void writeBuffer(const SampleFrame* _ab, fpp_t const frames); + +private: + static void threadedExportFunction(LmmsExporterSample* thisExporter, volatile bool* abortExport); + + void stopThread(); + bool openFile(const QString& outputLocationAndName, std::shared_ptr buffer); + void exportBuffer(std::shared_ptr buffer); + void closeFile(); + + std::vector>> m_buffers; + + volatile bool m_abortExport; + bool m_isThreadRunning; + std::mutex m_readMutex; + std::thread* m_thread; + + SNDFILE* m_fileDescriptor; +}; + +} // namespace lmms + +#endif // LMMS_LMMS_EXPORTER_H diff --git a/src/core/LmmsExporterSample.cpp b/src/core/LmmsExporterSample.cpp new file mode 100644 index 00000000000..ae16a070878 --- /dev/null +++ b/src/core/LmmsExporterSample.cpp @@ -0,0 +1,188 @@ +/* + * LmmsExporterSample.cpp - exports .flac files outside of AudioEngine + * + * Copyright (c) 2024 szeli1 + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include + +#include +#include + +#include "LmmsExporterSample.h" + +#include "SampleBuffer.h" + +namespace lmms +{ + +LmmsExporterSample::LmmsExporterSample() : + m_abortExport(false), + m_isThreadRunning(false), + m_readMutex(), + m_thread(nullptr), + m_fileDescriptor(NULL) +{ + +} + +LmmsExporterSample::~LmmsExporterSample() +{ + stopExporting(); +} + + +void LmmsExporterSample::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer) +{ + QString filteredName(QFileInfo(outputLocationAndName).absolutePath() + "/" + QFileInfo(outputLocationAndName).baseName()+ ".flac"); + m_readMutex.lock(); + m_buffers.push_back(std::make_pair(filteredName, buffer)); + m_readMutex.unlock(); + + if (m_isThreadRunning == false) + { + stopExporting(); + m_isThreadRunning = true; + m_thread = new std::thread(&LmmsExporterSample::threadedExportFunction, this, &m_abortExport); + } +} + +void LmmsExporterSample::stopExporting() +{ + if (m_thread != nullptr) + { + if (m_isThreadRunning == true) + { + m_abortExport = true; + } + m_thread->join(); + delete m_thread; + m_thread = nullptr; + m_isThreadRunning = false; + m_abortExport = false; + } +} + + +void LmmsExporterSample::threadedExportFunction(LmmsExporterSample* thisExporter, volatile bool* abortExport) +{ + thisExporter->m_isThreadRunning = true; + + while (*abortExport == false) + { + std::pair> curBuffer = std::make_pair(QString(""), nullptr); + thisExporter->m_readMutex.lock(); + bool shouldExit = thisExporter->m_buffers.size() <= 0; + if (shouldExit == false) + { + curBuffer = thisExporter->m_buffers[thisExporter->m_buffers.size() - 1]; + } + thisExporter->m_readMutex.unlock(); + if (shouldExit) { break; } + + bool success = thisExporter->openFile(curBuffer.first, curBuffer.second); + if (success) + { + thisExporter->exportBuffer(curBuffer.second); + thisExporter->closeFile(); + } + + thisExporter->m_buffers.pop_back(); + } + + thisExporter->m_isThreadRunning = false; +} + +bool LmmsExporterSample::openFile(const QString& outputLocationAndName, std::shared_ptr buffer) +{ + bool success = true; + QFile targetFile(outputLocationAndName); + if (targetFile.exists() == false) + { + // creating new file + success = targetFile.open(QIODevice::WriteOnly); + if (success == false) { return false; } + targetFile.close(); + } + + constexpr int channelCount = 2; + SF_INFO exportInfo; + + memset(&exportInfo, 0, sizeof(exportInfo)); + exportInfo.frames = static_cast(buffer->size() * channelCount); + exportInfo.samplerate = buffer->sampleRate(); + exportInfo.channels = channelCount; + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); + +#if defined(LMMS_BUILD_WIN32) || defined(LMMS_BUILD_WIN64) + std::wstring characters = outputLocationAndName.toWString(); + // wstring::c_str should guarantee null termination character at end + // this should be in big endian byte order + m_fileDescriptor = sf_open(characters.c_str(), SFM_WRITE, &exportInfo); +#else + QByteArray characters = outputLocationAndName.toUtf8(); + m_fileDescriptor = sf_open(characters.data(), SFM_WRITE, &exportInfo); +#endif + success = m_fileDescriptor != NULL; + + if (success != 0) + { + printf("LmmsExporterSample sf_open error"); + } + + return success; +} + +void LmmsExporterSample::exportBuffer(std::shared_ptr buffer) +{ + if (m_fileDescriptor == NULL) { return; } + constexpr size_t channelCount = 2; + // multiply by 2 since there is 2 channels + std::vector outputBuffer(buffer->size() * channelCount); + size_t i = 0; + for (auto it = buffer->begin(); it != buffer->end(); ++it) + { + outputBuffer[i] = static_cast(it->left()); + outputBuffer[i + 1] = static_cast(it->right()); + outputBuffer[i] = outputBuffer[i] > 1.0f ? 1.0f : outputBuffer[i] < -1.0f ? -1.0f : outputBuffer[i]; + outputBuffer[i + 1] = outputBuffer[i + 1] > 1.0f ? 1.0f : outputBuffer[i + 1] < -1.0f ? -1.0f : outputBuffer[i + 1]; + i = i + channelCount; + } + size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(buffer->size())); + if (count != buffer->size()) + { + printf("LmmsExporterSample sf_writef_float error"); + } +} + +void LmmsExporterSample::closeFile() +{ + if (m_fileDescriptor == NULL) { return; } + int success = sf_close(m_fileDescriptor); + if (success != 0) + { + printf("LmmsExporterSample sf_close error"); + } + m_fileDescriptor = NULL; +} + +} // namespace lmms + From 318d8b49d00024f7ecae799a0464f0926ba44d08 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:57:36 +0100 Subject: [PATCH 02/32] CMakeLists_adding_new_class_target --- src/core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1e2c4f3cfdb..b0842446ae2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -38,6 +38,7 @@ set(LMMS_SRCS core/LadspaManager.cpp core/LfoController.cpp core/LinkedModelGroups.cpp + core/LmmsExporterSample.cpp core/LocklessAllocator.cpp core/MeterModel.cpp core/Metronome.cpp From a9248c427bd8ed8d0b801686c0d550f7570f722d Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:58:10 +0100 Subject: [PATCH 03/32] LmmsExporterSample_fixing_printf --- include/LmmsExporterSample.h | 6 +++--- src/core/LmmsExporterSample.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/LmmsExporterSample.h b/include/LmmsExporterSample.h index e432bc40c84..fa25333bed5 100644 --- a/include/LmmsExporterSample.h +++ b/include/LmmsExporterSample.h @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_LMMS_EXPORTER_H -#define LMMS_LMMS_EXPORTER_H +#ifndef LMMS_LMMS_EXPORTER_SAMPLE_H +#define LMMS_LMMS_EXPORTER_SAMPLE_H #include #include @@ -71,4 +71,4 @@ class LmmsExporterSample } // namespace lmms -#endif // LMMS_LMMS_EXPORTER_H +#endif // LMMS_LMMS_EXPORTER_SAMPLE_H diff --git a/src/core/LmmsExporterSample.cpp b/src/core/LmmsExporterSample.cpp index ae16a070878..80f225204aa 100644 --- a/src/core/LmmsExporterSample.cpp +++ b/src/core/LmmsExporterSample.cpp @@ -143,9 +143,9 @@ bool LmmsExporterSample::openFile(const QString& outputLocationAndName, std::sha #endif success = m_fileDescriptor != NULL; - if (success != 0) + if (success == false) { - printf("LmmsExporterSample sf_open error"); + printf("LmmsExporterSample sf_open error\n"); } return success; @@ -169,7 +169,7 @@ void LmmsExporterSample::exportBuffer(std::shared_ptr buffer size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(buffer->size())); if (count != buffer->size()) { - printf("LmmsExporterSample sf_writef_float error"); + printf("LmmsExporterSample sf_writef_float error\n"); } } @@ -179,7 +179,7 @@ void LmmsExporterSample::closeFile() int success = sf_close(m_fileDescriptor); if (success != 0) { - printf("LmmsExporterSample sf_close error"); + printf("LmmsExporterSample sf_close error\n"); } m_fileDescriptor = NULL; } From 50d20a7951de4ce9c6ec21dac3427ac257b88ded Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:58:58 +0100 Subject: [PATCH 04/32] SampleClip_implementing_static_exporter --- include/SampleClip.h | 3 +++ src/core/SampleClip.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/include/SampleClip.h b/include/SampleClip.h index 3beca338bcd..e7850c9c06a 100644 --- a/include/SampleClip.h +++ b/include/SampleClip.h @@ -32,6 +32,7 @@ namespace lmms { +class LmmsExporterSample; class SampleBuffer; namespace gui @@ -93,6 +94,8 @@ public slots: Sample m_sample; BoolModel m_recordModel; bool m_isPlaying; + + static std::unique_ptr s_sampleExporter; friend class gui::SampleClipView; diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 5ef001e20d1..7ae152bdf66 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -27,6 +27,7 @@ #include #include +#include "LmmsExporterSample.h" #include "PathUtil.h" #include "SampleBuffer.h" #include "SampleClipView.h" @@ -37,6 +38,9 @@ namespace lmms { +std::unique_ptr SampleClip::s_sampleExporter = std::make_unique(); + + SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying) : Clip(_track) , m_sample(std::move(sample)) @@ -79,6 +83,7 @@ SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying) setAutoResize( false ); break; } + updateTrackClips(); } From 3d98c779a39aec95cf31422e063fe6bab62aa4af Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:59:29 +0100 Subject: [PATCH 05/32] SampleClipView_implementing_exporting_context_menu_option --- include/SampleClipView.h | 1 + src/gui/clips/SampleClipView.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/SampleClipView.h b/include/SampleClipView.h index 4ff218fb0ef..69083286549 100644 --- a/include/SampleClipView.h +++ b/include/SampleClipView.h @@ -48,6 +48,7 @@ public slots: void updateSample(); void reverseSample(); void setAutomationGhost(); + void exportSampleBuffer(); diff --git a/src/gui/clips/SampleClipView.cpp b/src/gui/clips/SampleClipView.cpp index a7251be8de6..d84d4c7fb73 100644 --- a/src/gui/clips/SampleClipView.cpp +++ b/src/gui/clips/SampleClipView.cpp @@ -31,6 +31,8 @@ #include "GuiApplication.h" #include "AutomationEditor.h" #include "embed.h" +#include "FileDialog.h" +#include "LmmsExporterSample.h" #include "PathUtil.h" #include "SampleClip.h" #include "SampleLoader.h" @@ -81,6 +83,13 @@ void SampleClipView::constructContextMenu(QMenu* cm) tr( "Set/clear record" ), m_clip, SLOT(toggleRecord()));*/ + cm->addAction( + embed::getIconPixmap("flip_x"), + tr("export sample buffer"), + this, + SLOT(exportSampleBuffer()) + ); + cm->addAction( embed::getIconPixmap("flip_x"), tr("Reverse sample"), @@ -376,5 +385,27 @@ bool SampleClipView::splitClip( const TimePos pos ) else { return false; } } +void SampleClipView::exportSampleBuffer() +{ + auto openFileDialog = FileDialog(nullptr, tr("Export audio file"), QString(), tr("Audio files (*.wav *.flac *.ogg *.mp3);;WAV (*.wav);;FLAC (*.flac);;OGG (*.ogg);;MP3 (*.mp3)")); + + + if (openFileDialog.exec() == QDialog::Accepted) + { + QStringList curSelectedFiles(openFileDialog.selectedFiles()); + if (curSelectedFiles.isEmpty() == false) + { + QString outputFileName = curSelectedFiles.first(); + if (outputFileName.isEmpty()) { return; } + if (outputFileName.endsWith(".flac") == false) + { + outputFileName = PathUtil::stripPrefix(outputFileName) + ".flac"; + } + + m_clip->s_sampleExporter->startExporting(outputFileName, m_clip->m_sample.buffer()); + } + } +} + } // namespace lmms::gui From 0c630d0eb0b057d24c3b78cad7c4dcfb3f02aa40 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:20:33 +0100 Subject: [PATCH 06/32] LmmsExporterSample_fixing_typo --- include/LmmsExporterSample.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LmmsExporterSample.h b/include/LmmsExporterSample.h index fa25333bed5..7415c16dce0 100644 --- a/include/LmmsExporterSample.h +++ b/include/LmmsExporterSample.h @@ -39,7 +39,7 @@ namespace lmms class SampleBuffer; -class LmmsExporterSample +class LMMS_EXPORT LmmsExporterSample { public: LmmsExporterSample(); From baab754993a497c9c9bf5522116b5d5ac4dcf552 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:20:53 +0100 Subject: [PATCH 07/32] SamleClipView_fixing_typo --- src/gui/clips/SampleClipView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/clips/SampleClipView.cpp b/src/gui/clips/SampleClipView.cpp index d84d4c7fb73..aeaa43d0a37 100644 --- a/src/gui/clips/SampleClipView.cpp +++ b/src/gui/clips/SampleClipView.cpp @@ -85,7 +85,7 @@ void SampleClipView::constructContextMenu(QMenu* cm) cm->addAction( embed::getIconPixmap("flip_x"), - tr("export sample buffer"), + tr("Export sample buffer"), this, SLOT(exportSampleBuffer()) ); From 77cfaaeeb545dc1081375da64976dac056c0b140 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:23:58 +0100 Subject: [PATCH 08/32] LmmsExporterSample_removing_blank_line --- src/core/LmmsExporterSample.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/LmmsExporterSample.cpp b/src/core/LmmsExporterSample.cpp index 80f225204aa..4b8b2fb11bd 100644 --- a/src/core/LmmsExporterSample.cpp +++ b/src/core/LmmsExporterSample.cpp @@ -185,4 +185,3 @@ void LmmsExporterSample::closeFile() } } // namespace lmms - From 58f4e159ddd9291562c81904e4d5d42dda88a9eb Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:33:45 +0100 Subject: [PATCH 09/32] LmmsExporterSample_removing_LMMS_EXPORT --- include/LmmsExporterSample.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/LmmsExporterSample.h b/include/LmmsExporterSample.h index 7415c16dce0..b3197775bf8 100644 --- a/include/LmmsExporterSample.h +++ b/include/LmmsExporterSample.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -39,7 +38,7 @@ namespace lmms class SampleBuffer; -class LMMS_EXPORT LmmsExporterSample +class LmmsExporterSample { public: LmmsExporterSample(); From b25142f785cb2a1fc1df8c892c64a3536309f34c Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:46:38 +0100 Subject: [PATCH 10/32] LmmsExporterSample_removing_ifdef --- src/core/LmmsExporterSample.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core/LmmsExporterSample.cpp b/src/core/LmmsExporterSample.cpp index 4b8b2fb11bd..161eb20eff0 100644 --- a/src/core/LmmsExporterSample.cpp +++ b/src/core/LmmsExporterSample.cpp @@ -132,15 +132,9 @@ bool LmmsExporterSample::openFile(const QString& outputLocationAndName, std::sha exportInfo.channels = channelCount; exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); -#if defined(LMMS_BUILD_WIN32) || defined(LMMS_BUILD_WIN64) - std::wstring characters = outputLocationAndName.toWString(); - // wstring::c_str should guarantee null termination character at end - // this should be in big endian byte order - m_fileDescriptor = sf_open(characters.c_str(), SFM_WRITE, &exportInfo); -#else QByteArray characters = outputLocationAndName.toUtf8(); m_fileDescriptor = sf_open(characters.data(), SFM_WRITE, &exportInfo); -#endif + success = m_fileDescriptor != NULL; if (success == false) From 61e7ca948a87500d74fde83eb3edeb3ba7649f88 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 19 Dec 2024 21:49:46 +0100 Subject: [PATCH 11/32] LmmsExporterSample_removing_more_blank_lines --- src/core/LmmsExporterSample.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/LmmsExporterSample.cpp b/src/core/LmmsExporterSample.cpp index 161eb20eff0..8fe0ea3e7a0 100644 --- a/src/core/LmmsExporterSample.cpp +++ b/src/core/LmmsExporterSample.cpp @@ -40,9 +40,7 @@ LmmsExporterSample::LmmsExporterSample() : m_readMutex(), m_thread(nullptr), m_fileDescriptor(NULL) -{ - -} +{} LmmsExporterSample::~LmmsExporterSample() { From 2bc670dd1e8202ee2620812aa783e4bafc46b215 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 14:25:56 +0100 Subject: [PATCH 12/32] LmmsMassExporter_renaming --- ...mmsExporterSample.h => LmmsMassExporter.h} | 18 ++++++------ ...xporterSample.cpp => LmmsMassExporter.cpp} | 28 +++++++++---------- 2 files changed, 24 insertions(+), 22 deletions(-) rename include/{LmmsExporterSample.h => LmmsMassExporter.h} (83%) rename src/core/{LmmsExporterSample.cpp => LmmsMassExporter.cpp} (81%) diff --git a/include/LmmsExporterSample.h b/include/LmmsMassExporter.h similarity index 83% rename from include/LmmsExporterSample.h rename to include/LmmsMassExporter.h index b3197775bf8..c637e919bc9 100644 --- a/include/LmmsExporterSample.h +++ b/include/LmmsMassExporter.h @@ -1,5 +1,5 @@ /* - * LmmsExporterSample.h - exports .flac files outside of AudioEngine + * LmmsMassExporter.h - exports .flac files outside of AudioEngine * * Copyright (c) 2024 - 2025 szeli1 * @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_LMMS_EXPORTER_SAMPLE_H -#define LMMS_LMMS_EXPORTER_SAMPLE_H +#ifndef LMMS_LMMS_MASS_EXPORTER_H +#define LMMS_LMMS_MASS_EXPORTER_H #include #include @@ -38,11 +38,13 @@ namespace lmms class SampleBuffer; -class LmmsExporterSample + + +class LmmsMassExporter { public: - LmmsExporterSample(); - ~LmmsExporterSample(); + LmmsMassExporter(); + ~LmmsMassExporter(); //! outputLocationAndName: should include path and name, could include ".flac" void startExporting(const QString& outputLocationAndName, std::shared_ptr buffer); @@ -51,7 +53,7 @@ class LmmsExporterSample //void writeBuffer(const SampleFrame* _ab, fpp_t const frames); private: - static void threadedExportFunction(LmmsExporterSample* thisExporter, volatile bool* abortExport); + static void threadedExportFunction(LmmsMassExporter* thisExporter, volatile bool* abortExport); void stopThread(); bool openFile(const QString& outputLocationAndName, std::shared_ptr buffer); @@ -70,4 +72,4 @@ class LmmsExporterSample } // namespace lmms -#endif // LMMS_LMMS_EXPORTER_SAMPLE_H +#endif // LMMS_LMMS_MASS_EXPORTER_H diff --git a/src/core/LmmsExporterSample.cpp b/src/core/LmmsMassExporter.cpp similarity index 81% rename from src/core/LmmsExporterSample.cpp rename to src/core/LmmsMassExporter.cpp index 8fe0ea3e7a0..a6290422cbb 100644 --- a/src/core/LmmsExporterSample.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -1,5 +1,5 @@ /* - * LmmsExporterSample.cpp - exports .flac files outside of AudioEngine + * LmmsMassExporter.cpp - exports .flac files outside of AudioEngine * * Copyright (c) 2024 szeli1 * @@ -27,14 +27,14 @@ #include #include -#include "LmmsExporterSample.h" +#include "LmmsMassExporter.h" #include "SampleBuffer.h" namespace lmms { -LmmsExporterSample::LmmsExporterSample() : +LmmsMassExporter::LmmsMassExporter() : m_abortExport(false), m_isThreadRunning(false), m_readMutex(), @@ -42,13 +42,13 @@ LmmsExporterSample::LmmsExporterSample() : m_fileDescriptor(NULL) {} -LmmsExporterSample::~LmmsExporterSample() +LmmsMassExporter::~LmmsMassExporter() { stopExporting(); } -void LmmsExporterSample::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer) +void LmmsMassExporter::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer) { QString filteredName(QFileInfo(outputLocationAndName).absolutePath() + "/" + QFileInfo(outputLocationAndName).baseName()+ ".flac"); m_readMutex.lock(); @@ -59,11 +59,11 @@ void LmmsExporterSample::startExporting(const QString& outputLocationAndName, st { stopExporting(); m_isThreadRunning = true; - m_thread = new std::thread(&LmmsExporterSample::threadedExportFunction, this, &m_abortExport); + m_thread = new std::thread(&LmmsMassExporter::threadedExportFunction, this, &m_abortExport); } } -void LmmsExporterSample::stopExporting() +void LmmsMassExporter::stopExporting() { if (m_thread != nullptr) { @@ -80,7 +80,7 @@ void LmmsExporterSample::stopExporting() } -void LmmsExporterSample::threadedExportFunction(LmmsExporterSample* thisExporter, volatile bool* abortExport) +void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, volatile bool* abortExport) { thisExporter->m_isThreadRunning = true; @@ -109,7 +109,7 @@ void LmmsExporterSample::threadedExportFunction(LmmsExporterSample* thisExporter thisExporter->m_isThreadRunning = false; } -bool LmmsExporterSample::openFile(const QString& outputLocationAndName, std::shared_ptr buffer) +bool LmmsMassExporter::openFile(const QString& outputLocationAndName, std::shared_ptr buffer) { bool success = true; QFile targetFile(outputLocationAndName); @@ -137,13 +137,13 @@ bool LmmsExporterSample::openFile(const QString& outputLocationAndName, std::sha if (success == false) { - printf("LmmsExporterSample sf_open error\n"); + printf("LmmsMassExporter sf_open error\n"); } return success; } -void LmmsExporterSample::exportBuffer(std::shared_ptr buffer) +void LmmsMassExporter::exportBuffer(std::shared_ptr buffer) { if (m_fileDescriptor == NULL) { return; } constexpr size_t channelCount = 2; @@ -161,17 +161,17 @@ void LmmsExporterSample::exportBuffer(std::shared_ptr buffer size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(buffer->size())); if (count != buffer->size()) { - printf("LmmsExporterSample sf_writef_float error\n"); + printf("LmmsMassExporter sf_writef_float error\n"); } } -void LmmsExporterSample::closeFile() +void LmmsMassExporter::closeFile() { if (m_fileDescriptor == NULL) { return; } int success = sf_close(m_fileDescriptor); if (success != 0) { - printf("LmmsExporterSample sf_close error\n"); + printf("LmmsMassExporter sf_close error\n"); } m_fileDescriptor = NULL; } From f87af45e615ad3a6afe903e59f168b8696f632ec Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:24:19 +0100 Subject: [PATCH 13/32] LmmsMassExporter_moving_sndfile_code_to_new_class --- include/LmmsMassExporter.h | 23 ++++- src/core/LmmsMassExporter.cpp | 153 ++++++++++++++++++---------------- 2 files changed, 98 insertions(+), 78 deletions(-) diff --git a/include/LmmsMassExporter.h b/include/LmmsMassExporter.h index c637e919bc9..3c9deef9aa5 100644 --- a/include/LmmsMassExporter.h +++ b/include/LmmsMassExporter.h @@ -25,20 +25,35 @@ #ifndef LMMS_LMMS_MASS_EXPORTER_H #define LMMS_LMMS_MASS_EXPORTER_H +#include #include -#include #include #include #include +#include + #include namespace lmms { class SampleBuffer; +class SampleFrame; +class FlacExporter +{ +public: + FlacExporter(int sampleRate, int bitDepth, const QString& outputLocationAndName); + ~FlacExporter(); + void writeThisBuffer(const SampleFrame* samples, size_t sampleCount); + bool getIsSuccesful() const; + +private: + bool m_isSuccesful; + SNDFILE* m_fileDescriptor; +}; class LmmsMassExporter { @@ -53,7 +68,7 @@ class LmmsMassExporter //void writeBuffer(const SampleFrame* _ab, fpp_t const frames); private: - static void threadedExportFunction(LmmsMassExporter* thisExporter, volatile bool* abortExport); + static void threadedExportFunction(LmmsMassExporter* thisExporter, volatile std::atomic* abortExport); void stopThread(); bool openFile(const QString& outputLocationAndName, std::shared_ptr buffer); @@ -62,12 +77,12 @@ class LmmsMassExporter std::vector>> m_buffers; - volatile bool m_abortExport; + volatile std::atomic m_abortExport; bool m_isThreadRunning; std::mutex m_readMutex; std::thread* m_thread; - SNDFILE* m_fileDescriptor; + }; } // namespace lmms diff --git a/src/core/LmmsMassExporter.cpp b/src/core/LmmsMassExporter.cpp index a6290422cbb..bd955038c28 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -34,12 +34,85 @@ namespace lmms { +FlacExporter::FlacExporter(int sampleRate, int bitDepth, const QString& outputLocationAndName) : + m_isSuccesful(false), + m_fileDescriptor(NULL) +{ + constexpr int channelCount = 2; + SF_INFO exportInfo; + + memset(&exportInfo, 0, sizeof(exportInfo)); + exportInfo.frames = 1; + exportInfo.samplerate = sampleRate; + exportInfo.channels = channelCount; + if (bitDepth == 16) + { + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_16); + } + else if (bitDepth == 24) + { + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); + } + else + { + // there is no 32 bit support + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); + } + + QByteArray characters = outputLocationAndName.toUtf8(); + m_fileDescriptor = sf_open(characters.data(), SFM_WRITE, &exportInfo); + + m_isSuccesful = m_fileDescriptor != NULL; + + if (m_isSuccesful == false) + { + printf("LmmsMassExporter sf_open error\n"); + } +} + +FlacExporter::~FlacExporter() +{ + if (m_fileDescriptor == NULL) { return; } + m_isSuccesful = sf_close(m_fileDescriptor) == 0; + if (m_isSuccesful == false) + { + printf("FlacExporter sf_close error\n"); + } +} + +void FlacExporter::writeThisBuffer(const SampleFrame* samples, size_t sampleCount) +{ + if (m_fileDescriptor == NULL) { m_isSuccesful = false; return; } + constexpr size_t channelCount = 2; + // multiply by 2 since there is 2 channels + std::vector outputBuffer(sampleCount * channelCount); + size_t i = 0; + for (size_t j = 0; j < sampleCount; j++) + { + outputBuffer[i] = static_cast((samples + j)->left()); + outputBuffer[i + 1] = static_cast((samples + j)->right()); + outputBuffer[i] = outputBuffer[i] > 1.0f ? 1.0f : outputBuffer[i] < -1.0f ? -1.0f : outputBuffer[i]; + outputBuffer[i + 1] = outputBuffer[i + 1] > 1.0f ? 1.0f : outputBuffer[i + 1] < -1.0f ? -1.0f : outputBuffer[i + 1]; + i = i + channelCount; + } + size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(sampleCount)); + if (count != sampleCount) + { + m_isSuccesful = false; + printf("LmmsMassExporter sf_writef_float error\n"); + } +} + +bool FlacExporter::getIsSuccesful() const +{ + return m_isSuccesful; +} + LmmsMassExporter::LmmsMassExporter() : m_abortExport(false), m_isThreadRunning(false), m_readMutex(), - m_thread(nullptr), - m_fileDescriptor(NULL) + m_thread(nullptr) {} LmmsMassExporter::~LmmsMassExporter() @@ -80,7 +153,7 @@ void LmmsMassExporter::stopExporting() } -void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, volatile bool* abortExport) +void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, volatile std::atomic* abortExport) { thisExporter->m_isThreadRunning = true; @@ -96,11 +169,10 @@ void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, vo thisExporter->m_readMutex.unlock(); if (shouldExit) { break; } - bool success = thisExporter->openFile(curBuffer.first, curBuffer.second); - if (success) + FlacExporter exporter(curBuffer.second->sampleRate(), 24, curBuffer.first); + if (exporter.getIsSuccesful()) { - thisExporter->exportBuffer(curBuffer.second); - thisExporter->closeFile(); + exporter.writeThisBuffer(curBuffer.second->data(), curBuffer.second->size()); } thisExporter->m_buffers.pop_back(); @@ -109,71 +181,4 @@ void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, vo thisExporter->m_isThreadRunning = false; } -bool LmmsMassExporter::openFile(const QString& outputLocationAndName, std::shared_ptr buffer) -{ - bool success = true; - QFile targetFile(outputLocationAndName); - if (targetFile.exists() == false) - { - // creating new file - success = targetFile.open(QIODevice::WriteOnly); - if (success == false) { return false; } - targetFile.close(); - } - - constexpr int channelCount = 2; - SF_INFO exportInfo; - - memset(&exportInfo, 0, sizeof(exportInfo)); - exportInfo.frames = static_cast(buffer->size() * channelCount); - exportInfo.samplerate = buffer->sampleRate(); - exportInfo.channels = channelCount; - exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); - - QByteArray characters = outputLocationAndName.toUtf8(); - m_fileDescriptor = sf_open(characters.data(), SFM_WRITE, &exportInfo); - - success = m_fileDescriptor != NULL; - - if (success == false) - { - printf("LmmsMassExporter sf_open error\n"); - } - - return success; -} - -void LmmsMassExporter::exportBuffer(std::shared_ptr buffer) -{ - if (m_fileDescriptor == NULL) { return; } - constexpr size_t channelCount = 2; - // multiply by 2 since there is 2 channels - std::vector outputBuffer(buffer->size() * channelCount); - size_t i = 0; - for (auto it = buffer->begin(); it != buffer->end(); ++it) - { - outputBuffer[i] = static_cast(it->left()); - outputBuffer[i + 1] = static_cast(it->right()); - outputBuffer[i] = outputBuffer[i] > 1.0f ? 1.0f : outputBuffer[i] < -1.0f ? -1.0f : outputBuffer[i]; - outputBuffer[i + 1] = outputBuffer[i + 1] > 1.0f ? 1.0f : outputBuffer[i + 1] < -1.0f ? -1.0f : outputBuffer[i + 1]; - i = i + channelCount; - } - size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(buffer->size())); - if (count != buffer->size()) - { - printf("LmmsMassExporter sf_writef_float error\n"); - } -} - -void LmmsMassExporter::closeFile() -{ - if (m_fileDescriptor == NULL) { return; } - int success = sf_close(m_fileDescriptor); - if (success != 0) - { - printf("LmmsMassExporter sf_close error\n"); - } - m_fileDescriptor = NULL; -} - } // namespace lmms From 071a0029d7d8522ba43c7918bd963604aa9a72d0 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:25:15 +0100 Subject: [PATCH 14/32] CMakeLists_updating_class_names --- src/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b0842446ae2..07bddea71c8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -38,7 +38,7 @@ set(LMMS_SRCS core/LadspaManager.cpp core/LfoController.cpp core/LinkedModelGroups.cpp - core/LmmsExporterSample.cpp + core/LmmsMassExporter.cpp core/LocklessAllocator.cpp core/MeterModel.cpp core/Metronome.cpp From 0e34ec43f34565865bc7e1cf7ee07bf9734921d6 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:25:32 +0100 Subject: [PATCH 15/32] SampleClip_updating_class_names --- include/SampleClip.h | 4 ++-- src/core/SampleClip.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/SampleClip.h b/include/SampleClip.h index e7850c9c06a..696bdaf89cd 100644 --- a/include/SampleClip.h +++ b/include/SampleClip.h @@ -32,7 +32,7 @@ namespace lmms { -class LmmsExporterSample; +class LmmsMassExporter; class SampleBuffer; namespace gui @@ -95,7 +95,7 @@ public slots: BoolModel m_recordModel; bool m_isPlaying; - static std::unique_ptr s_sampleExporter; + static std::unique_ptr s_sampleExporter; friend class gui::SampleClipView; diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 7ae152bdf66..3414434fa8f 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -27,7 +27,7 @@ #include #include -#include "LmmsExporterSample.h" +#include "LmmsMassExporter.h" #include "PathUtil.h" #include "SampleBuffer.h" #include "SampleClipView.h" @@ -38,7 +38,7 @@ namespace lmms { -std::unique_ptr SampleClip::s_sampleExporter = std::make_unique(); +std::unique_ptr SampleClip::s_sampleExporter = std::make_unique(); SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying) From 8bf5f0e71866eb501c6ddc3b9d0d157c13a8d020 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:25:44 +0100 Subject: [PATCH 16/32] SampleClipView_updating_class_names --- src/gui/clips/SampleClipView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/clips/SampleClipView.cpp b/src/gui/clips/SampleClipView.cpp index aeaa43d0a37..487a66f6979 100644 --- a/src/gui/clips/SampleClipView.cpp +++ b/src/gui/clips/SampleClipView.cpp @@ -32,7 +32,7 @@ #include "AutomationEditor.h" #include "embed.h" #include "FileDialog.h" -#include "LmmsExporterSample.h" +#include "LmmsMassExporter.h" #include "PathUtil.h" #include "SampleClip.h" #include "SampleLoader.h" @@ -387,7 +387,7 @@ bool SampleClipView::splitClip( const TimePos pos ) void SampleClipView::exportSampleBuffer() { - auto openFileDialog = FileDialog(nullptr, tr("Export audio file"), QString(), tr("Audio files (*.wav *.flac *.ogg *.mp3);;WAV (*.wav);;FLAC (*.flac);;OGG (*.ogg);;MP3 (*.mp3)")); + auto openFileDialog = FileDialog(nullptr, tr("Export audio file"), QString(), tr("FLAC (*.flac)")); if (openFileDialog.exec() == QDialog::Accepted) From 98cd250a3ce0c07c9f9bfdcabcb5176a46628546 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:28:31 +0100 Subject: [PATCH 17/32] LmmsMassExporter_removing_include_QFile --- src/core/LmmsMassExporter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/LmmsMassExporter.cpp b/src/core/LmmsMassExporter.cpp index bd955038c28..4f8d306c0a9 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -24,7 +24,6 @@ #include -#include #include #include "LmmsMassExporter.h" From 02025eb08e7145d05ae1d4efbec7509b5bd575b0 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 19:02:15 +0100 Subject: [PATCH 18/32] LmmsMassExporter_implementing_callback --- include/LmmsMassExporter.h | 9 ++++++--- src/core/LmmsMassExporter.cpp | 25 ++++++++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/LmmsMassExporter.h b/include/LmmsMassExporter.h index 3c9deef9aa5..d983af931eb 100644 --- a/include/LmmsMassExporter.h +++ b/include/LmmsMassExporter.h @@ -1,7 +1,7 @@ /* * LmmsMassExporter.h - exports .flac files outside of AudioEngine * - * Copyright (c) 2024 - 2025 szeli1 + * Copyright (c) 2024 - 2025 szeli1 * * This file is part of LMMS - https://lmms.io * @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,8 @@ namespace lmms class SampleBuffer; class SampleFrame; +typedef void (*callbackFn)(void*); + class FlacExporter { public: @@ -62,7 +65,7 @@ class LmmsMassExporter ~LmmsMassExporter(); //! outputLocationAndName: should include path and name, could include ".flac" - void startExporting(const QString& outputLocationAndName, std::shared_ptr buffer); + void startExporting(const QString& outputLocationAndName, std::shared_ptr buffer, callbackFn callbackFunction = nullptr, void* callbackObject = nullptr); void stopExporting(); //void writeBuffer(const SampleFrame* _ab, fpp_t const frames); @@ -75,7 +78,7 @@ class LmmsMassExporter void exportBuffer(std::shared_ptr buffer); void closeFile(); - std::vector>> m_buffers; + std::vector, callbackFn, void*>> m_buffers; volatile std::atomic m_abortExport; bool m_isThreadRunning; diff --git a/src/core/LmmsMassExporter.cpp b/src/core/LmmsMassExporter.cpp index 4f8d306c0a9..dfa52deb618 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -1,7 +1,7 @@ /* * LmmsMassExporter.cpp - exports .flac files outside of AudioEngine * - * Copyright (c) 2024 szeli1 + * Copyright (c) 2024 - 2025 szeli1 * * This file is part of LMMS - https://lmms.io * @@ -41,7 +41,6 @@ FlacExporter::FlacExporter(int sampleRate, int bitDepth, const QString& outputLo SF_INFO exportInfo; memset(&exportInfo, 0, sizeof(exportInfo)); - exportInfo.frames = 1; exportInfo.samplerate = sampleRate; exportInfo.channels = channelCount; if (bitDepth == 16) @@ -120,11 +119,11 @@ LmmsMassExporter::~LmmsMassExporter() } -void LmmsMassExporter::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer) +void LmmsMassExporter::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer, callbackFn callbackFunction, void* callbackObject) { QString filteredName(QFileInfo(outputLocationAndName).absolutePath() + "/" + QFileInfo(outputLocationAndName).baseName()+ ".flac"); m_readMutex.lock(); - m_buffers.push_back(std::make_pair(filteredName, buffer)); + m_buffers.push_back(std::make_tuple(filteredName, buffer, callbackFunction, callbackObject)); m_readMutex.unlock(); if (m_isThreadRunning == false) @@ -158,23 +157,31 @@ void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, vo while (*abortExport == false) { - std::pair> curBuffer = std::make_pair(QString(""), nullptr); + std::tuple, callbackFn, void*> curBuffer = std::make_tuple(QString(""), nullptr, nullptr, nullptr); thisExporter->m_readMutex.lock(); bool shouldExit = thisExporter->m_buffers.size() <= 0; if (shouldExit == false) { curBuffer = thisExporter->m_buffers[thisExporter->m_buffers.size() - 1]; + thisExporter->m_buffers.pop_back(); } thisExporter->m_readMutex.unlock(); if (shouldExit) { break; } - FlacExporter exporter(curBuffer.second->sampleRate(), 24, curBuffer.first); - if (exporter.getIsSuccesful()) + // important new scope { - exporter.writeThisBuffer(curBuffer.second->data(), curBuffer.second->size()); + FlacExporter exporter(std::get<1>(curBuffer)->sampleRate(), 24, std::get<0>(curBuffer)); + if (exporter.getIsSuccesful()) + { + exporter.writeThisBuffer(std::get<1>(curBuffer)->data(), std::get<1>(curBuffer)->size()); + } } - thisExporter->m_buffers.pop_back(); + if (std::get<2>(curBuffer)) + { + // calling callback funcion + std::get<2>(curBuffer)(std::get<3>(curBuffer)); + } } thisExporter->m_isThreadRunning = false; From adba32721b6a37a30915cfa4503fa9148d10fb7a Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 19:02:40 +0100 Subject: [PATCH 19/32] SampleClip_implementing_sample_reloading --- include/SampleClip.h | 6 ++++++ src/core/SampleClip.cpp | 23 +++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/SampleClip.h b/include/SampleClip.h index 696bdaf89cd..9dc1bad8335 100644 --- a/include/SampleClip.h +++ b/include/SampleClip.h @@ -91,9 +91,15 @@ public slots: private: + void exportSampleBuffer(const QString& fileName); + static void exportSampleBufferCallback(void* thisObject); + Sample m_sample; BoolModel m_recordModel; bool m_isPlaying; + + //! used when a sample is exported and before it is reinported + QString m_exportedSampleName; static std::unique_ptr s_sampleExporter; diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 3414434fa8f..7d2f4335551 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -41,10 +41,11 @@ namespace lmms std::unique_ptr SampleClip::s_sampleExporter = std::make_unique(); -SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying) - : Clip(_track) - , m_sample(std::move(sample)) - , m_isPlaying(false) +SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying) : + Clip(_track), + m_sample(std::move(sample)), + m_isPlaying(false), + m_exportedSampleName("") { saveJournallingState( false ); setSampleFile( "" ); @@ -341,5 +342,19 @@ gui::ClipView * SampleClip::createView( gui::TrackView * _tv ) return new gui::SampleClipView( this, _tv ); } +void SampleClip::exportSampleBuffer(const QString& fileName) +{ + m_exportedSampleName = fileName; + s_sampleExporter->startExporting(fileName, m_sample.buffer(), &SampleClip::exportSampleBufferCallback, this); +} + +void SampleClip::exportSampleBufferCallback(void* thisObject) +{ + if (thisObject == nullptr) { return; } + SampleClip* castedThis = static_cast(thisObject); + castedThis->setSampleFile(castedThis->m_exportedSampleName); + castedThis->m_exportedSampleName.clear(); +} + } // namespace lmms From 5c30c30047765c6df3a3a8419a0bfc273b6ab290 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sat, 4 Jan 2025 19:03:46 +0100 Subject: [PATCH 20/32] SampleClipView_updating_names --- src/gui/clips/SampleClipView.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/clips/SampleClipView.cpp b/src/gui/clips/SampleClipView.cpp index 487a66f6979..1e74f3c215b 100644 --- a/src/gui/clips/SampleClipView.cpp +++ b/src/gui/clips/SampleClipView.cpp @@ -395,14 +395,14 @@ void SampleClipView::exportSampleBuffer() QStringList curSelectedFiles(openFileDialog.selectedFiles()); if (curSelectedFiles.isEmpty() == false) { - QString outputFileName = curSelectedFiles.first(); - if (outputFileName.isEmpty()) { return; } - if (outputFileName.endsWith(".flac") == false) + QString outputFilename = curSelectedFiles.first(); + if (outputFilename.isEmpty()) { return; } + if (outputFilename.endsWith(".flac") == false) { - outputFileName = PathUtil::stripPrefix(outputFileName) + ".flac"; + outputFilename = PathUtil::stripPrefix(outputFilename) + ".flac"; } - m_clip->s_sampleExporter->startExporting(outputFileName, m_clip->m_sample.buffer()); + m_clip->exportSampleBuffer(outputFilename); } } } From 3566660591f3b33d9ddabd2e9c262ce9edeb7c82 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 4 Jan 2025 22:36:55 +0100 Subject: [PATCH 21/32] Use FileDialog::getSaveFileName Use `FileDialog::getSaveFileName` to retrieve the file name of the file into which the sample buffer is saved. This gives us lots of functionality automatically, e.g. the request if an existing file should be overwritten. Also let remove the appending of the `.flac` file extension and let the users decide using the system file dialog. --- src/gui/clips/SampleClipView.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/gui/clips/SampleClipView.cpp b/src/gui/clips/SampleClipView.cpp index 1e74f3c215b..87e134a4a58 100644 --- a/src/gui/clips/SampleClipView.cpp +++ b/src/gui/clips/SampleClipView.cpp @@ -387,24 +387,12 @@ bool SampleClipView::splitClip( const TimePos pos ) void SampleClipView::exportSampleBuffer() { - auto openFileDialog = FileDialog(nullptr, tr("Export audio file"), QString(), tr("FLAC (*.flac)")); + const auto outputFilename = FileDialog::getSaveFileName(nullptr, tr("Export audio file"), QString(), tr("FLAC (*.flac)")); - - if (openFileDialog.exec() == QDialog::Accepted) + if (!outputFilename.isEmpty()) { - QStringList curSelectedFiles(openFileDialog.selectedFiles()); - if (curSelectedFiles.isEmpty() == false) - { - QString outputFilename = curSelectedFiles.first(); - if (outputFilename.isEmpty()) { return; } - if (outputFilename.endsWith(".flac") == false) - { - outputFilename = PathUtil::stripPrefix(outputFilename) + ".flac"; - } - - m_clip->exportSampleBuffer(outputFilename); - } - } + m_clip->exportSampleBuffer(outputFilename); + } } From 7c317b46d31ca60c63c41747993ee6cf9067333a Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sun, 5 Jan 2025 13:46:15 +0100 Subject: [PATCH 22/32] LmmsMassExporter_moving_flac_exporter --- include/LmmsMassExporter.h | 15 ------- src/core/LmmsMassExporter.cpp | 76 +---------------------------------- 2 files changed, 1 insertion(+), 90 deletions(-) diff --git a/include/LmmsMassExporter.h b/include/LmmsMassExporter.h index d983af931eb..0573a17258f 100644 --- a/include/LmmsMassExporter.h +++ b/include/LmmsMassExporter.h @@ -40,24 +40,9 @@ namespace lmms { class SampleBuffer; -class SampleFrame; typedef void (*callbackFn)(void*); -class FlacExporter -{ -public: - FlacExporter(int sampleRate, int bitDepth, const QString& outputLocationAndName); - ~FlacExporter(); - - void writeThisBuffer(const SampleFrame* samples, size_t sampleCount); - bool getIsSuccesful() const; - -private: - bool m_isSuccesful; - SNDFILE* m_fileDescriptor; -}; - class LmmsMassExporter { public: diff --git a/src/core/LmmsMassExporter.cpp b/src/core/LmmsMassExporter.cpp index dfa52deb618..d20995b4e90 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -22,90 +22,16 @@ * */ -#include - #include #include "LmmsMassExporter.h" +#include "FlacExporter.h" #include "SampleBuffer.h" namespace lmms { -FlacExporter::FlacExporter(int sampleRate, int bitDepth, const QString& outputLocationAndName) : - m_isSuccesful(false), - m_fileDescriptor(NULL) -{ - constexpr int channelCount = 2; - SF_INFO exportInfo; - - memset(&exportInfo, 0, sizeof(exportInfo)); - exportInfo.samplerate = sampleRate; - exportInfo.channels = channelCount; - if (bitDepth == 16) - { - exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_16); - } - else if (bitDepth == 24) - { - exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); - } - else - { - // there is no 32 bit support - exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); - } - - QByteArray characters = outputLocationAndName.toUtf8(); - m_fileDescriptor = sf_open(characters.data(), SFM_WRITE, &exportInfo); - - m_isSuccesful = m_fileDescriptor != NULL; - - if (m_isSuccesful == false) - { - printf("LmmsMassExporter sf_open error\n"); - } -} - -FlacExporter::~FlacExporter() -{ - if (m_fileDescriptor == NULL) { return; } - m_isSuccesful = sf_close(m_fileDescriptor) == 0; - if (m_isSuccesful == false) - { - printf("FlacExporter sf_close error\n"); - } -} - -void FlacExporter::writeThisBuffer(const SampleFrame* samples, size_t sampleCount) -{ - if (m_fileDescriptor == NULL) { m_isSuccesful = false; return; } - constexpr size_t channelCount = 2; - // multiply by 2 since there is 2 channels - std::vector outputBuffer(sampleCount * channelCount); - size_t i = 0; - for (size_t j = 0; j < sampleCount; j++) - { - outputBuffer[i] = static_cast((samples + j)->left()); - outputBuffer[i + 1] = static_cast((samples + j)->right()); - outputBuffer[i] = outputBuffer[i] > 1.0f ? 1.0f : outputBuffer[i] < -1.0f ? -1.0f : outputBuffer[i]; - outputBuffer[i + 1] = outputBuffer[i + 1] > 1.0f ? 1.0f : outputBuffer[i + 1] < -1.0f ? -1.0f : outputBuffer[i + 1]; - i = i + channelCount; - } - size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(sampleCount)); - if (count != sampleCount) - { - m_isSuccesful = false; - printf("LmmsMassExporter sf_writef_float error\n"); - } -} - -bool FlacExporter::getIsSuccesful() const -{ - return m_isSuccesful; -} - LmmsMassExporter::LmmsMassExporter() : m_abortExport(false), m_isThreadRunning(false), From e19bb60778d339ca243e9f96667dd95c6fb88b49 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sun, 5 Jan 2025 13:46:42 +0100 Subject: [PATCH 23/32] FlacExporter_moving_to_new_file --- include/FlacExporter.h | 53 ++++++++++++++++ src/core/audio/FlacExporter.cpp | 109 ++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 include/FlacExporter.h create mode 100644 src/core/audio/FlacExporter.cpp diff --git a/include/FlacExporter.h b/include/FlacExporter.h new file mode 100644 index 00000000000..2ca2b2fe858 --- /dev/null +++ b/include/FlacExporter.h @@ -0,0 +1,53 @@ +/* + * FlacExporter.h - exports .flac files outside of AudioEngine + * + * Copyright (c) 2024 - 2025 szeli1 + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_FLAC_EXPORTER_H +#define LMMS_FLAC_EXPORTER_H + +#include + +#include + +namespace lmms +{ + +class SampleFrame; + +class FlacExporter +{ +public: + FlacExporter(int sampleRate, int bitDepth, const QString& outputLocationAndName); + ~FlacExporter(); + + void writeThisBuffer(const SampleFrame* samples, size_t sampleCount); + bool getIsSuccesful() const; + +private: + bool m_isSuccesful; + SNDFILE* m_fileDescriptor; +}; + +} // namespace lmms + +#endif // LMMS_FLAC_EXPORTER_H diff --git a/src/core/audio/FlacExporter.cpp b/src/core/audio/FlacExporter.cpp new file mode 100644 index 00000000000..2a59ff91175 --- /dev/null +++ b/src/core/audio/FlacExporter.cpp @@ -0,0 +1,109 @@ +/* + * FlacExporter.cpp - exports .flac files outside of AudioEngine + * + * Copyright (c) 2024 - 2025 szeli1 + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include + +#include + +#include "FlacExporter.h" + +#include "SampleFrame.h" + +namespace lmms +{ + +FlacExporter::FlacExporter(int sampleRate, int bitDepth, const QString& outputLocationAndName) : + m_isSuccesful(false), + m_fileDescriptor(NULL) +{ + constexpr int channelCount = 2; + SF_INFO exportInfo; + + memset(&exportInfo, 0, sizeof(exportInfo)); + exportInfo.samplerate = sampleRate; + exportInfo.channels = channelCount; + if (bitDepth == 16) + { + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_16); + } + else if (bitDepth == 24) + { + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); + } + else + { + // there is no 32 bit support + exportInfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); + } + + QByteArray characters = outputLocationAndName.toUtf8(); + m_fileDescriptor = sf_open(characters.data(), SFM_WRITE, &exportInfo); + + m_isSuccesful = m_fileDescriptor != NULL; + + if (m_isSuccesful == false) + { + printf("FlacExporter sf_open error\n"); + } +} + +FlacExporter::~FlacExporter() +{ + if (m_fileDescriptor == NULL) { return; } + m_isSuccesful = sf_close(m_fileDescriptor) == 0; + if (m_isSuccesful == false) + { + printf("FlacExporter sf_close error\n"); + } +} + +void FlacExporter::writeThisBuffer(const SampleFrame* samples, size_t sampleCount) +{ + if (m_fileDescriptor == NULL) { m_isSuccesful = false; return; } + constexpr size_t channelCount = 2; + // multiply by 2 since there is 2 channels + std::vector outputBuffer(sampleCount * channelCount); + size_t i = 0; + for (size_t j = 0; j < sampleCount; j++) + { + outputBuffer[i] = static_cast((samples + j)->left()); + outputBuffer[i + 1] = static_cast((samples + j)->right()); + outputBuffer[i] = outputBuffer[i] > 1.0f ? 1.0f : outputBuffer[i] < -1.0f ? -1.0f : outputBuffer[i]; + outputBuffer[i + 1] = outputBuffer[i + 1] > 1.0f ? 1.0f : outputBuffer[i + 1] < -1.0f ? -1.0f : outputBuffer[i + 1]; + i = i + channelCount; + } + size_t count = sf_writef_float(m_fileDescriptor, outputBuffer.data(), static_cast(sampleCount)); + if (count != sampleCount) + { + m_isSuccesful = false; + printf("FlacExporter sf_writef_float error\n"); + } +} + +bool FlacExporter::getIsSuccesful() const +{ + return m_isSuccesful; +} + +} // namespace lmms From 1ba312e54a16d65c4aa00e557248d6f783f96e1d Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:09:07 +0100 Subject: [PATCH 24/32] LmmsMassExporter_updating_description --- include/LmmsMassExporter.h | 2 +- src/core/LmmsMassExporter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LmmsMassExporter.h b/include/LmmsMassExporter.h index 0573a17258f..ab27a0e3fd5 100644 --- a/include/LmmsMassExporter.h +++ b/include/LmmsMassExporter.h @@ -1,5 +1,5 @@ /* - * LmmsMassExporter.h - exports .flac files outside of AudioEngine + * LmmsMassExporter.h - exports files in .flac format on an other thread * * Copyright (c) 2024 - 2025 szeli1 * diff --git a/src/core/LmmsMassExporter.cpp b/src/core/LmmsMassExporter.cpp index d20995b4e90..a2adab9a875 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -1,5 +1,5 @@ /* - * LmmsMassExporter.cpp - exports .flac files outside of AudioEngine + * LmmsMassExporter.cpp - exports files in .flac format on an other thread * * Copyright (c) 2024 - 2025 szeli1 * From 0452b7f6ec5a0f58a58d161bec260c692eeeda39 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:25:46 +0100 Subject: [PATCH 25/32] CMakeLists_adding_FlacExporter_cmake_target --- src/core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 07bddea71c8..c9abac9a4a4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -107,6 +107,7 @@ set(LMMS_SRCS core/audio/AudioPulseAudio.cpp core/audio/AudioSampleRecorder.cpp core/audio/AudioSdl.cpp + core/audio/FlacExporter.cpp core/lv2/Lv2Basics.cpp core/lv2/Lv2ControlBase.cpp From 5228076188ce18630e9fe28852edc46ad385e172 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:33:55 +0100 Subject: [PATCH 26/32] LmmsMassExporter_removing_blank_line --- include/LmmsMassExporter.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/LmmsMassExporter.h b/include/LmmsMassExporter.h index ab27a0e3fd5..d7f1a3c0058 100644 --- a/include/LmmsMassExporter.h +++ b/include/LmmsMassExporter.h @@ -69,8 +69,6 @@ class LmmsMassExporter bool m_isThreadRunning; std::mutex m_readMutex; std::thread* m_thread; - - }; } // namespace lmms From 5fa60b35503edf50742923c00e072ff77e4e2363 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Mon, 6 Jan 2025 20:59:42 +0100 Subject: [PATCH 27/32] Save file with user selected name Save the exported file under the name that the users have selected and do not append ".flac". This fixes an exception that was thrown because the file is saved with the appended extension but then attempted to load without it. --- src/core/LmmsMassExporter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/LmmsMassExporter.cpp b/src/core/LmmsMassExporter.cpp index a2adab9a875..94153d4a8d8 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/LmmsMassExporter.cpp @@ -47,9 +47,8 @@ LmmsMassExporter::~LmmsMassExporter() void LmmsMassExporter::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer, callbackFn callbackFunction, void* callbackObject) { - QString filteredName(QFileInfo(outputLocationAndName).absolutePath() + "/" + QFileInfo(outputLocationAndName).baseName()+ ".flac"); m_readMutex.lock(); - m_buffers.push_back(std::make_tuple(filteredName, buffer, callbackFunction, callbackObject)); + m_buffers.push_back(std::make_tuple(outputLocationAndName, buffer, callbackFunction, callbackObject)); m_readMutex.unlock(); if (m_isThreadRunning == false) From 5a0eeb7de7f2736aae1aac980904a9ef100dcf84 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 8 Jan 2025 06:52:03 +0100 Subject: [PATCH 28/32] LmmsMassExporter_renaming_to_ThreadedExportManager --- ...MassExporter.h => ThreadedExportManager.h} | 16 ++++++------- ...Exporter.cpp => ThreadedExportManager.cpp} | 24 +++++++++---------- 2 files changed, 19 insertions(+), 21 deletions(-) rename include/{LmmsMassExporter.h => ThreadedExportManager.h} (82%) rename src/core/{LmmsMassExporter.cpp => ThreadedExportManager.cpp} (71%) diff --git a/include/LmmsMassExporter.h b/include/ThreadedExportManager.h similarity index 82% rename from include/LmmsMassExporter.h rename to include/ThreadedExportManager.h index d7f1a3c0058..42fade28125 100644 --- a/include/LmmsMassExporter.h +++ b/include/ThreadedExportManager.h @@ -1,5 +1,5 @@ /* - * LmmsMassExporter.h - exports files in .flac format on an other thread + * ThreadedExportManager.h - exports files in .flac format on an other thread * * Copyright (c) 2024 - 2025 szeli1 * @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_LMMS_MASS_EXPORTER_H -#define LMMS_LMMS_MASS_EXPORTER_H +#ifndef LMMS_THREADED_EXPORT_MANAGER_H +#define LMMS_THREADED_EXPORT_MANAGER_H #include #include @@ -43,11 +43,11 @@ class SampleBuffer; typedef void (*callbackFn)(void*); -class LmmsMassExporter +class ThreadedExportManager { public: - LmmsMassExporter(); - ~LmmsMassExporter(); + ThreadedExportManager(); + ~ThreadedExportManager(); //! outputLocationAndName: should include path and name, could include ".flac" void startExporting(const QString& outputLocationAndName, std::shared_ptr buffer, callbackFn callbackFunction = nullptr, void* callbackObject = nullptr); @@ -56,7 +56,7 @@ class LmmsMassExporter //void writeBuffer(const SampleFrame* _ab, fpp_t const frames); private: - static void threadedExportFunction(LmmsMassExporter* thisExporter, volatile std::atomic* abortExport); + static void threadedExportFunction(ThreadedExportManager* thisExporter, volatile std::atomic* abortExport); void stopThread(); bool openFile(const QString& outputLocationAndName, std::shared_ptr buffer); @@ -73,4 +73,4 @@ class LmmsMassExporter } // namespace lmms -#endif // LMMS_LMMS_MASS_EXPORTER_H +#endif // LMMS_THREADED_EXPORT_MANAGER_H diff --git a/src/core/LmmsMassExporter.cpp b/src/core/ThreadedExportManager.cpp similarity index 71% rename from src/core/LmmsMassExporter.cpp rename to src/core/ThreadedExportManager.cpp index 94153d4a8d8..e1b89658c7d 100644 --- a/src/core/LmmsMassExporter.cpp +++ b/src/core/ThreadedExportManager.cpp @@ -1,5 +1,5 @@ /* - * LmmsMassExporter.cpp - exports files in .flac format on an other thread + * ThreadedExportManager.cpp - exports files in .flac format on an other thread * * Copyright (c) 2024 - 2025 szeli1 * @@ -22,9 +22,7 @@ * */ -#include - -#include "LmmsMassExporter.h" +#include "ThreadedExportManager.h" #include "FlacExporter.h" #include "SampleBuffer.h" @@ -32,20 +30,20 @@ namespace lmms { -LmmsMassExporter::LmmsMassExporter() : +ThreadedExportManager::ThreadedExportManager() : m_abortExport(false), m_isThreadRunning(false), m_readMutex(), m_thread(nullptr) {} -LmmsMassExporter::~LmmsMassExporter() +ThreadedExportManager::~ThreadedExportManager() { stopExporting(); } -void LmmsMassExporter::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer, callbackFn callbackFunction, void* callbackObject) +void ThreadedExportManager::startExporting(const QString& outputLocationAndName, std::shared_ptr buffer, callbackFn callbackFunction, void* callbackObject) { m_readMutex.lock(); m_buffers.push_back(std::make_tuple(outputLocationAndName, buffer, callbackFunction, callbackObject)); @@ -55,11 +53,11 @@ void LmmsMassExporter::startExporting(const QString& outputLocationAndName, std: { stopExporting(); m_isThreadRunning = true; - m_thread = new std::thread(&LmmsMassExporter::threadedExportFunction, this, &m_abortExport); + m_thread = new std::thread(&ThreadedExportManager::threadedExportFunction, this, &m_abortExport); } } -void LmmsMassExporter::stopExporting() +void ThreadedExportManager::stopExporting() { if (m_thread != nullptr) { @@ -76,7 +74,7 @@ void LmmsMassExporter::stopExporting() } -void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, volatile std::atomic* abortExport) +void ThreadedExportManager::threadedExportFunction(ThreadedExportManager* thisExporter, volatile std::atomic* abortExport) { thisExporter->m_isThreadRunning = true; @@ -95,10 +93,10 @@ void LmmsMassExporter::threadedExportFunction(LmmsMassExporter* thisExporter, vo // important new scope { - FlacExporter exporter(std::get<1>(curBuffer)->sampleRate(), 24, std::get<0>(curBuffer)); - if (exporter.getIsSuccesful()) + FlacExporter flacExporter(std::get<1>(curBuffer)->sampleRate(), 24, std::get<0>(curBuffer)); + if (flacExporter.getIsSuccesful()) { - exporter.writeThisBuffer(std::get<1>(curBuffer)->data(), std::get<1>(curBuffer)->size()); + flacExporter.writeThisBuffer(std::get<1>(curBuffer)->data(), std::get<1>(curBuffer)->size()); } } From 96f9888e9329c1e9f615df6f337b53cfbbd46c72 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 8 Jan 2025 06:52:48 +0100 Subject: [PATCH 29/32] CMakeLists_renaming_class --- src/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c9abac9a4a4..f41996ec4e3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -38,7 +38,6 @@ set(LMMS_SRCS core/LadspaManager.cpp core/LfoController.cpp core/LinkedModelGroups.cpp - core/LmmsMassExporter.cpp core/LocklessAllocator.cpp core/MeterModel.cpp core/Metronome.cpp @@ -78,6 +77,7 @@ set(LMMS_SRCS core/SerializingObject.cpp core/Song.cpp core/TempoSyncKnobModel.cpp + core/ThreadedExportManager.cpp core/ThreadPool.cpp core/Timeline.cpp core/TimePos.cpp From 65ec0af038f99b9bed75f701a6359dce08bc2304 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 8 Jan 2025 06:53:16 +0100 Subject: [PATCH 30/32] SampleClipView_removing_LmmsMassExporter_include --- src/gui/clips/SampleClipView.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/clips/SampleClipView.cpp b/src/gui/clips/SampleClipView.cpp index 87e134a4a58..353069032af 100644 --- a/src/gui/clips/SampleClipView.cpp +++ b/src/gui/clips/SampleClipView.cpp @@ -32,7 +32,6 @@ #include "AutomationEditor.h" #include "embed.h" #include "FileDialog.h" -#include "LmmsMassExporter.h" #include "PathUtil.h" #include "SampleClip.h" #include "SampleLoader.h" From 9fec78c60051cbdb3eb469f14a31438a474f042b Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 8 Jan 2025 06:53:43 +0100 Subject: [PATCH 31/32] SampleClip_renaming_class --- include/SampleClip.h | 4 ++-- src/core/SampleClip.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/SampleClip.h b/include/SampleClip.h index 9dc1bad8335..b98d1450fe5 100644 --- a/include/SampleClip.h +++ b/include/SampleClip.h @@ -32,7 +32,7 @@ namespace lmms { -class LmmsMassExporter; +class ThreadedExportManager; class SampleBuffer; namespace gui @@ -101,7 +101,7 @@ public slots: //! used when a sample is exported and before it is reinported QString m_exportedSampleName; - static std::unique_ptr s_sampleExporter; + static std::unique_ptr s_sampleExporter; friend class gui::SampleClipView; diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 7d2f4335551..0b496af754c 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -27,7 +27,7 @@ #include #include -#include "LmmsMassExporter.h" +#include "ThreadedExportManager.h" #include "PathUtil.h" #include "SampleBuffer.h" #include "SampleClipView.h" @@ -38,7 +38,7 @@ namespace lmms { -std::unique_ptr SampleClip::s_sampleExporter = std::make_unique(); +std::unique_ptr SampleClip::s_sampleExporter = std::make_unique(); SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying) : From bc59f5f733d011d38fa4d4cfe75a527a5505e18a Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 8 Jan 2025 07:01:39 +0100 Subject: [PATCH 32/32] FlacExporter_adding_sync_function_before_destructing --- src/core/audio/FlacExporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/audio/FlacExporter.cpp b/src/core/audio/FlacExporter.cpp index 2a59ff91175..9ea7fb2a99d 100644 --- a/src/core/audio/FlacExporter.cpp +++ b/src/core/audio/FlacExporter.cpp @@ -71,6 +71,7 @@ FlacExporter::FlacExporter(int sampleRate, int bitDepth, const QString& outputLo FlacExporter::~FlacExporter() { if (m_fileDescriptor == NULL) { return; } + sf_write_sync(m_fileDescriptor); m_isSuccesful = sf_close(m_fileDescriptor) == 0; if (m_isSuccesful == false) {