Nathan, you said:
unique track exports can easily export unique BB sounds by assigning
> corresponding mixer channels explicitly to each sound.
>
Actually, I don't know if this is possible---at least I don't know how to
do it. You can assign unique BB sounds to corresponding FX channel, but as
far as I know, that's only for applying FX. What I see in the "mixer" view
is the FX channels. The tracks I export are the ones you see in the song
view.
Am I missing something? Is there a way to assign a BB sound to an
individual song track?
Devin
> Also i tend to layer sounds, and this would be a bad if i didnt have the
> effects i wanted on layered sounds.
>
> but i repeat, if you added the feature instead of replacing/changing it
> from a mixer track export, that would be awesome.
>
> just my two cents
>
> 2012/10/29 Devin Venable <[email protected]>
>
>> Running out of time tonight, but going to submit working patch for
>> individual track export (for review).
>>
>> (Note, I think the LMMS submitting a patch page should say to use "git
>> diff --cached" instead of "git diff" since right above you instruct the
>> reader to add the changed files to the staging area.)
>>
>> This code exports each track in the song view as a separate wav file.
>> However, I think I want to go back in and change the algorithm, as what I
>> really want to do is export Beat/Bassline tracks differently. The purpose
>> of the track export is to isolate sounds, and B/B exports all different
>> sounds---which then get exported again, usually with a different pattern,
>> for each B/B track.
>>
>> I really want something like this:
>>
>> For all unique_sounds in all B/B tracks:
>> For each B/B track:
>> Select unique_sound (like kick.ogg)
>> Mute other sounds
>> Export track
>>
>> The result would be to mute all tracks except for all B/B tracks, and
>> then all sounds except for kick.ogg. Then export kick.ogg.track.wav.
>>
>> I may not be making sense as I'm quite tired...so I'll re-read and
>> re-think in the AM. Thanks!
>>
>> Devin
>>
>>
>>
>>
>>
>>
>> diff --git a/include/export_project_dialog.h
>> b/include/export_project_dialog.h
>> index 266b9f9..944e5fe 100644
>> --- a/include/export_project_dialog.h
>> +++ b/include/export_project_dialog.h
>> @@ -28,17 +28,17 @@
>> #define _EXPORT_PROJECT_DIALOG_H
>>
>> #include <QtGui/QDialog>
>> -
>> +#include <vector>
>> #include "ui_export_project.h"
>>
>> -class ProjectRenderer;
>> +#include "ProjectRenderer.h"
>>
>>
>> class exportProjectDialog : public QDialog, public
>> Ui::ExportProjectDialog
>> {
>> Q_OBJECT
>> public:
>> - exportProjectDialog( const QString & _file_name, QWidget * _parent );
>> + exportProjectDialog( const QString & _file_name, QWidget * _parent,
>> bool multi_export );
>> virtual ~exportProjectDialog();
>>
>>
>> @@ -50,12 +50,20 @@ protected:
>> private slots:
>> void startBtnClicked( void );
>> void updateTitleBar( int );
>> -
>> + void render(ProjectRenderer* renderer);
>> + void multi_render();
>> + ProjectRenderer* prep_render();
>> + void pop_render();
>> + void accept();
>>
>> private:
>> QString m_fileName;
>> - ProjectRenderer * m_renderer;
>> -
>> + QString m_dirName;
>> + std::vector<ProjectRenderer*> m_renderers;
>> + bool m_multi_export;
>> + std::vector<track*> m_unmuted;
>> + ProjectRenderer::ExportFileFormats m_ft;
>> + std::vector<track*> m_to_render_vec;
>> } ;
>>
>> #endif
>> diff --git a/include/song.h b/include/song.h
>> index 3b12971..6eafefa 100644
>> --- a/include/song.h
>> +++ b/include/song.h
>> @@ -207,7 +207,8 @@ public slots:
>> void resumeFromPause();
>>
>> void importProject();
>> - void exportProject();
>> + void exportProject(bool multiExport=false);
>> + void exportProjectTracks();
>>
>> void startExport();
>> void stopExport();
>> diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp
>> index 37de20e..89f3f46 100644
>> --- a/src/core/ProjectRenderer.cpp
>> +++ b/src/core/ProjectRenderer.cpp
>> @@ -35,7 +35,7 @@
>> #ifdef LMMS_HAVE_SCHED_H
>> #include <sched.h>
>> #endif
>> -
>> +#include <QMutexLocker>
>>
>> FileEncodeDevice __fileEncodeDevices[] =
>> {
>> @@ -126,6 +126,7 @@ ProjectRenderer::ExportFileFormats
>> ProjectRenderer::getFileFormatFromExtension(
>>
>> void ProjectRenderer::startProcessing()
>> {
>> +
>> if( isReady() )
>> {
>> // have to do mixer stuff with GUI-thread-affinity in order to
>> @@ -139,11 +140,11 @@ void ProjectRenderer::startProcessing()
>> QThread::HighPriority
>> #endif
>> );
>> +
>> }
>> }
>>
>>
>> -
>> void ProjectRenderer::run()
>> {
>> #if 0
>> @@ -157,6 +158,7 @@ void ProjectRenderer::run()
>> #endif
>> #endif
>>
>> +
>> engine::getSong()->startExport();
>>
>> song::playPos & pp = engine::getSong()->getPlayPos(
>> diff --git a/src/core/song.cpp b/src/core/song.cpp
>> index 8962e73..75f4f2e 100644
>> --- a/src/core/song.cpp
>> +++ b/src/core/song.cpp
>> @@ -60,7 +60,8 @@
>> #include "templates.h"
>> #include "text_float.h"
>> #include "timeline.h"
>> -
>> +#include <vector>
>> +using namespace std;
>>
>> tick_t midiTime::s_ticksPerTact = DefaultTicksPerTact;
>>
>> @@ -1136,9 +1137,12 @@ void song::restoreControllerStates( const
>> QDomElement & _this )
>> }
>>
>>
>> +void song::exportProjectTracks()
>> +{
>> + exportProject(true);
>> +}
>>
>> -
>> -void song::exportProject()
>> +void song::exportProject(bool multiExport)
>> {
>> if( isEmpty() )
>> {
>> @@ -1151,38 +1155,51 @@ void song::exportProject()
>> }
>>
>> QFileDialog efd( engine::mainWindow() );
>> - efd.setFileMode( QFileDialog::AnyFile );
>> - efd.setAcceptMode( QFileDialog::AcceptSave );
>> - int idx = 0;
>> - QStringList types;
>> - while( __fileEncodeDevices[idx].m_fileFormat !=
>> - ProjectRenderer::NumFileFormats )
>> + if (multiExport)
>> {
>> - types << tr( __fileEncodeDevices[idx].m_description );
>> - ++idx;
>> - }
>> - efd.setFilters( types );
>> -
>> - QString base_filename;
>> - if( !m_fileName.isEmpty() )
>> - {
>> - efd.setDirectory( QFileInfo( m_fileName ).absolutePath() );
>> - base_filename = QFileInfo( m_fileName ).completeBaseName();
>> + efd.setFileMode( QFileDialog::Directory);
>> + efd.setWindowTitle( tr( "Select directory for writing exported
>> tracks..." ) );
>> + if( !m_fileName.isEmpty() )
>> + {
>> + efd.setDirectory( QFileInfo( m_fileName ).absolutePath() );
>> + }
>> }
>> else
>> {
>> - efd.setDirectory( configManager::inst()->userProjectsDir() );
>> - base_filename = tr( "untitled" );
>> + efd.setFileMode( QFileDialog::AnyFile );
>> + int idx = 0;
>> + QStringList types;
>> + while( __fileEncodeDevices[idx].m_fileFormat !=
>> + ProjectRenderer::NumFileFormats )
>> + {
>> + types << tr( __fileEncodeDevices[idx].m_description );
>> + ++idx;
>> + }
>> + efd.setFilters( types );
>> + QString base_filename;
>> + if( !m_fileName.isEmpty() )
>> + {
>> + efd.setDirectory( QFileInfo( m_fileName ).absolutePath() );
>> + base_filename = QFileInfo( m_fileName ).completeBaseName();
>> + }
>> + else
>> + {
>> + efd.setDirectory( configManager::inst()->userProjectsDir() );
>> + base_filename = tr( "untitled" );
>> + }
>> + efd.selectFile( base_filename + __fileEncodeDevices[0].m_extension );
>> + efd.setWindowTitle( tr( "Select file for project-export..." ) );
>> }
>> - efd.selectFile( base_filename + __fileEncodeDevices[0].m_extension );
>> - efd.setWindowTitle( tr( "Select file for project-export..." ) );
>> +
>> + efd.setAcceptMode( QFileDialog::AcceptSave );
>> +
>>
>> if( efd.exec() == QDialog::Accepted &&
>> !efd.selectedFiles().isEmpty() && !efd.selectedFiles()[0].isEmpty() )
>> {
>> const QString export_file_name = efd.selectedFiles()[0];
>> exportProjectDialog epd( export_file_name,
>> - engine::mainWindow() );
>> + engine::mainWindow(), multiExport );
>> epd.exec();
>> }
>> }
>> diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
>> index 4966ff1..262ef41 100644
>> --- a/src/gui/MainWindow.cpp
>> +++ b/src/gui/MainWindow.cpp
>> @@ -255,6 +255,12 @@ void MainWindow::finalize( void )
>> engine::getSong(),
>> SLOT( exportProject() ),
>> Qt::CTRL + Qt::Key_E );
>> + project_menu->addAction( embed::getIconPixmap( "project_export" ),
>> + tr( "E&xport tracks..." ),
>> + engine::getSong(),
>> + SLOT( exportProjectTracks() ),
>> + Qt::CTRL + Qt::Key_E );
>> +
>> project_menu->addSeparator();
>> project_menu->addAction( embed::getIconPixmap( "exit" ), tr( "&Quit" ),
>> qApp, SLOT( closeAllWindows() ),
>> diff --git a/src/gui/export_project_dialog.cpp
>> b/src/gui/export_project_dialog.cpp
>> index c3804ea..a0bb876 100644
>> --- a/src/gui/export_project_dialog.cpp
>> +++ b/src/gui/export_project_dialog.cpp
>> @@ -23,20 +23,21 @@
>> */
>>
>> #include <QtCore/QFileInfo>
>> +#include <QtCore/QDir>
>> #include <QtGui/QMessageBox>
>>
>> #include "export_project_dialog.h"
>> +#include "song.h"
>> #include "engine.h"
>> #include "MainWindow.h"
>> -#include "ProjectRenderer.h"
>>
>>
>> exportProjectDialog::exportProjectDialog( const QString & _file_name,
>> - QWidget * _parent ) :
>> + QWidget * _parent, bool multi_export=false ) :
>> QDialog( _parent ),
>> Ui::ExportProjectDialog(),
>> m_fileName( _file_name ),
>> - m_renderer( NULL )
>> + m_multi_export(multi_export)
>> {
>> setupUi( this );
>> setWindowTitle( tr( "Export project to %1" ).arg(
>> @@ -83,7 +84,12 @@ exportProjectDialog::exportProjectDialog( const
>> QString & _file_name,
>>
>> exportProjectDialog::~exportProjectDialog()
>> {
>> - delete m_renderer;
>> +
>> + for( std::vector<ProjectRenderer*>::const_iterator it =
>> m_renderers.begin();
>> + it != m_renderers.end(); ++it )
>> + {
>> + delete (*it);
>> + }
>> }
>>
>>
>> @@ -91,13 +97,31 @@ exportProjectDialog::~exportProjectDialog()
>>
>> void exportProjectDialog::reject()
>> {
>> - if( m_renderer == NULL )
>> + for( std::vector<ProjectRenderer*>::const_iterator it =
>> m_renderers.begin();
>> + it != m_renderers.end(); ++it )
>> {
>> - accept();
>> + (*it)->abortProcessing();
>> + }
>> +}
>> +void exportProjectDialog::accept()
>> +{
>> + // If more to render, kick off next render job
>> + if (m_renderers.size() > 0)
>> + {
>> + pop_render( );
>> }
>> else
>> {
>> - m_renderer->abortProcessing();
>> + // If done, then reset mute states
>> + while(!m_unmuted.empty())
>> + {
>> + track* restore_track = m_unmuted.back();
>> + m_unmuted.pop_back();
>> + restore_track->setMuted(false);
>> + }
>> +
>> + QDialog::accept();
>> +
>> }
>> }
>>
>> @@ -106,19 +130,106 @@ void exportProjectDialog::reject()
>>
>> void exportProjectDialog::closeEvent( QCloseEvent * _ce )
>> {
>> - if( m_renderer != NULL && m_renderer->isRunning() )
>> + for( std::vector<ProjectRenderer*>::const_iterator it =
>> m_renderers.begin();
>> + it != m_renderers.end(); ++it )
>> {
>> - m_renderer->abortProcessing();
>> + if( (*it)->isRunning() )
>> + {
>> + (*it)->abortProcessing();
>> + }
>> }
>> QDialog::closeEvent( _ce );
>> }
>>
>> +void exportProjectDialog::pop_render() {
>>
>> + track* render_track = m_to_render_vec.back();
>> + m_to_render_vec.pop_back();
>>
>> + for (std::vector<track*>::const_iterator it = m_unmuted.begin();
>> + it != m_unmuted.end(); ++it) {
>> + if ((*it) == render_track) {
>> + (*it)->setMuted(false);
>> + } else {
>> + (*it)->setMuted(true);
>> + }
>> + }
>> +
>> + // Pop next render job and start
>> + ProjectRenderer* r = m_renderers.back();
>> + m_renderers.pop_back();
>> + render(r);
>> +}
>> +
>> +void exportProjectDialog::multi_render()
>> +{
>> + m_dirName = m_fileName;
>> + QString path = QDir(m_fileName).filePath("text.txt");
>> + std::string strTest = path.toStdString();
>> +
>> + const trackContainer::trackList & tl = engine::getSong()->tracks();
>> +
>> + // Check for all unmuted tracks. Remember list.
>> + int x = 0;
>> + for( trackContainer::trackList::const_iterator it = tl.begin();
>> + it != tl.end(); ++it )
>> + {
>> + // Don't mute automation tracks
>> + if (! (*it)->isMuted() && (*it)->nodeName() != "automationtrack")
>> + {
>> + m_unmuted.push_back((*it));
>> + QString nextName = (*it)->name();
>> + nextName = nextName.remove(QRegExp("[^a-zA-Z]"));
>> + QString name = QString("%1_%2.wav").arg(x++).arg(nextName);
>> + m_fileName = QDir(m_dirName).filePath(name);
>> + std::string strTest = m_fileName.toStdString();
>> + prep_render();
>> + }
>> + }
>> +
>> + m_to_render_vec = m_unmuted;
>> +
>> + pop_render( );
>> +}
>> +
>> +ProjectRenderer* exportProjectDialog::prep_render(
>> + ) {
>> + mixer::qualitySettings qs =
>> + mixer::qualitySettings(
>> +
>> static_cast<mixer::qualitySettings::Interpolation>(interpolationCB->currentIndex()),
>> +
>> static_cast<mixer::qualitySettings::Oversampling>(oversamplingCB->currentIndex()),
>> + sampleExactControllersCB->isChecked(),
>> + aliasFreeOscillatorsCB->isChecked());
>> + ProjectRenderer::OutputSettings os = ProjectRenderer::OutputSettings(
>> + samplerateCB->currentText().section(" ", 0, 0).toUInt(), false,
>> + bitrateCB->currentText().section(" ", 0, 0).toUInt(),
>> + static_cast<ProjectRenderer::Depths>(depthCB->currentIndex()));
>> + ProjectRenderer* renderer = new ProjectRenderer(qs, os, m_ft,
>> m_fileName);
>> + m_renderers.push_back(renderer);
>> + return renderer;
>> +}
>> +
>> +void exportProjectDialog::render(ProjectRenderer* renderer)
>> +{
>> +
>> + if (renderer->isReady()) {
>> + connect(renderer, SIGNAL( progressChanged( int ) ), progressBar,
>> + SLOT( setValue( int ) ));
>> + connect(renderer, SIGNAL( progressChanged( int ) ), this,
>> + SLOT( updateTitleBar( int ) ));
>> + connect(renderer, SIGNAL( finished() ), this, SLOT( accept() ));
>> + connect(renderer, SIGNAL( finished() ), engine::mainWindow(),
>> + SLOT( resetWindowTitle() ));
>> +
>> + renderer->startProcessing();
>> + } else {
>> + accept();
>> + }
>> +}
>>
>> void exportProjectDialog::startBtnClicked()
>> {
>> - ProjectRenderer::ExportFileFormats ft =
>> ProjectRenderer::NumFileFormats;
>> + m_ft = ProjectRenderer::NumFileFormats;
>>
>> for( int i = 0; i < ProjectRenderer::NumFileFormats; ++i )
>> {
>> @@ -126,12 +237,12 @@ void exportProjectDialog::startBtnClicked()
>> ProjectRenderer::tr(
>> __fileEncodeDevices[i].m_description ) )
>> {
>> - ft = __fileEncodeDevices[i].m_fileFormat;
>>
>>
>>
>> ------------------------------------------------------------------------------
>> The Windows 8 Center - In partnership with Sourceforge
>> Your idea - your app - 30 days.
>> Get started!
>> http://windows8center.sourceforge.net/
>> what-html-developers-need-to-know-about-coding-windows-8-metro-style-apps/
>> _______________________________________________
>> LMMS-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/lmms-devel
>>
>>
>
>
> --
> - No, The other other nathan....
>
------------------------------------------------------------------------------
The Windows 8 Center - In partnership with Sourceforge
Your idea - your app - 30 days.
Get started!
http://windows8center.sourceforge.net/
what-html-developers-need-to-know-about-coding-windows-8-metro-style-apps/
_______________________________________________
LMMS-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lmms-devel