-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
adding sample exporter #7627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
adding sample exporter #7627
Changes from all commits
94258b4
98cffce
96a2287
9117d77
43328ea
020e425
5dc1651
7cf8bb8
a884d1c
6da5e91
43c19cc
8e39af2
083085e
e0633e1
974634c
efdb5a6
acef235
d201257
94bc1e2
fb446ab
ce014e5
43661fb
67918a9
fbe413f
4b8ba9b
cca3c0b
8f450ac
15ce7cd
76fa656
cdf7b8c
dbff613
b8916c2
bc3a485
e1bad1b
ed6494d
a27a600
cc300ad
8f35a86
252d357
db54a46
488078b
f8d5c56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <sndfile.h> | ||
|
|
||
| #include <QString> | ||
|
|
||
| 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 = false; | ||
| SNDFILE* m_fileDescriptor = nullptr; | ||
| }; | ||
|
|
||
| } // namespace lmms | ||
|
|
||
| #endif // LMMS_FLAC_EXPORTER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| /* | ||
| * ThreadedExportManager.h - exports files in .flac format on an other thread | ||
| * | ||
| * 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_THREADED_EXPORT_MANAGER_H | ||
| #define LMMS_THREADED_EXPORT_MANAGER_H | ||
|
|
||
| #include <atomic> | ||
| #include <memory> | ||
| #include <thread> | ||
| #include <tuple> | ||
| #include <vector> | ||
| #include <mutex> | ||
|
|
||
| #include <sndfile.h> | ||
|
|
||
| #include <QString> | ||
|
|
||
| namespace lmms | ||
| { | ||
|
|
||
| class SampleBuffer; | ||
|
|
||
| typedef void (*callbackFn)(void*); | ||
|
|
||
| class ThreadedExportManager | ||
| { | ||
| public: | ||
| ThreadedExportManager(); | ||
| ~ThreadedExportManager(); | ||
|
|
||
| //! @param outputLocationAndName: should include path and name, could include ".flac" | ||
| void startExporting(const QString& outputLocationAndName, std::shared_ptr<const SampleBuffer> buffer, callbackFn callbackFunction = nullptr, void* callbackObject = nullptr); | ||
| void stopExporting(); | ||
|
|
||
| private: | ||
| static void threadedExportMethod(ThreadedExportManager* thisExporter, std::atomic<bool>* shouldRun); | ||
|
|
||
| std::vector<std::tuple<QString, std::shared_ptr<const SampleBuffer>, callbackFn, void*>> m_buffers; | ||
|
|
||
| std::atomic<bool> m_isThreadRunning = false; | ||
| std::mutex m_readMutex; | ||
| std::thread* m_thread = nullptr; | ||
| }; | ||
|
|
||
| } // namespace lmms | ||
|
|
||
| #endif // LMMS_THREADED_EXPORT_MANAGER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| /* | ||
| * ThreadedExportManager.cpp - exports files in .flac format on an other thread | ||
| * | ||
| * 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 "ThreadedExportManager.h" | ||
|
|
||
| #include "FlacExporter.h" | ||
| #include "SampleBuffer.h" | ||
|
|
||
| namespace lmms | ||
| { | ||
|
|
||
| ThreadedExportManager::ThreadedExportManager() | ||
| {} | ||
|
|
||
| ThreadedExportManager::~ThreadedExportManager() | ||
| { | ||
| stopExporting(); | ||
| } | ||
|
|
||
|
|
||
| void ThreadedExportManager::startExporting(const QString& outputLocationAndName, std::shared_ptr<const SampleBuffer> buffer, callbackFn callbackFunction, void* callbackObject) | ||
| { | ||
| m_readMutex.lock(); | ||
| m_buffers.push_back(std::make_tuple(outputLocationAndName, buffer, callbackFunction, callbackObject)); | ||
JohannesLorenz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| m_readMutex.unlock(); | ||
|
|
||
| if (m_isThreadRunning == false) | ||
| { | ||
| stopExporting(); | ||
| m_isThreadRunning = true; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this variable can be elided? Rather just test for
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, setting the variable here seems redundant (and possibly dangerous?) since threadedExportFunction just does that.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @szeli1 This comment is resolved, but why did you keep the variable?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because I have refactored the design, to only use 1 boolean. I believe once a thread is finished, the pointer will not point to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, before I can answer here, we need to discuss my new comment :) |
||
| m_thread = new std::thread(&ThreadedExportManager::threadedExportMethod, this, &m_isThreadRunning); | ||
| } | ||
| } | ||
|
|
||
| void ThreadedExportManager::stopExporting() | ||
| { | ||
| if (m_thread != nullptr) | ||
| { | ||
| m_isThreadRunning = false; | ||
| m_thread->join(); | ||
| delete m_thread; | ||
| m_thread = nullptr; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| void ThreadedExportManager::threadedExportMethod(ThreadedExportManager* thisExporter, std::atomic<bool>* shouldRun) | ||
| { | ||
| while (*shouldRun == true) | ||
| { | ||
| std::tuple<QString, std::shared_ptr<const SampleBuffer>, callbackFn, void*> curBuffer = std::make_tuple(QString(""), nullptr, nullptr, nullptr); | ||
| thisExporter->m_readMutex.lock(); | ||
| bool shouldExit = thisExporter->m_buffers.size() <= 0; | ||
| if (shouldExit == false) | ||
JohannesLorenz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| curBuffer = thisExporter->m_buffers[thisExporter->m_buffers.size() - 1]; | ||
| thisExporter->m_buffers.pop_back(); | ||
| } | ||
| thisExporter->m_readMutex.unlock(); | ||
| if (shouldExit) { break; } | ||
|
|
||
| // important new scope | ||
| // can't call back if flacExporter's file is open | ||
| { | ||
| FlacExporter flacExporter(std::get<1>(curBuffer)->sampleRate(), 24, std::get<0>(curBuffer)); | ||
| if (flacExporter.getIsSuccesful()) | ||
| { | ||
| flacExporter.writeThisBuffer(std::get<1>(curBuffer)->data(), std::get<1>(curBuffer)->size()); | ||
| } | ||
| } | ||
|
|
||
| if (std::get<2>(curBuffer)) | ||
| { | ||
| // calling callback funcion | ||
| std::get<2>(curBuffer)(std::get<3>(curBuffer)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace lmms | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let us assume I close LMMS while there are still buffers left to be rendered... Then this here will set
m_isThreadRunningtofalse. Hence,threadedExportMethodwill seeshouldRunasfalseand will discard all pending requests - which means data loss. So, why not remove them_isThreadRunningand just letstopExportingcallm_thread->join(), which will wait until all pending requests are finished?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect things to be lost when I start to export something and then close the application. However nothing indicates that the exporting was finished.
Maybe use the callback function? (To display a Text Float)